Community
    • Login

    [Python] Edit > Block Comment doesn't use triple double-quotes

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    9 Posts 3 Posters 503 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.
    • S
      Shohreh
      last edited by

      Hell,

      After selecting a block of code and hitting Edit > Comment/Uncomment > Block Comment, I expected N++ to use the “triple double-quote” syntax, but instead, if prepends each line with a pound sign:

      """
      some
      block
      comment
      """
      

      Do I need to edit N++'s configuration?

      Thank you.

      860dde93-955d-46ab-b279-c9904c2daf4e-image.png

      PeterJonesP 2 Replies Last reply Reply Quote 0
      • PeterJonesP
        PeterJones @Shohreh
        last edited by PeterJones

        @Shohreh said in [Python] Edit > Block Comment doesn't use triple double-quotes:

        Do I need to edit N++'s configuration?

        Right now, there is no way in native Notepad++ to change a configuration for what gets used for the block comment action for a given language. (And I don’t know of a plugin that will; I cannot even think of a way with the PythonScript or other scripting plugin to change the native behavior. Sorry. Obviously, with the PythonScript plugin, one could define a separate command, and give it a keyboard shortcut, to insert the “”" before and after the selected text, which might be sufficient for you)

        And technically, that syntax is “docstring” syntax in Python, not actually a comment, though many people use it as such. But I have run across when trying to put psuedo-unicode escapes \uVWXYZ that go outside of the range that it likes, and when I put it in a docstring instead of a comment, the python parser complained about invalid unicode character, because it’s actually interpreting that section as a string internally, rather than just ignoring commented text, so I had to change from using a docstring to using individual comments. Thus, my “and technically” isn’t just me being pedantic; it has real implications that have influenced me and made me change my code in the past:

        c:> python
        Python 3.12.0 (tags/v3.12.0:0fb18b0, Oct  2 2023, 13:03:39) [MSC v.1935 64 bit (AMD64)] on win32
        Type "help", "copyright", "credits" or "license" for more information.
        >>> # \u+2611other
        >>> """
        ... \u+2611other
        ... """
          File "<stdin>", line 1
            """
            ^^
        SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 1-2: truncated \uXXXX escape
        >>>
        
        1 Reply Last reply Reply Quote 1
        • PeterJonesP
          PeterJones @Shohreh
          last edited by PeterJones

          @Shohreh ,

          Right now, there is no way in native Notepad++ to change a configuration for what gets used for the block comment action for a given language.

          Well, I was wrong (hence, I crossed it out). I started peeking into the source code to see how block comments were implemented, and got a hint that led me to a solution:

          Following the User Manual’s advice for editing Notepad++ config files, edit %AppData%\Notepad++\langs.xml: go to the <Language name="python" ... line; after the commentLine="#" in that line, add commentStart="&quot;&quot;&quot;" commentEnd="&quot;&quot;&quot;" and save; exit Notepad++ and restart, and now when you use Block Comment, it will use the triple-quote as the start and end.

          I had forgotten that was defined in the langs.xml file. Sorry for the original misinformation.

          —
          update: D’OH! It’s even implied in the User Manual already, so I really should have known/remembered it. :-(

          b3f36bb4-4b4a-466c-8e0e-63535dd7e06d-image.png

          I will, however, clarify the UM to make it 100% obvious which attributes apply to which.

          _update 2: coming soon to a User Manual near you:

          e2c8e5e2-47d5-4366-a3aa-feaa63cf9ce8-image.png

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

            In addition to what @PeterJones said:

            • triple-quoted strings are NOT comments (this is just to reinforce what Peter already said, for emphasis!)
            • if you ever have any \ in the line(s) you are trying to use this method of “commenting” on, you will very likely run into trouble (Python 3 will give you errors when you run your code) – you’d have better luck with a raw triple-quoted string, i.e., r"""I am a comment"""
            • indentation must be correct for this – you can’t, in a block of code that is indented, start one of these ‘comments’ at an arbitrary indentation level – it must match the indentation level of the surrounding lines of code
            S 1 Reply Last reply Reply Quote 5
            • S
              Shohreh @Alan Kilborn
              last edited by

              @Alan-Kilborn Thank you. Too bad because I like it better to comment a block.

              Alan KilbornA PeterJonesP 2 Replies Last reply Reply Quote 0
              • Alan KilbornA
                Alan Kilborn @Shohreh
                last edited by

                @Shohreh said in [Python] Edit > Block Comment doesn't use triple double-quotes:

                I like it better to comment a block.

                Well, that’s fine; you can certainly make use of it.
                My main point was to point out further caveats for its usage (in addition to what Peter said).

                BTW, I tried Peter’s advice for changing langs.xml, and the advice is sound as to the “how to”, but the result for Python is lacking (not Peter’s fault)…

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

                  @Shohreh said in [Python] Edit > Block Comment doesn't use triple double-quotes:

                  Too bad because I like it better to comment a block.

                  If you want, you can use the docstring for pseudo-comments – many python programmers do – but you just have to understand that the Python interpreter treats them differently than a # comment, so you have to maintain valid string syntax in any block of text that you put between """ markers; if you are willing to accept that limitation, then feel free to use docstrings for comments – and feel free to update the langs.xml to allow you to use the block-comment feature in Notepad++ to do that wrapping.

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

                    @PeterJones said:

                    edit %AppData%\Notepad++\langs.xml: go to the <Language name="python" … line; after the commentLine="#" in that line, add commentStart="&quot;&quot;&quot;" commentEnd="&quot;&quot;&quot;"

                    feel free to update the langs.xml to allow you to use the block-comment feature in Notepad++ to do that wrapping.

                    The basic problem with that…as I alluded to before when I said:

                    …but the result for Python is lacking

                    …is that it often gives an unsatisfying result. For instance, click and drag in the line number margin to select some lines, and then invoke Block Comment. When I do this, I don’t even obtain code that is syntactically correct. I could hand-adjust it to be correct, but…yuck.

                    Much better would be a script that would toggle these triple-quoted string “comments”.


                    Here’s a script I call PythonBlockCommentToggle.py:

                    # -*- coding: utf-8 -*-
                    from __future__ import print_function  # Python2 vestige!
                    
                    #########################################
                    #
                    #  PythonBlockCommentToggle (PBCT)
                    #
                    #########################################
                    
                    # note:
                    #  This script was developed and tested under Python3 64-bit on unicode (non-ANSI) encoded data.
                    #  It may work as-is using Python2 and/or ANSI-encoded data and/or 32-bits, but that would be incidental.
                    
                    # references:
                    #  https://community.notepad-plus-plus.org/topic/26463/python-edit-block-comment-doesn-t-use-triple-double-quotes
                    #  for newbie info on PythonScripts, see https://community.notepad-plus-plus.org/topic/23039/faq-desk-how-to-install-and-run-a-script-in-pythonscript
                    
                    #-------------------------------------------------------------------------------
                    
                    from Npp import *
                    
                    #-------------------------------------------------------------------------------
                    
                    def lines_touched_by_single_stream_selection():
                        retval = ()
                        rect_sel_mode = editor.getSelectionMode() in [ SELECTIONMODE.RECTANGLE, SELECTIONMODE.THIN ]
                        if rect_sel_mode or editor.getSelections() > 1 or editor.getSelectionEmpty() or len(editor.getSelText()) == 0: return retval
                        sel_start_pos = editor.getSelectionStart()
                        sel_end_pos = editor.getSelectionEnd()
                        line_start = editor.lineFromPosition(sel_start_pos)
                        line_end = editor.lineFromPosition(sel_end_pos)
                        # if caret at end of selection is selecting nothing on the caret's line, don't consider that line as part of the selection:
                        if sel_end_pos == editor.positionFromLine(line_end): line_end -= 1
                        # if very last line of file is somehow part of the selection, don't consider that line as part of the selection if there is nothing on it:
                        elif editor.lineLength(line_end) == 0: line_end -= 1  # note: the last line of a file is the only one that can possibly have length of 0
                        retval = (line_start, line_end)
                        return retval
                    
                    #-------------------------------------------------------------------------------
                    
                    class PBCT(object):
                    
                        def __init__(self):
                    
                            if notepad.getLangType() != LANGTYPE.PYTHON: return
                    
                            quot3 = '"' * 3
                            quot3_comment_start = 'pass; r{three}START-BC '.format(three=quot3)  # moderator fixed
                            quot3_comment_end = ' END-BC{three}'.format(three=quot3)
                            apos3 = "'" * 3
                            apos3_comment_start = quot3_comment_start.replace(quot3, apos3)
                            apos3_comment_end = quot3_comment_end.replace(quot3, apos3)
                    
                            line_span_tup = lines_touched_by_single_stream_selection()
                    
                            if len(line_span_tup) == 0:
                    
                                curr_pos = editor.getCurrentPos()
                                first_line = editor.lineFromPosition(curr_pos)
                                start_line_p1 = editor.getLineIndentPosition(first_line)
                                start_line_p2 = editor.getLineEndPosition(first_line)
                                didnt_do_anything = True
                                end_comment = quot3_comment_end
                                find_result_tup = editor.findText(FINDOPTION.MATCHCASE, start_line_p1, start_line_p2, quot3_comment_start)
                                if find_result_tup is None:
                                    end_comment = apos3_comment_end
                                    find_result_tup = editor.findText(FINDOPTION.MATCHCASE, start_line_p1, start_line_p2, apos3_comment_start)
                                if find_result_tup is not None:
                                    (start_comment_p1, start_comment_p2) = find_result_tup
                                    if start_comment_p1 == start_line_p1:
                                        find_result_tup = editor.findText(FINDOPTION.MATCHCASE, start_comment_p2, editor.getLength(), end_comment)
                                        if find_result_tup is not None:
                                            (end_comment_p1, end_comment_p2) = find_result_tup
                                            editor.beginUndoAction()
                                            editor.deleteRange(end_comment_p1, end_comment_p2 - end_comment_p1)
                                            editor.deleteRange(start_comment_p1, start_comment_p2 - start_comment_p1)
                                            editor.endUndoAction()
                                            didnt_do_anything = False
                                if didnt_do_anything:
                                    self.mb('Make a stream selection to block-comment the lines of that selection; to remove later, '
                                        'run with no selection (i.e., just the caret) on FIRST line of the block-comment.')
                    
                            elif len(line_span_tup) >= 2:
                    
                                ( first_line, second_line ) = line_span_tup
                                start_line_p1 = editor.getLineIndentPosition(first_line)
                                start_line_p2 = editor.getLineEndPosition(second_line)
                                text_to_be_commented = editor.getTextRange(start_line_p1, start_line_p2)
                                if quot3 in text_to_be_commented and apos3 in text_to_be_commented:
                                    self.mb('Cannot turn the block of selected lines into a comment; a triple-quoted string is present in selected lines.')
                                    return
                                use_quot3 = quot3 not in text_to_be_commented
                                comment_start = quot3_comment_start if use_quot3 else apos3_comment_start
                                comment_end = quot3_comment_end if use_quot3 else apos3_comment_end
                                editor.beginUndoAction()
                                editor.insertText(start_line_p2, comment_end)
                                editor.insertText(start_line_p1, comment_start)
                                editor.endUndoAction()
                    
                        def mb(self, msg, flags=0, title=''):  # a message-box function
                            return notepad.messageBox(msg, title, flags)
                    
                    #-------------------------------------------------------------------------------
                    
                    if __name__ == '__main__': PBCT()
                    

                    How to use:

                    To comment lines:

                    • select (even partially) the lines you want to “comment out”
                    • run the script

                    To remove the commenting:

                    • put the caret (note: don’t select any text) on the FIRST line of the commented section
                    • run the script

                    Here is an example:

                    We want to “comment out” these lines:

                    0d21b935-f304-434b-9517-13b6d0f73430-image.png

                    Since we’ve already selected (partially, but wholly works too) these lines, we just run the script to obtain:

                    5eeba629-7f44-4e63-adfa-5a2bfee4dd3f-image.png

                    You can see the orange text is the comment, but what is the pass; text before it? Well, this keeps the code syntactically correct if you want to turn an entire indented block after an if, elif or else into a comment.

                    Now let’s remove it; place the caret here for example (it could be placed anywhere on line 85):

                    83fbca9a-a014-4cd4-acaa-554dfce2c19b-image.png

                    and run the script again to be back to where we started:

                    9820c254-028b-4f3b-a147-3e091318f45b-image.png

                    —
                    2025-01-02: moderator added the missing r per comment below, so that copy/paste of code would work right

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

                      In the script code, I accidentally left out the r I was preaching about earlier.

                      quot3_comment_start = 'pass; {three}START-BC '.format(three=quot3)

                      should be:

                      quot3_comment_start = 'pass; r{three}START-BC '.format(three=quot3)

                      See the r? I bolded it in the revised line of code. :-)


                      BTW, I added the START-BC (start block comment) and END-BC (end block comment) text in there so one can be sure that the triple quoted string stuff really IS temporarily commented out code. If you don’t want that, just remove the text of those strings from the source code for the script.

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