Sublime Forum

Plugin to highlighting trailing whitespace?

#1

I need to be able to highlight all trailing spaces in red as well as all tabs. I was wondering if anyone here has an idea of how hard it would be to do that in sublime2. I don’t want to simply remove them, I just need to be able to highlight them. Ideally I would just like to pass it a regex to search for these things. This was fairly trivial in VIM but I have no idea how hard this would be in sublime2. Any help is appreciated. My company is very particular about not adding any tabs or trailing whitespace, and I really need something that stands out like I have in VIM. Hopefully this is doable, thanks for any help.

0 Likes

#2

Consider adding a rule to the syntax definition for the language you’re using so that it gives trailing whitespace an invalid/illegal scope. This depends on the color scheme you’re using too, though (as any other method I can think of now, btw).

More on editing syntax defs here:

sublimetext.info/docs/en/extensi … xdefs.html

0 Likes

#3

Do you know if there is a way to apply this globally? I need it for every format I work with. I could theoretically add it to every syntax definition but I was hoping there might be a global way of doing it.

Thanks

0 Likes

#4

Not that I know of… In that case, I believe a plugin is the only option. It should be fairly easy to highlight offending lines by making use of the “scope” parameter in .add_regions(). Although I haven’t tried, I anticipate it won’t be very usable with large files–it might slow down Sublime Text considerably. If you just need to highlight trailing whitespace in the current line or in the visible region, then it should work just fine.

Other than that, I haven’t got any more ideas how you could highlight regions in the way you need to…

0 Likes

#5

https://bitbucket.org/wuub/miscst2plugins/src/8f34c34b14e0/highlight_trailing_whitespace.py

0 Likes

#6

No plugin is necessary, the solution is built in. Go to Preferences->File Settings - User, and set these three settings to true:

“translate_tabs_to_spaces”: true,
“trim_automatic_white_space”: true,
“trim_trailing_white_space_on_save”: true,

Then it isn’t necessary to highlight anything during editing, because it will always get fixed when saving.

0 Likes

#7

I created a plugin to both highlight trailing spaces, and enable deletion of those text regions. I’d rather use a plugin and a command bound to a shortcut than the auto-delete feature, as in some cases, trailing spaces must/should not be deleted (whether they’re meaningful, or you’re reviewing a script but won’t touch it, and/or your auto-save feature would mess it up, and so on).

It’s here: github.com/SublimeText/TrailingSpaces
It’s inspired by the bitbucket version above, but revamped and extended, leveraging ST2’s new Plugin API, so I encourage you to use it instead of the old, broken version :wink:

Trailing spaces detection is basic and I’m using Linux, so please report any bug.

0 Likes

#8

I am going to throw my two cents in here. I like the idea, but I think this shouldn’t be running on every key press, at least not without some kind of debouncing (I do like that you gave a max size though). But generally I think this would work better as an on demand thing, that way you wouldn’t even need a max size.

I think in general you don’t need a constant checking of trailing spaces because the spaces are usually a mistake; something in general you get accustomed to avoiding, but can still occur by mistake. More often I would like to check after I am done coding.

What I think would work better is if you could set up a shortcut or a sublime command to toggle highlighting on and off. So if you issue the command, it will find all trailing spaces, if you issue the command again and the view is dirty (trailing is currently highlighted) it would clear all highlighting. If you wanted to delete trailing spaces you could bind that to a different shortcut, or a sublime command, so after viewing all the trailing spaces, you could decide “yeah, I want to delete all of that”, or no and just delete what you want and hide it.

This is all just my personal opinion. I may fork it for personal use and do what I described if this is not the direction you would like to go, but I do think this plugin could be very useful for controlled trailing space deletion in cases where you don’t want to obliterate all trailing spaces.

0 Likes

#9

I like the idea. Actually, my focus was on enabling trailing spaces monitoring over auto-deletion (which it what ST2 provides by default as an option), so it makes sense to provide another way than live highlighting :smile:

On my daily workflow, live highlighting is what I need, but I’ll hack the toggling option. This should be available tomorrow. I think I’ll stick to live highlighting by default though, as this is what most people around me seem to require.

As for debouncing, well, throttling, I’m working on it.

A line-by-line deletion mode could be nice too, but this may be too much overhead for no real use-cases.

0 Likes

#10

Cool.

Yeah, I realize my suggestion is a matter of taste.

After taking a look at some of the plugins I used, I realized more how much they can impact usability individually and more so when multiple live plugins are executing together on the same event. That is why I personally try to minimize live plugins on my system. The performance hit adds up.

Anyways, look forward to seeing what you cook up. I find controlled whitespace deletion good mainly because when I make a change at work, I like not to impact a 100+ lines of code. Corporate metrics and all like it when we have little impact…even if the impact makes the code better. It can be silly, but I figure at least I can keep my edits clean. :smile:

0 Likes

#11

I went ahead and gave it the ability to be toggled on my system. When toggled on, it will go ahead an perform a pass on toggle else it will clear any view that has already been highlighted during the on state. This is for anyone who would like it to be toggled. By default it is on, so this change would leave things how they are by default. You can change the default state to be off.

@chikamichi: If you want to pull these changes, let me know and I will create a pull request; I just wanted to go ahead and get this functionality a little early so I didn’t have to have it running all the time.

[code]’’’
Provides both a trailing spaces highlighter and a deletion command.

Config summary (see README.md for details):

# key binding
{ "keys": "ctrl+shift+t"], "command": "delete_trailing_spaces" }

# file settings
{
  "trailing_spaces_highlight_color": "invalid",
  "trailing_spaces_file_max_size": 1000
}

@author: Jean-Denis Vauguet jd@vauguet.fr, Oktay Acikalin ok@ryotic.de
@license: MIT (http://www.opensource.org/licenses/mit-license.php)
@since: 2011-02-25
‘’’

import sublime, sublime_plugin

DEFAULT_MAX_FILE_SIZE = 1048576
DEFAULT_COLOR_SCOPE_NAME = “invalid”
DEFAULT_IS_ENABLED = True

#Set whether the plugin is on or off
TrailingSpacesEnabled = DEFAULT_IS_ENABLED

Return an array of regions matching trailing spaces.

def find_trailing_spaces(view):
return view.find_all(’ \t]+$’)

Highlight trailing spaces

def highlight_trailing_spaces(view):
max_size = view.settings().get(‘trailing_spaces_file_max_size’,
DEFAULT_MAX_FILE_SIZE)
color_scope_name = view.settings().get(‘trailing_spaces_highlight_color’,
DEFAULT_COLOR_SCOPE_NAME)
if view.size() <= max_size:
regions = find_trailing_spaces(view)
view.add_regions(‘TrailingSpacesHighlightListener’,
regions, color_scope_name,
sublime.DRAW_EMPTY)

Clear all trailing spaces

def clear_trailing_spaces_highlight(window):
for view in window.views():
view.erase_regions(‘TrailingSpacesHighlightListener’)

Toggle the event listner on or off

class ToggleTrailingSpacesCommand(sublime_plugin.WindowCommand):
def run(self):
global TrailingSpacesEnabled
TrailingSpacesEnabled = False if(TrailingSpacesEnabled) else True

# If toggling on go ahead and perform a pass, if not clear the highlighting in all views
if(TrailingSpacesEnabled):
  highlight_trailing_spaces(self.window.active_view())
else:
  clear_trailing_spaces_highlight(self.window)

Highlight matching regions.

class TrailingSpacesHighlightListener(sublime_plugin.EventListener):
def on_modified(self, view):
if(TrailingSpacesEnabled):
highlight_trailing_spaces(view)

def on_activated(self,view):
if(TrailingSpacesEnabled):
highlight_trailing_spaces(view)

def on_load(self,view):
if(TrailingSpacesEnabled):
highlight_trailing_spaces(view)

Allows to erase matching regions.

class DeleteTrailingSpacesCommand(sublime_plugin.TextCommand):
def run(self, edit):
regions = find_trailing_spaces(self.view)
if regions:
# deleting a region changes the other regions positions, so we
# handle this maintaining an offset
offset = 0
for region in regions:
r = sublime.Region(region.a + offset, region.b + offset)
self.view.erase(edit, sublime.Region(r.a, r.b))
offset -= r.size()

        msg_parts = {"nbRegions": len(regions),
                     "plural":    's' if len(regions) > 1 else ''}
        msg = "Deleted %(nbRegions)s trailing spaces region%(plural)s" % msg_parts
    else:
        msg = "No trailing spaces to delete!"

    sublime.status_message(msg)

[/code]

I didn’t add it here, but also what would be nice, if when enabled, it did a pass when the view became active; that way I don’t have to edit the file force it find the white space in a file.

EDIT: It was trivial, so I went ahead and added an on_load and on_activated event so you don’t have to edit the file to see the highlights. I find being forced to make unneeded edits to see the trailing spaces undesirable.

0 Likes

#12

Ah, nice! I didn’t have the time tonight, so this is great. Pull request is the way to go, yes :smile:

Your edits are great. We may add a config key to set whether highlighting is enabled by default or not.

0 Likes

#13

Pull request has been made.

I agree that whether it is initiated by default should be controlled via a setting. That is something I had not yet tackled.

I may have accidentally had it configured to be disabled by default. I would check that on the merge.

**Edit: **I set it to be enabled to True by default now.

0 Likes