Feature Request: Show only line-final whitespace.
-
FWIW, @dail 's solution works perfectly fine when I try it:
-
Yes, you are right, I also no longer have the initial whitespace being displayed with @dail’s script. However, the whitespace between characters are still shown. I am only interested in showing the final whitespaces instead.
What else can you think of? thx.
-
I can already easily see the spaces between characters because there is space between them, so I don’t need those marked. I just can’t see the line final spaces unless highlighting them. So, maybe there is a command like 'SCWS_VISIBLEAFTERLASTCHARACTER" I mean, there is already one for ‘visibleafterindent’.
-
@SalviaSage said:
So, maybe there is a command like 'SCWS_VISIBLEAFTERLASTCHARACTER"
Nope. Would have suggested it it if there was. :)
-
Hello @salviasage, @scott-sumner, @dail, @vtech7 and All,
Sorry, @salviasage, but Scintilla does not handle a function call, named
SCWS_VISIBLEAFTERLASTCHARACTER
:-((. Just look at that link, below :http://www.scintilla.org/ScintillaDoc.html#SCI_SETVIEWWS
But don’t be sad ! It’s quite possible to build two macros, with a specific shortcut, for each of them, which will be able to highlight / un-highlight all the trailing blank characters ( Tabulation or Space characters ) of the current file !
Note that I’m currently using the last
7.5.6
version of N++
So :
-
Open Notepad++
-
Open your active configuration file, named
shortcuts.xml
Select the text, below, and place it in the clipboard with
Ctrl + C
<Macro name="Visible Ending Blanks" Ctrl="no" Alt="yes" Shift="no" Key="32"> <Action type="3" message="1700" wParam="0" lParam="0" sParam="" /> <Action type="3" message="1601" wParam="0" lParam="0" sParam="\h+$" /> <Action type="3" message="1625" wParam="0" lParam="2" sParam="" /> <Action type="3" message="1702" wParam="0" lParam="772" sParam="" /> <Action type="3" message="1701" wParam="0" lParam="1615" sParam="" /> </Macro> <Macro name="Invisible Ending Blanks" Ctrl="no" Alt="yes" Shift="yes" Key="32"> <Action type="3" message="1700" wParam="0" lParam="0" sParam="" /> <Action type="3" message="1601" wParam="0" lParam="0" sParam="^" /> <Action type="3" message="1625" wParam="0" lParam="2" sParam="" /> <Action type="3" message="1702" wParam="0" lParam="772" sParam="" /> <Action type="3" message="1701" wParam="0" lParam="1615" sParam="" /> </Macro>
-
Now, place your cursor at the very beginning of the
</macros>
line, in the shortcut.xml file -
Then paste the clipboard contents, with
Ctrl + V
-
Save the changes done, in shortcut.xml, with
Ctrl + S
-
Close and Restart Notepad++ ( IMPORTANT )
-
From now on, every time you want :
-
To visualize the ending blank characters, use the
Alt + Spacebar
shortcut -
To suppress the previous Find highlighting, use the
Alt + Shift + Spacebar
shortcut
-
Of course, you may, also, choose the appropriate macro, in the Macro menu of N++
Notes :
-
I use the
\h+$
regex, in order to see the ending blank characters -
I use the
^
regex, which does not match anything, because it’s a zero-length assertion. ( Instead, you may use, as well, the$
assertion or, even, the zero-length string.{0}
) So, the previous highlighting is simply suppressed :-))
Cheers,
guy038
P.S. :
In the definition of these two macros :
-
The sParam string, of message
1601
, is the regex to search (\h+$
or^
) -
The value
2
, of message1625
, refers to theRegular expression
search mode -
The value
772
(512
+256
+4
) of message1702
, means :-
Search in
Down
direction -
Option
Wrap around
ticked -
Option
Purge for each search
ticked
-
-
The value
1615
, of message1701
, refers to theMark all
button
-
-
I wonder what is the Original Poster’s need? Why would you need to find a better way to view the trailing spaces?
If you need to trim the trailing spaces, you can do it by Find/Replace, with Find what: set to\h+$
or\s+$
, and Regular expression chosen.
If you need to trim the trailing spaces in a lot of files, you can go to the Find in Files… window.
If you just want to view it, you may just use Edit -> Mask…, which you may be already doing, since you said you can mark it manually. -
Thanks for your wonderful input.
I copy pasted your text into the macros subsection, and it looks correct to me. But, it is not being recognized.
What am I doing wrong? -
Hi, @salviasage and All,
You probably didn’t modify the right configuration file. First, you must know where your active configuration files are located :
-
Depending on your initial N++ installation ( with the installer OR from a ZIP or 7Z archive ), the active configuration files can be found :
-
In the
same
folder asNotepad++ .exe
, as well as the zero-length filedoLocalConf.xml
, in case of alocal
installation of N++ -
And, in case of an usual installation of N++, with the
installer
:-
In the folder
%AppData%\Roaming\Notepad++
, for a W7, W8 or W10 configuration -
In the folder
%AppData%\Notepad++
, for a XP or Vista configuration
-
-
Notes :
-
The environment variable
%AppData%
represents, generally, the path<Drive Letter>:\Documents and Settings\<User Name>\Application Data
-
BEWARE, the
Application Data
folder is, usually, an hidden folder. So, you’ll need to enable the visualization of hidden folders in Explorer, first ! -
I also advice you to BACKUP your active
shortcuts.xml
configuration file, before any change !
Everything should be OK :-))
Cheers,
guy038
-
-
You are right. I modified the shortcut.xml in the notepad++ installation directory, turns out this is not where you are supposed to add your own macros. (I discovered this just now)
And as for your macro, I just ran it and it is doing exactly what I want it to do, It marks only the line final spaces and tabs as a pink square.
The only downfault here is, it has to be ran each time and doesn’t update itself realtime. Can this be made so it works in real time as you are typing?
Also, how do you start a macro on startup of notepad++?
-
Hi, @salviasage and All,
A) Regarding your first question, I’m sorry, but I cannot do better :-( To go further on and add a real-time behavior, it needs the use of a language script, as the Python or Lua N++ plugins… and that task is over my technical skills ! May be some people, of the Community, could help you ?!
However, I really surprised why you do care about seeing trailing blank characters. Indeed, you may, either, use :
-
The Edit > Blank operations > Trim Trailing Space option ( You can, even, define a shortcut, using the Shortcut Mapper )
-
The Macro > Trim Trailing Space and Save (
Alt + Shift + S
) which, automatically, save your file, without these unneeded blank characters
B) Regarding your second question, presently, if you have a look to ? > Command Line Arguments…, there is not any
-Macro
argument, which could run a specific macro, on N++ startup. But, I know that some people, already did a request for such a feature !Best Regards,
guy038
-
-
…doesn’t update itself realtime. Can this be made so it works in real time as you are typing?
As I pointed out earlier in this thread, the regular expression solutions aren’t going to do this type of dynamic updating. If you are willing to install the Pythonscript plugin (currently only on 32-bit Notepad++), the script given in this thread is fairly easy to adapt to do what you wish, and it updates dynamically.
I did this modification to come up with this new script, which I call
EolWhitespaceHighlighter.py
:try: EWH__dict except NameError: EWH__dict = dict() EWH__dict['indic_to_use'] = 10 # pick a free indicator number def indicatorOptionsSet(indicator_number, indicator_style, rgb_color_tup, alpha, outline_alpha, draw_under_text, which_editor=editor): which_editor.indicSetStyle(indicator_number, indicator_style) # e.g. INDICATORSTYLE.ROUNDBOX which_editor.indicSetFore(indicator_number, rgb_color_tup) which_editor.indicSetAlpha(indicator_number, alpha) # integer which_editor.indicSetOutlineAlpha(indicator_number, outline_alpha) # integer which_editor.indicSetUnder(indicator_number, draw_under_text) # boolean for editorX in (editor1, editor2): indicatorOptionsSet(EWH__dict['indic_to_use'], INDICATORSTYLE.ROUNDBOX, (255,0,0), 100, 50, True, editorX) # white box rimmed in "pale violet red 2" def EWH__fileIsCloned(file_name_to_test): retval = False clone_detect_dict = {} file_tup_list = notepad.getFiles() for tup in file_tup_list: (filename, _, _, _) = tup if filename not in clone_detect_dict: clone_detect_dict[filename] = 0 else: clone_detect_dict[filename] += 1 if filename == file_name_to_test: break if file_name_to_test in clone_detect_dict: if clone_detect_dict[file_name_to_test] >= 1: retval = True return retval def EWH__fileIsClonedAndIsActiveInBothViews(file_name_to_test): retval = False if editor1 and editor2: # both views are in use if EWH__fileIsCloned(file_name_to_test): curr_doc_index_main_view = notepad.getCurrentDocIndex(0) curr_doc_index_2nd_view = notepad.getCurrentDocIndex(1) main_view_active_doc_bool = False secondary_view_active_doc_bool = False file_tup_list = notepad.getFiles() for tup in file_tup_list: (filename, _, index_in_view, view_number) = tup if filename == file_name_to_test: if view_number == 0: if index_in_view == curr_doc_index_main_view: main_view_active_doc_bool = True elif view_number == 1: if index_in_view == curr_doc_index_2nd_view: secondary_view_active_doc_bool = True if main_view_active_doc_bool and secondary_view_active_doc_bool: retval = True break return retval def EWH__getViewableEditorAndRangeTupleListList(work_across_both_views): retval = [] # retval looks like these examples: # [ ( editor, [ (0, 1000), (2020, 3000) ] ) ] # [ ( editor1, [ (0, 1000), (2020, 3000) ] ), ( editor2, [ (4000, 5000), (6020, 7000) ] ) ] def consolidate_range_tuple_list(range_tup_list): sorted_range_tup_list = sorted(range_tup_list) # sort criteria is first element of tuple in list saved_2element_list = list(sorted_range_tup_list[0]) for (start, end) in sorted_range_tup_list: if start <= saved_2element_list[1]: saved_2element_list[1] = max(saved_2element_list[1], end) else: yield tuple(saved_2element_list) saved_2element_list[0] = start saved_2element_list[1] = end yield tuple(saved_2element_list) def get_onscreen_pos_tup_list(which_editor): # which_editor is editor1 or editor2 (or maybe even just plain editor) # loosely based upon the N++ source for SmartHighlighter::highlightViewWithWord() retval_tup_list = list() temp_tup_list = [] MAXLINEHIGHLIGHT = 400 firstLine = which_editor.getFirstVisibleLine() currentLine = firstLine nbLineOnScreen = which_editor.linesOnScreen() nrLines = min(nbLineOnScreen, MAXLINEHIGHLIGHT) + 1 lastLine = firstLine + nrLines prevDocLineChecked = -1 break_out = False while currentLine < lastLine: docLine = which_editor.docLineFromVisible(currentLine) if docLine != prevDocLineChecked: prevDocLineChecked = docLine startPos = which_editor.positionFromLine(docLine) endPos = which_editor.positionFromLine(docLine + 1) if endPos == -1: endPos = which_editor.getTextLength() - 1 break_out = True if endPos > startPos: temp_tup_list.append((startPos, endPos)) if break_out: break currentLine += 1 if len(temp_tup_list) > 0: retval_tup_list = list(consolidate_range_tuple_list(temp_tup_list)) return retval_tup_list both_views_open = True if editor1 and editor2 else False curr_file_active_in_both_views = EWH__fileIsClonedAndIsActiveInBothViews(notepad.getCurrentFilename()) if both_views_open else False if both_views_open: ed1_range_tup_list = get_onscreen_pos_tup_list(editor1) ed2_range_tup_list = get_onscreen_pos_tup_list(editor2) if curr_file_active_in_both_views: range_tup_list = list(consolidate_range_tuple_list(ed1_range_tup_list + ed2_range_tup_list)) retval.append((editor, range_tup_list)) elif both_views_open and work_across_both_views: retval.append((editor1, ed1_range_tup_list)) retval.append((editor2, ed2_range_tup_list)) else: range_tup_list = get_onscreen_pos_tup_list(editor) retval.append((editor, range_tup_list)) return retval def EWH__callback_sci_UPDATEUI(args): for (editorX, pos_range_tuple_list) in EWH__getViewableEditorAndRangeTupleListList(True): # clear out any existing highlighting in areas the user can currently see for (start_pos, end_pos) in pos_range_tuple_list: editorX.setIndicatorCurrent(EWH__dict['indic_to_use']) editorX.indicatorClearRange(start_pos, end_pos - start_pos) def eolws_hilite_regex_search_match_found_callback(m): (span_start, span_end) = m.span() editorX.setIndicatorCurrent(EWH__dict['indic_to_use']) editorX.indicatorFillRange(span_start, span_end - span_start) for (start_pos, end_pos) in pos_range_tuple_list: editorX.research( r'\h+$', eolws_hilite_regex_search_match_found_callback, 0, #re.IGNORECASE, start_pos, end_pos ) editor.callbackSync(EWH__callback_sci_UPDATEUI, [SCINTILLANOTIFICATION.UPDATEUI]) # install callback else: editor.setSelectionMode(editor.getSelectionMode()) # force manual UPDATEUI to happen
The key area that makes this script different from the one in that other thread is this little segment:
for (start_pos, end_pos) in pos_range_tuple_list: editorX.research( r'\h+$', eolws_hilite_regex_search_match_found_callback, 0, #re.IGNORECASE, start_pos, end_pos )
Here you can see the regular expression
\h+$
that matches trailing whitespace on a line. -
Dear Scott Summer, I added your script to the startup.py and it is working perfectly. This is exactly the feature I want it, and now I got it. Thanks.
-
Yo dail… According to this page: https://www.scintilla.org/ScintillaDoc.html#SCI_SETVIEWWS
there is a visible only in indent command, which would only show these whitespace characters in the initial indentation area. and no where else.I am interested in doing that, I wrote the “SCWS_VISIBLEONLYININDENT” instead on your code above, but it didn’t work and syntax errored according to luascripts console.
the error is right where I put this new syntax, so i don’t know if their documentation is wrong or what…
and why are there two editor entries in there? Can you help me please? thx!
-
I wrote the “SCWS_VISIBLEONLYININDENT” instead on your code above,
This option is supported starting with Scintilla v3.6.2 and newer, however Notepad++ is using Scintilla v3.5.6…so this is due to Notepad++ using an old version of Scintilla…and nothing LuaScript can do about it.
and why are there two editor entries in there?
If you “move” or “clone” a document within Notepad++ you get a split view and can edit two files at once…each of these is an “editor” thus there is an
editor1
andeditor2
variable. Theeditor
variable always references the currently active editor. -
@dail said:
This option is supported starting with Scintilla v3.6.2 and newer, however Notepad++ is using Scintilla v3.5.6…so this is due to Notepad++ using an old version of Scintilla…and nothing LuaScript can do about it.
Thanks… I am crying a bucket right now :'( …
-
I found this code:
editor.WhitespaceSize = 0
basically, this hides the spaces indicator and not the tabs indicator.
Since tabs are only found at indents (or at least are supposed to be) we can see this symbol on indents
We can’t see the spaces symbol anywhere, but that’s okay. We will know it is spaces anyway, because if tab was used
then it would show.Final result:
https://i.imgur.com/rHARxzF.jpgsatisfactory enough for me!
-
I wrote a plugin that can be used to display whitespace used for indentation normally but after the first visible character, it is shown as dots and arrows. Its name is ExtSettings. You can download it >>> here <<<. It will also be available soon via PluginsAdmin.