Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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

3 Answers 3

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 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 at 16:31

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
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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.