Community
    • Login

    Maintain Indent While Pasting Multiple Lines

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    26 Posts 9 Posters 4.0k 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.
    • gstaviG
      gstavi @mkupper
      last edited by

      @mkupper said in Maintain Indent While Pasting Multiple Lines:

      I’ll take a guess at what @Dennis-Bareis is referring to but don’t think there’s a solution.

      Pasting and typing is not the same thing.

      The vast majority of users would want pasted multiline text to look exactly like it used to look in the source where is was copied from. Up to tab width which may be different.

      Basically the requirement is for a paste-special variant which will be paste-as-type. However the original copied text will usually already have its own tab chars inside that will conflict with whatever indenting scheme is active (and if the original text is indented with spaces it would be even worse). This is the kind of feature that nobody is happy with. It is always just almost right and never exactly right. Any attempt to fix it for one user makes it worse for other users.

      Fixing pasted text with block indenting is good enough.

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

        See:

        • https://community.notepad-plus-plus.org/topic/15791
        • https://github.com/notepad-plus-plus/notepad-plus-plus/issues/5923
        • https://github.com/notepad-plus-plus/notepad-plus-plus/issues/796

        Doing what the OP desires is (perhaps) deceptively non-trivial.
        I’ve had a script doing it for a long time now for my personal use; I’ll clean it up for general consumption and post it here soon…

        Dennis BareisD 1 Reply Last reply Reply Quote 2
        • Dennis BareisD
          Dennis Bareis @gstavi
          last edited by

          @gstavi said in Maintain Indent While Pasting Multiple Lines:

          @mkupper said in Maintain Indent While Pasting Multiple Lines:

          I’ll take a guess at what @Dennis-Bareis is referring to but don’t think there’s a solution.

          Pasting and typing is not the same thing.

          The vast majority of users would want pasted multiline text to look exactly like it used to look in the source where is was copied from. Up to tab width which may be different.

          Yes, exactly, npp doesn’t do that.

          Basically the requirement is for a paste-special variant which will be paste-as-type. However the original copied text will usually already have its own tab chars inside that will conflict with whatever indenting scheme is active (and if

          Imbedded tabs in the copied text is irrelevant for the initial indenting level EXCEPT where it starts a line.

          What npp currently does now is a solution that no one is happy with, what I want is a solution that most people will be happy with.

          1 Reply Last reply Reply Quote 0
          • Dennis BareisD
            Dennis Bareis @mkupper
            last edited by Dennis Bareis

            @mkupper said in Maintain Indent While Pasting Multiple Lines:

            Pasted end-of-line characters are not handled the same as the <enter> key in terms of the auto-indent logic. I have always shrugged and fixed the indentation on lines 5 and 6.

            Yes you have it correct, that is what npp should do. However if your pasted line 4 started with 2 tabs then those 2 tabs plus the initial indent would be used (plus the 2 extra tabs for line 4) so that the pasted text looks exactly like that copied except for any FURTHER indenting as defined by the initial line where the pasting occurs.

            @Mark-Olson

            If   Line 1 {
                 line 2
                 if   line 3
                      line 4
                 line 5
            }
            

            The above would look the same if pasted after lets say a tab or ‘x’ spaces:

                      If   Line 1 {
                           line 2
                           if   line 3
                                line 4
                           line 5
                      }
            
            1 Reply Last reply Reply Quote 0
            • Dennis BareisD
              Dennis Bareis @Alan Kilborn
              last edited by Dennis Bareis

              @Alan-Kilborn said in Maintain Indent While Pasting Multiple Lines:

              See:

              • https://community.notepad-plus-plus.org/topic/15791
              • https://github.com/notepad-plus-plus/notepad-plus-plus/issues/5923
              • https://github.com/notepad-plus-plus/notepad-plus-plus/issues/796

              None of those were answered well or even in my option understood. I even replied to the second one yesterday.

              Doing what the OP desires is (perhaps) deceptively non-trivial.
              I’ve had a script doing it for a long time now for my personal use; I’ll clean it up for general consumption and post it here soon…

              The OP (me) has done exactly what I suggest in a program of mine (powerful preprocessor), It is deceptively simple. It is little more than a one line of code to replace newline with newline followed by the initial indent.

              There is no language specific processing involved. I haven’t mentioned non-leading whitespace in the pasted text as I’m happy they remain exactly as they exist in the copied text. However that could be where my suggestion could be enhanced, perhaps controlled by a new npp option.

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

                @Dennis-Bareis said:

                None of those were answered well or even in my option understood…

                That was not the point of citing the links.
                The point of citing them was to simply share (or bind together) common history on the topic at hand.


                I haven’t mentioned non-leading whitespace in the pasted text as I’m happy they remain exactly as they exist…

                So right there something that makes you happy would make many others unhappy if this was an applied solution. Sure, you go on to say how this could be “enhanced” but you don’t admit that this further complicates your easy solution.


                It is deceptively simple. It is little more than a one line of code to replace newline with newline followed by the initial indent.

                So… if you’re going to say something like that, put your code in a Notepad++ context and share it as a working solution.
                In other words, put your money where your mouth is.

                mkupperM 1 Reply Last reply Reply Quote 0
                • mkupperM
                  mkupper @Alan Kilborn
                  last edited by

                  In thinking about it, an option for “Paste as typing” could be interesting but let’s look at some edge cases.

                  1. Should autocomplete be honored? For example, sometimes I have accepted autocomplete by typing tab. But, what if autocomplete offers a drop down list. Should down arrows or drill-down letters be accepted?
                  2. Normally we press the <enter> key when typing. Copy/pasted text often has CR LF pairs for the end of line. CR used to be Ctrl+M and LF is Ctrl+J. Notepad++'s default shortcut mapper has Ctrl+M assigned to the Mark dialog box and Ctrl+J assigned to Edit / Line Operations / Join Lines. To be literal about this, we would expect Ctrl+M and Ctrl+J to be processed as marking and joining. Marking is useful as that would allow for a form of scripting much like that ghost typing feature that Notepad++ already has.

                  Thus, while Paste-as-typing seems interesting I can see how people’s expectations of what it should do will differ as I think @Dennis-Bareis wants Paste-as-cooked-typing while I just described Pasted-as-raw-or-ghost-typing. There may well be medium rare typing variants.

                  Are plugins allowed to inject keystrokes into the message stream? It may well be that the pasting variants can be handled by a plugin.

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

                    @mkupper said :


                    an option for “Paste as typing” could be interesting

                    I think I see where you’re going with this, but we should probably ignore that direction (for now at least) because all indications from the OP are that that’s not what he’s interested in.


                    Are plugins allowed to inject keystrokes into the message stream?

                    Such a thing might be a “bad idea”.
                    :-)


                    It may well be that the pasting variants can be handled by a plugin.

                    A “pasting variant”…(what I would call a “paste special”)…can be supported as follows:

                    • write plugin/script code to insert text at the caret position (doing whatever needs to be done to the text in the clipboard–or even the document itself–before actually inserting it into the doc)

                    • provide the above to the user as a plugin menu first-level option, or as a script off of a scripting plugin’s first-level menu (thus in either case the execution is “shortcut mappable”)

                    • user unassigns his default system “paste” shortcut from Ctrl+v and points Ctrl+v at the plugin command or script (or, as maybe I’d suggest: creates a special keycombo, e.g. Ctrl+Shift+v ??) to run this new functionality

                    The script that I’ve yet to have time to tidy up and post will follow this model…

                    1 Reply Last reply Reply Quote 4
                    • gstaviG
                      gstavi
                      last edited by

                      With respect to the original issue, @Dennis-Bareis presents a self-centered approach that does not acknowledge the fact that different users use the product differently. His issue is basically: “I am too lazy to do block indent after paste, fix it for me and to hell with everyone else”.

                      The cool thing with paste-as-type is that indent rules can be different for different users.
                      If 5 users paste-as-type the same text into their document they can get 5 different results based on the indent rules that they are currently using, It is kind of a selective code-beautification. And since it does not change normal pasting it does not break users experience.

                      I still don’t think that it is worth the effort. I still stand by my original claim that implementation details will always slightly miss expectations of some of the users. But there is some coolness to it.

                      Dennis BareisD 1 Reply Last reply Reply Quote 2
                      • Dennis BareisD
                        Dennis Bareis @gstavi
                        last edited by

                        @gstavi What npp does now is the worst possible solution to the problem that helps no-one. My suggestion would suit most users who are often copying/pasting their own code.

                        Some languages have blocks that rely on indentation to work, so forgetting to indent a line is a critical mistake, not a relatively minor formatting issue. For those copying other people’s code the solution is still way better than what npp does, so I’d say this is a major improvement that eliminates major problems with npp auto indentation.

                        As for lazy, I assume you don’t use notepad because like me, you are too lazy to do all the formatting manually?

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

                          @Dennis-Bareis said in Maintain Indent While Pasting Multiple Lines:

                          worst possible solution to the problem that helps no-one

                          In your opinion.

                          If Notepad++ started behaving like you seem to want it when I paste into Notepad++, it would completely and totally and utterly disrupt my workflow having to fix what it messed up.

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

                            @PeterJones said in Maintain Indent While Pasting Multiple Lines:

                            it would completely and totally and utterly disrupt my workflow having to fix what it messed up

                            I think you should hold judgement and wait on the script – I don’t know how saving some reformatting after a paste would disrupt a workflow, except making it smoother because you don’t have to do some steps… :-)

                            PeterJonesP Dennis BareisD 2 Replies Last reply Reply Quote 0
                            • PeterJonesP
                              PeterJones @Alan Kilborn
                              last edited by

                              @Alan-Kilborn ,

                              Possibly. Since I don’t remember seeing the differently-indented first line from a multi line paste, perhaps I don’t ever paste multiple lines on an already-indented line, so maybe it wouldn’t affect me at all.

                              But since the status quo works for me, and with all the problems of recent “improvements”, I would be reluctant to see it implemented, with the fear that the implementation, even if not the basic idea, messes up my workflow.

                              As a script, it wouldn’t be a problem: if it helps me, great; if it does nothing or messes me up, I would just not use it. But as a feature of the app, if it messed me up, I’d have to lobby for a new zero byte config file, and I don’t want to have to do that.

                              1 Reply Last reply Reply Quote 0
                              • Dennis BareisD
                                Dennis Bareis @Alan Kilborn
                                last edited by

                                @Alan-Kilborn said in Maintain Indent While Pasting Multiple Lines:

                                @PeterJones said in Maintain Indent While Pasting Multiple Lines:

                                I think you should hold judgement and wait on the script – I don’t know how saving some reformatting after a paste would disrupt a workflow

                                I could be wrong but I took it as sarcasm 😀

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

                                  @Dennis-Bareis said in Maintain Indent While Pasting Multiple Lines:

                                  I could be wrong but I took it as sarcasm

                                  PJ is rarely sarcastic (as a moderator here he is somewhat required to be “even keel”). Usually, the farthest he’ll go is something like this:

                                  …recent “improvements”…

                                  1 Reply Last reply Reply Quote 1
                                  • StoopidoManS
                                    StoopidoMan
                                    last edited by StoopidoMan

                                    I would really want this too
                                    I posted about it on reddit:
                                    https://www.reddit.com/r/notepadplusplus/comments/1cp6r8x/apply_autoindent_on_multiline_paste_is_there_away/

                                    I keep a lot of notes on Notepad++ and I use the Auto-indent feature a lot but it doesn’t work when you paste text.

                                    for example:

                                    How to do X?
                                                                1) just do the X
                                                                2) Blah Blah X 
                                    

                                    When I paste something from the clipboard I expect it to look like this:

                                    How to do X?
                                                                1) just do the X
                                                                2) Blah Blah X 
                                                                 Random copied text from internet line 1
                                                                 Random copied text from internet line 2
                                                                        Random copied text from internet line 3
                                                                        Random copied text from internet line 4
                                    

                                    but it get pasted like this:

                                    How to do X?
                                                                1) just do the X
                                                                2) Blah Blah X 
                                                                Random copied text from internet line 1
                                    Random copied text from internet line 2
                                           Random copied text from internet line 3
                                           Random copied text from internet line 4
                                    

                                    So since I pressed enter and pasted the text, the first pasted line respect the auto-indent, but the subsequent lines does not.

                                    I think this would be a nice optional feature to add on top of Notepad++ Auto-indent setting, as Follow auto-indent on paste

                                    ☐ Auto-indent 
                                           ☐ follow auto-indent on paste
                                    
                                    1 Reply Last reply Reply Quote 0
                                    • guy038G
                                      guy038
                                      last edited by guy038

                                      Hello, @stoopidoman and All,

                                      The example provided by @stoopidoman is not clearly explained ! I suppose that what he wants to say is :

                                      I have this text in a new tab, after hitting the Enter key right after the X char and the trailing space, of the second line :

                                      How to do X?
                                                                  1) just do the X
                                                                  2) Blah Blah X 
                                                                  
                                      

                                      So, the cursor is presently right before the 2) string, but on the third line, after some tabulation or space chars

                                      Be aware that some plugins may change the default indent behaviour of Notepad++, like, for example, the Elastic Tabstops plugin. In this case, before doing the test, simply disable the plugin !


                                      Now, I pasted the text , below, from Internet :

                                      Random copied text from internet line 1
                                      Random copied text from internet line 2
                                             Random copied text from internet line 3
                                             Random copied text from internet line 4
                                      

                                      When I paste the above text in my new tab, I get the following text :

                                      How to do X?
                                                                  1) just do the X
                                                                  2) Blah Blah X 
                                                                  Random copied text from internet line 1
                                      Random copied text from internet line 2
                                             Random copied text from internet line 3
                                             Random copied text from internet line 4
                                      

                                      However, I would have expected this kind of text :

                                      How to do X?
                                                                  1) just do the X
                                                                  2) Blah Blah X 
                                                                  Random copied text from internet line 1
                                                                  Random copied text from internet line 2
                                                                      Random copied text from internet line 3
                                                                      Random copied text from internet line 4
                                      

                                      How to get this last behaviour with pasted text ?

                                      Best Regards,

                                      guy038

                                      IMPORTANT POINT :

                                      To respect the same displaying as the @stoopidoman’s one, I had to do the following operation, too :

                                      Edit > Blank Operations > TAB to Space

                                      Thus, all this story is a bit tricky !


                                      Certainly, @stoopidoman, previously configured his N++ installation as :

                                      • Go to Settings > Preferences... > Language > Tab Settings

                                      • In the list, choose the Normal option

                                      • Uncheck the Use Default Value option

                                      • Don’t change the Tab size option

                                      • Check the Replace by space option

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

                                        Sorry all… earlier in this thread I promised a script… and I haven’t delivered.
                                        It IS more difficult to do a comprehensive solution on this than one would think – and sometimes that can keep one from finishing something to their own satisfaction.
                                        Let me see what I can do about dumbing it down and at least getting something posted…

                                        Alan KilbornA 1 Reply Last reply Reply Quote 1
                                        • mpheathM
                                          mpheath @Dennis Bareis
                                          last edited by

                                          Quite fresh code that uses PythonScript. Got the getClipboardText() idea from a post by @Alan-Kilborn .

                                          from Npp import editor, notepad
                                          import re
                                          
                                          def main():
                                              def getClipboardText():
                                                  editor = notepad.createScintilla()
                                                  editor.paste()
                                                  editor.convertEOLs(eolMode)
                                                  text = editor.getText()
                                                  notepad.destroyScintilla(editor)
                                                  return text
                                          
                                              def repl(m):
                                                  if useTabs:
                                                      result = m.group(1).replace(' ' * tabWidth, '\t')
                                                      size = result.count('\t')
                                                  else:
                                                      result = m.group(1).replace('\t', ' ' * tabWidth)
                                                      size = result.count(' ' * tabWidth)
                                          
                                                  if not minSize[0] or size < minSize[0]:
                                                      minSize[0] = size
                                          
                                                  return result
                                          
                                              pos = editor.getCurrentPos()
                                              tabWidth = editor.getTabWidth()
                                              useTabs = editor.getUseTabs()
                                              eolMode = editor.getEOLMode()
                                              eol = ['\r\n', '\r', '\n'][eolMode]
                                              minSize = [0]
                                              text = getClipboardText()
                                          
                                              if not text:
                                                  return
                                          
                                              parts = re.split(r'\r?\n', text)
                                          
                                              # Normalize indents.
                                              re_indents = re.compile(r'^([\t ]+)')
                                          
                                              for index, line in enumerate(parts):
                                                  modified = re_indents.sub(repl, line)
                                                  parts[index] = modified
                                          
                                              # Remove indents to flatten.
                                              tabLiteral = '\t' if useTabs else ' ' * tabWidth
                                          
                                              while minSize[0]:
                                                  for index, line in enumerate(parts):
                                                      parts[index] = line.replace(tabLiteral, '', 1)
                                          
                                                  minSize[0] -= 1
                                          
                                              # Add indents to finalize.
                                              line = editor.lineFromPosition(pos)
                                              indentSize = editor.getLineIndentation(line)
                                          
                                              while indentSize > 0:
                                                  for index, line in enumerate(parts):
                                                      if index > 0:
                                                          parts[index] = tabLiteral + line
                                          
                                                  indentSize -= tabWidth
                                          
                                              # Join lines and insert into editor.
                                              text = eol.join(parts)
                                              editor.insertText(pos, text)
                                          
                                          main()
                                          

                                          It should get the text from the clipboard, normalize and flatten the indenting, add indents from position from the current editor line and then insert into the editor.

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

                                            @Alan-Kilborn said in Maintain Indent While Pasting Multiple Lines:

                                            Let me see what I can do about dumbing it down and at least getting something posted…

                                            Here’s my entry; I call the script PasteSpecialAtCurrentIndentColumn.py.

                                            # -*- coding: utf-8 -*-
                                            from __future__ import print_function
                                            
                                            #########################################
                                            #
                                            #  PasteSpecialAtCurrentIndentColumn (PSACIC)
                                            #
                                            #########################################
                                            
                                            # references:
                                            #  https://community.notepad-plus-plus.org/topic/25295
                                            #  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 *
                                            import os, re # script modified by moderator; see May 11 9:27p posting (by mpheath) below
                                            
                                            #-------------------------------------------------------------------------------
                                            
                                            try:
                                                editor3h  # third editor, hidden
                                            except NameError:
                                                editor3h = notepad.createScintilla()
                                            
                                            #-------------------------------------------------------------------------------
                                            
                                            class PSACIC(object):
                                            
                                                def __init__(self):
                                            
                                                    if not editor.canPaste() or not editor3h.canPaste():
                                                        return
                                            
                                                    rect_sel_mode = editor.getSelectionMode() in [ SELECTIONMODE.RECTANGLE, SELECTIONMODE.THIN ]
                                                    if rect_sel_mode:
                                                        self.mb('Cannot use this paste-special when in column-block mode.')
                                                        return
                                            
                                                    if editor.getSelections() > 1:
                                                        self.mb('Cannot use this paste-special when more than a single caret is active.')
                                                        return
                                            
                                                    if len(editor.getSelText()) > 0:
                                                        self.mb('Cannot use this paste-special when text is selected.')
                                                        return
                                            
                                                    curr_pos = editor.getCurrentPos()
                                                    curr_line_starting_pos = editor.positionFromLine(editor.lineFromPosition(curr_pos))
                                                    if curr_pos == curr_line_starting_pos:
                                                        # caret at start of line; just do normal/simple paste
                                                        editor.paste()
                                                        return
                                            
                                                    curr_line_text_before_caret = editor.getTextRange(curr_line_starting_pos, curr_pos)
                                                    if re.search(r'\S', curr_line_text_before_caret):
                                                        self.mb('Cannot use this paste-special at an insertion point with non-whitespace to its left.')
                                                        return
                                            
                                                    clipboard_text = self.clipboard_get_text()
                                                    eol = [ '\r\n', '\r', '\n' ][editor.getEOLMode()]
                                                    if eol not in clipboard_text:
                                                        # no 2nd+ line(s) in data to paste, so nothing to adjust; just do normal/simple paste
                                                        editor.paste()
                                                        return
                                            
                                                    clipboard_lines_list = clipboard_text.splitlines()
                                            
                                                    # see if there's a common all-whitespace prefix on the clipboard lines
                                                    m = re.search(r'^\s+', os.path.commonprefix(clipboard_lines_list))
                                                    common_ws_prefix_on_clipboard_lines = m.group(0) if m else ''
                                            
                                                    # remove any common all-whitespace prefix on the clipboard lines
                                                    clipboard_lines_list = [ re.sub('^' + common_ws_prefix_on_clipboard_lines, '', s) for s in clipboard_lines_list ]
                                            
                                                    # prepend the current line's indentation whitespace to all of the clipboard lines:
                                                    first_clipboard_line_text = clipboard_lines_list[0]  # remember the first clipboard line before indenting all the rest
                                                    # add new indentation to all of the modified clipboard lines except the first line:
                                                    clipboard_lines_list = [ re.sub('^', curr_line_text_before_caret, s) for s in clipboard_lines_list[1:] ]
                                                    clipboard_lines_list.insert(0, first_clipboard_line_text)  # put the first line back into the list at its old position
                                            
                                                    # do our modified "paste" and set new caret appropriately:
                                                    old_doc_len = editor.getLength()
                                                    editor.insertText(curr_pos, eol.join(clipboard_lines_list) + eol)  # "paste" in the appropriately indented new text
                                                    new_caret_pos = curr_pos + editor.getLength() - old_doc_len
                                                    editor.setSel(new_caret_pos, new_caret_pos)  # set caret at end of "pasted" text; scroll viewport if needed
                                            
                                                def clipboard_get_text(self, eol_mode=None):
                                                    # if eol_mode arg is not-specified, use the current editor's eol mode:
                                                    editor3h.setEOLMode(editor.getEOLMode() if eol_mode is None else eol_mode)
                                                    editor3h.clearAll()
                                                    editor3h.paste()
                                                    retval = editor3h.getText()
                                                    return retval
                                            
                                                def mb(self, msg, flags=0, title=''):  # a message-box function
                                                    return notepad.messageBox(msg, title if title else 'PSACIC', flags)
                                            
                                            #-------------------------------------------------------------------------------
                                            
                                            if __name__ == '__main__': PSACIC()
                                            
                                            mpheathM Dennis BareisD 2 Replies Last reply Reply Quote 4
                                            • Alan KilbornA Alan Kilborn referenced this topic on
                                            • First post
                                              Last post
                                            The Community of users of the Notepad++ text editor.
                                            Powered by NodeBB | Contributors