Bash-Completion, an example


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Bash-Completion, an example
# 1  
Old 11-21-2014
Lightbulb Bash-Completion, an example

Hello

I've followed several bash-completion threads, usualy none were answered, because of obvious reasons. (of which i'm just aware since a day or a few)
Non-the-less, because i was writing scripts, i never considered it to be possible to add this functionality.

Also, because i though that my 'script idea' for which i wanted bash-completition seemed quite challenging, since it is based upon files within several folders, using the folders as arguments to the actual script, i thought it was too difficult.
I was terribly wrong! Smilie Smilie

First of all, read into: An Introduction to Programmable Completion
Then look into some existing ones in: /usr/share/bash-completion/completions or /etc/bash_completion.d

Once you understand that it is only checking the current(last) and previous 'argument', comparing them with the first (the application), the achievment seems alot easier.

For this example, you should know, that the 'application' in this case, has these 'arguments':
(The find command lists all items found in directory 'menu', sed replacing 'menu' with 'ds' and every '/' with a space, removing 'default' items, since they will not be shown in tab-completion)
So for the application 'ds' i have these arguments, which are based on folders and files.
Code:
find menu|sed s,"/"," ",g|sed s,menu,ds,g|grep -v default

ds
ds prj
ds prj edit
ds prj rpm
ds prj rpm changelog
ds prj rpm edit
ds prj rpm make
ds prj rpm list
ds prj rpm add
ds prj git
ds prj git edit
ds prj git commit
ds prj git status
ds prj git upl
ds prj git add
ds prj ks
ds prj ks edit
ds prj ks make
ds prj ks add
ds prj list
ds ssh
ds ssh make
ds ssh info
ds ssh setup
ds make
ds review
ds new
ds new manpage
ds setup
ds add

NOTE: What in this example is named 'cur' and 'prev', could be named anything else, or would not even need to be set, as they simply represent: $2 (prev) and $3 (cur).
You can check yourself, by simply adding:
Code:
echo "1$1 2$2 3$3 4$4 5$5"

Into any existing function within that file, also this helps debuging.
Speaking of which, the easiest way to test new changes, is to source the file providing the bash-completition code.

Anyway, so given above list, and knowing that it only checks $2 (prev) and $3 (cur), it is the simplest to work with a case statement.
The $2 (cur) is used if you are currently writing an argument.
The $3 (prev) is when you are looking for new words.
So we need a case statement for $2 (cur) and for $3 (prev).

This said, we need to decide wether we can use a single list several times, read out the values of a directory, or decide upon even diffrent circumstances and call even another function.
To get started, i decided to set a specific list to some of the entries, and share a single list for multiple entries.
So you have both, and its simpler to handle, as the list applies to them, and i took care that the given words expect the same values, so those lists can be shared.

Anyway, so looking at the application 'ds', we see its first line of arguments would be: prj new ssh add review setup
Looking at the 'pre' argument word 'prj', its values would be: ks git rpm edit list
And so forth...
So one simply makes a list for each of the entry.

Luckily, we can use the 'string mechanism' used here, to use regular bash commands.
So, instead of a list of words inside the quotes after an -W, you could use something like:
Code:
$(grep <pattern> <file>)
# or
$(cd /some/dir ; ls)

And when all this is put together, it looks like this:
(This is an example of my first completion-task, and may not be a perfect one, but simple and working)
Code:
# bash completion for dev-scripts
# file: /etc/bash_completion.d/dev-scripts_compl.bash
# 2014.11.21 by sea, based on blkid
# ---------------------------------

_dev-scripts_module()
{
#
#	Variables
#
	local cur prev OPTS DIR
	COMPREPLY=()
	cur="${COMP_WORDS[COMP_CWORD]}"
	prev="${COMP_WORDS[COMP_CWORD-1]}"
	OPTS="-3 -6 -h -v"
	DIR="$HOME/.config/dev-scripts/prjs"
#
#	Action
#
	# This completes the custom entries from $DIR
	# But only use this, if 'prev' was one using entries from $DIR
	# This list is dynamicly (automaticly) updated
	case $prev in
	"-"[36v]|add|make|list|edit|review)
		case $cur in
		[a-zA-Z]*)	COMPREPLY=( $( compgen -W "$(cd $DIR 2>/dev/null && echo $cur*)" -- "$cur" ) ) 
				return 0
				;;
		esac
		;;
	esac
	
	# This completes the word you are currently writing
	# These need manual maintainance
	case $cur in
		-*)	COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) )
			return 0
			;;
		a*)	COMPREPLY=( $(compgen -W "add" -- $cur) )
			return 0
			;;
		c*)	COMPREPLY=( $(compgen -W "changelog commit" -- $cur) )
			return 0
			;;
		e*)	COMPREPLY=( $(compgen -W "edit" -- $cur) )
			return 0
			;;
		g*)	COMPREPLY=( $(compgen -W "git" -- $cur) )
			return 0
			;;
		i*)	COMPREPLY=( $(compgen -W "info" -- $cur) )
			return 0
			;;
		k*)	COMPREPLY=( $(compgen -W "ks" -- $cur) )
			return 0
			;;
		l*)	COMPREPLY=( $(compgen -W "list" -- $cur) )
			return 0
			;;
		m*)	COMPREPLY=( $(compgen -W "make manpage" -- $cur) )
			return 0
			;;
		n*)	COMPREPLY=( $(compgen -W "new" -- $cur) )
			return 0
			;;
		p*)	COMPREPLY=( $(compgen -W "prj" -- $cur) )
			return 0
			;;
		r*)	COMPREPLY=( $(compgen -W "review rpm" -- $cur) )
			return 0
			;;
		s*)	COMPREPLY=( $(compgen -W "setup ssh" -- $cur) )
			return 0
			;;
	esac
	
	# This shows a list of words applying to your last argument
	# These need manual maintainance
	case $prev in
	# This lists the entries of current path.
	#	'-c')
	#		local IFS=$'\n'
	#		compopt -o filenames
	#		COMPREPLY=( $(compgen -f -- $cur) )
	#		return 0
	#		;;
		"-"[36v]|add|make|list|edit|review)
			COMPREPLY=( $( compgen -W "$(cd $DIR 2>/dev/null && echo *)" -- "$cur" ) ) 
			return 0
			;;
		rpm)
			COMPREPLY=( $(compgen -W "add changelog edit list make" -- $cur) )
			return 0
			;;
		ks)
			COMPREPLY=( $(compgen -W "add edit make" -- $cur) )
			return 0
			;;
		prj)	
			COMPREPLY=( $(compgen -W "git ks rpm edit list" -- $cur) )
			return 0
			;;
		git)
			COMPREPLY=( $(compgen -W "add commit edit status upl" -- $cur) )
			return 0
			;;
		ssh)
			COMPREPLY=( $(compgen -W "info make setup" -- $cur) )
			return 0
			;;
		new)
			COMPREPLY=( $(compgen -W "manpage" -- $cur) )
			return 0
			;;
		ds)
			COMPREPLY=( $(compgen -W "new prj ssh add make review setup" -- $cur) )
			return 0
			;;
		'-h')
			return 0
			;;
	esac
}
# Actualy make it available to the shell
complete -F _dev-scripts_module ds

Now to test this, all you would need to do is this, in order:
  1. Save the above text as: ./dev-scripts_compl.bash
  2. Code:
    source ./dev-scripts_compl.bash

  3. Code:
    touch ./ds ; chmod +x ./ds

  4. Code:
    ./ds<hit-the-tab>


NOTE:
When testing, you obviously would not get an output as the screenshot shows, as the file created by 'touch' is empty.
But the completition will work, as it depends on the ./dev-scripts_compl.bash, just checking for an executeable named 'ds'.

Hope this helps you to get started,
enjoy your bash-completions Smilie
Bash-Completion, an example-ds-bash-completitionjpg
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. UNIX for Advanced & Expert Users

Bash-Completion, installed but not applied

Heyas For my project TUI i had prepared bash completion. Bash-completion works, at least if i source that file manualy. However, when i'm installing it, it wont apply, not even for new opened terminals. Allthough i had it working once, i dont get why it doesnt work now. <...> + '' +... (0 Replies)
Discussion started by: sea
0 Replies

2. UNIX for Advanced & Expert Users

Bash-Completion, one list shown, the other not.

Heyas I'm trying to read out a file which contains a variable and use that list to complete a bash command. Difficult part on this is, that 2 (actualy 3) different lists are to be used, but the 'dynamic' ones from the external file dont work properly. It only seems to work with the list... (2 Replies)
Discussion started by: sea
2 Replies

3. UNIX for Dummies Questions & Answers

Bash-completion on shell script

Hello I want use bash_completion on a script but the information on the internet give me not a solution. The scrip start with "cd" to a direction Than the script do "ls" Than I must give a name of a sub-direction and here I want to use <TAB>, so when I have a direction with the name smith... (2 Replies)
Discussion started by: thailand
2 Replies

4. UNIX for Dummies Questions & Answers

Bash Tab Completion Hanging

Hi, I'm having a problem with tab completion at the bash command line. For some reason, whenever I type g<tab>, the terminal will freeze up for 5-10 seconds before asking me if I want to display all 325 possibilities. I thought that maybe it's because of the high number of commands, but I have... (4 Replies)
Discussion started by: Raz716
4 Replies

5. Shell Programming and Scripting

Programmable completion for two arguments in bash

Hi there! I have this script which handles bookmarks. Bookmarks are basically a string that point to a certain path, e.g., project -> ~/code/projects/project. Currently I have working completion for the bookmarks: ~ $ m p<Tab> ~ $ m project What I want to implement now is the cd... (0 Replies)
Discussion started by: KevinSjoberg
0 Replies

6. Shell Programming and Scripting

configure bash completion for multiple possibilities

Hello, Bash completion is great, but there are some features I'd like to change. One thing is the behaviour when there are lots of very similar possibilities. E.g., my directory contains 133 files, from pubmed_result1.txt to pubmed_result133.txt $ ls Lyonprim/p Display all 133... (2 Replies)
Discussion started by: jossojjos
2 Replies

7. Shell Programming and Scripting

bash completion

hello, I have been trying for a couple days to figure this out to no avail. I am converting some csh code to bash. I have converted everything except the completion code. #bashrc (I set this alias in my bashrc) alias test='source ${PATH}/test.sh' #${PATH}/test.sh (returns some aliases and... (0 Replies)
Discussion started by: platypuus
0 Replies

8. Ubuntu

set completion-ignore-case on doesn't work in bash

completion-ignore-case option doesn't work in my version: /home/user $ echo $BASH_VERSION 3.2.48(1)-release /home/user $ ls -l * -rw-r--r-- 1 user user 0 2009-10-18 00:09 somefile -rw-r--r-- 1 user user 0 2009-10-18 00:09 Somefile /home/user $ set completion-ignore-case on But when I... (2 Replies)
Discussion started by: Sapfeer
2 Replies

9. Shell Programming and Scripting

[tcsh2bash] Tab completion - 'enhanced' equivalent in bash?

I really like tcsh's: set completion='enhanced' because it treats underscores and dash signs the same. I don't have to reach for the shift key when trying to complete files that have underscores. As far as I know, there is nothing like this in bash. Does such a thing exist in bash? If... (2 Replies)
Discussion started by: sarnobat
2 Replies
Login or Register to Ask a Question