How to prevent Sublime Text 2 from swallowing closing brackets, quotes and parentheses?

AutocompleteSublimetext2EditingBrackets

Autocomplete Problem Overview


Sublime has this behaviour which is really annoying sometimes when you have to type in constructions with lots of brackets. When you type ( it adds () and puts the cursor in the middle, all fine, if you however will type ) it will silently swallow the closing bracket.

This is really annoying when typing long regexps because the brackets gets unbalanced pretty quick and this is driving me crazy. So you end up with constructions like (([a-z]).

So the question is - is there a way to disable this? If I type a closing bracket I want it to stay, not be swallowed.

I have checked through Sublime configs, googled, but nobody seems to mind this behaviour. Am I using it wrong?

Update

You might want to check out Sublime: Jump out of matching brackets shortcut as well.

Full version that allows you to type through with () but will not swallow the closing symbol if you have entered any text:

  { "keys": ["\""], "command": "insert", "args": {"characters": "\""}, "context":
      [
          { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
          { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
          { "key": "following_text", "operator": "regex_contains", "operand": "^\"", "match_all": true },
          { "key": "preceding_text", "operator": "regex_contains", "operand": "[^\"]$", "match_all": true }
      ]
  },
  { "keys": [")"], "command": "insert", "args": {"characters": ")"}, "context":
      [
          { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
          { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
          { "key": "following_text", "operator": "regex_contains", "operand": "^\\)", "match_all": true },
          { "key": "preceding_text", "operator": "regex_contains", "operand": "[^(]$", "match_all": true }
      ]
  },
  { "keys": [")"], "command": "move", "args": {"by": "characters", "forward": true}, "context":
      [
          { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
          { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
          { "key": "following_text", "operator": "regex_contains", "operand": "^\\)", "match_all": true },
          { "key": "preceding_text", "operator": "regex_contains", "operand": "\\($", "match_all": true }
      ]
  },
  { "keys": ["'"], "command": "insert", "args": {"characters": "'"}, "context":
      [
          { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
          { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
          { "key": "following_text", "operator": "regex_contains", "operand": "^'", "match_all": true },
          { "key": "preceding_text", "operator": "regex_contains", "operand": "'$", "match_all": true }
      ]
  },
  { "keys": ["]"],"command": "insert", "args": {"characters": "]"}, "context":
      [
          { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
          { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
          { "key": "following_text", "operator": "regex_contains", "operand": "^\\]", "match_all": true },
          { "key": "preceding_text", "operator": "regex_contains", "operand": "[$", "match_all": true }
      ]
  },
  { "keys": ["}"], "command": "insert", "args": {"characters": "}"}, "context":
      [
          { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
          { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
          { "key": "following_text", "operator": "regex_contains", "operand": "^\\}", "match_all": true },
          { "key": "preceding_text", "operator": "regex_contains", "operand": "{$", "match_all": true }

      ]
  }

Autocomplete Solutions


Solution 1 - Autocomplete

add this to your user keybindings file

{ "keys": [")"], "command": "insert", "args": {"characters": ")"}, "context":
	[
		{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
		{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
		{ "key": "following_text", "operator": "regex_contains", "operand": "^\\)", "match_all": true }
	]
}

it will override the one keybinding that instead of inserting a closing bracket just moves the cursor one position forward. so essentially it should do exactly what you want.

if you want to disable this behaviour completely, for all kinds of brackets and quotes, here is the complete user keybindings part:

{ "keys": ["\""], "command": "insert", "args": {"characters": "\""}, "context":
	[
		{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
		{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
		{ "key": "following_text", "operator": "regex_contains", "operand": "^\"", "match_all": true }
	]
},
{ "keys": [")"], "command": "insert", "args": {"characters": ")"}, "context":
	[
		{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
		{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
		{ "key": "following_text", "operator": "regex_contains", "operand": "^\\)", "match_all": true }
	]
},
{ "keys": ["'"], "command": "insert", "args": {"characters": "'"}, "context":
	[
		{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
		{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
		{ "key": "following_text", "operator": "regex_contains", "operand": "^'", "match_all": true }
	]
},
{ "keys": ["]"],"command": "insert", "args": {"characters": "]"}, "context":
	[
		{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
		{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
		{ "key": "following_text", "operator": "regex_contains", "operand": "^\\]", "match_all": true }
	]
},
{ "keys": ["}"], "command": "insert", "args": {"characters": "}"}, "context":
	[
		{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
		{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
		{ "key": "following_text", "operator": "regex_contains", "operand": "^\\}", "match_all": true }
	]
}

EDIT:

In case you want to skip the closing bracket if the cursor is right after an opening bracket and print it in all other cases, you can split your keybindings up to distinguish beetween these two possibilities:

{ "keys": [")"], "command": "insert", "args": {"characters": ")"}, "context":
	[
		{ "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
		{ "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
		{ "key": "following_text", "operator": "regex_contains", "operand": "^\\)", "match_all": true },
		{ "key": "preceding_text", "operator": "regex_contains", "operand": "[^(]$", "match_all": true }
	]
},
{ "keys": [")"], "command": "move", "args": {"by": "characters", "forward": true}, "context":
    [
        { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true },
        { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true },
        { "key": "following_text", "operator": "regex_contains", "operand": "^\\)", "match_all": true },
		{ "key": "preceding_text", "operator": "regex_contains", "operand": "\\($", "match_all": true }
    ]
},

The first one inserts the charcater if the preceding text doesn't end with an opening bracket. The second one moves the cursor one position forward if it does end with an opening bracket. If you are a little familiar with regular expressions you can do the same for all other kinds of brackets and quotes.

Solution 2 - Autocomplete

Redefine the ) key binding:

{ "keys": [")"], "command": "insert", "args": {"characters": ")"} }

Edit: Another way is to enable/disable the auto_match_enabled setting (thus changing the auto-pairing behavior), you can toggle it at will using a keyboard shortcut:

{ "keys": ["alt+m"], "command": "toggle_setting", "args": {"setting": "auto_match_enabled"} }

Solution 3 - Autocomplete

I found out when browsing the keybindings file 'preferences/key bindings - default' that if you select some text and type any of these ({[. It will place the brackets round your text.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionfiredevView Question on Stackoverflow
Solution 1 - AutocompletebasilikumView Answer on Stackoverflow
Solution 2 - AutocompletedusanView Answer on Stackoverflow
Solution 3 - Autocompleteuser2137588View Answer on Stackoverflow