Community
    • Login

    Function Completion: cycle through choices

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    autocompletefunction hint
    16 Posts 4 Posters 1.0k 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.
    • Michael VincentM
      Michael Vincent @Ekopalypse
      last edited by

      @Ekopalypse said in Function Completion: cycle through choices:

      SCN_CALLTIPCLICK

      It’s possible I’m completely incorrect, but it seems the SCN_CALLTIPCLICK is generated by the clicking of the arrow keys in the call tip. I think we want a keyboard key or key combo to generate that notification, so a bit backwards.

      Would this involve trapping keyboard input (like say the up / down arrow keys and then checking SCI_CALLTIPACTIVE and if TRUE, then post a SCN_CALLTIPCLICK notification?

      I’m trying to think about how to proof-of-concept this in PythonScript and not grokking where to start from the Scintilla docs - again it seems backwards - the clicking generates the notification and we want a keyboard key to generate the notification - not sure Scintilla supports that?

      I do think this is a smashing idea though!

      Cheers.

      EkopalypseE 2 Replies Last reply Reply Quote 1
      • EkopalypseE
        Ekopalypse @Michael Vincent
        last edited by

        @Michael-Vincent

        No, you are right.
        I put the cart before the horse in my description.

        It should be enough to use a Python script that sends the notification.
        Give me a moment.

        1 Reply Last reply Reply Quote 1
        • EkopalypseE
          Ekopalypse @Michael Vincent
          last edited by Ekopalypse

          @Michael-Vincent

          from Npp import notepad, editor, editor1, SCINTILLANOTIFICATION
          import ctypes
          from ctypes import wintypes
          
          # def on_calltip_click(args):
              # if args['position'] == 1:
                  # print('backward')
              # elif args['position'] == 2:
                  # print('forward')
                  
          
                  
          # editor.callbackSync(on_calltip_click, [SCINTILLANOTIFICATION.CALLTIPCLICK])
          
          
          class NMHDR(ctypes.Structure):
              _fields_ = [('hwndFrom', wintypes.HWND),
                          ('idFrom',   ctypes.c_size_t),
                          ('code',     wintypes.UINT)]
              def __init__(self, hwnd, id, code):
                  self.hwndFrom = hwnd
                  self.idFrom = id
                  self.code = code
          
          
          Sci_Position = ctypes.c_size_t
          class SCNOTIFICATION(ctypes.Structure):
              _fields_ = [('nmhdr', NMHDR),
                          ('position', Sci_Position),
                          ('ch', wintypes.INT),
                          ('modifiers', wintypes.INT),
                          ('modificationType', wintypes.INT),
                          ('text', wintypes.LPCSTR),
                          ('length', Sci_Position),
                          ('linesAdded', Sci_Position),
                          ('message', wintypes.INT),
                          ('wParam', wintypes.WPARAM),
                          ('lParam', wintypes.LPARAM),
                          ('line', Sci_Position),
                          ('foldLevelNow', wintypes.INT),
                          ('foldLevelPrev', wintypes.INT),
                          ('margin', wintypes.INT),
                          ('listType', wintypes.INT),
                          ('x', wintypes.INT),
                          ('y', wintypes.INT),
                          ('token', wintypes.INT),
                          ('annotationLinesAdded', Sci_Position),
                          ('updated', wintypes.INT),
                          ('listCompletionMethod', wintypes.INT)]
          
          SendMessage = ctypes.windll.user32.SendMessageW
          SendMessage.argtype = [wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM]
          SendMessage.restype = wintypes.LPARAM
          
          
          nmhdr = NMHDR(editor1.hwnd, 0, SCINTILLANOTIFICATION.CALLTIPCLICK)
          notification = SCNOTIFICATION()
          notification.nmhdr = nmhdr
          notification.position = 2
          
          WM_NOTIFY = 0x4e
          SendMessage(notepad.hwnd, WM_NOTIFY, 0, ctypes.addressof(notification))
          

          I have not checked if the fields in the supplied nmhdr structure are really set correctly.

          Michael VincentM 1 Reply Last reply Reply Quote 2
          • Michael VincentM
            Michael Vincent @Ekopalypse
            last edited by

            @Ekopalypse said in Function Completion: cycle through choices:

            SendMessage(notepad.hwnd, WM_NOTIFY, 0, ctypes.addressof(notification))

            Trying this out, I get an error:

            Traceback (most recent call last):
              File "C:\usr\bin\npp64\plugins\Config\PythonScript\scripts\callTipClick.py", line 67, in <module>
                SendMessage(notepad.hwnd, WM_NOTIFY, 0, ctypes.addressof(notification))
            ctypes.ArgumentError: argument 4: <class 'OverflowError'>: int too long to convert
            

            Cheers.

            Michael VincentM 1 Reply Last reply Reply Quote 0
            • Michael VincentM
              Michael Vincent @Michael Vincent
              last edited by

              @Michael-Vincent
              @Ekopalypse

              Fixed (probably should have noted I’m on 64-bit):

              SendMessage(notepad.hwnd, WM_NOTIFY, 0, ctypes.c_longlong(ctypes.addressof(notification)))
              

              Cheers.

              Michael VincentM 1 Reply Last reply Reply Quote 1
              • Michael VincentM
                Michael Vincent @Michael Vincent
                last edited by

                @Michael-Vincent said in Function Completion: cycle through choices:

                @Michael-Vincent
                @Ekopalypse
                Fixed (probably should have noted I’m on 64-bit):
                @PeterJones

                Works nicely now:

                callTipClick.py:

                from Npp import notepad, editor, editor1, editor2, SCINTILLANOTIFICATION
                import ctypes
                from ctypes import wintypes
                
                class NMHDR(ctypes.Structure):
                    _fields_ = [('hwndFrom', wintypes.HWND),
                                ('idFrom',   ctypes.c_size_t),
                                ('code',     wintypes.UINT)]
                    def __init__(self, hwnd, id, code):
                        self.hwndFrom = hwnd
                        self.idFrom = id
                        self.code = code
                
                Sci_Position = ctypes.c_size_t
                class SCNOTIFICATION(ctypes.Structure):
                    _fields_ = [('nmhdr', NMHDR),
                                ('position', Sci_Position),
                                ('ch', wintypes.INT),
                                ('modifiers', wintypes.INT),
                                ('modificationType', wintypes.INT),
                                ('text', wintypes.LPCSTR),
                                ('length', Sci_Position),
                                ('linesAdded', Sci_Position),
                                ('message', wintypes.INT),
                                ('wParam', wintypes.WPARAM),
                                ('lParam', wintypes.LPARAM),
                                ('line', Sci_Position),
                                ('foldLevelNow', wintypes.INT),
                                ('foldLevelPrev', wintypes.INT),
                                ('margin', wintypes.INT),
                                ('listType', wintypes.INT),
                                ('x', wintypes.INT),
                                ('y', wintypes.INT),
                                ('token', wintypes.INT),
                                ('annotationLinesAdded', Sci_Position),
                                ('updated', wintypes.INT),
                                ('listCompletionMethod', wintypes.INT)]
                
                if editor.callTipActive():
                    SendMessage = ctypes.windll.user32.SendMessageW
                    SendMessage.argtype = [wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM]
                    SendMessage.restype = wintypes.LPARAM
                
                    hwnd = notepad.getCurrentView()
                    if hwnd == 0:
                        hwnd = editor1.hwnd
                    else:
                        hwnd = editor2.hwnd
                
                    nmhdr = NMHDR(hwnd, 0, SCINTILLANOTIFICATION.CALLTIPCLICK)
                    notification = SCNOTIFICATION()
                    notification.nmhdr = nmhdr
                    notification.position = 2
                
                    WM_NOTIFY = 0x4e
                    SendMessage(notepad.hwnd, WM_NOTIFY, 0, ctypes.c_longlong(ctypes.addressof(notification)))
                

                NOTE: This relies in your PythonScript startup having some logic to get the editor1 and 2 HWND and create those variables I use in the script.

                Then I just added this to my PythonScript menu and added a shortcut to it. Works like a charm:

                2d96ab2c-905a-4950-8392-42959a3e4c78-image.png

                Cheers.

                EkopalypseE Michael VincentM 2 Replies Last reply Reply Quote 2
                • EkopalypseE
                  Ekopalypse @Michael Vincent
                  last edited by

                  @Michael-Vincent

                  I am also working with x64 bit.
                  The problem could be that you already have a SendMessage function declaration somewhere in your used Python script codes, which is defined slightly different.

                  >>> from ctypes import wintypes
                  
                  >>> wintypes.LPARAM
                  <class 'ctypes.c_longlong'>
                  

                  wintypes.LPARAM is already a c_longlong, so this cast would not be necessary, since the whole point of

                  SendMessage.argtype = [wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM]
                  SendMessage.restype = wintypes.LPARAM
                  

                  is to give Python the information how to interpret certain variables.

                  Michael VincentM 1 Reply Last reply Reply Quote 3
                  • Michael VincentM
                    Michael Vincent @Ekopalypse
                    last edited by

                    @Ekopalypse said in Function Completion: cycle through choices:

                    The problem could be that you already have a SendMessage function declaration somewhere in your used Python script codes, which is defined slightly different.

                    Indeed, you are correct, and I’ve fixed it so your original code:

                        SendMessage(notepad.hwnd, WM_NOTIFY, 0, ctypes.addressof(notification))
                    

                    WORKS!

                    Cheers.

                    1 Reply Last reply Reply Quote 1
                    • Michael VincentM
                      Michael Vincent @Michael Vincent
                      last edited by

                      @Michael-Vincent said in Function Completion: cycle through choices:

                      SendMessage.argtype = [wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM]
                      

                      Note this line should be:

                      SendMessage.argtypes = [wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPARAM]
                      

                      Note: argtypes

                      Cheers.

                      1 Reply Last reply Reply Quote 2
                      • Michael VincentM
                        Michael Vincent @PeterJones
                        last edited by

                        @PeterJones said in Function Completion: cycle through choices:

                        @Ekopalypse & @guy038 ,
                        Thanks for the confirmation. I thought as much, but wanted to make sure.
                        Issue #11950 created

                        PR #12017 created.

                        Cheers.

                        Michael VincentM 1 Reply Last reply Reply Quote 1
                        • Michael VincentM
                          Michael Vincent @Michael Vincent
                          last edited by

                          @Michael-Vincent said in Function Completion: cycle through choices:

                          PR #12017 created.
                          Cheers.

                          @PeterJones
                          @Ekopalypse
                          @guy038

                          DONE! - via commit 8519003

                          Cheers.

                          EkopalypseE 1 Reply Last reply Reply Quote 2
                          • EkopalypseE
                            Ekopalypse @Michael Vincent
                            last edited by

                            @Michael-Vincent - cool, a nice one, thx.

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