Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am looking for a way to expand some predefined strings in the terminal when tab (or another key combination) is pressed. This is different from tab completion. My terminal already expands ~ to my home directory (I cannot remember how I figured it out, but I am pretty sure this is just an special case of what I am looking for).

Examples:

Assume you type cdd and press tab, it is expanded to cd /your/home/folder/Downloads/ and the cursor is placed at the end of the line. So, you can type the name of a folder inside the Downloads folder and run the command. A better example would be to expand sshu to ssh |@a-pre-defined-host.foo and place the cursor behind the @ sign to type in the username.

The is similar to code snippet expansion capability in many IDEs. Please don't say I can achieved the same thing through bash functions with parameters written in .bashrc file.

What is the point?

So what's the point of using such a thing compared to a function call? Well, unlike many of you command-liners, I don't have a good memory. Even for the commands that I use frequently, I cannot remember the details such as the parameters. I usually search the web for things like "how to POST a json file using curl?". Well, I can create a function that accepts a file name, a host name, a port name and probably a few other parameters and do the POST. But, remembering the parameters and the order of them is not simpler than remembering the whole command then. With the snippet expansion, I only need to remember the name of the snippet, something like snppost, or maybe I dont even need to remember the name of the snippet. I can type snp and press tab to get a list of snippets, find the one that I am looking for. Press tab again to expand the snippet. And I have the command that I was looking for without searching the web and copy/pasting. I can do whatever customization that I like to the command and run it.

share|improve this question
    
What is |@ supposed to be? | is a control operator. Wouldn't it make more sense to type e.g. sshh, then type the username and then press tab for adding @a-pre-defined-host.foo? What is the advantage of first printing the host and moving the cursor backwards then? Furthermore the cursor would have to be in front of the @, not behind. –  Hauke Laging Apr 6 at 13:19
1  
If sshu is a function, you can just type sshu $user, without having to type Tab first, and you get the same result. The completion features in IDEs are designed for an environment where the completion itself needs to be stored in the source file, rather than a function that can be evaluated when the source file is read. –  chepner Apr 6 at 14:40
    
While this is possible, it's going to clash a lot with the usual working of completion. What's the point anyway? Why would you want to insert this directory name after cdd: if you're using a custom command name, that custom command would presumably have the directory name built in. Same thing with the ssh example, best dealt with through aliases in .ssh/config. You're trying to fit a square peg in a round hole, or as we say here, it's an XY problem. –  Gilles Apr 6 at 22:49
    
@HaukeLaging: | means the cursor location. Sorry if it was confusing. –  Mohsen Apr 6 at 23:27
    
@Gilles I guess the point is that the command does not have only one argument so that just the start directory is hard coded into the function / completion but that it must be possible to select paths below this point. –  Hauke Laging Apr 6 at 23:37

1 Answer 1

This is not going to be as easy as you want. Programmable completion is not capable of replacing commands. And you have to finish (i.e. trailing whitespace) the command word before programmable completion kicks in.

This means you must create an alias or function for cdd which replaces it by cd. That shouldn't be a problem (except for directory names containing newline...). The rest can be done this way:

_cdd () { IFS=$'\n'; if [ 1 -eq "$COMP_CWORD" -a 0 -eq "${#COMP_WORDS[1]}" ]; 
then COMPREPLY=("/your/home/folder/Downloads/"); 
else COMPREPLY=($(compgen -A directory "${COMP_WORDS[1]}"));fi; }

complete -o filenames -F _cdd cdd

putting the cursor inside a word

I don't think this is a good idea. But with this in mind: It is possible to move the cursor backwards but I didn't get that working from within programmable completion:

back_seq=$'\e[D'
output=""; for((i=0;i<5;i++)); do output+="$back_seq"; done
echo -n 123456789"$output"; sleep 5
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.