Moveable multi-line carets
-
@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
, orEnd
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.)
-
@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
-