Community
    • Login

    Feature Request: Show only line-final whitespace.

    Scheduled Pinned Locked Moved General Discussion
    whitespace
    28 Posts 7 Posters 16.6k 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.
    • SalviaSageS
      SalviaSage
      last edited by SalviaSage

      dail, I copied the LuaScript.dll into the plugins folder and then edited the startup.lua to look like this

      – Startup script
      – Changes will take effect once Notepad++ is restarted

      npp.AddEventHandler(“OnReady”, function()
      editor1.ViewWS = SCWS_VISIBLEAFTERINDENT
      editor2.ViewWS = SCWS_VISIBLEAFTERINDENT
      end)

      But, I see all whitespace, and not just the line end.

      1 Reply Last reply Reply Quote 0
      • dailD
        dail
        last edited by

        That’s odd. Try opening the LuaScript console and running this:

        editor.ViewWS = SCWS_VISIBLEAFTERINDENT
        

        You should see an immediate change. If that works then there is something odd going on with the startup script. Try changing it too this (to see if it prints anything to the console during startup):

        npp.AddEventHandler("OnReady", function()
            print("whitespace")
            editor1.ViewWS = SCWS_VISIBLEAFTERINDENT
            editor2.ViewWS = SCWS_VISIBLEAFTERINDENT   
        end)
        
        1 Reply Last reply Reply Quote 2
        • SalviaSageS
          SalviaSage
          last edited by

          This code is just enabling the show whitespace characters that notepad++ already has. Does it only show the line-final whitespace for you?

          dailD 1 Reply Last reply Reply Quote 0
          • dailD
            dail @SalviaSage
            last edited by

            @SalviaSage It shows the whitespace as the image I posted above.

            1 Reply Last reply Reply Quote 0
            • SalviaSageS
              SalviaSage
              last edited by

              I don’t see anything there, I can only see the whitespace by highlighting the text. I don’t see any kind of marker for them.

              dailD Scott SumnerS 2 Replies Last reply Reply Quote 0
              • dailD
                dail @SalviaSage
                last edited by

                @SalviaSage No clue then because it works fine for me.

                1 Reply Last reply Reply Quote 0
                • vtech7V
                  vtech7
                  last edited by

                  Hi, to highlight all whitespaces at the end of lines you can do this:
                  1- Open “Mark” part of the search tools. (Search > Mark…)
                  2- In “Find what :” type " $" (a whitespace then a $ sign)(without qouting)
                  3- Select “Wrap around”
                  4- On “Search Mode” part select “Regular expression”
                  5- Now push “Mark All” button
                  Notepad++ will highlight that whitespaces. You can clear all the highlighting by “Clear all marks” button.

                  But if you like to exam thoes whitespaces one by one and then remove them, do this:
                  1- Open “Replace” by “Search > Replace…” or by Ctrl+H shortcut.
                  2- In “Find what :” type " $" (a whitespace then a $ sign)(without qouting)
                  3- “Replace with:” has to be empty
                  4- Select “Wrap around”
                  5- On “Search Mode” part select “Regular expression”
                  Now you can use “Find Next” button to find them one by one and remove them by “Replace” button.

                  Scott SumnerS 1 Reply Last reply Reply Quote 0
                  • Scott SumnerS
                    Scott Sumner @vtech7
                    last edited by

                    @vtech7

                    I think the OP’s desire was to see the whitespace continually… Marking it is fine, but you’d have to keep refreshing that over and over. Doing something one time ever (e.g. @dail 's solution) is a whole lot different than doing something constantly to see a desired effect.

                    1 Reply Last reply Reply Quote 0
                    • Scott SumnerS
                      Scott Sumner @SalviaSage
                      last edited by

                      @SalviaSage

                      FWIW, @dail 's solution works perfectly fine when I try it:

                      Imgur

                      1 Reply Last reply Reply Quote 3
                      • SalviaSageS
                        SalviaSage
                        last edited by

                        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.

                        1 Reply Last reply Reply Quote 0
                        • SalviaSageS
                          SalviaSage
                          last edited by SalviaSage

                          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’.

                          @dail

                          dailD 1 Reply Last reply Reply Quote 0
                          • dailD
                            dail @SalviaSage
                            last edited by

                            @SalviaSage said:

                            So, maybe there is a command like 'SCWS_VISIBLEAFTERLASTCHARACTER"

                            Nope. Would have suggested it it if there was. :)

                            1 Reply Last reply Reply Quote 0
                            • guy038G
                              guy038
                              last edited by guy038

                              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 message 1625, refers to the Regular expression search mode

                              • The value 772 ( 512 + 256 + 4 ) of message 1702, means :

                                • Search in Down direction

                                • Option Wrap around ticked

                                • Option Purge for each search ticked

                              • The value 1615, of message 1701, refers to the Mark all button

                              1 Reply Last reply Reply Quote 0
                              • 古旮古
                                古旮
                                last edited by

                                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.

                                1 Reply Last reply Reply Quote 0
                                • SalviaSageS
                                  SalviaSage
                                  last edited by SalviaSage

                                  @guy038

                                  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?

                                  1 Reply Last reply Reply Quote 0
                                  • guy038G
                                    guy038
                                    last edited by guy038

                                    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 as Notepad++ .exe, as well as the zero-length file doLocalConf.xml, in case of a local 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

                                    1 Reply Last reply Reply Quote 0
                                    • SalviaSageS
                                      SalviaSage
                                      last edited by

                                      @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++?

                                      Scott SumnerS 1 Reply Last reply Reply Quote 0
                                      • guy038G
                                        guy038
                                        last edited by guy038

                                        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

                                        1 Reply Last reply Reply Quote 0
                                        • Scott SumnerS
                                          Scott Sumner @SalviaSage
                                          last edited by

                                          @SalviaSage

                                          …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.

                                          1 Reply Last reply Reply Quote 2
                                          • SalviaSageS
                                            SalviaSage
                                            last edited by

                                            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.

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