Community
    • Login

    How to change syntax via hotkey ?

    Scheduled Pinned Locked Moved General Discussion
    27 Posts 8 Posters 5.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
      last edited by PeterJones

      @Barbados said in How to change syntax via hotkey ?:

      Is it possible to add a switch in the language switching script to default (User-defined) language when I press the hotkey again ? And loop it ? An encoding switch script needs an “ANSI” switch (default)

      If you want one script that will set it to HTML if it’s set to XML, and to XML if it’s not set to XML (ie, toggle between the two), it’s a simple if statement:

      from Npp import * 
      if notepad.getLangType() == LANGTYPE.XML:
          notepad.setLangType(LANGTYPE.HTML)
      else:
          notepad.setLangType(LANGTYPE.XML)
      

      If your alternate language is a UDL (user-defined language), then I’m not sure. There is a LANGTYPE.USER – unfortunately, it selects the generic UDL “User-Defined”, rather than whichever of the various UDL is appropriate for the filename. I don’t know that there’s a way to get it to reload the correct UDL for the filetype. (It might be possible with some clever programming… but I am not sure where I’d start.)

      For UTF8-vs-ANSI toggle, there should be a way, using the notepad.getEncoding()/.setEncoding() pair… unfortunately, notepad.getEncoding() seems to always be returning BUFFERENCODING.COOKIE, which isn’t helpful. With the .getEncoding() not returning anything useful, I cannot get a smart encoding toggle. I am assuming that’s why @Ekopalypse 's example originally included the BUFFERENCODING in the import, but didn’t actually use it. :-)

      For a dumb encoding toggle, which will set it to UTF8 the first time you call it and ANSI the second (regardless of current state), you could use:

      from Npp import notepad, MENUCOMMAND
      
      try:
          toggle = 1 - toggle
      except NameError:
          toggle = 0
      
      notepad.menuCommand( (MENUCOMMAND.FORMAT_AS_UTF_8, MENUCOMMAND.FORMAT_ANSI)[toggle] )
      

      The toggle variable will go between 0 and 1 every call, and the menuCommand will choose between the tuple of encoding MENUCOMMAND enums, depending on the current value of toggle. (The try/except was a way to determine whether toggle had ever been initialized yet or not.)

      You could do a similar “dumb toggle” for the LANGTYPE, too.

      P.S. Is it possible to make a “User-defined” switch in the language macro and an “ANSI” switch in the encoding switching script?

      If you wanted the same toggle-between-two-states using macros: sorry. The macro doesn’t have any if/else or global variables that can hold the current state of a toggle, so you cannot do the toggle; you’d have to just use two different macros, and thus two different keystrokes.

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

        @Barbados
        not sure I understand 100% correctly but here the two scripts

        from Npp import notepad, editor
        
        
        if editor.getCodePage() == 0:
            notepad.menuCommand(MENUCOMMAND.FORMAT_AS_UTF_8)
        else:
            notepad.menuCommand(MENUCOMMAND.FORMAT_ANSI)
        

        and the language script

        from Npp import notepad, LANGTYPE
        import ctypes
        
        NAME_OF_UDL = 'DEFAULT' # <<- needs to be specified
        
        user32 = ctypes.windll.user32
        NPPM_GETLANGUAGEDESC = 1024+1000+84
        
        language = notepad.getLangType()
        npp_hwnd = user32.FindWindowW(u'Notepad++', None)
        length = user32.SendMessageW(npp_hwnd, NPPM_GETLANGUAGEDESC, language, None)
        buffer = ctypes.create_unicode_buffer(u' ' * length)
        user32.SendMessageW(npp_hwnd, NPPM_GETLANGUAGEDESC, language, ctypes.byref(buffer))
        
        if buffer.value == 'User Defined language file - %s' % NAME_OF_UDL:
            notepad.setLangType(LANGTYPE.HTML)
        else:
            notepad.runMenuCommand('Language', NAME_OF_UDL)
        

        Replace my DEFAULT name with your udl name exactly how it
        looks like from the language menu.

        @PeterJones, yes, it seems notepad.getEncoding isn’t correct always, strange.

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

          @Ekopalypse said in How to change syntax via hotkey ?:

          runMenuCommand()...

          Oh, right, I should have thought of that.

          I see you use SendMessageW for the language description here. Do notepad.getLanguageName() and notepad.getLanguageDesc() still have the bugs mentioned in your 2019 workaround code? Has anyone reported the bug to the PythonScript team – I cannot see a report – or has anyone proven whether it’s the plugin or Notepad++ that is mishandling those? (I have those two equivalent functions “working” in my Perl library… but I don’t know whether it’s just because I haven’t hit the edge cases that cause the problem, or whether the PythonScript implementation is buggy.)

          EkopalypseE PeterJonesP 2 Replies Last reply Reply Quote 1
          • EkopalypseE
            Ekopalypse @PeterJones
            last edited by

            @PeterJones

            it seems that it still is an issue, let me do some test to see if I can find out when and where it happens.

            If I run the code from below with PS it crashes my npp

            from Npp import notepad, LANGTYPE
            
            LANGUAGES = LANGTYPE.values.values()
            for language in LANGUAGES:
                print(notepad.getLanguageDesc(language))
            
            1 Reply Last reply Reply Quote 0
            • PeterJonesP
              PeterJones
              last edited by

              Using @Michael-Vincent’s NppConsole/plsh wrapper around my perl library,

              @language_keys = sort { $nppm{$a} <=> $nppm{$b} } grep { /^L_/ } keys %nppm;
              printf "%s => %s: '%s'\n", $_, $nppm{$_}, notepad->getLanguageDesc($nppm{$_}) for (@language_keys);
              

              gives

              L_TEXT => 0: 'Normal text file'
              L_PHP  => 1: 'PHP Hypertext Preprocessor file'
              L_C => 2: 'C source file'
              L_CPP => 3: 'C++ source file'
              L_CS => 4: 'C# source file'
              L_OBJC => 5: 'Objective-C source file'
              L_JAVA => 6: 'Java source file'
              L_RC => 7: 'Windows Resource file'
              L_HTML => 8: 'Hyper Text Markup Language file'
              L_XML => 9: 'eXtensible Markup Language file'
              L_MAKEFILE => 10: 'Makefile'
              L_PASCAL => 11: 'Pascal source file'
              L_BATCH => 12: 'Batch file'
              L_INI => 13: 'MS ini file'
              L_ASCII => 14: 'MSDOS Style/ASCII Art'
              L_USER => 15: 'User Defined language file'
              L_ASP => 16: 'Active Server Pages script file'
              L_SQL => 17: 'Structured Query Language file'
              L_VB => 18: 'Visual Basic file'
              L_JS => 19: 'JavaScript file'
              L_CSS => 20: 'Cascade Style Sheets File'
              L_PERL => 21: 'Perl source file'
              L_PYTHON => 22: 'Python file'
              L_LUA => 23: 'Lua source File'
              L_TEX => 24: 'TeX file'
              L_FORTRAN => 25: 'Fortran free form source file'
              L_BASH => 26: 'Unix script file'
              L_FLASH => 27: 'Flash ActionScript file'
              L_NSIS => 28: 'Nullsoft Scriptable Install System script file'
              L_TCL => 29: 'Tool Command Language file'
              L_LISP => 30: 'List Processing language file'
              L_SCHEME => 31: 'Scheme file'
              L_ASM => 32: 'Assembly language source file'
              L_DIFF => 33: 'Diff file'
              L_PROPS => 34: 'Properties file'
              L_PS => 35: 'PostScript file'
              L_RUBY => 36: 'Ruby file'
              L_SMALLTALK => 37: 'Smalltalk file'
              L_VHDL => 38: 'VHSIC Hardware Description Language file'
              L_KIX => 39: 'KiXtart file'
              L_AU3 => 40: 'AutoIt'
              L_CAML => 41: 'Categorical Abstract Machine Language'
              L_ADA => 42: 'Ada file'
              L_VERILOG => 43: 'Verilog file'
              L_MATLAB => 44: 'MATrix LABoratory'
              L_HASKELL => 45: 'Haskell'
              L_INNO => 46: 'Inno Setup script'
              L_SEARCHRESULT => 47: 'Internal Search'
              L_CMAKE => 48: 'CMake file'
              L_YAML => 49: 'YAML Ain't Markup Language'
              L_COBOL => 50: 'COmmon Business Oriented Language'
              L_GUI4CLI => 51: 'Gui4Cli file'
              L_D => 52: 'D programming language'
              L_POWERSHELL => 53: 'Windows PowerShell'
              L_R => 54: 'R programming language'
              L_JSP => 55: 'JavaServer Pages script file'
              L_COFFEESCRIPT => 56: 'CoffeeScript file'
              L_JSON => 57: 'JSON file'
              L_JAVASCRIPT => 58: 'JavaScript file'
              L_FORTRAN_77 => 59: 'Fortran fixed form source file'
              L_BAANC => 60: 'BaanC File'
              L_SREC => 61: 'Motorola S-Record binary data'
              L_IHEX => 62: 'Intel HEX binary data'
              L_TEHEX => 63: 'Tektronix extended HEX binary data'
              L_SWIFT => 64: 'Swift file'
              L_ASN1 => 65: 'Abstract Syntax Notation One file'
              L_AVS => 66: 'AviSynth scripts files'
              L_BLITZBASIC => 67: 'BlitzBasic file'
              L_PUREBASIC => 68: 'PureBasic file'
              L_FREEBASIC => 69: 'FreeBasic file'
              L_CSOUND => 70: 'Csound file'
              L_ERLANG => 71: 'Erlang file'
              L_ESCRIPT => 72: 'ESCRIPT file'
              L_FORTH => 73: 'Forth file'
              L_LATEX => 74: 'LaTeX file'
              L_MMIXAL => 75: 'MMIXAL file'
              L_NIMROD => 76: 'Nimrod file'
              L_NNCRONTAB => 77: 'extended crontab file'
              L_OSCRIPT => 78: 'OScript source file'
              L_REBOL => 79: 'REBOL file'
              L_REGISTRY => 80: 'registry file'
              L_RUST => 81: 'Rust file'
              L_SPICE => 82: 'spice file'
              L_TXT2TAGS => 83: 'txt2tags file'
              L_VISUALPROLOG => 84: 'Visual Prolog file'
              L_EXTERNAL => 85: 'External'
              

              without crashing.
              I think there must be a bug in the PythonScript implementation.

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

                … working on bug report now…

                https://github.com/bruderstein/PythonScript/issues/146

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

                  @PeterJones

                  it seems that this doesn’t create a null-terminated buffer

                  and if I use some python code like

                      length = self.__npp_send(NPPM_GETLANGUAGEDESC, langType, 0)
                      lang_desc = ctypes.create_unicode_buffer(length)
                      self.__npp_send(NPPM_GETLANGUAGEDESC, langType, ctypes.byref(lang_desc))
                  

                  I do get the same behavior aka the crash but if I do, what I expect that needs to be done

                      length = self.__npp_send(NPPM_GETLANGUAGEDESC, langType, 0)
                      lang_desc = ctypes.create_unicode_buffer(length+1)
                      self.__npp_send(NPPM_GETLANGUAGEDESC, langType, ctypes.byref(lang_desc))
                  

                  then it works.

                  If one is confused about the previous example with create_unicode_buffer,
                  please note that create_unicode_buffer allocates the buffer differently
                  depending on the initialization with Int or String.

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

                    @PeterJones said

                    Do notepad.getLanguageName() and notepad.getLanguageDesc() still have the bugs mentioned in your 2019 workaround code?

                    v1.5.4 was released a couple weeks ago (mid-April), with the fix to the getLanguageDesc() bug. I forgot to reply then.

                    Thanks, @bruderstein !

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

                      @PeterJones

                      I don’t want to diminish the work of @bruderstein,
                      but I think @chcg did the fix, thanks for that.

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

                        @Ekopalypse ,

                        You are right. Sorry @chcg – no slight intended.

                        1 Reply Last reply Reply Quote 1
                        • László BeneL
                          László Bene @PeterJones
                          last edited by

                          Hi, thanks for this easy solution. Unfortunately I need to set up hotkey for Markdown language, which is the only language that doesn’t seem accessible this way. Markdown is in a kind of secondary block in the Language menu, like so:
                          Markdown from menu
                          Is there still an ID for Markdown that is missing from the list?

                          PeterJonesP 1 Reply Last reply Reply Quote 0
                          • PeterJonesP
                            PeterJones @László Bene
                            last edited by PeterJones

                            @lászló-bene said in How to change syntax via hotkey ?:

                            Is there still an ID for Markdown that is missing from the list?

                            No. Markdown is a UDL (User Defined Language), and they are treated differently than the built-in lexers, since users can manipulate UDLs on-the-fly; so they don’t get constants for notepad.setLangType(LANGTYPE.xxxx).

                            Thus, as one of @Ekopalypse’s posts above pointed out (after the phrase “and the language script”), it requires different syntax (using notepad.runMenuCommand(...)) to switch the Language to a UDL. So you could just use that script, with putting in Markdown (preinstalled) as the NAME_OF_UDL.

                            However, Ekopalypse’s script shown above had to work around a limitation in older PythonScript versions. If you have at least PythonScript 1.5.4 or 2.0.0, then you can use a simplified script like I show below. (If you have one of the PythonScript 3.x alpha releases, the ones below should still work, I think; I don’t use PythonScript 3.x yet, and I’m not a Python3 expert, so I forget whether my .format() syntax still works in Python3, but I think it does.)

                            So, here are some example scripts with PythonScript 1.5.4/2.0.0:

                            • If you want to toggle between HTML and the Markdown (preinstalled) UDL:
                            from Npp import notepad, LANGTYPE
                            
                            NAME_OF_UDL = 'Markdown (preinstalled)' # <<- needs to be specified to match the UDL you want to select
                            
                            language = notepad.getLangType()
                            desc = notepad.getLanguageDesc(language)    # this needs PythonScript 1.5.4 or newer
                            
                            if desc == 'User Defined language file - {}'.format(NAME_OF_UDL):
                                notepad.setLangType(LANGTYPE.HTML)
                            else:
                                notepad.runMenuCommand('Language', NAME_OF_UDL)
                            
                            • If you want to toggle between two UDL, like Markdown (preinstalled) and Markdown (preinstalled dark mode):
                            from Npp import notepad, LANGTYPE
                            
                            NAME_OF_UDL = 'Markdown (preinstalled)' # <<- needs to be specified to match the UDL you want to select
                            NAME_OF_UDL2 = 'Markdown (preinstalled dark mode)' # <<- needs to be specified to match the UDL you want to select
                            
                            language = notepad.getLangType()
                            desc = notepad.getLanguageDesc(language)    # this needs PythonScript 1.5.4 or newer
                            
                            if desc == 'User Defined language file - {}'.format(NAME_OF_UDL):
                                notepad.runMenuCommand('Language', NAME_OF_UDL2)
                            else:
                                notepad.runMenuCommand('Language', NAME_OF_UDL)
                            
                            • If you want to just always set the current language to the Markdown UDL, regardless of the current language, it’s even more simple:
                            from Npp import notepad
                            
                            NAME_OF_UDL = 'Markdown (preinstalled)' # <<- needs to be specified to match the UDL you want to select
                            
                            notepad.runMenuCommand('Language', NAME_OF_UDL)
                            

                            Just save one or more of those scripts, and assign keyboard shortcut(s) as desired, and you can either toggle between two languages, or just use that shortcut for always setting to the same UDL.

                            Good luck.

                            László BeneL 1 Reply Last reply Reply Quote 5
                            • László BeneL
                              László Bene @PeterJones
                              last edited by

                              @peterjones, thank you so much for your help! Toggling between HTML and MarkDown via one hotkey is more than I wished for, and it works just fine.

                              1 Reply Last reply Reply Quote 1
                              • Szymon SzymonS
                                Szymon Szymon @PeterJones
                                last edited by

                                @PeterJones Works like a charm, 2minutes and configured, thanks

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