Community
    • Login

    Column-block Paste problem with source block having jagged right edge

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    6 Posts 4 Posters 2.8k 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.
    • Alan KilbornA
      Alan Kilborn
      last edited by

      Sometimes I need to copy column block data and paste it into the middle (column-wise) of existing text. This works fine as long as all of the lines in the column are full (i.e., all of the columns are populated–if it is an “N” column block, then each column truly has N characters in it); however, it gets messy if some of the lines in the column block are shorter than N.

      Perhaps an example explains better:

      Selecting and copying the column block defined by A and G (including those characters) in the following data:

      aaaaaaaAaaaaaaaaaaaaa
      bbbbbbbbbb
      ccc
      d
      eeee
      ffffffff
      gggggggggggGgggg
      

      …and then pasting that column block into this data immediately to the right of the column of - characters:

      1111111-111111111111111111
      2222222-222222222222222222
      3333333-333333333333333333
      4444444-444444444444444444
      5555555-555555555555555555
      6666666-666666666666666666
      7777777-777777777777777777
      

      (note the nicely aligned right edge!)

      results in:

      1111111-Aaaaa111111111111111111
      2222222-bbb222222222222222222
      3333333-333333333333333333
      4444444-444444444444444444
      5555555-555555555555555555
      6666666-f666666666666666666
      7777777-ggggG777777777777777777
      

      (note the now messy right-edge!)

      but it would be more desirable to result in:

      1111111-Aaaaa111111111111111111
      2222222-bbb  222222222222222222
      3333333-     333333333333333333
      4444444-     444444444444444444
      5555555-     555555555555555555
      6666666-f    666666666666666666
      7777777-ggggG777777777777777777
      

      (note again the nicely aligned right edge!)

      Is there a reasonable way to make Notepad++ do this, (without going to the trouble of padding the shorter source lines with spaces on their right first, in order to “fill out” the column block)?

      1 Reply Last reply Reply Quote 0
      • Parpaluck209P
        Parpaluck209
        last edited by

        That’s because Npp has a problem with blank spaces: It simply ignores them. I too think that’s a wrong action. It bothers me when I press Home to go to the beginning of a line that starts with blank spaces. Notepad++ always takes me to the beginning of the first non-blank-space word, instead of the very beginning of the line.

        Maybe a new feature… although I heard from posters here that the author is quite stubborn in ignoring feature-requests…

        Peace be with you and this community!

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

          @Parpaluck209 said:

          That’s because Npp has a problem with blank spaces: It simply ignores them.

          No, that’s not it. PLEASE try not to spread misinformation via this Community. If you don’t know something to a high degree of certainty, don’t state it. Others might read these postings in the future and be misled by your wrong statements. Sure, everybody is wrong occasionally, but I can tell from what you stated that you have no idea what you are talking about.

          1 Reply Last reply Reply Quote 0
          • guy038G
            guy038
            last edited by guy038

            Hello, @alan-kilborn,

            Alan, the old TextFX plugin has this kind of feature ( TextFX > TextFX Edit > Paddle rectangular selection with spaces )

            But, here is, below, my work-around, with native N++ commands !


            • Perform a single left click after the G letter

            • Press, simultaneously, the Alt and Shift keys and hit, six times, on the Up arrow

            => A 6 x 0 column block should be defined, at column 13

            • Hit the Space key and, right after, the Backspace key

            => This time, the 6 x 0 column block is preceded by some Space characters

            • Now, press, simultaneously, the Alt and Shift keys and hit, five times, on the Left arrow

            => The column block between the letters A and G included, containing space characters, is, then, selected

            • Hit the usual Ctrl + C shortcut to copy this column block selection

            • If you prefer to keep that block unchanged, hit, twice, the Ctrl + Z shortcut

            • Finally, move the caret to the line 1111111-111111111111111111, after the dash character

            • Hit the usual Ctrl + V shortcut to column-paste it, at the caret position

            => The seven “digit-lines” should be, correctly, modified, as below :

            1111111-Aaaaa111111111111111111
            2222222-bbb  222222222222222222
            3333333-     333333333333333333
            4444444-     444444444444444444
            5555555-     555555555555555555
            6666666-f    666666666666666666
            7777777-ggggG777777777777777777
            

            Cheers,

            guy038

            1 Reply Last reply Reply Quote 2
            • Scott SumnerS
              Scott Sumner
              last edited by

              @guy038

              From reading your description, I thought it was going to be a painful process. But no, it is pretty clean and it works nicely. Nice technique.

              I’ve had a Pythonscript (surprise!) for doing this sort of operation. It works well; I’ve noticed it seems a bit slow on a large chunk of data, but no matter. Also, the source data (in the clipoard) can be a column block or a normal stream block (in which case the varying length lines are turned into a truly rectangular column block upon “pasting”).

              Start by copying some data to the clipboard, then put the caret at the desired Top/Left insertion point. Then invoke PasteAsTrueRectBlock.py:

              import ctypes
              
              def PATRB__GetClipboardText():
                  # see https://notepad-plus-plus.org/community/topic/12525/replace-current-line-without-inserting-a-new-line/12
                  # not the most error-proof function in the world!
                  if ctypes.windll.user32.OpenClipboard(None):
                      clipboard_handle = ctypes.windll.user32.GetClipboardData(1)
                      if clipboard_handle:
                          pointer_to_content = ctypes.windll.kernel32.GlobalLock(clipboard_handle)
                          clipboard_data = ctypes.c_char_p(pointer_to_content).value
                          ctypes.windll.kernel32.GlobalUnlock(clipboard_handle)
                      else:
                          return ''  # invalid handle
                      ctypes.windll.user32.CloseClipboard()
                      return clipboard_data
                  else:
                      return ''  # error
              
              def PATRB__main():
              
                  # "paste" current clipboard contents as a column block with TOP LEFT of resultant block at the caret point
                  current_text_in_clipboard = PATRB__GetClipboardText()
                  if editor.canPaste() and len(current_text_in_clipboard) > 0 and editor.getSelections() == 1 and editor.getSelectionEmpty():
                      line_ending = [ '\r\n', '\r', '\n' ][notepad.getFormatType()]
                      lines_list = current_text_in_clipboard.split(line_ending)
                      if len(lines_list[-1]) == 0: lines_list.pop()  # if text in clipboard ended with line_ending, need to remove empty element at end of list
                      longest_line_length = max([ len(z) for z in lines_list ])
                      uniform_horiz_len_lines_list = [ z + ' ' * (longest_line_length - len(z)) for z in lines_list ]  # pad shorter lines out to length of longest
                      starting_line_nbr = editor.lineFromPosition(editor.getCurrentPos())
                      orig_line_count = editor.getLineCount()
                      insert_starting_col = editor.getColumn(editor.getCurrentPos()) + editor.getSelectionNCaretVirtualSpace(0)
                      editor.beginUndoAction()
                      if starting_line_nbr + len(uniform_horiz_len_lines_list) > orig_line_count - 1:
                          # need to add some blank lines at bottom of file to hold line data we will be inserting
                          nbr_of_new_lines_to_add = starting_line_nbr + len(uniform_horiz_len_lines_list) - orig_line_count
                          editor.appendText(line_ending * nbr_of_new_lines_to_add)
                      for line_nbr_offset in xrange(len(uniform_horiz_len_lines_list)):
                          editor.gotoPos(editor.findColumn(starting_line_nbr + line_nbr_offset, insert_starting_col))  # try to go to the correct column; if can't, go to last column of the line
                          col_data_to_ins = ''
                          col_diff = insert_starting_col - editor.getColumn(editor.getCurrentPos())
                          if col_diff: col_data_to_ins = ' ' * col_diff  # the correct column does not exist; pad with spaces out to the correct column:
                          col_data_to_ins += uniform_horiz_len_lines_list[line_nbr_offset]
                          editor.addText(col_data_to_ins)
                      editor.endUndoAction()
              
              PATRB__main()
              
              Scott SumnerS 1 Reply Last reply Reply Quote 0
              • Scott SumnerS
                Scott Sumner @Scott Sumner
                last edited by

                I found some deficiencies in PasteAsTrueRectBlock.py. There are situations where the desired rectangular blocking can’t be known at paste time, but only at copy time. So I wrote CopyAsTrueRectBlock.py. Running this new script on a single selection, be it a normal selection or a column-based one, will result in a truly rectangular block in the clipboard, which can subsequently be pasted via a normal paste (e.g., ctrl+v). As a bonus, the logic for this script is simpler and shorter than the earlier script. :-)

                Here’s CopyAsTrueRectBlock.py:

                def CATRB__main():  # (C)opy (A)s (T)rue (R)ectangular (B)lock
                    if not editor.getSelectionEmpty():
                        if editor.selectionIsRectangle() or editor.getSelections() == 1:
                            line_ending = [ '\r\n', '\r', '\n' ][notepad.getFormatType()]
                            lines_list = editor.getSelText().split(line_ending)
                            if len(lines_list[-1]) == 0: lines_list.pop()  # if text ended with line_ending, need to remove empty element at end of list
                            rect_width = 0
                            if editor.selectionIsRectangle():
                                rect_anchor = editor.getColumn(editor.getRectangularSelectionAnchor())
                                rect_anchor += editor.getRectangularSelectionAnchorVirtualSpace()
                                rect_caret = editor.getColumn(editor.getRectangularSelectionCaret())
                                rect_caret += editor.getRectangularSelectionCaretVirtualSpace()
                                rect_width = abs(rect_anchor - rect_caret)
                            longest_line_length = max([ len(line) for line in lines_list ] + [ rect_width ])
                            # pad shorter lines out to length of longest:
                            truly_rectangular_lines_list = [ line + ' ' * (longest_line_length - len(line)) for line in lines_list ]
                            remember_active_file = notepad.getCurrentFilename()
                            notepad.new()
                            editor.addText(line_ending.join(truly_rectangular_lines_list) + line_ending)
                            editor.setSel(0, (longest_line_length + len(line_ending)) * len(truly_rectangular_lines_list))
                            editor.setSelectionMode(SELECTIONMODE.RECTANGLE)
                            editor.copy()
                            editor.undo()
                            notepad.close()
                            notepad.activateFile(remember_active_file)
                
                CATRB__main()
                
                1 Reply Last reply Reply Quote 1
                • First post
                  Last post
                The Community of users of the Notepad++ text editor.
                Powered by NodeBB | Contributors