Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am looking for a tool that can auto-close brackets and quotes in a terminal. For example, when I type

echo "

It should automatically expand into

echo ""

and put the cursor in the middle.

This is already doable in vim and many other editors, I would like to have the same feature in a terminal also.

share|improve this question

Assuming your shell is bash and you use emacs editing mode (set -o emacs), this answers your question for parenthesis and double quotes.

To explain what is going on there, here's one that works for {}:

bind '"{" "\C-v{}\e[D"'

Let's take a walk through the interior of the '. In the first pair of " we have:

{

This is pretty simple, it just means to replace a left curly brace with the following stuff.

The second pair of " starts off with:

\C-v{}

Here we insert the open and close brace. We need both because we're replacing what was originally typed, not appending to it. The \C-v is a Control-v character, which stands for a verbatim insert (brief history of terminal keys). This allows us to insert the { without triggering this binding again. Finally, we have:

\e[D

This is just the escape code for the left arrow key, so it moves the cursor to between the braces.

share|improve this answer
    
This is all nice, but if I have set editing-mode vi, it puts me out of insert mode after autocompletion, which is quite annoying. – qed Mar 6 '14 at 10:04
    
Fair enough, I'll add a note about this being an emacs editing mode only thing to my answer and give yours an upvote. – 8bittree Mar 6 '14 at 16:31
up vote 1 down vote accepted

A better way of doing this if you use the vi mode of readline in bash:

set editing-mode vi
set keymap vi-insert
"\C-b": backward-char
"(": "\C-v()\C-b"
"[": "\C-v[]\C-b"
"{": "\C-v{}\C-b"
"\"": "\C-v\"\C-v\"\C-b"
"\'": "\C-v\'\C-v\'\C-b"
share|improve this answer

I ended up making five bash scripts as below:

# terminal_autocomplete_brackets.sh
#!/bin/bash

myw=$(xdotool getactivewindow)
if [[ \
    $(xprop -id ${myw} | egrep 'bash .* Konsole') || \
    $(xprop -id ${myw} | egrep 'WM_CLASS.*Navigator.*Firefox') || \
    $(xprop -id ${myw} | egrep 'WM_CLASS.*google-chrome') \
    ]]
then
    xvkbd -xsendevent -text "[]\[Left]" >/dev/null 2>&1
else
    xvkbd -xsendevent -text "["  >/dev/null 2>&1
fi



# terminal_autocomplete_curly.sh
#!/bin/bash

myw=$(xdotool getactivewindow)
if [[ \
    $(xprop -id ${myw} | egrep 'bash .* Konsole') || \
    $(xprop -id ${myw} | egrep 'WM_CLASS.*Navigator.*Firefox') || \
    $(xprop -id ${myw} | egrep 'WM_CLASS.*google-chrome') \
    ]]
then
    xvkbd -xsendevent -text "{}\[Left]" >/dev/null 2>&1
else
    xvkbd -xsendevent -text "{" >/dev/null 2>&1
fi



# terminal_autocomplete_parentheses.sh
#!/bin/bash

myw=$(xdotool getactivewindow)
if [[ \
    $(xprop -id ${myw} | egrep 'bash .* Konsole') || \
    $(xprop -id ${myw} | egrep 'WM_CLASS.*Navigator.*Firefox') || \
    $(xprop -id ${myw} | egrep 'WM_CLASS.*google-chrome') \
    ]]
then
    xvkbd -xsendevent -text "()\[Left]" >/dev/null 2>&1
else
    xvkbd -xsendevent -text "(" >/dev/null  2>&1
fi




# terminal_autocomplete_quotes.sh
#!/bin/bash

myw=$(xdotool getactivewindow)
if [[ \
    $(xprop -id ${myw} | egrep 'bash .* Konsole') || \
    $(xprop -id ${myw} | egrep 'WM_CLASS.*Navigator.*Firefox') || \
    $(xprop -id ${myw} | egrep 'WM_CLASS.*google-chrome') \
    ]]
then
    xvkbd -xsendevent -text "\"\"\[Left]" >/dev/null  2>&1
else
    xvkbd -xsendevent -text "\"" >/dev/null  2>&1
fi



# terminal_autocomplete_squotes.sh
#!/bin/bash

myw=$(xdotool getactivewindow)
if [[ \
    $(xprop -id ${myw} | egrep 'bash .* Konsole') || \
    $(xprop -id ${myw} | egrep 'WM_CLASS.*Navigator.*Firefox') || \
    $(xprop -id ${myw} | egrep 'WM_CLASS.*google-chrome') \
    ]]
then
    xvkbd -xsendevent -text "''\[Left]" >/dev/null 2>&1
else
    xvkbd -xsendevent -text "'"  >/dev/null 2>&1
fi

Then you can use xbindkeys to bind "'[{( to each of these five scripts, it works quite well.

share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .