I’m creating a plugin to get all the properties ( CSS ) within the selector and sort all of them alphabetically, then replace the sorted one with the original one. This way, I don’t have to use mouse to select all the properties and press f9 each time, and a key binding would do the job now with my plugin.
It’s working well, but the Sublime Text would clash every time when I try to run this plugin for the last selector of the CSS file. Assume we have the below CSS:
#second {
right: 0;
position: relative;
left: 0;
position: absolute;
bottom: 0;
}
.test {
position: absolute;
bottom: 0;
top: 0;
}
.second {
right: 0;
position: relative;
left: 0;
}
You can try to put the cursor at any property, it will work. But if the active line is right: 0;
or position: relative;
or left: 0;
from the selector .second
. 100% Sublime Text will clash.
I cannot figure why as the plugin looks fine. I’m not sure if my code is wrong logically or technically or this is a bug from Sublime Text, any expert here can help?
Update: I found that it will only clash when the }
of the last selector is the last line of the file
Below is the plugin code:
import sublime
import sublime_plugin
class sort_css_properties(sublime_plugin.TextCommand):
def run(self, edit):
view = self.view
position = view.sel()[0].end()
lineNumber = view.rowcol(position)[0]
currentNumber = [0, 1]
backwardNumber = [-1, 0]
forwardNumber = [1, 2]
currentLineStart = view.text_point(lineNumber + currentNumber[0], 0)
currentLineEnd = view.text_point(lineNumber + currentNumber[1], 0)
currentLineContent = view.substr(sublime.Region(currentLineStart, currentLineEnd))
previousLineStart = view.text_point(lineNumber + backwardNumber[0], 0)
previousLineEnd = view.text_point(lineNumber + backwardNumber[1], 0)
previousLineContent = view.substr(sublime.Region(previousLineStart, previousLineEnd))
nextLineStart = view.text_point(lineNumber + forwardNumber[0], 0)
nextLineEnd = view.text_point(lineNumber + forwardNumber[1], 0)
nextLineContent = view.substr(sublime.Region(nextLineStart, nextLineEnd))
currentLineContent = currentLineContent[:-1]
previousLineContent = previousLineContent[:-1]
nextLineContent = nextLineContent[:-1]
propertyLineStart = None
propertyLineEnd = None
sortedProperties = None
totalRegion = None
properties = []
properties.append(currentLineContent)
properties.append(previousLineContent)
properties.append(nextLineContent)
def get_line ( direction, find, target ):
nonlocal propertyLineStart
nonlocal propertyLineEnd
nonlocal sortedProperties
nonlocal totalRegion
lineStart = ''
lineEnd = ''
while lineNumber > 0:
if direction == 'Backward':
for i in range(len(backwardNumber)):
backwardNumber[i] = backwardNumber[i] - 1
lineStart = view.text_point(lineNumber + backwardNumber[0], 0)
lineEnd = view.text_point(lineNumber + backwardNumber[1], 0)
elif direction == 'Forward':
for i in range(len(forwardNumber)):
forwardNumber[i] = forwardNumber[i] + 1
lineStart = view.text_point(lineNumber + forwardNumber[0], 0)
lineEnd = view.text_point(lineNumber + forwardNumber[1], 0)
region = sublime.Region(lineStart, lineEnd)
lineContent = view.substr(region)
lineContent = lineContent[:-1]
if lineContent.endswith(find):
if direction == 'Backward':
propertyLineStart = view.text_point(lineNumber + backwardNumber[1], 0)
elif direction == 'Forward':
propertyLineEnd = view.text_point(lineNumber + forwardNumber[0], 0)
break
else:
properties.append(lineContent)
properties.sort()
sortedProperties = '\n'.join(properties)
sortedProperties += '\n'
get_line ( 'Backward', '{', 'selectorLine' )
get_line ( 'Forward', '}', 'closingLine' )
totalRegion = sublime.Region(propertyLineStart, propertyLineEnd)
view.replace(edit, totalRegion, sortedProperties)