Function Completion: cycle through choices
-
I was going to put in a feature request regarding Function Completion autocomplete, but I wanted to make sure it wasn’t just a lack of knowledge on my part (there are many features of Notepad++ that I don’t know about or don’t remember).
Function Completion allowed multiple “overload” variants. I know when it pops down, you can click on the up and down arrows to cycle through those variants:
But is there a keyboard shortcut for that?
In Visual Studio, when there are overloaded functions, I can just hit the up and down arrow keys to cycle through the choices. But in Notepad++, I tried the arrows (plain, and modified with various combos of Alt/Ctrl/Shift) and TAB and PgUp/PgDn, but nothing I tried worked.
I did already check to make sure I hadn’t previously documented that but forgotten about it. And I tried searching the forum, but couldn’t find anything, even thought I thought it had been asked-and-answered before; sometimes my search-fu is weak.
It just seems odd that the word/function-name completion allows arrowing to select, but the function-parameter completion does not.
Does someone know if I’m just missing an obvious (or not-so-obvious) keystroke? Or is this really a feature that requires a mouse to cycle through the options?
If I get confirmation that it’s the latter, I will put in a feature request.
question triggered by a perlmonks post talking about IDE-like features in editors like Notepad++
-
If I’ve done my homework, then completion is invoked by showNextOverload, which in turn is invoked by callTipClick, which in turn is assigned by SCN_CALLTIPCLICK or short, I assume you’re right, no shortcut.
-
Hello, @peterjones, @ekopalypse and All,
Unlike Eko, I basically tried a lot of possible shortcuts, including the
Alt
andAltGr
keys. Unfortunately , I could not find any :-(( So, your assumption about the lack of shortcut, for that feature, seems correct !BTW, as you did not mention the language used, I immediately supposed that it could be the
Perl
language. Bingo, I was right about it :-))Best Regards,
guy038
-
@Ekopalypse & @guy038 ,
Thanks for the confirmation. I thought as much, but wanted to make sure.
Issue #11950 created
-
@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 ifTRUE
, then post aSCN_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.
-
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. -
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.
-
@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.
-
Fixed (probably should have noted I’m on 64-bit):
SendMessage(notepad.hwnd, WM_NOTIFY, 0, ctypes.c_longlong(ctypes.addressof(notification)))
Cheers.
-
@Michael-Vincent said in Function Completion: cycle through choices:
@Michael-Vincent
@Ekopalypse
Fixed (probably should have noted I’m on 64-bit):
@PeterJonesWorks 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:
Cheers.
-
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.
-
@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.
-
@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.
-
@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 createdPR #12017 created.
Cheers.
-
@Michael-Vincent said in Function Completion: cycle through choices:
PR #12017 created.
Cheers.@PeterJones
@Ekopalypse
@guy038DONE! - via commit 8519003
Cheers.
-
@Michael-Vincent - cool, a nice one, thx.