aboutsummaryrefslogtreecommitdiff
path: root/bash/bash_completion.d
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2016-07-30 01:17:09 +1200
committerTom Ryder <tom@sanctum.geek.nz>2016-07-30 02:09:30 +1200
commit4cbbd121c012b3962f12fdff0f1820c3b8636a44 (patch)
tree00149270df365ed0b7a1b9e9f4922fe7d5a80eb3 /bash/bash_completion.d
parentChange ca from Bash func to sh script (diff)
downloaddotfiles-4cbbd121c012b3962f12fdff0f1820c3b8636a44.tar.gz
dotfiles-4cbbd121c012b3962f12fdff0f1820c3b8636a44.zip
Move bash completion setup into separate dir
Diffstat (limited to 'bash/bash_completion.d')
-rw-r--r--bash/bash_completion.d/bash.bash38
-rw-r--r--bash/bash_completion.d/bd.bash22
-rw-r--r--bash/bash_completion.d/ftp.bash33
-rw-r--r--bash/bash_completion.d/git.bash27
-rw-r--r--bash/bash_completion.d/gpg.bash17
-rw-r--r--bash/bash_completion.d/keep.bash2
-rw-r--r--bash/bash_completion.d/make.bash44
-rw-r--r--bash/bash_completion.d/man.bash63
-rw-r--r--bash/bash_completion.d/mkcd.bash1
-rw-r--r--bash/bash_completion.d/mysql.bash34
-rw-r--r--bash/bash_completion.d/pass.bash39
-rw-r--r--bash/bash_completion.d/path.bash60
-rw-r--r--bash/bash_completion.d/prompt.bash2
-rw-r--r--bash/bash_completion.d/sd.bash39
-rw-r--r--bash/bash_completion.d/ssh.bash22
-rw-r--r--bash/bash_completion.d/td.bash18
-rw-r--r--bash/bash_completion.d/ud.bash28
-rw-r--r--bash/bash_completion.d/vared.bash1
-rw-r--r--bash/bash_completion.d/vis.bash22
-rw-r--r--bash/bash_completion.d/vr.bash1
20 files changed, 513 insertions, 0 deletions
diff --git a/bash/bash_completion.d/bash.bash b/bash/bash_completion.d/bash.bash
new file mode 100644
index 00000000..5d944b9b
--- /dev/null
+++ b/bash/bash_completion.d/bash.bash
@@ -0,0 +1,38 @@
+# Various easy completions
+
+# Bash builtins
+complete -A builtin builtin
+
+# Bash options
+complete -A setopt set
+
+# Commands
+complete -A command command complete coproc exec hash type
+
+# Directories
+complete -A directory cd pushd mkdir rmdir
+
+# Functions
+complete -A function function
+
+# Help topics
+complete -A helptopic help
+
+# Jobspecs
+complete -A job disown fg jobs
+complete -A stopped bg
+
+# Readline bindings
+complete -A binding bind
+
+# Shell options
+complete -A shopt shopt
+
+# Signal names
+complete -A signal trap
+
+# Variables
+complete -A variable declare export readonly typeset
+
+# Both functions and variables
+complete -A function -A variable unset
diff --git a/bash/bash_completion.d/bd.bash b/bash/bash_completion.d/bd.bash
new file mode 100644
index 00000000..68589dff
--- /dev/null
+++ b/bash/bash_completion.d/bd.bash
@@ -0,0 +1,22 @@
+# Completion setup for bd
+_bd() {
+
+ # Only makes sense for the first argument
+ ((COMP_CWORD == 1)) || return 1
+
+ # Build a list of dirnames in $PWD
+ local -a dirnames
+ IFS=/ read -d '' -a dirnames < <(printf '%s\0' "${PWD#/}")
+
+ # Remove the last element in the array (the current directory)
+ ((${#dirnames[@]})) || return 1
+ dirnames=("${dirnames[@]:0:"$((${#dirnames[@]}-1))"}")
+
+ # Add the matching dirnames to the reply
+ local dirname
+ for dirname in "${dirnames[@]}" ; do
+ [[ $dirname == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue
+ COMPREPLY=("${COMPREPLY[@]}" "$(printf %q "$dirname")")
+ done
+}
+complete -F _bd bd
diff --git a/bash/bash_completion.d/ftp.bash b/bash/bash_completion.d/ftp.bash
new file mode 100644
index 00000000..5770f137
--- /dev/null
+++ b/bash/bash_completion.d/ftp.bash
@@ -0,0 +1,33 @@
+# Completion for ftp with .netrc machines
+_ftp() {
+
+ # Bail if the .netrc file is illegible
+ local netrc
+ netrc=$HOME/.netrc
+ [[ -r $netrc ]] || return 1
+
+ # Tokenize the file
+ local -a tokens
+ read -a tokens -d '' -r < "$netrc"
+
+ # Iterate through tokens and collect machine names
+ local -a machines
+ local -i nxm
+ local token
+ for token in "${tokens[@]}" ; do
+ if ((nxm)) ; then
+ machines[${#machines[@]}]=$token
+ nxm=0
+ elif [[ $token == machine ]] ; then
+ nxm=1
+ fi
+ done
+
+ # Generate completion reply
+ local machine
+ for machine in "${machines[@]}" ; do
+ [[ $machine == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue
+ COMPREPLY[${#COMPREPLY[@]}]=$machine
+ done
+}
+complete -F _ftp -o default ftp
diff --git a/bash/bash_completion.d/git.bash b/bash/bash_completion.d/git.bash
new file mode 100644
index 00000000..496712ae
--- /dev/null
+++ b/bash/bash_completion.d/git.bash
@@ -0,0 +1,27 @@
+# Completion for git local branch names
+_git() {
+
+ # Bail if not a git repo (or no git!)
+ git rev-parse --git-dir >/dev/null 2>&1 || return 1
+
+ # Switch on the previous word
+ case ${COMP_WORDS[1]} in
+
+ # If the first word is appropriate, complete with branch/tag names
+ checkout|merge|rebase)
+ local branch
+ while read -r _ _ branch ; do
+ branch=${branch##*/}
+ [[ $branch == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue
+ COMPREPLY[${#COMPREPLY[@]}]=$branch
+ done < <(git for-each-ref refs/heads refs/tags 2>/dev/null)
+ return
+ ;;
+
+ # Bail if it isn't
+ *)
+ return 1
+ ;;
+ esac
+}
+complete -F _git -o default git
diff --git a/bash/bash_completion.d/gpg.bash b/bash/bash_completion.d/gpg.bash
new file mode 100644
index 00000000..c2f08415
--- /dev/null
+++ b/bash/bash_completion.d/gpg.bash
@@ -0,0 +1,17 @@
+# Completion for gpg with long options
+_gpg() {
+
+ # Bail if no gpg(1)
+ hash gpg 2>/dev/null || return 1
+
+ # Bail if not completing an option
+ [[ ${COMP_WORDS[COMP_CWORD]} == --* ]] || return 1
+
+ # Generate completion reply from gpg(1) options
+ local option
+ while read -r option ; do
+ [[ $option == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue
+ COMPREPLY[${#COMPREPLY[@]}]=$option
+ done < <(gpg --dump-options 2>/dev/null)
+}
+complete -F _gpg -o default gpg
diff --git a/bash/bash_completion.d/keep.bash b/bash/bash_completion.d/keep.bash
new file mode 100644
index 00000000..bfe5dd2f
--- /dev/null
+++ b/bash/bash_completion.d/keep.bash
@@ -0,0 +1,2 @@
+# Complete calls to keep with existing function names and variable names
+complete -A function -A variable keep
diff --git a/bash/bash_completion.d/make.bash b/bash/bash_completion.d/make.bash
new file mode 100644
index 00000000..ca209e8e
--- /dev/null
+++ b/bash/bash_completion.d/make.bash
@@ -0,0 +1,44 @@
+# Completion setup for Make, completing targets
+_make() {
+
+ # Bail if no legible Makefile
+ [[ -r Makefile ]] || return 1
+
+ # Iterate through the Makefile, line by line
+ while IFS= read -r line ; do
+ case $line in
+
+ # We're looking for targets but not variable assignments
+ $'\t'*) ;;
+ *:=*) ;;
+ *:*)
+
+ # Break the target up with space delimiters
+ local -a targets
+ IFS=' ' read -a targets -d '' < \
+ <(printf '%s\0' "${line%%:*}")
+
+ # Iterate through the targets and add suitable ones
+ local target
+ for target in "${targets[@]}" ; do
+ case $target in
+
+ # Don't complete special targets beginning with a
+ # period
+ .*) ;;
+
+ # Don't complete targets with names that have
+ # characters outside of the POSIX spec (plus slashes)
+ *[^[:word:]./-]*) ;;
+
+ # Add targets that match what we're completing
+ ${COMP_WORDS[COMP_CWORD]}*)
+ COMPREPLY[${#COMPREPLY[@]}]=$target
+ ;;
+ esac
+ done
+ ;;
+ esac
+ done < Makefile
+}
+complete -F _make -o default make
diff --git a/bash/bash_completion.d/man.bash b/bash/bash_completion.d/man.bash
new file mode 100644
index 00000000..f1762a01
--- /dev/null
+++ b/bash/bash_completion.d/man.bash
@@ -0,0 +1,63 @@
+# Autocompletion for man(1)
+_man() {
+
+ # Don't even bother if we don't have manpath(1)
+ hash manpath || return 1
+
+ # Snarf the word
+ local word
+ word=${COMP_WORDS[COMP_CWORD]}
+
+ # If this is the second word, and the previous word started with a number,
+ # we'll assume that's the section to search
+ local section subdir
+ if ((COMP_CWORD > 1)) && [[ ${COMP_WORDS[COMP_CWORD-1]} == [0-9]* ]] ; then
+ section=${COMP_WORDS[COMP_CWORD-1]}
+ subdir=man${section%%[^0-9]*}
+ fi
+
+ # Read completion results from a subshell and add them to the COMPREPLY
+ # array individually
+ while IFS= read -rd '' page ; do
+ COMPREPLY[${#COMPREPLY[@]}]=$page
+ done < <(
+
+ # Do not return dotfiles, give us extended globbing, and expand empty
+ # globs to just nothing
+ shopt -u dotglob
+ shopt -s extglob nullglob
+
+ # Start an array of pages
+ declare -a pages
+
+ # Break manpath(1) output into an array of paths
+ IFS=: read -a manpaths -r < <(manpath 2>/dev/null)
+
+ # Iterate through the manual page paths and add every manual page we find
+ for manpath in "${manpaths[@]}" ; do
+ [[ $manpath ]] || continue
+ if [[ $section ]] ; then
+ for page in "$manpath"/"$subdir"/"$word"*."$section"?(.[glx]z|.bz2|.lzma|.Z) ; do
+ pages[${#pages[@]}]=$page
+ done
+ else
+ for page in "$manpath"/man[0-9]*/"$word"*.* ; do
+ pages[${#pages[@]}]=$page
+ done
+ fi
+ done
+
+ # Strip paths, .gz suffixes, and finally .<section> suffixes
+ pages=("${pages[@]##*/}")
+ pages=("${pages[@]%.@([glx]z|bz2|lzma|Z)}")
+ pages=("${pages[@]%.[0-9]*}")
+
+ # Bail out if we ended up with no pages somehow to prevent us from
+ # printing
+ ((${#pages[@]})) || exit 1
+
+ # Print the pages array to stdout, quoted and null-delimited
+ printf '%q\0' "${pages[@]}"
+ )
+}
+complete -F _man -o default man
diff --git a/bash/bash_completion.d/mkcd.bash b/bash/bash_completion.d/mkcd.bash
new file mode 100644
index 00000000..0db967d8
--- /dev/null
+++ b/bash/bash_completion.d/mkcd.bash
@@ -0,0 +1 @@
+complete -A directory mkcd
diff --git a/bash/bash_completion.d/mysql.bash b/bash/bash_completion.d/mysql.bash
new file mode 100644
index 00000000..f64b6f32
--- /dev/null
+++ b/bash/bash_completion.d/mysql.bash
@@ -0,0 +1,34 @@
+# Completion setup for MySQL for configured databases
+_mysql() {
+
+ # Only makes sense for first argument
+ ((COMP_CWORD == 1)) || return 1
+
+ # Bail if directory doesn't exist
+ local dirname
+ dirname=$HOME/.mysql
+ [[ -d $dirname ]] || return 1
+
+ # Return the names of the .cnf files sans prefix as completions
+ local db
+ while IFS= read -rd '' db ; do
+ COMPREPLY[${#COMPREPLY[@]}]=$db
+ done < <(
+
+ # Set options so that globs expand correctly
+ shopt -s dotglob nullglob
+
+ # Collect all the config file names, strip off leading path and .cnf
+ local -a cnfs
+ cnfs=("$dirname"/"${COMP_WORDS[COMP_CWORD]}"*.cnf)
+ cnfs=("${cnfs[@]#"$dirname"/}")
+ cnfs=("${cnfs[@]%.cnf}")
+
+ # Bail if no files to prevent empty output
+ ((${#cnfs[@]})) || exit 1
+
+ # Print the conf names, null-delimited
+ printf '%q\0' "${cnfs[@]}"
+ )
+}
+complete -F _mysql -o default mysql
diff --git a/bash/bash_completion.d/pass.bash b/bash/bash_completion.d/pass.bash
new file mode 100644
index 00000000..28941952
--- /dev/null
+++ b/bash/bash_completion.d/pass.bash
@@ -0,0 +1,39 @@
+# Requires Bash >= 4.0 for globstar
+((BASH_VERSINFO[0] >= 4)) || return
+
+# Custom completion for pass(1), because I don't like the one included with the
+# distribution
+_pass()
+{
+ # If we can't read the password directory, just bail
+ local passdir
+ passdir=${PASSWORD_STORE_DIR:-"$HOME"/.password-store}
+ [[ -r $passdir ]] || return 1
+
+ # Iterate through list of .gpg paths, extension stripped, null-delimited,
+ # and filter them down to the ones matching the completing word (compgen
+ # doesn't seem to do this properly with a null delimiter)
+ local entry
+ while IFS= read -rd '' entry ; do
+ COMPREPLY[${#COMPREPLY[@]}]=$entry
+ done < <(
+
+ # Set shell options to expand globs the way we expect
+ shopt -u dotglob
+ shopt -s globstar nullglob
+
+ # Gather the entries and remove their .gpg suffix
+ declare -a entries
+ entries=("$passdir"/"${COMP_WORDS[COMP_CWORD]}"*/**/*.gpg \
+ "$passdir"/"${COMP_WORDS[COMP_CWORD]}"*.gpg)
+ entries=("${entries[@]#"$passdir"/}")
+ entries=("${entries[@]%.gpg}")
+
+ # Bail if no entries to prevent empty output
+ ((${#entries[@]})) || exit 1
+
+ # Print all the entries, null-delimited
+ printf '%q\0' "${entries[@]}"
+ )
+}
+complete -F _pass pass
diff --git a/bash/bash_completion.d/path.bash b/bash/bash_completion.d/path.bash
new file mode 100644
index 00000000..fd94b7c4
--- /dev/null
+++ b/bash/bash_completion.d/path.bash
@@ -0,0 +1,60 @@
+# Completion for path
+_path() {
+
+ # What to do depends on which word we're completing
+ if ((COMP_CWORD == 1)) ; then
+
+ # Complete operation as first word
+ local cmd
+ for cmd in help list insert append remove set check ; do
+ [[ $cmd == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue
+ COMPREPLY[${#COMPREPLY[@]}]=$cmd
+ done
+
+ # Complete with either directories or $PATH entries as all other words
+ else
+ case ${COMP_WORDS[1]} in
+
+ # Complete with a directory
+ insert|i|append|add|a|check|c|set|s)
+ local dirname
+ while IFS= read -rd '' dirname ; do
+ COMPREPLY[${#COMPREPLY[@]}]=$dirname
+ done < <(
+
+ # Set options to glob correctly
+ shopt -s dotglob nullglob
+
+ # Collect directory names, strip trailing slash
+ local -a dirnames
+ dirnames=("${COMP_WORDS[COMP_CWORD]}"*/)
+ dirnames=("${dirnames[@]%/}")
+
+ # Bail if no results to prevent empty output
+ ((${#dirnames[@]})) || exit 1
+
+ # Print results, quoted and null-delimited
+ printf '%q\0' "${dirnames[@]}"
+ )
+ ;;
+
+ # Complete with directories from PATH
+ remove|rm|r)
+ local -a promptarr
+ IFS=: read -d '' -a promptarr < <(printf '%s\0' "$PATH")
+ local part
+ for part in "${promptarr[@]}" ; do
+ [[ $part == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue
+ COMPREPLY[${#COMPREPLY[@]}]=$(printf '%q\0' "$part")
+ done
+ ;;
+
+ # No completion
+ *)
+ return 1
+ ;;
+ esac
+ fi
+}
+
+complete -F _path path
diff --git a/bash/bash_completion.d/prompt.bash b/bash/bash_completion.d/prompt.bash
new file mode 100644
index 00000000..b114b7bb
--- /dev/null
+++ b/bash/bash_completion.d/prompt.bash
@@ -0,0 +1,2 @@
+# Complete words
+complete -W 'on off git hg svn vcs ret job' prompt
diff --git a/bash/bash_completion.d/sd.bash b/bash/bash_completion.d/sd.bash
new file mode 100644
index 00000000..f8017591
--- /dev/null
+++ b/bash/bash_completion.d/sd.bash
@@ -0,0 +1,39 @@
+# Completion function for sd; any sibling directories, excluding the self
+_sd() {
+
+ # Only makes sense for the first argument
+ ((COMP_CWORD == 1)) || return 1
+
+ # Current directory can't be root directory
+ [[ $PWD != / ]] || return 1
+
+ # Build list of matching sibiling directories
+ while IFS= read -rd '' dirname ; do
+ COMPREPLY[${#COMPREPLY[@]}]=$dirname
+ done < <(
+
+ # Set options to glob correctly
+ shopt -s dotglob nullglob
+
+ # Collect directory names, strip leading ../ and trailing /
+ local -a dirnames
+ dirnames=(../"${COMP_WORDS[COMP_CWORD]}"*/)
+ dirnames=("${dirnames[@]#../}")
+ dirnames=("${dirnames[@]%/}")
+
+ # Iterate again, but exclude the current directory this time
+ local -a sibs
+ local dirname
+ for dirname in "${dirnames[@]}" ; do
+ [[ $dirname != "${PWD##*/}" ]] || continue
+ sibs[${#sibs[@]}]=$dirname
+ done
+
+ # Bail if no results to prevent empty output
+ ((${#sibs[@]})) || exit 1
+
+ # Print results, null-delimited
+ printf '%q\0' "${sibs[@]}"
+ )
+}
+complete -F _sd sd
diff --git a/bash/bash_completion.d/ssh.bash b/bash/bash_completion.d/ssh.bash
new file mode 100644
index 00000000..bbb9b246
--- /dev/null
+++ b/bash/bash_completion.d/ssh.bash
@@ -0,0 +1,22 @@
+# Completion for ssh/sftp/ssh-copy-id with config hostnames
+_ssh() {
+
+ # Read hostnames from existent config files, no asterisks
+ local -a hosts
+ local config option value
+ for config in "$HOME"/.ssh/config /etc/ssh/ssh_config ; do
+ [[ -e $config ]] || continue
+ while read -r option value _ ; do
+ [[ $option == Host ]] || continue
+ [[ $value != *'*'* ]] || continue
+ hosts[${#hosts[@]}]=$value
+ done < "$config"
+ done
+
+ # Generate completion reply
+ for host in "${hosts[@]}" ; do
+ [[ $host == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue
+ COMPREPLY[${#COMPREPLY[@]}]=$host
+ done
+}
+complete -F _ssh -o default ssh sftp ssh-copy-id
diff --git a/bash/bash_completion.d/td.bash b/bash/bash_completion.d/td.bash
new file mode 100644
index 00000000..ffb9c973
--- /dev/null
+++ b/bash/bash_completion.d/td.bash
@@ -0,0 +1,18 @@
+# Complete filenames for td(1)
+_td() {
+ local dir
+ dir=${TODO_DIR:-"$HOME"/Todo}
+ while IFS= read -rd '' fn ; do
+ COMPREPLY[${#COMPREPLY[@]}]=$fn
+ done < <(
+ shopt -s extglob nullglob
+ shopt -u dotglob
+ local -a fns
+ fns=("$dir"/"${COMP_WORDS[COMP_CWORD]}"*)
+ fns=("${fns[@]#"$dir"/}")
+ ((${#fns[@]})) || exit 1
+ printf '%s\0' "${fns[@]##"$dir"/}"
+ )
+ return
+}
+complete -F _td td
diff --git a/bash/bash_completion.d/ud.bash b/bash/bash_completion.d/ud.bash
new file mode 100644
index 00000000..47171b78
--- /dev/null
+++ b/bash/bash_completion.d/ud.bash
@@ -0,0 +1,28 @@
+# Completion setup for ud
+_ud() {
+
+ # Only makes sense for the second argument
+ ((COMP_CWORD == 2)) || return 1
+
+ # Iterate through directories, null-separated, add them to completions
+ local dirname
+ while IFS= read -rd '' dirname ; do
+ COMPREPLY[${#COMPREPLY[@]}]=$dirname
+ done < <(
+
+ # Set options to glob correctly
+ shopt -s dotglob nullglob
+
+ # Collect directory names, strip trailing slashes
+ local -a dirnames
+ dirnames=("${COMP_WORDS[COMP_CWORD]}"*/)
+ dirnames=("${dirnames[@]%/}")
+
+ # Bail if no results to prevent empty output
+ ((${#dirnames[@]})) || exit 1
+
+ # Print results null-delimited
+ printf '%s\0' "${dirnames[@]}"
+ )
+}
+complete -F _ud -o filenames ud
diff --git a/bash/bash_completion.d/vared.bash b/bash/bash_completion.d/vared.bash
new file mode 100644
index 00000000..ea8cefd1
--- /dev/null
+++ b/bash/bash_completion.d/vared.bash
@@ -0,0 +1 @@
+complete -A variable vared
diff --git a/bash/bash_completion.d/vis.bash b/bash/bash_completion.d/vis.bash
new file mode 100644
index 00000000..f84cb702
--- /dev/null
+++ b/bash/bash_completion.d/vis.bash
@@ -0,0 +1,22 @@
+# Complete args to vis(1) with existing executables in $VISPATH, defaulting to
+# ~/.local/bin
+_vis() {
+ local vispath
+ vispath=${VISPATH:-"$HOME"/.local/bin}
+ [[ -d $vispath ]] || return
+ while IFS= read -rd '' executable ; do
+ COMPREPLY[${#COMPREPLY[@]}]=$executable
+ done < <(
+ shopt -s dotglob nullglob
+ declare -a files
+ files=("${VISPATH:-"$HOME"/.local/bin}"/"${COMP_WORDS[COMP_CWORD]}"*)
+ declare -a executables
+ for file in "${files[@]}" ; do
+ [[ -f $file && -x $file ]] || continue
+ executables[${#executables[@]}]=${file##*/}
+ done
+ ((${#executables[@]})) || exit 1
+ printf '%q\0' "${executables[@]}"
+ )
+}
+complete -F _vis vis
diff --git a/bash/bash_completion.d/vr.bash b/bash/bash_completion.d/vr.bash
new file mode 100644
index 00000000..2d5120f0
--- /dev/null
+++ b/bash/bash_completion.d/vr.bash
@@ -0,0 +1 @@
+complete -A directory vr