The following will work in Sublime Text 2 and 3. However, due to some issues discussed later, it has the potential to block the program when editing large files, and/or on slow computers. A Sublime Text 3-specific version using an asynchronous method is at the bottom.
Open a new file in Sublime, and set its syntax to Python. Paste the following into it:
import sublime_plugin
class ShowZeroWidthSpace(sublime_plugin.EventListener):
def on_modified(self, view):
spaces = []
p = 0
while True:
s = view.find(u'\u200b', p + 1)
if not s:
break
spaces.append(s)
p = s.a
if spaces:
view.add_regions("zero-width", spaces, "invalid")
else:
view.erase_regions("zero-width")
Save the file in your Packages/User
directory as show_zero_width_space.py
, and it should start working immediately. Basically what it does is every time the current view is modified, it searches through it character by character looking for the zero-width space character, U+200B
. If it finds one, it adds the location to a list and keeps looking until it reaches the end of the file. Then, if any characters were found, they are highlighted according to the invalid
scope in your theme. Once highlighted, they can be selected and deleted.
Since this plugin runs every single time the view is modified (after every keystroke, for example), it has the potential to really slow down Sublime, especially for large files. Therefore, if you are working on files you know are clean, simply rename the plugin to show_zero_width_space.py.old
and make sure you delete any file named show_zero_width_space.pyc
, and it won't be active. For a Sublime Text 3-specific workaround, see below.
Sublime Text 3-specific version
The Sublime Text 3 API for EventListener
now includes an on_modified_async()
method, in keeping with the fact that all ST3 functions are now thread-safe. This runs the code asynchronously, in a non-blocking manner, so Sublime shouldn't be slowed down by it. The new plugin is as follows:
import sublime_plugin
class ShowZeroWidthSpace(sublime_plugin.EventListener):
def on_modified_async(self, view):
spaces = []
p = 0
while True:
s = view.find('\u200b', p + 1)
if not s:
break
spaces.append(s)
p = s.a
if spaces:
view.add_regions("zero-width", spaces, "invalid")
else:
view.erase_regions("zero-width")