customize bash autocompletion - bash

How to customize bash autocomplete to list the files in another directory for only one script option (-seq), for other script options (-speed, -define) default autocomplete is O.K. this is what I have
export files=`ls /home/tests/`
echo $files #debug
_xtest () { .
local cur
COMPREPLY=() cur=${COMP_WORDS[COMP_CWORD]}
#case "$cur" in
COMPREPLY=( $(compgen -W "${files}" -- ${cur}) )
# esac
return 0
}
complete -F _xtest -o filenames xtest
When I try to run from shell I get the below message before the list of files
> xtest -seq [TAB][TAB]
bash: .: filename argument required
.: usage: . filename [arguments]
Is there a way not to receive this message before the file list ?
How to enable default bash completion for other options ?

should use $prev instead of $cur :
_xtest () {
local prev
COMPREPLY=()
prev=${COMP_WORDS[COMP_CWORD-1]}
case "$prev" in
-seq )
COMPREPLY=( $(compgen -W "${files}" -- ${cur}) ) ;;
esac
return 0
}
complete -F _xtest -o filenames xtest

Related

how to add custom completion to ls command in bash_completion?

i am trying for suggest custom options in bash completion in commands linux ( centos 7 )
i am know the this code add custom command to bash and suggest options
path : /etc/bash_completion.d/foo
_foo()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="-i(--incoming) -o(-outgoing) -m(--missed) -a(-all) "
if [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}
complete -F _foo foo
foo -[tab]
-i(--incoming) -o(-outgoing) -m(--missed) -a(-all)
goal me is extend this source code to built in commands in linux such as ls
trying me is :
path : /etc/bash_completion.d/ls
_ls()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="-a(--all) -h(--human-readable) -r(--reverse) "
if [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}
complete -F _ls ls
when this code used not suggest folders and files complete in ls command
ls -[tab]
-a(--all) -h(--human-readable) -r(--reverse)
ls[tab]
not suggest files and directory
goal me is add custom option for suggest in bash and not behaviour command

bash complete with colon

I'm trying to add auto-complete function to mytool command with following _mytool complete function:
_mytool()
{
local cur
_get_comp_words_by_ref -n : cur
# my implementation here
COMPREPLY=() # Array variable storing the possible completions.
cur=${COMP_WORDS[COMP_CWORD]}
if [[ $cur = -* ]]; then
COMPREPLY=( $(compgen -W '-a:first -a:second' -- $cur) )
fi
__ltrim_colon_completions "$cur"
}
complete -F _mytool mytool
Because there is ":" in my COMPREPLY, I try to make it work by using _get_comp_words_by_ref and __ltrim_colon_completions function, which is learnt from: here
But it still not work when type:
$mytool -a:[TAB]
there is no auto-complete at all. I was expecting bash will print the following completion for me:
-a:first -a:second
my bash version:
4.3.46(1)-release
What am I missing? Thanks!

How to make bash completion ignore certain directories?

I am trying to write a completion function that ignores file names ending with *.bak and also directories named backup. Apart from this it should work like the default Readline completion (for example the one used for the ls command). Here is my first attempt:
$ cat setup.sh
_compTest() {
local cur
FIGNORE='bak:backup'
cur="${COMP_WORDS[$COMP_CWORD]}"
compopt -o filenames
COMPREPLY=( $(compgen -f "$cur") )
}
complete -F _compTest aaa
After sourcing:
$ . setup.sh
I can type
$ aaa <tab><tab>
and I get a completion list excluding *.bak files, but unfortunately not backup directories.
How can I extend this function to exclude also backup directories from the completion list?
This can be done by post processing the array returned by compgen:
_compTest() {
local cur words
cur="${COMP_WORDS[$COMP_CWORD]}"
compopt -o filenames
words=( $(compgen -f "$cur") )
COMPREPLY=()
for val in "${words[#]}" ; do
name=$(basename "$val")
if [[ $name == *.bak || $name == "backup" ]] ; then
continue
fi
COMPREPLY+=( "$val" )
done
}

How do I enable bash tab complete from a different path?

I want to enable bash tab-complete to look for directories, but not in the current directory.
So for instance, if I do:
$ ls $P
dirs/ are/ here/
$ cd /not/the/P/path
$ ls
other/ stuff/
$ myProg <tab>
dirs/ are/ here
This changes the usual behavior, where I would normally see files in the current directory.
Due diligence: The best I could come up with is:
_myProg ()
{
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
if [ "${P}x" = "x" ]; then
return 1
fi
case "$cur" in
*)
pth=${P}/$( echo $cur | egrep -o "^.*/[^/]*$" )
COMPREPLY=( $( compgen -W "$( cd $pth && ls -1d "$cur"* 2>/dev/null -- "$cur" )" ) )
;;
esac
return 0
}
complete -o nospace -F _myProg myProg
which initially shows directories, but doesnt let me drill down into the directories how I want (like ls works).
Is $CDPATH helpful for you? See Advanced Bash Scripting Guide.
_myProg()
{
COMPREPLY=($(cd $P; compgen -f $2))
}
complete -onospace -F_myProg myProg

Conditional trailing space with bash programmable completion

I'm creating a function to provide programmable completion for a command that I use (with much help from http://www.debian-administration.org/articles/317). The shell script usage is as follows:
script.sh command [command options]
where command can be either 'foo' or 'bar' and command options for 'foo' are 'a_foo=value' and 'b_foo=value' and command options for 'bar' are 'a_bar=value' and 'b_bar=value'.
Here's the configuration I'm using:
_script() {
local cur command all_commands
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
command="${COMP_WORDS[1]}"
all_commands="foo bar"
case "${command}" in
foo)
COMPREPLY=( $(compgen -W "--a_foo --b_foo" -- ${cur}) ); return 0;;
bar)
COMPREPLY=( $(compgen -W "--a_bar --b_bar" -- ${cur}) ); return 0;;
*) ;;
esac
COMPREPLY=( $(compgen -W "${all_commands}" -- ${cur}) )
return 0
}
complete -F _script script.sh
This mostly works as I'd like:
% script.sh f[TAB]
completes to:
% script.sh foo
(with a trailing space as desired)
However, this:
% script.sh foo a[TAB]
completes to:
% script.sh foo a_foo
(also with a trailing space)
I'd like to replace the trailing space with an '='. Alternatively, I'd be willing to change the values passed to compgen to be "--a_foo= --b_foo=", in which case I could just delete the trailing space.
Unfortunately, the command is not under my control, so I can't change the command line options to be of format "--a_foo value" instead of "--a_foo=value".
First you need to add = to the COMPREPLY:
COMPREPLY=( $(compgen -W "--a_foo= --b_foo=" -- ${cur}) )
next you need to tell completion not to add space after = with
compopt -o nospace
So, you script lines should be:
foo)
COMPREPLY=( $(compgen -W "--a_foo= --b_foo=" -- ${cur}) ); compopt -o nospace; return 0;;
bar)
COMPREPLY=( $(compgen -W "--a_bar= --b_bar=" -- ${cur}) ); compopt -o nospace; return 0;;

Resources