Find and Add To Selection In 7.7
-
One of the features I’ve been anxiously awaiting in the next Scintilla update was being able to ‘find’ something, and then finding again so I could get several occurrences in a multi-select status. I downloaded the minimalist version of 7.7 but there’s nothing in the edit or find menu that exposes that capability and I don’t see anything in the shortcut mapper list either. Am I not seeing something? Is this possible with a python script now? I think the Scintilla command I’m looking for is IDM_SELECTIONADDNEXT or 2688 . Cntrl-Shift-D is the default key combo in SciTe that I’m trying to get in NPP. I’ve used @Claudia-Frank 's script from here but I was hoping to easily go one ‘find’ at a time w/o the dialog.
-
See one of the sub-points of this thread …meaning that you can currently do it with LuaScript.
Pythonscript will need to be updated to include the functionality, and it just hasn’t been done yet.
Of course, Notepad++ itself could be updated as well to do it…
-
Thanks Alan, I need to get over to plug-in development more often. Hopefully the Python maintainers are able to get something out soon. Or maybe @dail converted me to Lua!
-
@dail , @cipher-1024 , @Alan-Kilborn and all
I’ve tried to get the benefit of
SCI_MULTIPLESELECTADDNEXT
andSCI_MULTIPLESELECTADDEACH
following the advice of @dail in this already mentioned thread , but I wasn’t successful.I’ve set up the little script of @dail as a LUA Script plugin startup script and restarted Notepad++. I can confirm that after that there was a new entry in the submenu of the LUA Script plugin showing the expected text and keyboard shortcut. I selected a word by double-clicking on it or pressing CTRL+Right.The word became the main selection and all other instances of it in the whole text became marked. Then I pressed the keyboard shortcut assigned to the new Scintilla features, but I got no multiple cursors, nothing happened.
Of course I’ve used Notepad++ v7.7 and the latest version of the LUA Script plugin, i.e. v0.9 from the provided download link.
I’ve tried something similar using the NppExec plugin with the bare numeric message codes for
SCI_MULTIPLESELECTADDNEXT
(2688) andSCI_MULTIPLESELECTADDEACH
(2689) but it didn’t work either.Has anybody some advice whether there are some Notepad++ settings that might interfere with
SCI_MULTIPLESELECTADDNEXT
andSCI_MULTIPLESELECTADDEACH
to prevent them from working properly? -
@dinkumoil
you need to set target start and end before calling one of the new functions. -
Thank you, that helped! I’ve used the
NppExec
plugin and the sequence:- Select a word.
- Send
SCI_TARGETWHOLEDOCUMENT
(message code 2690) to set Scintilla’s target. - Send
SCI_MULTIPLESELECTADDEACH
(message code 2689) to multi-edit all instances of the word.
-
if different findoption should be used you can add a step 2a.
SCI_SETSEARCHFLAGS
-
Thanks for that additional hint, much appreciated!
Here is my complete NppExec script:
sci_sendmsg SCI_GETSELECTIONEMPTY if $(MSG_RESULT) == 1 then sci_sendmsg SCI_WORDRIGHTEXTEND endif sci_sendmsg SCI_SETSEARCHFLAGS SCFIND_WHOLEWORD sci_sendmsg 2690 sci_sendmsg 2689
It automatically selects the word right from the cursor but only if there is no active selection.
-
@dinkumoil - nice one, thanks for sharing.
One question, as I don’t have NppExec currently installed,
is it really needed to do SCI_WORDRIGHTEXTEND?From the docs it states If the current selection is empty then select word around caret
-
@Ekopalypse said:
is it really needed to do SCI_WORDRIGHTEXTEND?
According to my tests - yes.
If the
SCI_WORDRIGHTEXTEND
part is removed from the script, executing it (without an active selection) selects the word right from the cursor and marks all other instances of the word in the whole text but there are no multiple cursors. -
@dinkumoil - thanks for clarifying.
-
It automatically selects the word right from the cursor but only if there is no active selection.
I tried the NppExec script and I found that if I run it without a selection but with the caret inside or at the start of a word, it will select from the caret to the right to just before the start of the next word, and then fail to give multiple carets; example with caret sitting on second
s
of highlighted sci_sendmsg:Starting with an entire word preselected (here the 2nd sci_sendmsg in the file) however works just fine:
Perhaps I miss something about the case where there is no selected text first…
-
@all
Improved version of my NppExec script:
sci_sendmsg SCI_GETSELECTIONEMPTY if $(MSG_RESULT) == 1 then sci_sendmsg SCI_GETCURRENTPOS set local $(CurPos) ~ $(MSG_RESULT) sci_sendmsg SCI_WORDSTARTPOSITION $(CurPos) 1 if $(MSG_RESULT) != $(CurPos) then sci_sendmsg SCI_WORDLEFT endif sci_sendmsg SCI_WORDRIGHTEXTEND endif sci_sendmsg SCI_SETSEARCHFLAGS SCFIND_WHOLEWORD sci_sendmsg 2690 sci_sendmsg 2689
If the cursor is placed in the middle of a word without an active selection when executing the script, it is moved to the next word boundary to its left before selecting the word to the right of its new position, i.e. the word in whose mid it was placed before.
@Alan-Kilborn
Oh, I’ve posted before I could even see your posting… -
@dinkumoil said:
Oh, I’ve posted before I could even see your posting…
I tried the NppExec script just above and had the same result as the earlier NppExec script when no selection before running…
-
@Alan-Kilborn said:
I tried the NppExec script just above and had the same result as the earlier NppExec script when no selection before running…
It works at my site. Did you restart Notepad++ after updating the script?
-
Did you restart Notepad++ after updating the script?
No, but I didn’t “save” it, I was just running it as a NppExec temporary script…
-
Totally just for fun, I managed to replicate the functionality with Pythonscript in its current (1.4) form:
import ctypes from ctypes.wintypes import HWND from ctypes import byref, wintypes, Structure, sizeof def get_focused_window(): class GUITHREADINFO(Structure): _fields_ = [ ("cbSize", wintypes.DWORD), ("flags", wintypes.DWORD), ("hwndActive", wintypes.HWND), ("hwndFocus", wintypes.HWND), # <--- what we really want ("hwndCapture", wintypes.HWND), ("hwndMenuOwner", wintypes.HWND), ("hwndMoveSize", wintypes.HWND), ("hwndCaret", wintypes.HWND), ("rcCaret", wintypes.RECT) ] guiThreadInfo = GUITHREADINFO(cbSize=sizeof(GUITHREADINFO)) ctypes.windll.user32.GetGUIThreadInfo(0, byref(guiThreadInfo)) return guiThreadInfo.hwndFocus current_view_hwnd = get_focused_window() SciLexer = ctypes.WinDLL('SciLexer.dll', use_last_error = True) Scintilla_DirectFunction = SciLexer.Scintilla_DirectFunction direct_pointer = SendMessage(current_view_hwnd, 2185, 0, 0) editor.setSearchFlags(FINDOPTION.WHOLEWORD | FINDOPTION.MATCHCASE) if editor.getSelectionEmpty(): start_of_word_pos = editor.wordStartPosition(editor.getCurrentPos(), True) end_of_word_pos = editor.wordEndPosition(start_of_word_pos, True) if start_of_word_pos != end_of_word_pos: editor.setSelection(end_of_word_pos, start_of_word_pos) Scintilla_DirectFunction(direct_pointer, 2689, 1, 0)
-
Hmm, I found a strange pitfall with my code.
I use for testing the same snippet of source code @dail used in his posting in the other thread:
static std::string getWordAt(GUI::ScintillaWindow *window, int pos) { int word_start = window->Call(SCI_WORDSTARTPOSITION, pos, true); int word_end = window->Call(SCI_WORDENDPOSITION, pos, true); return getRange(window, word_start, word_end); }
If I place the cursor before the word
pos
near the end of line 1 and press my keyboard shortcut everything works fine. If I do the same with placeing it before the wordint
near the end of line 1, the script selects the wordint
and the following space character and nothing more happens. It looks like thesci_sendmsg SCI_WORDRIGHTEXTEND
gives a wrong result.I will try to figure out what’s going on…
EDIT: It’s because
int
is followed by a space character andpos
by opening parenthesis. This would make this feature nearly useless. Gonna do further investigations… -
Yea, if you’ll take note, I had an intentional big amount of spaces to the right of the word I had my caret in for my testing. :)
-
Does your Python script work as intended or is it a problem with the algorithm used?