• Login
Community
  • Login

Function List and PL/SQL packages

Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
29 Posts 5 Posters 30.3k Views
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C
    Claudia Frank
    last edited by Mar 7, 2017, 9:50 PM

    I still had to split (first part)

    import time
    
    # -----------------------------------------------------------------------------
    
    import re
    
    from ctypes import windll, byref, wintypes, WINFUNCTYPE, Structure, sizeof
    
    # -----------------------------------------------------------------------------
    # You need to indicate, in the TEMP_FILE_NAME variable, below, the
    # fully qualified file name of the TEXT file containing the REGEX(ES) to test !
    #
    # Note : DOUBLE backslash is needed  ( e.g. D:\\tests\\RegexTests.txt )
    #
    # The COMMENT_CHAR can be changed, if needed, but keep in mind that, if your regex
    # begins with a COMMENT_CHAR, you must escape it, to make the whole regex working.
    # ( For instance the regex \#.* colors all the comments of a python file )
    #
    # If you do not want to be informed, by coloring the current regex, that it didn't match
    # set the INFORM_ABOUT_NO_MATCHES flag to False
    #
    # 2 shortcuts can be configured:
    #  - JUMP_FORWARD_SHORTCUT  = to jump to matches in forward mode,
    #  - JUMP_BACKWARD_SHORTCUT = for backward mode,
    #
    # IMPORTANT:
    #   If using modifiers (SHIFT, CTRL and ALT) the ordering is critical.
    #   A shortcut is defined as a python string using the plus sign to
    #   separate modifiers from letters and function keys.
    #
    #   E.g. 'SHIFT+CTRL+O' means you have to press SHIFT, CTRL and the literal O together.
    #   As already said, if you would define 'CTRL+SHIFT+O' it won't work as the script
    #   expects that SHIFT is the first modifier, if used, followed by CTRL and then ALT key.
    #
    #   One can only define shortcuts which aren't used by notepad, scintilla
    #   and plugins already. Meaning, you cannot define a shortcut 'CTRL+F'
    #   as this is already used to show the file dialog
    #
    #   The possible function keys are listed in dictionary FUNC_KEYS.
    #   Basically, the keys are ESC and F1 to F12
    
    
    # ---------------------------- <CONFIGURATION AREA> ---------------------------
    
    TEMP_FILE_NAME          = 'C:\\RegexTester.txt'
    COMMENT_CHAR            = '#'
    INFORM_ABOUT_NO_MATCHES = True
    JUMP_FORWARD_SHORTCUT   = 'F9'
    JUMP_BACKWARD_SHORTCUT  = 'SHIFT+F9'
    # ORDERING IS CRITICAL!! SHIFT CTRL ALT
    DEBUG_ON                = True
    # ---------------------------- </CONFIGURATION AREA> ---------------------------
    
    FUNC_KEYS = {0x1B:'ESC',
                 0x70:'F1',
                 0x71:'F2',
                 0x72:'F3',
                 0x73:'F4',
                 0x74:'F5',
                 0x75:'F6',
                 0x76:'F7',
                 0x77:'F8',
                 0x78:'F9',
                 0x79:'F10',
                 0x7A:'F11',
                 0x7B:'F12',}
    
    # -----------------------------------------------------------------------------
    
    # winapi constants - used by ctypes
    WM_KEYDOWN    = 0x0100
    WM_KEYUP      = 0x0101
    WM_SYSKEYDOWN = 0x104
    WM_SYSKEYUP   = 0x105
    
    WM_SETFOUCS   = 0x07
    WM_KILLFOUCS  = 0x08
    
    VK_SHIFT         = 0x10
    VK_CONTROL       = 0x11
    VK_MENU = VK_ALT = 0x12
    VK_UP            = 0x26
    VK_DOWN          = 0x28
    
    
    
    WndProcType = WINFUNCTYPE(wintypes.LONG, wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM)
    GWL_WNDPROC = -4
    
    # -----------------------------------------------------------------------------
    
    _g = globals()
    REGEX_TESTER_IS_RUNNING = _g.get('REGEX_TESTER_IS_RUNNING', False)
    OLD_WND_PROC = _g.get('OLD_WND_PROC', None)
    REGEX_TESTER_HWND = _g.get('REGEX_TESTER_HWND', None)
    REGEX_TESTER_INPUT_TAB = _g.get('REGEX_TESTER_INPUT_TAB', 0)
    COLORED_DOCS_LIST = _g.get('COLORED_DOCS_LIST', [])
    TIME_REGEX = False
    USE_PYTHON_ENGINE = False
    # -----------------------------------------------------------------------------
    
    editor1.indicSetStyle(8,INDICATORSTYLE.CONTAINER)
    editor1.indicSetFore(8,(100,215,100))
    editor1.indicSetAlpha(8,55)
    editor1.indicSetOutlineAlpha(8,255)
    editor1.indicSetUnder(8,True)
    
    editor1.indicSetStyle(9,INDICATORSTYLE.ROUNDBOX)
    editor1.indicSetFore(9,(195,215,184))
    editor1.indicSetAlpha(9,55)
    editor1.indicSetOutlineAlpha(9,255)
    editor1.indicSetUnder(9,True)
    
    editor1.indicSetStyle(10,INDICATORSTYLE.ROUNDBOX)
    editor1.indicSetFore(10,(95,215,184))
    editor1.indicSetAlpha(10,55)
    editor1.indicSetOutlineAlpha(10,255)
    editor1.indicSetUnder(10,True)
    
    editor2.indicSetStyle(11,INDICATORSTYLE.STRAIGHTBOX)
    editor2.indicSetFore(11,(255,0,0))      # (192,192,192)  (255,0,0)
    editor2.indicSetAlpha(11,155)
    editor2.indicSetOutlineAlpha(11,255)
    editor2.indicSetUnder(11,True)
    
    editor2.indicSetStyle(12,INDICATORSTYLE.STRAIGHTBOX)
    editor2.indicSetFore(12,(0,255, 0))
    editor2.indicSetAlpha(12,155)
    editor2.indicSetOutlineAlpha(12,255)
    editor2.indicSetUnder(12,True)
    
    editor1.indicSetStyle(13,INDICATORSTYLE.STRAIGHTBOX)
    editor1.indicSetFore(13,(0, 0, 255))     # (192,192,192) (0, 0, 255)
    editor1.indicSetAlpha(13,155)
    editor1.indicSetOutlineAlpha(13,55)
    editor1.indicSetUnder(13,True)
    
    editor2.indicSetStyle(14,INDICATORSTYLE.STRAIGHTBOX)
    editor2.indicSetFore(14,(255,120,0))      # (192,192,192)  (255,0,0)
    editor2.indicSetAlpha(14,155)
    editor2.indicSetOutlineAlpha(14,255)
    editor2.indicSetUnder(14,True)
    
    # -----------------------------------------------------------------------------
    
    IS_ODD = False
    PREVIOUS_REGEX = {}
    # POS_FIRST_OCCURANCE = None
    # POS_LAST_OCCURANCE = None
    NO_MATCH_FOUND = True
    MATCH_POSITIONS = {}
    
    CURRENT_BUFFER_ID = None
    LAST_POSITION = -1
    FORWARD_SEARCH = 0
    BACKWARD_SEARCH = 1
    REGEX_LINE_CLEAR = 0
    REGEX_LINE_NO_MATCH = 1
    REGEX_LINE_INVALID = -1
    
    # -----------------------------------------------------------------------------
    
    class GUITHREADINFO(Structure):
        _fields_ = [
                    ('cbSize', wintypes.DWORD),
                    ('flags', wintypes.DWORD),
                    ('hwndActive', wintypes.HWND),
                    ('hwndFocus', wintypes.HWND),
                    ('hwndCapture', wintypes.HWND),
                    ('hwndMenuOwner', wintypes.HWND),
                    ('hwndMoveSize', wintypes.HWND),
                    ('hwndCaret', wintypes.HWND),
                    ('rcCaret', wintypes.RECT)
                   ]
    
    
    def get_focused_window():
        guiThreadInfo = GUITHREADINFO(cbSize=sizeof(GUITHREADINFO))
        windll.user32.GetGUIThreadInfo(0, byref(guiThreadInfo))
        return guiThreadInfo.hwndFocus
    
    # -----------------------------------------------------------------------------
    
    def signature(func, args, kwargs, result):
        func = func.__name__
        result = unicode(result)
        try:
            return u'{}({}, {}) -> {}'.format(func, unicode(args), unicode(kwargs), result)
        except:
            return u'{}(...) -> {}'.format(func, result)
    
    # -----------------------------------------------------------------------------
    
    def time_function(func):
        def inner(*args, **kwargs):
            start = time.time()
            result = func(*args, **kwargs)
            stop = time.time()
            re_engine = u'python' if USE_PYTHON_ENGINE else u'boost'
            call_signature = signature(func, args, kwargs, result)
            console.write(u'{} took {} seconds using {} re engine\n'.format(call_signature, stop-start, re_engine))
            return result
        return inner
    
    # -----------------------------------------------------------------------------
    
    def match_found(m):
        global IS_ODD
        # global POS_FIRST_OCCURANCE
        # global POS_LAST_OCCURANCE
        global MATCH_POSITIONS
        global NO_MATCH_FOUND
    
        _match_positions = []
    
        if DEBUG_ON:
            _m = m.span()
            console.write(u'Match:{} = {}\n'.format(_m, editor1.getTextRange(*_m)))
    
        if m.lastindex > 0:
            editor1.setIndicatorCurrent(8)
            editor1.indicatorFillRange(m.span(0)[0], m.span(0)[1] - m.span(0)[0])
    
            _match_positions.append(m.span())
            for i in range(1, m.lastindex + 1):
                if (m.span(i)[0] != m.span(0)[0]) or (m.span(i)[1] != m.span(0)[1]):
                    editor1.setIndicatorCurrent(9 if IS_ODD else 10)
                    editor1.indicatorFillRange(m.span(i)[0], m.span(i)[1] - m.span(i)[0])
                    IS_ODD = False if IS_ODD else True
    
            # POS_LAST_OCCURANCE = m.span(i)
    
        else:
            editor1.setIndicatorCurrent(9 if IS_ODD else 10)
            editor1.indicatorFillRange(m.span(0)[0], m.span(0)[1] - m.span(0)[0])
            IS_ODD = False if IS_ODD else True
            # POS_LAST_OCCURANCE = m.span(0)
            _match_positions.append(m.span())
    
        MATCH_POSITIONS[CURRENT_BUFFER_ID].extend(_match_positions)
    
        # if POS_FIRST_OCCURANCE == None:
            # POS_FIRST_OCCURANCE = m.span(0)
        NO_MATCH_FOUND = False
    
    # -----------------------------------------------------------------------------
    
    def set_current_buffer_id():
        global CURRENT_BUFFER_ID
        doc_idx = notepad.getCurrentDocIndex(0)
        CURRENT_BUFFER_ID = notepad.getFiles()[doc_idx][1]
    
    # -----------------------------------------------------------------------------
    
    def track_document():
        global COLORED_DOCS_LIST
        set_current_buffer_id()
        if not CURRENT_BUFFER_ID in COLORED_DOCS_LIST:
            COLORED_DOCS_LIST.append(CURRENT_BUFFER_ID)
    
    # -----------------------------------------------------------------------------
    
    def clear_indicator():
        for i in [8,9,10,13]:
            editor1.setIndicatorCurrent(i)
            editor1.indicatorClearRange(0,editor1.getTextLength())
    
    # -----------------------------------------------------------------------------
    
    def get_regex_flags():
        global TIME_REGEX
        global USE_PYTHON_ENGINE
        TIME_REGEX = False
        USE_PYTHON_ENGINE = False
    
        flags = 0
        flag_line = editor2.getLine(0)
        for char in range(flag_line.find('[')+1,flag_line.find(']')):
            if flag_line[char].upper() == 'I':
                flags |= re.IGNORECASE
            elif flag_line[char].upper() == 'L':
                flags |= re.LOCALE
            elif flag_line[char].upper() == 'M':
                flags |= re.MULTILINE
            elif flag_line[char].upper() == 'S':
                flags |= re.DOTALL
            elif flag_line[char].upper() == 'U':
                flags |= re.UNICODE
            elif flag_line[char].upper() == 'X':
                flags |= re.VERBOSE
            elif flag_line[char].upper() == 'T':
                TIME_REGEX = True
            elif flag_line[char].upper() == 'P':
                USE_PYTHON_ENGINE = True
        return flags
    
    # -----------------------------------------------------------------------------
    
    @time_function
    def regex_exec(pattern, flags):
        try:
            for i in range(1):
                # editor1.research(pattern, lambda m: m, flags)
                editor1.research(pattern, match_found, flags)
            return True
        except:
            return False
    
    def regex():
        # global POS_FIRST_OCCURANCE
        global PREVIOUS_REGEX
        global NO_MATCH_FOUND
        global MATCH_POSITIONS
        global IS_ODD
    
        IS_ODD = False
        MATCH_POSITIONS[CURRENT_BUFFER_ID] = []
    
        clear_indicator()
        pattern = u''
    
        if (editor2.getSelections() == 1) and (editor2.getSelectionEmpty() == False):
            start = editor2.lineFromPosition(editor2.getSelectionNStart(0))
            end = editor2.lineFromPosition(editor2.getSelectionNEnd(0))
            for i in range(start,end+1):
                pattern += editor2.getLine(i).rstrip('\r\n')
        else:
            pattern = current_regex()
    
        PREVIOUS_REGEX[CURRENT_BUFFER_ID] = pattern
        NO_MATCH_FOUND = True
    
        if (pattern != '' and
            pattern != '.' and
            pattern != '()' and not
            pattern.startswith(COMMENT_CHAR) and not
            pattern.isspace() and
            editor2.lineFromPosition(editor2.getCurrentPos()) > 0):
    
            # POS_FIRST_OCCURANCE = None
    
            regex_flag = get_regex_flags()
    
            if TIME_REGEX:
                if regex_exec(pattern,regex_flag):
                    track_document()
                else:
                    NO_MATCH_FOUND = None
            else:
                try:
                    if USE_PYTHON_ENGINE:
                        txt = editor1.getText()
                        for m in re.finditer(pattern, txt, regex_flag):
                            match_found(m)
                    else:
                        editor1.research(pattern, match_found, regex_flag)
                    track_document()
                except:
                    NO_MATCH_FOUND = None
    
        else:
            NO_MATCH_FOUND = None
    
    # -----------------------------------------------------------------------------
    
    1 Reply Last reply Reply Quote 0
    • C
      Claudia Frank
      last edited by Mar 7, 2017, 9:51 PM

      second part

      def current_regex():
          return editor2.getCurLine().rstrip()
      
      # -----------------------------------------------------------------------------
      
      def regex_tester_doc_is_current_doc():
          return REGEX_TESTER_INPUT_TAB == notepad.getCurrentBufferID()
      
      # -----------------------------------------------------------------------------
      
      def scroll_to_position(_position):
          if _position is not None:
              start_pos, end_pos = _position
              editor1.setIndicatorCurrent(13)
              editor1.indicatorFillRange(start_pos, end_pos-start_pos)
              current_line = editor1.lineFromPosition(start_pos)
              editor1.ensureVisible(current_line)
              editor1.gotoPos(start_pos)
              editor1.verticalCentreCaret()
              editor1.setXCaretPolicy(CARETPOLICY.EVEN|CARETPOLICY.JUMPS,10)
              editor1.scrollCaret()
      
      # -----------------------------------------------------------------------------
      
      def get_current_regex_position_and_length():
          current_line = editor2.lineFromPosition(editor2.getCurrentPos())
          if current_line != 0 and not editor2.getLine(current_line).startswith(COMMENT_CHAR):
              lenght_line = editor2.lineLength(current_line)
              position = editor2.positionFromLine(current_line)
              return position, lenght_line
          return None, None
      
      # -----------------------------------------------------------------------------
      
      def mark_regex_line(match_indicator):
          position, lenght = get_current_regex_position_and_length()
          if position:
              if match_indicator == REGEX_LINE_NO_MATCH:
                      editor2.setIndicatorCurrent(14)
                      editor2.indicatorFillRange(position, lenght)
              elif match_indicator == REGEX_LINE_INVALID:
                  editor2.setIndicatorCurrent(11)
                  editor2.indicatorFillRange(position, lenght)
              else:
                  for i in [11,14]:
                      editor2.setIndicatorCurrent(i)
                      editor2.indicatorClearRange(0, editor2.getTextLength())
      
      # -----------------------------------------------------------------------------
      
      def regex_tester_updateui_callback(args):
          if (regex_tester_doc_is_current_doc() and PREVIOUS_REGEX.get(CURRENT_BUFFER_ID, '') != current_regex()):
              mark_regex_line(REGEX_LINE_CLEAR)
              regex()
              if NO_MATCH_FOUND and INFORM_ABOUT_NO_MATCHES:
                  mark_regex_line(REGEX_LINE_NO_MATCH)
              elif NO_MATCH_FOUND is None:
                  mark_regex_line(REGEX_LINE_INVALID)
              # else:
                  # scroll_to_position(POS_FIRST_OCCURANCE)
      # -----------------------------------------------------------------------------
      
      def regex_tester_file_before_close_callback(args):
          if (args['bufferID'] == REGEX_TESTER_INPUT_TAB):
              stop_regex_tester()
      
      # -----------------------------------------------------------------------------
      
      def regex_tester_buffer_activated_callback(args):
          global PREVIOUS_REGEX
          set_current_buffer_id()
      
          if not PREVIOUS_REGEX.has_key(CURRENT_BUFFER_ID):
              PREVIOUS_REGEX[CURRENT_BUFFER_ID] = ''
      
          if not REGEX_TESTER_IS_RUNNING:
              global COLORED_DOCS_LIST
              if args['bufferID'] in COLORED_DOCS_LIST:
                  clear_indicator()
                  COLORED_DOCS_LIST.remove(args['bufferID'])
      
              if len(COLORED_DOCS_LIST) == 0:
                  notepad.clearCallbacks([NOTIFICATION.BUFFERACTIVATED])
      
      # -----------------------------------------------------------------------------
      
      def jump_through_matches(search_direction):
          global MATCH_POSITIONS
          global LAST_POSITION
      
          if MATCH_POSITIONS.has_key(CURRENT_BUFFER_ID):
              editor1.setIndicatorCurrent(13)
              editor1.indicatorClearRange(0,editor1.getTextLength())
      
              match_count = len(MATCH_POSITIONS[CURRENT_BUFFER_ID])
      
              if match_count == 0:
                  return
      
              elif match_count == 1:
                  _position = MATCH_POSITIONS[CURRENT_BUFFER_ID][0]
      
              else:
                  current_position = editor1.getCurrentPos()
      
                  if search_direction == 0:
                      while True:
                          _position = MATCH_POSITIONS[CURRENT_BUFFER_ID].pop(0)
                          MATCH_POSITIONS[CURRENT_BUFFER_ID].append(_position)
      
                          if _position[0] != LAST_POSITION:
                              break
                  else:
                      while True:
                          _position = MATCH_POSITIONS[CURRENT_BUFFER_ID].pop()
                          MATCH_POSITIONS[CURRENT_BUFFER_ID].insert(0, _position)
      
                          if _position[0] != LAST_POSITION:
                              break
      
              LAST_POSITION = _position[0]
              scroll_to_position(_position)
      
      # -----------------------------------------------------------------------------
      
      def regex_tester_doc_already_exists():
          files = notepad.getFiles()
          f = [i[1][1] for i in enumerate(files) if i[1][0].upper() == TEMP_FILE_NAME.upper()]
          if f:
              return f[0]
          else:
              return 0
      
      # -----------------------------------------------------------------------------
      
      def color_regex_tester_status():
          status_line = editor2.getLine(0)
          if REGEX_TESTER_IS_RUNNING:
              start = status_line.find('[')
              stop = status_line.find(']')+1
              editor2.setIndicatorCurrent(12)
              editor2.indicatorFillRange(0,20)
              editor2.setIndicatorCurrent(12)
              editor2.indicatorFillRange(start,stop-start)
          else:
              editor2.setIndicatorCurrent(12)
              editor2.indicatorClearRange(0,len(status_line))
      
      # -----------------------------------------------------------------------------
      
      def start_regex_tester():
          if TEMP_FILE_NAME == '':
              notepad.messageBox('You need to indicate, in the TEMP_FILE_NAME variable,\n' +
                                 'the fully qualified file name of the TEXT file containing ' +
                                 'the REGEX(ES) to test', 'TEMP_FILE_NAME is not set')
              return False
      
          current_document = 0 if notepad.getCurrentView() == 1 else notepad.getCurrentBufferID()
      
          global REGEX_TESTER_INPUT_TAB
          REGEX_TESTER_INPUT_TAB = regex_tester_doc_already_exists()
          if REGEX_TESTER_INPUT_TAB == 0 :
              notepad.open(TEMP_FILE_NAME)
              if notepad.getCurrentFilename().upper() == TEMP_FILE_NAME.upper():
                  REGEX_TESTER_INPUT_TAB = notepad.getCurrentBufferID()
              else:
                  notepad.messageBox('Could not open specified file\n' +
                                     '{0}'.format(TEMP_FILE_NAME),
                                     'Regex Tester Startup Failed', 0)
                  return False
          else:
              notepad.activateBufferID(REGEX_TESTER_INPUT_TAB)
      
          if notepad.getCurrentView() != 1:
              notepad.menuCommand(MENUCOMMAND.VIEW_GOTO_ANOTHER_VIEW)
      
          STATUS_LINE = 'RegexTester isActive [] flags:sitp, '
      
          STATUS_LINE += 'fwd:{}  bwd:{}\r\n'.format(JUMP_FORWARD_SHORTCUT,
                                                     JUMP_BACKWARD_SHORTCUT,)
      
          current_status_line = editor2.getLine(0)
          if 'RegexTester' in current_status_line:
              editor2.replace('RegexTester inActive', 'RegexTester isActive')
          else:
              editor2.insertText(0, STATUS_LINE)
      
      
          global REGEX_TESTER_IS_RUNNING
          REGEX_TESTER_IS_RUNNING = True
      
          color_regex_tester_status()
      
          set_current_buffer_id()
      
          global PREVIOUS_REGEX
          PREVIOUS_REGEX[CURRENT_BUFFER_ID] = ''
      
          editor.callbackSync(regex_tester_updateui_callback, [SCINTILLANOTIFICATION.UPDATEUI])
      
          if current_document != 0:
              notepad.activateBufferID(current_document)
      
          editor2.setFocus(True)
          editor2.gotoLine(0)
          notepad.save()
      
          global REGEX_TESTER_HWND
          REGEX_TESTER_HWND = get_focused_window()
      
          notepad.callback(regex_tester_file_before_close_callback, [NOTIFICATION.FILEBEFORECLOSE])
          notepad.callback(regex_tester_buffer_activated_callback, [NOTIFICATION.BUFFERACTIVATED])
      
          return True
      
      # -----------------------------------------------------------------------------
      
      def stop_regex_tester():
          editor.clearCallbacks([SCINTILLANOTIFICATION.UPDATEUI])
          notepad.clearCallbacks([NOTIFICATION.FILEBEFORECLOSE])
      
          notepad.activateBufferID(REGEX_TESTER_INPUT_TAB)
      
          if regex_tester_doc_is_current_doc():
              editor2.replace('RegexTester isActive', 'RegexTester inActive')
              notepad.save()
      
          global REGEX_TESTER_IS_RUNNING
          REGEX_TESTER_IS_RUNNING = False
      
          clear_indicator()
          color_regex_tester_status()
          mark_regex_line(0)
      
          global MATCH_POSITIONS
          MATCH_POSITIONS = {}
      
          _hook.unregister()
      
          editor1.setFocus(True)
      
      # -----------------------------------------------------------------------------
      
      class Hook():
      
          def __init__(self):
              self.nppHandle = windll.user32.FindWindowA('Notepad++',None)
              self.oldWndProc = None
      
              self.SHIFT_PRESSED = False
              self.CTRL_PRESSED = False
              self.ALT_PRESSED = False
      
          def register(self):
              if REGEX_TESTER_HWND:
                  self.new_wnd_proc = WndProcType(self.sciWndProc)
                  windll.kernel32.SetLastError(0)
                  self.oldWndProc = windll.user32.SetWindowLongA(REGEX_TESTER_HWND, GWL_WNDPROC, self.new_wnd_proc)
      
                  if self.oldWndProc:
                      global OLD_WND_PROC
                      OLD_WND_PROC = self.oldWndProc
                  else:
                      _err = 'GetLastError:{}'.format(windll.kernel32.GetLastError())
                      notepad.messageBox('Could not register hook:\n{}\n'.format(_err) +
                                          'Shortcuts won\'t work',
                                          'Register Hook Failure', 0)
      
          def unregister(self):
              if OLD_WND_PROC:
                  self.oldWndProc = OLD_WND_PROC
                  windll.kernel32.SetLastError(0)
                  dummy = windll.user32.SetWindowLongA(REGEX_TESTER_HWND, GWL_WNDPROC, self.oldWndProc)
                  if not dummy:
                      _err = 'GetLastError:{}'.format(windll.kernel32.GetLastError())
                      notepad.messageBox('Could not unregister hook:\n{}\n'.format(_err) +
                                          'It is recommended to save data and restart npp to prevent data loss',
                                          'Unregister Hook Failure', 0)
      
          def sciWndProc(self, hWnd, msg, wParam, lParam):
              if msg in [WM_KEYDOWN, WM_SYSKEYDOWN]:
                  if wParam == VK_SHIFT:
                      self.SHIFT_PRESSED = True
                  elif wParam == VK_CONTROL:
                      self.CTRL_PRESSED = True
                  elif wParam == VK_ALT:
                      self.ALT_PRESSED = True
      
              elif msg in [WM_KEYUP,WM_SYSKEYUP]:
                  if wParam == VK_SHIFT:
                      self.SHIFT_PRESSED = False
                  elif wParam == VK_CONTROL:
                      self.CTRL_PRESSED = False
                  elif wParam == VK_ALT:
                      self.ALT_PRESSED = False
                  else:
                      modifier = 'SHIFT+' if self.SHIFT_PRESSED else ''
                      modifier += 'CTRL+' if self.CTRL_PRESSED else ''
                      modifier += 'ALT+' if self.ALT_PRESSED else ''
                      if wParam in FUNC_KEYS:
                          key_combo = '{}{}'.format(modifier,FUNC_KEYS[wParam])
                      else:
                          key_combo = '{}{}'.format(modifier,chr(wParam))
      
                      func = dict_func.get(key_combo, None)
                      if func:
                          func()
      
              elif msg == WM_KILLFOUCS:
                  self.SHIFT_PRESSED = False
                  self.CTRL_PRESSED = False
                  self.ALT_PRESSED = False
      
              return windll.user32.CallWindowProcA (self.oldWndProc, hWnd, msg, wParam, lParam)
      
      # -----------------------------------------------------------------------------
      
      def main():
          if REGEX_TESTER_IS_RUNNING:
              stop_regex_tester()
          else:
              if start_regex_tester():
                  _hook.register()
      
      # -----------------------------------------------------------------------------
      
      dict_func={JUMP_FORWARD_SHORTCUT  : lambda: jump_through_matches(FORWARD_SEARCH),
                 JUMP_BACKWARD_SHORTCUT : lambda: jump_through_matches(BACKWARD_SEARCH),}
                 # JUMP_TO_FIRST_SHORTCUT : lambda: scroll_to_position(POS_FIRST_OCCURANCE),
                 # JUMP_TO_LAST_SHORTCUT  : lambda: scroll_to_position(POS_LAST_OCCURANCE)}
      
      
      _hook = Hook()
      main()
      
      1 Reply Last reply Reply Quote 0
      • MAPJe71M
        MAPJe71
        last edited by Mar 7, 2017, 9:53 PM

        Thanx!
        Will give it a try.

        C 1 Reply Last reply Mar 7, 2017, 9:58 PM Reply Quote 0
        • C
          Claudia Frank @MAPJe71
          last edited by Mar 7, 2017, 9:58 PM

          @MAPJe71

          one other thing.
          The script doesn’t rerun the same regexes. Meaning,
          if one line has

          ^def.*()
          

          and the next line also and you move the cursor from the first to the next line
          it doesn’t trigger another research. There must be a difference within the regexes.

          Cheers
          Claudia

          1 Reply Last reply Reply Quote 0
          • C
            Claudia Frank
            last edited by Claudia Frank Mar 7, 2017, 10:17 PM Mar 7, 2017, 10:17 PM

            One thing I forgot to mention,
            special thanks to Scott and Guy which provided
            a lot of information and doing beta testing.
            Without there patient it wouldn’t be what it is.

            THANK YOU!!
            Claudia

            1 Reply Last reply Reply Quote 1
            • Jean-Marc MalmedyJ
              Jean-Marc Malmedy @MAPJe71
              last edited by Mar 8, 2017, 8:50 AM

              @MAPJe71 said:

              Although my regular expressions work in RegexBuddy I’m not able to get them to show any packages in Notepad++ Function List.
              This needs more investigation, sorry I can’t give you a solution any time soon :(

              I’m not surprised since my regular expression worked too outside Function List.
              Anyway, thank you very much for trying.

              1 Reply Last reply Reply Quote 0
              • MAPJe71M
                MAPJe71
                last edited by Mar 8, 2017, 8:56 AM

                @Jean-Marc-Malmedy after using @Claudia-Frank 's (thanks Claudia, awesome script!) script I was able to create a working parser. Needs some fine tuning/cleaning though.

                1 Reply Last reply Reply Quote 0
                • MAPJe71M
                  MAPJe71
                  last edited by Mar 8, 2017, 9:10 AM

                  @Jean-Marc-Malmedy could you try this one:

                  			<parser
                  				displayName="SQL-mehods"
                  				id         ="sql_syntax"
                  				commentExpr="(?x)                                               # Utilize inline comments (see `RegEx - Pattern Modifiers`)
                  								(?s:\x2F\x2A.*?\x2A\x2F)                        # Multi Line Comment
                  							|	(?m-s:-{2}.*$)                                  # Single Line Comment
                  							"
                  			>
                  				<classRange
                  					mainExpr    ="(?x)                                          # Utilize inline comments (see `RegEx - Pattern Modifiers`)
                  							(?mi)                                               # case insensitive
                  							^\h*                                                # optional leading blanks
                  							CREATE\s+(?:OR\s+REPLACE\s+)?PACKAGE\s+(?:BODY\s+)? # start-of-package indicator
                  							(?:\w+\.)?                                          # schema name, optional
                  							(?'PACKAGE_ID'\w+)                                  # package name
                  							(?s:.*?)                                            # whatever, until...
                  							^\h*END(?:\s+\k'PACKAGE_ID')?\s*;                   # ...end-of-package indicator
                  						"
                  				>
                  					<className>
                  						<nameExpr expr="(?i:PACKAGE\s+(?:BODY\s+)?)\K(?:\w+\.)?\w+" />
                  					</className>
                  					<function
                  						mainExpr="^\h*(?i:FUNCTION|PROCEDURE)\s+\K\w+\s*\([^()]*\)"
                  					>
                  						<functionName>
                  							<funcNameExpr expr="\w+" />
                  						</functionName>
                  					</function>
                  				</classRange>
                  				<function
                  					mainExpr="^\h*(?i:FUNCTION|PROCEDURE)\s+\K\w+\s*\([^()]*\)"
                  				>
                  					<functionName>
                  						<nameExpr expr="\w+" />
                  					</functionName>
                  				</function>
                  			</parser>
                  
                  1 Reply Last reply Reply Quote 0
                  • Jean-Marc MalmedyJ
                    Jean-Marc Malmedy
                    last edited by Mar 8, 2017, 1:37 PM

                    Wonderful, it works.

                    I just had to make to small modifications:

                    • making the parenthesis optional for the declaration of function or procedure
                    • starting the declaration of a function or procedure outside a package with “create or replace”

                    This is my final version of the parser:

                            <parser
                                displayName="SQL-mehods"
                                id         ="sql_syntax"
                                commentExpr="(?x)                                               # Utilize inline comments (see `RegEx - Pattern Modifiers`)
                                                (?s:\x2F\x2A.*?\x2A\x2F)                        # Multi Line Comment
                                            |   (?m-s:-{2}.*$)                                  # Single Line Comment
                                            "
                            >
                                <classRange
                                    mainExpr    ="(?x)                                          # Utilize inline comments (see `RegEx - Pattern Modifiers`)
                                            (?mi)                                               # case insensitive
                                            ^\h*                                                # optional leading blanks
                                            CREATE\s+(?:OR\s+REPLACE\s+)?PACKAGE\s+(?:BODY\s+)? # start-of-package indicator
                                            (?:\w+\.)?                                          # schema name, optional
                                            (?'PACKAGE_ID'\w+)                                  # package name
                                            (?s:.*?)                                            # whatever, until...
                                            ^\h*END(?:\s+\k'PACKAGE_ID')?\s*;                   # ...end-of-package indicator
                                        "
                                >
                                    <className>
                                        <nameExpr expr="(?i:PACKAGE\s+(?:BODY\s+)?)\K(?:\w+\.)?\w+" />
                                    </className>
                                    <function
                                        mainExpr="^\h*(?i:FUNCTION|PROCEDURE)\s+\K\w+\s*(\([^()]*\)){0,1}"
                                    >
                                        <functionName>
                                            <funcNameExpr expr="\w+" />
                                        </functionName>
                                    </function>
                                </classRange>
                                <function
                                    mainExpr="^\h*CREATE\s+(?:OR\s+REPLACE\s+)?(?i:FUNCTION|PROCEDURE)\s+\K\w+\s*(\([^()]*\)){0,1}"
                                >
                                    <functionName>
                                        <nameExpr expr="\w+" />
                                    </functionName>
                                </function>
                            </parser>
                    

                    Many many thanks for your help.

                    Jean-Marc

                    1 Reply Last reply Reply Quote 0
                    • MAPJe71M
                      MAPJe71
                      last edited by Mar 8, 2017, 1:41 PM

                      @Jean-Marc-Malmedy FYI: {0,1} can be replaced with a ?.

                      1 Reply Last reply Reply Quote 0
                      • Jean-Marc MalmedyJ
                        Jean-Marc Malmedy
                        last edited by Mar 8, 2017, 2:02 PM

                        Yes, indeed. Thanks for the suggestion.

                        1 Reply Last reply Reply Quote 0
                        • MAPJe71M
                          MAPJe71
                          last edited by Mar 8, 2017, 2:02 PM

                          You’re welcome!

                          1 Reply Last reply Reply Quote 0
                          • Gábor MadácsG
                            Gábor Madács
                            last edited by Gábor Madács Sep 16, 2017, 10:03 PM Sep 16, 2017, 10:02 PM

                            HI! Wonderful, I came here for this… :D

                            I have tried his solution, but immediately bumped into a serious problem:
                            I can see only the first method in my package. :(

                            if i understand correctly, the classRange - mainExpr should match for the whole package body.
                            I think the problem lies here at the last line:

                            ^\h*END(?:\s+\k'PACKAGE_ID')?\s*;
                            

                            this matches the first “end;” in the code.

                            In a real-world code there is lots of “end;” statements, as we can close methods with it, and even there is unnamed blocks inside them.

                            Example:

                            CREATE OR REPLACE PACKAGE BODY sch_001.pck_001 AS
                              PROCEDURE p_proc_001(pn_id PLS_INTEGER) IS
                                sd date;
                              BEGIN
                                 -- unnamed block begin: "try-catch" in PL/SQL
                                 begin
                                    select sysdate into sd from dual;
                                 exception when others then
                                     sd := null;
                                 end;
                                 -- do something else
                              END;
                            END pck_001;
                            /
                            

                            Please help me on this.
                            Unfortunately I’m not really familiar with greedy multi-line regexp statements…

                            For start, it would be OK, if it could end only on the end of file…

                            It would be a huge help for us! :)

                            MAPJe71M 1 Reply Last reply Sep 16, 2017, 10:55 PM Reply Quote 0
                            • MAPJe71M
                              MAPJe71 @Gábor Madács
                              last edited by Sep 16, 2017, 10:55 PM

                              @Gábor-Madács
                              I don’t understand your problem.

                              1 Reply Last reply Reply Quote 0
                              • Gábor MadácsG
                                Gábor Madács
                                last edited by Sep 17, 2017, 11:22 AM

                                Thank you for the quick response!

                                Your results are better than mine… :)

                                What parser do you use? This is by the one from the last post from Jean-Marc Malmedy.
                                I have also tried the one before this - posted by you - that is showed the second procedure too, but out of the body.
                                (That’s because of here no “CREATE” in the procedure name - that is a difference between the two version. “CREATE” is for procedures not in packages.)

                                Please post your fine parser version! :)

                                Gabor

                                MAPJe71M 1 Reply Last reply Sep 17, 2017, 2:38 PM Reply Quote 0
                                • MAPJe71M
                                  MAPJe71 @Gábor Madács
                                  last edited by Sep 17, 2017, 2:38 PM

                                  @Gábor-Madács See my post on GitHub.

                                  1 Reply Last reply Reply Quote 0
                                  • Gábor MadácsG
                                    Gábor Madács
                                    last edited by Sep 17, 2017, 10:05 PM

                                    @MAPJe71 Wow… Thank you very much! :D
                                    (May I note, now the “I don’t understand your problem.” seems somewhat unfounded… ;) )

                                    Work like a charm! (Looks like a charm, indeed… ;) )

                                    Hope, it will be part of the official NPP distribution!

                                    Thank you again!

                                    Gabor

                                    1 Reply Last reply Reply Quote 0
                                    • Marco GonzalezM
                                      Marco Gonzalez
                                      last edited by Dec 3, 2020, 12:14 AM

                                      Beautiful work! But i have a little bit problem.
                                      When the procedure or function name is missing after the “end”, it seems the parser consumes the file to the end skipping other functions!

                                      Example:
                                      function foo is
                                      Begin
                                      –Todo function logic…
                                      null;
                                      End;

                                      function bar is…

                                      In this case function bar (and other functions after it) will be skipped! I know it is not the best practice but it’s pretty common.
                                      although it’s simple to fix that on the source code I will appreciate your help to fix the parser.

                                      Thanks in advance!

                                      1 Reply Last reply Reply Quote 0
                                      • Marco GonzalezM
                                        Marco Gonzalez
                                        last edited by Dec 3, 2020, 11:56 PM

                                        Hi guys, after a few little changes it seems to work now for all my Plsql files…
                                        <?xml version=“1.0” encoding=“UTF-8” ?>
                                        <!-- ==========================================================================\

                                        To learn how to make your own language parser, please check the following
                                        link:
                                        https://npp-user-manual.org/docs/function-list/

                                        |
                                        =========================================================================== -->
                                        <NotepadPlus>
                                        <functionList>
                                        <!-- ========================================================= [ PL/SQL ] -->
                                        <parser
                                        displayName=“SQL-mehods”
                                        id =“sql_syntax”
                                        commentExpr=“(?x) # Utilize inline comments (see RegEx - Pattern Modifiers)
                                        (?s:\x2F\x2A.?\x2A\x2F) # Multi Line Comment
                                        | (?m-s:-{2}.
                                        $) # Single Line Comment
                                        " >
                                        <classRange
                                        mainExpr =”(?x) # Utilize inline comments (see RegEx - Pattern Modifiers)
                                        (?mi) # case insensitive
                                        ^\h* # optional leading blanks
                                        (CREATE\s+(?:OR\s+REPLACE\s+)?)?PACKAGE\s+(?:BODY\s+)? # start-of-package indicator
                                        (?:\w+.)? # schema name, optional
                                        (?‘PACKAGE_ID’\w+) # package name
                                        (?s:.?) # whatever, until…
                                        ^\h
                                        END(?:\s+\k’PACKAGE_ID’)\s*; # …end-of-package indicator
                                        " >
                                        <className><nameExpr expr=“(?i:PACKAGE\s+(?:BODY\s+)?)\K(?:\w+.)?\w+” /></className>
                                        <function mainExpr=“^\h*(?i:FUNCTION|PROCEDURE)\s+\K\w+\s*(([^()]))?“>
                                        <functionName><funcNameExpr expr=”\w+" /></functionName>
                                        </function>
                                        </classRange>
                                        <function mainExpr="^\h
                                        (CREATE\s+(?:OR\s+REPLACE\s+)?)?(?i:FUNCTION|PROCEDURE)\s+\K\w+\s*(([^()]*))?” >
                                        <functionName><nameExpr expr=“\w+” /></functionName>
                                        </function>
                                        </parser>
                                        </functionList>
                                        </NotepadPlus>

                                        I also indented it my own way, sorry for that, enjoy it!

                                        1 Reply Last reply Reply Quote 1
                                        • First post
                                          Last post
                                        The Community of users of the Notepad++ text editor.
                                        Powered by NodeBB | Contributors