Community
    • Login

    Moveable multi-line carets

    Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
    25 Posts 6 Posters 3.3k 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.
    • CoisesC
      Coises @mkupper
      last edited by

      @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
      • Alan KilbornA
        Alan Kilborn
        last edited by Alan Kilborn

        @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
        • Alan KilbornA Alan Kilborn referenced this topic on
        • Alan KilbornA
          Alan Kilborn
          last edited by Alan Kilborn

          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).
          CoisesC 1 Reply Last reply Reply Quote 1
          • CoisesC
            Coises @Alan Kilborn
            last edited by

            @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.)

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

              @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
              • First post
                Last post
              The Community of users of the Notepad++ text editor.
              Powered by NodeBB | Contributors