Community
    • Login

    How can I get autocomplete working for Python 3? I'm using the PythonScript plugin.

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    11 Posts 5 Posters 4.4k 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.
    • PeterJonesP
      PeterJones @Jay S
      last edited by

      @Jay-S said,

      And then I want to reference the editor object. But when I type editor. (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:

      63e644b6-bb5e-44b2-99da-a0e680e17243-image.png

      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 doing editor.addText and then use backspace over the four character of Text, because you wanted to change to editor.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 on add rather than on editor.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 both editor.addText and a separate entry for just addText). 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)

      PeterJonesP 1 Reply Last reply Reply Quote 0
      • Alan KilbornA
        Alan Kilborn @Jay S
        last edited by PeterJones

        @Jay-S

        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.

        PeterJonesP 1 Reply Last reply Reply Quote 1
        • Alan KilbornA Alan Kilborn referenced this topic on
        • PeterJonesP
          PeterJones @PeterJones
          last edited by

          Installation Instructions:

          • see FAQ for detailed instructions
            • call it AutoCompletionForPythonScriptMethods.py
          • 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 the editor. and notepad. 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.

          1 Reply Last reply Reply Quote 0
          • PeterJonesP PeterJones referenced this topic on
          • PeterJonesP
            PeterJones @Alan Kilborn
            last edited by

            @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!

            PeterJonesP 1 Reply Last reply Reply Quote 0
            • Alan KilbornA
              Alan Kilborn
              last edited by Alan Kilborn

              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 after editor. or notepad.). Everyone’s mileage varies…

              1 Reply Last reply Reply Quote 1
              • Mark OlsonM
                Mark Olson
                last edited by Mark Olson

                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 and NOTIFICATION.

                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 in dictautocomp will regenerate the list of PythonScript autocompletions for a different version of PythonScript.

                1 Reply Last reply Reply Quote 1
                • Alan KilbornA
                  Alan Kilborn
                  last edited by

                  My script in this thread from earlier today is reminiscent of a similar script in this OTHER thread.

                  1 Reply Last reply Reply Quote 0
                  • EkopalypseE
                    Ekopalypse @Jay S
                    last edited by

                    @Jay-S

                    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.

                    1 Reply Last reply Reply Quote 3
                    • PeterJonesP
                      PeterJones @PeterJones
                      last edited by

                      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 )

                      1 Reply Last reply Reply Quote 0
                      • Alan KilbornA
                        Alan Kilborn
                        last edited by

                        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 text moderator 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).

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