How can I get autocomplete working for Python 3? I'm using the PythonScript plugin.
-
I am looking for a way to get better autocomplete for Python when developing scripts with PythonScript.
For instance, I start my document with:
from Npp import * import re
And then I want to reference the
editor
object. But when I typeeditor.
(Note the period) there are no autocomplete suggestions.I’m trying to learn more about how Python interfaces with N++ and having auto-completion for built in commands / classes / structures would make this a lot easier.
Also, is there documentation anywhere on the NP++ specific Python bindings anywhere?
Any help greatly appreciated.
-
@Jay-S said,
And then I want to reference the
editor
object. But when I typeeditor.
(Note the period) there are no autocomplete suggestions.If you have write permission to
C:\Program Files\Notepad++\autoCompletion\python.xml
, you can add new keywords to Python’s auto-completion list (see the online user manual for more about the structure for the auto-completion defininitions).On second read, I noticed you wanted to have more context-aware auto-completion, only giving you valid values after typing
editor.
(with the period).Unfortunately, the function auto-completion syntax wasn’t designed in a hierarchical way. One way you could do it is to use the
.
in the completion text, such as<KeyWord name="notepad.activateBufferID" />
. However, as the user manual points out:This means you probably shouldn’t use the
func="yes"
field, nor the<Overload>
nor<Param>
elements inside the<KeyWord>
if you’re going to be including the period in the auto-completion. Also note: if you started by doingeditor.addText
and then use backspace over the four character ofText
, because you wanted to change toeditor.addStyledText
instead, it will not do suggestion for the auto-completion because Notepad++'s algorithm for matching on the “current word” stops at the punctuation, so it’s trying to auto-complete onadd
rather than oneditor.add
.Because of the limitations of punctuation inside the keyword, you might want to consider not doing the
.
-notation requirement in your autoCompletion definition, and instead just add all the methods as barewords (or add them as botheditor.addText
and a separate entry for justaddText
). It’s not a perfect solution, but it’s better than no auto-completion.You also might want to put in a feature request for PythonScript 3 plugin to have them automatically add the object-aware auto-completion (though they might have to give it a different activation sequence than normal Notepad++ auto-completion), so that way the individual users don’t have to manually add all that to the builtin python auto-completion definition themselves. No guarantee that they’d actually implement it, but it wouldn’t hurt to have the request added.
(I searched through the existing open and closed PythonScript issues and couldn’t find that suggestion yet. However, I did find this question, in which @Ekopalypse suggested a script for PythonScript which provides an auto-completion list when period is typed… stay tuned, I may have a proof-of-concept extension of that script in the not-too-distant future.)
Also, is there documentation anywhere on the NP++ specific Python bindings anywhere?
The PythonScript plugin ships with its help files; it will end up in
C:\Program Files\Notepad++\Plugins\Doc\PythonScript\
or equivalent, which can always be accessed through Plugins > Python Script > Context-Help (and if you had your text-editing caret at a PythonScript method name in your source, it will show you the help for that method when it opens) -
Consider this script (quickly-written, I’m sure there are better ways to do it):
# -*- coding: utf-8 -*- from __future__ import print_function # references: # https://community.notepad-plus-plus.org/topic/24687 from Npp import * output_line_list = [] for obj_str in [ 'editor', 'notepad' ]: for item in dir(eval(obj_str)): obj_plus_item_str = obj_str + '.' + item if not item.startswith('_') and 'bound method' in str(eval(obj_plus_item_str)): output_line_list.append(obj_plus_item_str) notepad.new() eol = ['\r\n', '\r', '\n'][editor.getEOLMode()] editor.appendText(eol.join(output_line_list))
If you run this script, you’ll get output like this in a new tab:
... editor.wordRightEndExtend editor.wordRightExtend editor.wordStartPosition editor.wrapCount editor.write editor.zoomIn editor.zoomOut notepad.activateBufferID notepad.activateFile notepad.activateIndex notepad.allocateCmdID notepad.allocateMarker ...
You can then save that tab to a real file, and reference that when you’re seeking a PS function you just can’t quite remember the exact name of, and you can use Peter’s “context help” hint on its data to get further information about a function.
–
Moderator EDIT (2024-Jan-14): The author of the script has found a fairly serious bug with the code published here for those that use Mac-style or Linux-style line-endings in their files. The logic for Mac and Linux was reversed, and thus if the script was used on one type of file, the line-endings for the opposite type of file could end up in the file after the script is run. This is insidious, because unless one works with visible line-endings turned on, this is likely not noticed. Some detail on the problem is HERE. The script above has been corrected per that instruction. -
-
Installation Instructions:
- see FAQ for detailed instructions
- call it
AutoCompletionForPythonScriptMethods.py
- call it
- run it once to turn on the dot-based autocomplete
- run it again to turn it back off
- I like having a shortcut for Plugins > PythonScript > Run Previous Script to make such toggle-scripts easy (Settings > Shortcut Mapper to assign that key)
- or follow instructions in the FAQ to add a shortcut to this specific script
This is only proof-of-concept; you would have to add the other methods to the list; and you could also add completions for the
console.
prefix as well as any of the enumeration prefixes, using the same logic as theeditor.
andnotepad.
that are currently shown.# encoding=utf-8 """in response to https://community.notepad-plus-plus.org/topic/24687/ Auto-completion for PythonScript methods (complete-on-dot) when a dot is entered. Derived from https://github.com/bruderstein/PythonScript/issues/275#issuecomment-1383132656 as starting point Installation Instructions: - call it `AutoCompletionForPythonScriptMethods.py` - see FAQ for instructions: https://community.notepad-plus-plus.org/topic/23039/faq-desk-how-to-install-and-run-a-script-in-pythonscript """ from Npp import editor,notepad,console,SCINTILLANOTIFICATION class ACFPSM(object): sci_methods = ';'.join(""" addRefDocument addSelection addStyledText addTabStop addText addUndoAction """.split()) npp_methods = ';'.join(""" activateBufferID activateFile activateIndex """.split()) def __init__(self): console.write("Registered AutoCompletionForPythonScriptMethods.py callbacks\n") editor.callback(self.on_charadded, [SCINTILLANOTIFICATION.CHARADDED]) self.active = True self.bufferIDs = [] def toggle(self): self.active = not self.active console.write("AutoCompletionForPythonScriptMethods.py callbacks are {}\n".format('active' if self.active else 'inactive')) def get_current_dotted_words(self, p): end_p = p while p > 0: p -= 1 c = editor.getCharAt(p) # . or _ is valid if c == ord('.') or c == ord('_'): continue # digit is valid if ord('0') <= c and c <= ord('9'): continue # uppercase is valid if ord('A') <= c and c <= ord('Z'): continue # lowercase is valid if ord('a') <= c and c <= ord('z'): continue # otherwise, not valid, so do not include this character in the string p+=1 break return editor.getTextRange(p, end_p) def on_charadded(self, args): if not self.active: return if args['ch'] == ord('.'): word = self.get_current_dotted_words(editor.getCurrentPos()) clist = None if word in ['editor.', 'editor1.', 'editor2.']: clist = self.sci_methods elif word == 'notepad.': clist = self.npp_methods if clist is not None: editor.autoCSetSeparator(ord(';')) editor.autoCShow(0, clist) if __name__ == '__main__': try: _ACFPSM.toggle() except NameError: _ACFPSM = ACFPSM()
Any bugfixes/improvements that I make will be in my github scripts repo. Over the next few days, I will try to find the time to add more methods and enums to its logic.
- see FAQ for detailed instructions
-
-
@Alan-Kilborn said in How can I get autocomplete working for Python 3? I’m using the PythonScript plugin.:
for item in dir(eval(obj_str)):
Ooh, I might have to update my script to use that rather than manually building the list of methods! Thanks for that idea!
-
The “problem” with the auto-complete approach is that you often have to know where you’re “going”, when you don’t know that. There are A LOT of
editor
object functions. A lot of them begin with.get
, but sometimes the one you want (when you are trying to “get” something) doesn’t start that way. That’s why I like the approach I presented; you can search around in the data for a partial string that isn’t necessarily at the start (i.e., right aftereditor.
ornotepad.
). Everyone’s mileage varies… -
My dictionary autocompletion tool I made a while back actually has PythonScript autocompletion built in. I mean, there are already some perfectly fine solutions posted here, but the good thing about this one is that it also provides autocompletion for all the enums in PythonScript, like
SCINTILLANOTIFICATION
andNOTIFICATION
.Just add this to
settings.json
:"%AppData%\\Roaming\\Notepad++\\plugins\\config\\PythonScript\\scripts\\dictautocomp\\pythonscript_autocompletions.txt": { "extensions": "\\.(?:py|foobar)$", "ignorecase": false, "min_autocomplete_length": 3 }
Running
get_pythonscript_autocompletions.py
indictautocomp
will regenerate the list of PythonScript autocompletions for a different version of PythonScript. -
My script in this thread from earlier today is reminiscent of a similar script in this OTHER thread.
-
Depending on how you use the PythonScript plugin, you can add something like jedi to help you write Python code.
There are also two alpha versions of an lsp plugin, kered13 and mine,
that can be used with lsp servers like python-lsp-server, pylyzer or pyright …
What they all have in common is that you need some kind of stubs file, that you can create using the techniques already mentioned so that they discover the methods that Notepad, Editor and Console offer. -
I said earlier,
I might have to update my script to use that rather than manually building the list of methods
My repo version of my script has been updated to use Alan’s algorithm to populate the methods and elements of PythonScript’s built-in instances and enumerations.
(While I understand the “problem” with the auto-complete approach, the technical details of implementing it intrigued me … especially expanding @Alan-Kilborn’s algorithm to also get the enumerations like
NOTIFICATION
to have dot-completion for their elements. @Mark-Olson’s solution is a great idea if you also want extra ) -
If you’ve used a script in this thread, you might want to double check your copy of it for a bug I’ve discovered.
Look to previous postings in this topic thread where the script has been changed – find the textmoderator edit (2024-Jan-14)
.
There’s a link there that describes the bug in more detail, and shows what needs to be changed in an old copy (or you can simply grab a copy of the current version).