• Login
Community
  • Login

Moveable multi-line carets

Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
25 Posts 6 Posters 2.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.
  • C
    Coises @mkupper
    last edited by Nov 12, 2024, 1:11 AM

    @mkupper said in Moveable multi-line carets:

    If I, recall, we already went down the road of asking for automatic cancellation of a multi-selection when the Up/Down arrow keys were used. The best we got was the Enable Column Selection to Multi-Editing switch which disables multi-selection when any of the arrow keys, Home, or End are used.

    I think you are failing to distinguish between rectangular (aka column) selections and multiple selections. They are not interchangeable.

    Cursor arrows and the Home and End keys have never, to the best of my knowledge, canceled multiple selections. What those of us who use column selections more often than multiple selections requested, and received, was the ability to restore the previously familiar behavior of having cursor movement keys cancel column selections.

    The new behavior, when Enable Column Selection to Multi-Editing is checked, is that a column selection is changed to a multiple selection when a cursor movement key is pressed, then moved accordingly. (It has never been possible to move a column selection and keep it as a column selection. There would, for example, be glaring inconsistencies when using proportional fonts.)

    You can (almost) tell the difference by looking at the status bar; a zero-width column selection looks like Sel: 4 x 0 = 0 while a multiple selection looks like Sel 4: 0 | 4.

    I say “almost” because Scintilla creates something called a thin selection after you type into a rectangular selection. A thin selection behaves like a zero-width column selection, but the status bar indicator shown in Notepad++ looks like the one for a multiple selection. (I don’t know why this choice was made; it might be an oversight.)

    1 Reply Last reply Reply Quote 4
    • A
      Alan Kilborn
      last edited by Alan Kilborn Nov 12, 2024, 7:49 PM Nov 12, 2024, 5:41 PM

      @Bas-de-Reuver said:

      but wouldn’t it be better to cancel multiline selection on cursor up and cursor down? 🤔

      A script can allow an up/down arrow press with an active column selection to cancel the selection.

      Here’s a Python3 script for it, I call the script ArrowUpOrDownCancelsColumnSelection.py:

      # -*- coding: utf-8 -*-
      
      #########################################
      #
      #  ArrowUpOrDownCancelsColumnSelection (AUODCCS)
      #
      #########################################
      
      # 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/25221/moveable-multi-line-carets
      #  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 *
      from ctypes import ( WinDLL, WINFUNCTYPE )
      from ctypes.wintypes import ( HWND, UINT, INT, WPARAM, LPARAM )
      
      user32 = WinDLL('user32')
      
      LRESULT = LPARAM
      
      WndProcType = WINFUNCTYPE(
          LRESULT,  # return type
          HWND, UINT, WPARAM, LPARAM  # arguments
          )
      
      SetWindowLong = user32.SetWindowLongPtrW
      SetWindowLong.restype = WndProcType
      SetWindowLong.argtypes = [ HWND, INT, WndProcType ]
      GWL_WNDPROC = -4
      
      WM_KEYDOWN = 0x0100
      VK_SHIFT = 0x10
      VK_CONTROL = 0x11
      VK_MENU = 0x12
      VK_UP = 38
      VK_DOWN = 40
      
      class AUODCCS(object):
      
          def __init__(self):
              self.new_editor1_wnd_proc_hook_for_SetWindowLong = WndProcType(self.new_editor1_wnd_proc_hook)
              self.orig_editor1_wnd_proc = SetWindowLong(editor1.hwnd, GWL_WNDPROC, self.new_editor1_wnd_proc_hook_for_SetWindowLong)
              self.new_editor2_wnd_proc_hook_for_SetWindowLong = WndProcType(self.new_editor2_wnd_proc_hook)
              self.orig_editor2_wnd_proc = SetWindowLong(editor2.hwnd, GWL_WNDPROC, self.new_editor2_wnd_proc_hook_for_SetWindowLong)
      
          def new_editor1_wnd_proc_hook(self, hwnd, msg, wParam, lParam):
              retval = self.common_editor_wnd_proc_hook(hwnd, msg, wParam, lParam)
              if retval: retval = self.orig_editor1_wnd_proc(hwnd, msg, wParam, lParam)
              return retval
      
          def new_editor2_wnd_proc_hook(self, hwnd, msg, wParam, lParam):
              retval = self.common_editor_wnd_proc_hook(hwnd, msg, wParam, lParam)
              if retval: retval = self.orig_editor2_wnd_proc(hwnd, msg, wParam, lParam)
              return retval
      
          def common_editor_wnd_proc_hook(self, hwnd, msg, wParam, lParam):
              retval = True  # default to letting N++ handle the message
              if msg == WM_KEYDOWN:
                  if (wParam == VK_UP or wParam == VK_DOWN) and \
                          (user32.GetAsyncKeyState(VK_SHIFT) & 0x8000) == 0 and \
                          (user32.GetAsyncKeyState(VK_CONTROL) & 0x8000) == 0 and \
                          (user32.GetAsyncKeyState(VK_MENU) & 0x8000) == 0:
                      sel_mode = editor.getSelectionMode()
                      rect_sel_mode = True if (sel_mode == SELECTIONMODE.RECTANGLE or sel_mode == SELECTIONMODE.THIN) else False
                      if rect_sel_mode:
                          cp = editor.getCurrentPos()
                          editor.setSelectionMode(SELECTIONMODE.STREAM)
                          editor.setSel(cp, cp)
                      else:
                          editor.lineUp() if wParam == VK_UP else editor.lineDown()
                      retval = False  # don't let N++ do any more processing on the key that was pressed
              return retval
      
      ARROW_UP_OR_DOWN_CANCELS_COLUMN_SELECTION = AUODCCS()
      

      To try out the script, all you have to do is run it ONCE. It will then sit there and listen for up or down arrow presses.

      If you like the script and you want to have it always active, you can set this script to run from user startup.py by adding the following line to that file:

      from ArrowUpOrDownCancelsColumnSelection import ARROW_UP_OR_DOWN_CANCELS_COLUMN_SELECTION

      1 Reply Last reply Reply Quote 5
      • A Alan Kilborn referenced this topic on Nov 12, 2024, 5:41 PM
      • A
        Alan Kilborn
        last edited by Alan Kilborn Nov 18, 2024, 12:24 PM Nov 18, 2024, 12:22 PM

        Just a couple of notes about the script above:

        • it won’t do its intended functionality if you are also using the BetterMultiSelection plugin and you have it Enable’d (at least on my system that plugin seems to steal keystrokes before the script can get ahold of them)
        • the script is not needed if you have Enable Column Selection to Multi-Editing uncheckmarked, ref. (this is I guess obvious, but it tripped me up at one point so I’m noting it here).
        C 1 Reply Last reply Nov 18, 2024, 5:25 PM Reply Quote 1
        • C
          Coises @Alan Kilborn
          last edited by Nov 18, 2024, 5:25 PM

          @Alan-Kilborn said in Moveable multi-line carets:

          BetterMultiSelection

          Since you apparently use that plugin, I have a question. In release notes for Columns++ v 1.1.2 I wrote:

          Some new features and fixes are probably incompatible with the BetterMultiSelection plugin. I believe that most if not all of that plugin’s features are now incorporated natively in current versions of Notepad++; if there are specific problems you cannot solve without that plugin and you observe conflicts with Columns++, please open an issue in the GitHub repository for Columns++ and I will see if there is anything I can do about it.

          Are there features you use from BetterMultiSelection that haven’t been made native to Notepad++? (If so, I’d like to identify them, test whether there is a conflict and see if I can resolve any conflicts that do occur. BetterMultiSelection hasn’t been updated in two and a half years, but then again there are only two open issues and one open pull request, none later than June 2022.)

          A 1 Reply Last reply Nov 19, 2024, 12:12 PM Reply Quote 0
          • A
            Alan Kilborn @Coises
            last edited by Nov 19, 2024, 12:12 PM

            @Coises said :

            Since you apparently use that plugin,

            Actually… I only use it because I forgot I had it hanging around! :-)
            I’ve now disabled it and I will see if my workflow is impacted at all…

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