Home Download Buy Blog Forum Support

Move behind next "|'|)|]|}|> character?

Move behind next "|'|)|]|}|> character?

Postby highend on Sun Dec 02, 2012 9:00 pm

Hi,

Atm I use this keybinding:

Code: Select all
   // Move out of parenthesis, quotes, etc.
   { "keys": ["ctrl+l"], "command": "move", "args": {"by": "characters", "forward": true}, "context":
      [
         { "key": "following_text", "operator": "regex_contains", "operand": "^[\"')\\]}>]", "match_all": true },
         { "key": "auto_complete_visible", "operator": "equal", "operand": false }
      ]
   },


This works for all characters that are defined in the regex (single / double quote, square / round / angle / curly bracket), but only when the cursor is right in front of any of them.

Two questions:
1.) Is it possible to modify this binding so that it jumps behind the _next_ bracket / quote, regardless if the cursor isn't in front of such a character?
E.g.: The "|" is the current position of the cursor
Code: Select all
"sm|arter"

and when I press the associated keyboard shortcut the cursor moves behind the second quote?

2.) Would it also be possible to modify it in a way, that it jumps behind the _last_ bracket / quote that it can find on the same line?
E.g.:
Code: Select all
find(["sm|arter", "newer"]);

and after pressing the shortcut the cursor is at:
Code: Select all
find(["smarter", "newer"])|;


Regards,
Highend
highend
 
Posts: 94
Joined: Fri Jan 20, 2012 2:47 pm

Re: Move behind next "|'|)|]|}|> character?

Postby adzenith on Mon Dec 03, 2012 4:24 pm

I recommend checking out the BracketHighlighter plugin—I believe it has a keyboard shortcut to move to the end of "brackets", such as quotes or parentheses (or brackets).
adzenith
 
Posts: 1215
Joined: Mon Oct 19, 2009 9:12 pm

Re: Move behind next "|'|)|]|}|> character?

Postby highend on Fri Dec 07, 2012 8:28 pm

I've written my first plugin that does (exactly) what I want.

It moves the cursor behind the next / last occurrence of any of the 5 delimiters on the right side of the current cursor position (only on the same line) and to the previous / first occurrence on the left. Keybindings are only triggered as long as you are inside a pair of any of these delimiters.

If anyone can make some use of it, here is the code (I've put all files in a folder named "JumpOverDelimiters" in the packages directory):

Please bare with me, it's my first experience with a scripting language... If anyone wants to comment on how I could make the code better, don't hesitate to do so^^

JumpOverDelimiters.py
Code: Select all
import re
import sublime
import sublime_plugin

class JumpOverDelimitersCommand(sublime_plugin.TextCommand):
   def run(self, edit, direction={}, find={}):
      cur_position = self.view.sel()[0]
      current_line = self.view.line(cur_position)

      if direction == "right":
         if find == "next":
            tokens = [r'\>', r'\)', r'\]', r'\}', r'\"', r'\'']
         elif find == "last":
            tokens = [r'\>(?!.*\>)', r'\)(?!.*\))', r'\](?!.*\])', r'\}(?!.*\})', r'\"(?!.*\")', r'\'(?!.*\')']
         search_line_part = self.view.substr(sublime.Region(cur_position.begin(), current_line.end()))
      elif direction == "left":
         if find == "next":
            tokens = [r'\<(?!.*\<)', r'\((?!.*\()', r'\[(?!.*\[)', r'\{(?!.*\{)', r'\"(?!.*\")', r'\'(?!.*\')']
         elif find == "first":
            tokens = [r'\<', r'\(', r'\[', r'\{', r'\"', r'\'']
         search_line_part = self.view.substr(sublime.Region(current_line.begin(), cur_position.begin()))

      distances = []
      for token in tokens:
         value = re.search(token, search_line_part)
         if value is not None:
            distances.append(value.start())

      # Valid values (Matches found) => continue
      if distances != "[]":
         min_distance = min(distances)
         max_distance = max(distances)
         if direction == "right":
            if find == "next":
               new_cursor = cur_position.begin() + min_distance +1
            elif find == "last":
               new_cursor = cur_position.begin() + max_distance +1
         elif direction == "left":
            if find == "next":
               new_cursor = current_line.begin() + max_distance
            elif find == "first":
               new_cursor = current_line.begin() + min_distance
         self.view.sel().clear()
         self.view.sel().add(sublime.Region(new_cursor))


Default.sublime-commands (if you want to have it in the command palette):
Code: Select all
[
   {
      "caption": "Jump behind next right delimiter",
      "command": "jump_over_delimiters",
      "args": {"direction": "right", "find": "next"}
   },
   {
      "caption": "Jump behind last right delimiter",
      "command": "jump_over_delimiters",
      "args": {"direction": "right", "find": "last"}
   },
   {
      "caption": "Jump before next left delimiter",
      "command": "jump_over_delimiters",
      "args": {"direction": "left", "find": "previous"}
   },
   {
      "caption": "Jump before first left delimiter",
      "command": "jump_over_delimiters",
      "args": {"direction": "left", "find": "first"}
   }
]


User keybinding look like this:
If you want the cursor to move before the previous / first delimiter:
"direction": "left"
"find": "previous" | "find": "first"

Code: Select all
   { "keys": ["ctrl+l"], "command": "jump_over_delimiters", "args": {"direction": "right", "find": "next"}, "context":
      [
         { "key": "preceding_text", "operator": "regex_contains", "operand": "[\"'(\\[{<]", "match_all": true },
         { "key": "following_text", "operator": "regex_contains", "operand": "[\"')\\]}>]", "match_all": true },
         { "key": "auto_complete_visible", "operator": "equal", "operand": false }
      ]
   },
   // Move out left
   { "keys": ["ctrl+shift+l"], "command": "jump_over_delimiters", "args": {"direction": "right", "find": "last"}, "context":
      [
         { "key": "preceding_text", "operator": "regex_contains", "operand": "[\"'(\\[{<]", "match_all": true },
         { "key": "following_text", "operator": "regex_contains", "operand": "[\"')\\]}>]", "match_all": true },
         { "key": "auto_complete_visible", "operator": "equal", "operand": false }
      ]
   },
highend
 
Posts: 94
Joined: Fri Jan 20, 2012 2:47 pm

Re: Move behind next "|'|)|]|}|> character?

Postby gabrielalack on Fri Oct 25, 2013 10:10 pm

Nice script. Works great, exactly what I needed, except it doesn't support multiple cursors.

If I had the time and the knowhow, I'd add the feature myself.

Does anyone know of an updated version of this?
gabrielalack
 
Posts: 1
Joined: Fri Oct 25, 2013 10:08 pm


Return to Technical Support

Who is online

Users browsing this forum: Google [Bot], Yahoo [Bot] and 25 guests