Permalink
Browse files

sublime: Add basic quote style cycler

  • Loading branch information...
1 parent c5045b1 commit cc944464503f159f948f3e02522edf5203f9c22f @sj26 committed Mar 19, 2013
Showing with 50 additions and 1 deletion.
  1. +2 −1 Sublime Text 2/Packages/User/Default (OSX).sublime-keymap
  2. +48 −0 Sublime Text 2/Packages/User/user.py
View
3 Sublime Text 2/Packages/User/Default (OSX).sublime-keymap
@@ -5,5 +5,6 @@
{"keys": ["super+ctrl+r"], "command": "reveal_in_side_bar"},
{"keys": ["shift+super+,"], "command": "open_file", "args": {"file": "${packages}/User/Default ($platform).sublime-keymap"}},
{"keys": ["ctrl+w"], "command": "delete_word", "args": {"forward": false, "sub_words": true}},
- {"keys": ["super+shift+r"], "command": "reindent"}
+ {"keys": ["super+shift+r"], "command": "reindent"},
+ {"keys": ["shift+super+'"], "command": "cycle_quotes"}
]
View
48 Sublime Text 2/Packages/User/user.py
@@ -1,3 +1,4 @@
+import sublime
import sublime_plugin
import inflection
@@ -6,6 +7,53 @@ def run(self):
self.window.run_command("save")
self.window.run_command("close")
+class CycleQuotesCommand(sublime_plugin.TextCommand):
+ # Pairs of quote styles
+ styles = dict(
+ single=("'", "'"),
+ double=('"', '"'),
+ )
+
+ # Make sure we have an immutable ordered list of quote styles
+ style_keys = CycleQuotesStyles.keys()
+
+ def run(self, edit):
+ for region in self.view.sel():
+ # We don't want reversed regions, so left/right pairs are matched correctly
+ if region.a > region.b:
+ region = sublime.Region(region.b, region.a)
+
+ # Examine to scopes to make sure we're in a quoted string
+ scopes = self.view.scope_name(region.a).split()
+ while scopes and not scopes[-1].startswith("string.quoted."):
+ scopes.pop()
+ if not scopes:
+ continue
+
+ # Figure out which type of quotes we're looking for
+ style = scopes[-1].split(".")[2]
+ if style not in CycleQuotesCommand.styles:
+ continue
+ opening, closing = CycleQuotesCommand.styles[style]
+
+ # Search for the opening and closing quotes, as neccessary
+ while (region.a == region.b or self.view.substr(region.a) != opening) and self.view.scope_name(region.a - 1).split()[:len(scopes)] == scopes:
+ region = sublime.Region(region.a - 1, region.b)
+ while (region.a == region.b or self.view.substr(region.b) != closing) and self.view.scope_name(region.b + 1).split()[:len(scopes)] == scopes:
+ region = sublime.Region(region.a, region.b + 1)
+
+ # Find the new style
+ new_style_index = CycleQuotesCommand.style_keys.index(style) + 1
+ new_style_index %= len(CycleQuotesCommand.style_keys)
+ new_style = CycleQuotesCommand.style_keys[new_style_index]
+ new_opening, new_closing = CycleQuotesCommand.styles[new_style]
+
+ # TODO: (Un)Escape as neccessary
+
+ # Substitute them in
+ self.view.replace(edit, sublime.Region(region.a, region.a + 1), new_opening)
+ self.view.replace(edit, sublime.Region(region.b, region.b + 1), new_closing)
+
class CamelizeCommand(sublime_plugin.TextCommand):
def run(self, edit):
for region in self.view.sel():

0 comments on commit cc94446

Please sign in to comment.