64

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 }

      ]
  }
Community
  • 1
  • 1
firedev
  • 20,898
  • 20
  • 64
  • 94
  • Though I'm not familiar with it, this SO post provides some info. on the BracketHighLighter plugin, which may provide some relief: stackoverflow.com/questions/10372004/how-to-change-style-of-matched-brackets-in-sublime-text-2. – chuff Dec 25 '12 at 16:02
  • Thanks but this is for highlighting brackets. What I am trying to find is the way to prevent loosing brackets when the cursor is on the closing bracket and you are typing it. – firedev Dec 26 '12 at 02:59
  • 2
    An alternative around that problem would be to turn off parenthesis matching temporarily -- e.g.: while working with RegEx. This answer does just that: http://superuser.com/questions/392200/turn-off-parenthesis-matching-in-sublime-text-2/482898#482898 – Fabien Snauwaert Jan 22 '15 at 20:29
  • It's so simple ! :O – Manu Apr 22 '17 at 19:49

3 Answers3

50

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.

basilikum
  • 10,378
  • 5
  • 45
  • 58
  • Ok, I can repeat it for square and curly braces. But what should I do for double- and single- quotes? – firedev Apr 29 '13 at 16:36
  • I just edited my answer. What i did by the way: i just looked in the default keybindings file and copied every part where a keystroke of for instance ')' results in an 'move' command. You can find these sections by searching for 'Auto-pair'. Then i just changed the 'move' command to an 'insert' command that inserts the appropriate character. – basilikum Apr 30 '13 at 16:12
  • This works, however there is one caveat, do you think it is possible to let it swallow closing bracket if it's right after the opening one? So when I am typing `function()` it doesn't end up with `function())` ? Sort of like it doesn't add a closing bracket if you put an opening one before some text. – firedev May 02 '13 at 11:32
  • Thanks a lot for this. I didn't know I needed it before actually finding your answer. This makes my day. – Bite code Aug 14 '13 at 17:58
  • My question is: Why doesn't Sublime Text 3 fix what is obviously a bug? – Argent May 27 '17 at 22:10
8

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"} }
dusan
  • 9,104
  • 3
  • 35
  • 55
  • But then I would have to redefine all keys ) } ] " '. Is there another way? – firedev Dec 27 '12 at 05:58
  • 6
    The other way is to disable the auto-pairing completely, changing the `auto_match_enabled` to `false` – dusan Dec 27 '12 at 12:17
  • Sorry bu disabling auto-match will disable adding the closing bracket when I am typing the opening one. I don't have problem with that, but I want to be able to type a closing one and see it because auto-matching doesn't work sometimes. To put it short - I want Sublime to behave like Textmate. – firedev Dec 28 '12 at 13:47
  • Sorry but this is incorrect, turning off automatching disables everything. – firedev Apr 08 '13 at 12:38
  • Exactly. I want to stop pairing quotes but I want to keep pairing braces. Disabling automatching is not the perfect solution. – fIwJlxSzApHEZIl May 30 '14 at 19:17
-2

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.

  • Of course, but then after you type in some text inside the brackets and press `)` it won't add additional bracket in the end if there is one already there. – firedev Mar 06 '13 at 03:17