From 06f5ca98018fd4ba357b0e70b1e710b682b6cdb5 Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Mon, 14 Dec 2015 17:48:52 +1300 Subject: Switch to a faster method of array appending Does away with the nasty hack around man page discovery, and still compatible with Bash 2.05a --- bash/bashrc.d/apf.bash | 2 +- bash/bashrc.d/bd.bash | 2 +- bash/bashrc.d/cd.bash | 2 +- bash/bashrc.d/ftp.bash | 4 ++-- bash/bashrc.d/git.bash | 2 +- bash/bashrc.d/gpg.bash | 2 +- bash/bashrc.d/grep.bash | 8 ++++---- bash/bashrc.d/ls.bash | 2 +- bash/bashrc.d/make.bash | 15 ++++++++------- bash/bashrc.d/man.bash | 16 ++++++++++------ bash/bashrc.d/mysql.bash | 2 +- bash/bashrc.d/pass.bash | 2 +- bash/bashrc.d/path.bash | 22 +++++++++------------- bash/bashrc.d/pd.bash | 2 +- bash/bashrc.d/prompt.bash | 16 ++++++++-------- bash/bashrc.d/sd.bash | 6 +++--- bash/bashrc.d/ssh.bash | 4 ++-- bash/bashrc.d/ud.bash | 4 ++-- bash/bashrc.d/vis.bash | 4 ++-- 19 files changed, 59 insertions(+), 58 deletions(-) (limited to 'bash') diff --git a/bash/bashrc.d/apf.bash b/bash/bashrc.d/apf.bash index 01b38437..a9cd115e 100644 --- a/bash/bashrc.d/apf.bash +++ b/bash/bashrc.d/apf.bash @@ -86,7 +86,7 @@ apf() { local -a args local arg while IFS= read -d '' -r arg ; do - args=("${args[@]}" "$arg") + args[${#args[@]}]=$arg done < "$argfile" # Next argument is the command to run diff --git a/bash/bashrc.d/bd.bash b/bash/bashrc.d/bd.bash index bc474901..20274f56 100644 --- a/bash/bashrc.d/bd.bash +++ b/bash/bashrc.d/bd.bash @@ -12,7 +12,7 @@ bd() { ;; -*) shift - opts=("${opts[@]}" "$arg") + opts[${#opts[@]}]=$arg ;; *) break diff --git a/bash/bashrc.d/cd.bash b/bash/bashrc.d/cd.bash index 73c75202..9ccfce57 100644 --- a/bash/bashrc.d/cd.bash +++ b/bash/bashrc.d/cd.bash @@ -11,7 +11,7 @@ cd() { ;; -*) shift - opts=("${opts[@]}" "$arg") + opts[${#opts[@]}]=$arg ;; *) break diff --git a/bash/bashrc.d/ftp.bash b/bash/bashrc.d/ftp.bash index 218afc2c..4b4b63eb 100644 --- a/bash/bashrc.d/ftp.bash +++ b/bash/bashrc.d/ftp.bash @@ -16,7 +16,7 @@ _ftp() { local token for token in "${tokens[@]}" ; do if ((nxm)) ; then - machines=("${machines[@]}" "$token") + machines[${#machines[@]}]=$token nxm=0 elif [[ $token == machine ]] ; then nxm=1 @@ -27,7 +27,7 @@ _ftp() { local machine for machine in "${machines[@]}" ; do [[ $machine == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue - COMPREPLY=("${COMPREPLY[@]}" "$machine") + COMPREPLY[${#COMPREPLY[@]}]=$machine done } complete -F _ftp -o default ftp diff --git a/bash/bashrc.d/git.bash b/bash/bashrc.d/git.bash index 8c6fa466..7ac0524d 100644 --- a/bash/bashrc.d/git.bash +++ b/bash/bashrc.d/git.bash @@ -13,7 +13,7 @@ _git() { while read -r _ _ branch ; do branch=${branch##*/} [[ $branch == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue - COMPREPLY=("${COMPREPLY[@]}" "$branch") + COMPREPLY[${#COMPREPLY[@]}]=$branch done < <(git for-each-ref refs/heads refs/tags 2>/dev/null) return ;; diff --git a/bash/bashrc.d/gpg.bash b/bash/bashrc.d/gpg.bash index cea4a7cb..c2340520 100644 --- a/bash/bashrc.d/gpg.bash +++ b/bash/bashrc.d/gpg.bash @@ -25,7 +25,7 @@ _gpg() { local option while read -r option ; do [[ $option == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue - COMPREPLY=("${COMPREPLY[@]}" "$option") + COMPREPLY[${#COMPREPLY[@]}]=$option done < <(gpg --dump-options 2>/dev/null) } complete -F _gpg -o default gpg diff --git a/bash/bashrc.d/grep.bash b/bash/bashrc.d/grep.bash index 3f8e44e0..6a567e5a 100644 --- a/bash/bashrc.d/grep.bash +++ b/bash/bashrc.d/grep.bash @@ -12,16 +12,16 @@ grep_help=$(grep --help 2>/dev/null) # to change grep(1)'s actual behaviour inside scripts declare -a GREPOPTS if [[ -n $GREP_COLORS ]] && ((colors >= 8)) ; then - GREPOPTS=("${GREPOPTS[@]}" --color=auto) + GREPOPTS[${#GREPOPTS[@]}]='--color=auto' fi if [[ $grep_help == *--binary-files* ]] ; then - GREPOPTS=("${GREPOPTS[@]}" --binary-files=without-match) + GREPOPTS[${#GREPOPTS[@]}]='--binary-files=without-match' fi if [[ $grep_help == *--exclude* ]] ; then - GREPOPTS=("${GREPOPTS[@]}" --exclude={.gitignore,.gitmodules}) + GREPOPTS[${#GREPOPTS[@]}]='--exclude={.gitignore,.gitmodules}' fi if [[ $grep_help == *--exclude-dir* ]] ; then - GREPOPTS=("${GREPOPTS[@]}" --exclude-dir={.cvs,.git,.hg,.svn}) + GREPOPTS[${#GREPOPTS[@]}]='--exclude-dir={.cvs,.git,.hg,.svn}' fi # Done, unset helper vars diff --git a/bash/bashrc.d/ls.bash b/bash/bashrc.d/ls.bash index 0fd246fe..cd23bbe9 100644 --- a/bash/bashrc.d/ls.bash +++ b/bash/bashrc.d/ls.bash @@ -8,7 +8,7 @@ colors=$( { # function wrapper to do this declare -a LSOPTS if [[ -n $LS_COLORS ]] && ((colors >= 8)) ; then - LSOPTS=("${LSOPTS[@]}" --color=auto) + LSOPTS[${#LSOPTS[@]}]='--color=auto' fi # Done, unset helper var diff --git a/bash/bashrc.d/make.bash b/bash/bashrc.d/make.bash index ea0ccf1d..f4d0f5fd 100644 --- a/bash/bashrc.d/make.bash +++ b/bash/bashrc.d/make.bash @@ -6,24 +6,25 @@ _make() { # Build a list of targets by parsing the Makefile local -a targets tokens - local target line + local line target token while read -r line ; do if [[ $line == *:* ]] ; then target=$line target=${target%%:*} target=${target% } - if [[ $target != *[^[:alnum:][:space:]_-]* ]] ; then - IFS=' ' read -a tokens \ - < <(printf '%s\n' "$target") - targets=("${targets[@]}" "${tokens[@]}") - fi + [[ $target != *[^[:alnum:][:space:]_-]* ]] || continue + IFS=' ' read -a tokens \ + < <(printf '%s\n' "$target") + for token in "${tokens[@]}" ; do + targets[${#targets[@]}]=$token + done fi done < Makefile # Complete with matching targets for target in "${targets[@]}" ; do [[ $target == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue - COMPREPLY=("${COMPREPLY[@]}" "$target") + COMPREPLY[${#COMPREPLY[@]}]=$target done } complete -F _make -o default make diff --git a/bash/bashrc.d/man.bash b/bash/bashrc.d/man.bash index d982a166..be3dc830 100644 --- a/bash/bashrc.d/man.bash +++ b/bash/bashrc.d/man.bash @@ -15,9 +15,11 @@ _man() { section='man'${COMP_WORDS[COMP_CWORD-1]} fi - # Read slash-separated output from a subshell into the COMPREPLY array; use - # read -a rather than adding each element individually, as it's much faster - IFS=/ read -a COMPREPLY -d '' -r < <( + # Read completion results from a subshell and add them to the COMPREPLY + # array individually + while IFS= read -d '' -r page ; do + COMPREPLY[${#COMPREPLY[@]}]=$page + done < <( # Do not return dotfiles, give us extended globbing, and expand empty # globs to just nothing @@ -33,7 +35,9 @@ _man() { # Iterate through the manual page paths and add every manual page we find for manpath in "${manpaths[@]}" ; do [[ $manpath ]] || continue - pages=("${pages[@]}" "$manpath"/"$section"*/"$word"*.[0-9]*) + for page in "$manpath"/"$section"*/"$word"*.[0-9]* ; do + pages[${#pages[@]}]=$page + done done # Strip paths, .gz suffixes, and finally .
suffixes @@ -45,8 +49,8 @@ _man() { # printing ((${#pages[@]})) || exit 1 - # Print the pages array to stdout, slash-separated, null-terminated - (IFS=/ ; printf '%q\0' "${pages[*]}") + # Print the pages array to stdout, quoted and null-delimited + printf '%q\0' "${pages[@]}" ) } complete -F _man -o default man diff --git a/bash/bashrc.d/mysql.bash b/bash/bashrc.d/mysql.bash index 9efe3795..e967e3b0 100644 --- a/bash/bashrc.d/mysql.bash +++ b/bash/bashrc.d/mysql.bash @@ -35,7 +35,7 @@ _mysql() { # Return the names of the .cnf files sans prefix as completions local db while IFS= read -d '' -r db ; do - COMPREPLY=("${COMPREPLY[@]}" "$db") + COMPREPLY[${#COMPREPLY[@]}]=$db done < <( # Set options so that globs expand correctly diff --git a/bash/bashrc.d/pass.bash b/bash/bashrc.d/pass.bash index 348978ca..cc323086 100644 --- a/bash/bashrc.d/pass.bash +++ b/bash/bashrc.d/pass.bash @@ -15,7 +15,7 @@ _pass() # doesn't seem to do this properly with a null delimiter) local entry while IFS= read -d '' -r entry ; do - COMPREPLY=("${COMPREPLY[@]}" "$entry") + COMPREPLY[${#COMPREPLY[@]}]=$entry done < <( # Set shell options to expand globs the way we expect diff --git a/bash/bashrc.d/path.bash b/bash/bashrc.d/path.bash index 4122b03d..94c6207c 100644 --- a/bash/bashrc.d/path.bash +++ b/bash/bashrc.d/path.bash @@ -106,7 +106,7 @@ EOF "$FUNCNAME" "$dirname" >&2 return 1 fi - patharr=("${patharr[@]}" "$dirname") + patharr[${#patharr[@]}]=$dirname path set "${patharr[@]}" ;; @@ -131,7 +131,7 @@ EOF local part for part in "${patharr[@]}" ; do [[ $dirname == "$part" ]] && continue - newpatharr=("${newpatharr[@]}" "$part") + newpatharr[${#newpatharr[@]}]=$part done path set "${newpatharr[@]}" ;; @@ -141,7 +141,7 @@ EOF local -a newpatharr local dirname for dirname ; do - newpatharr=("${newpatharr[@]}" "$dirname") + newpatharr[${#newpatharr[@]}]=$dirname done PATH=$(IFS=: ; printf '%s' "${newpatharr[*]}") ;; @@ -187,7 +187,7 @@ _path() { 1) for cmd in help list insert append remove set check ; do [[ $cmd == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue - COMPREPLY=("${COMPREPLY[@]}" "$cmd") + COMPREPLY[${#COMPREPLY[@]}]=$cmd done ;; @@ -199,7 +199,7 @@ _path() { insert|i|append|add|a|check|c|set|s) local dirname while IFS= read -d '' -r dirname ; do - COMPREPLY=("${COMPREPLY[@]}" "$dirname") + COMPREPLY[${#COMPREPLY[@]}]=$dirname done < <( # Set options to glob correctly @@ -213,8 +213,8 @@ _path() { # Bail if no results to prevent empty output ((${#dirnames[@]})) || exit 1 - # Print results, null-delimited - printf '%s\0' "${dirnames[@]}" + # Print results, quoted and null-delimited + printf '%q\0' "${dirnames[@]}" ) ;; @@ -226,7 +226,7 @@ _path() { for part in "${promptarr[@]}" ; do [[ $part == "${COMP_WORDS[COMP_CWORD]}"* ]] \ || continue - COMPREPLY=("${COMPREPLY[@]}" "$part") + COMPREPLY[${#COMPREPLY[@]}]=$(printf '%q\0' "$part") done ;; @@ -239,9 +239,5 @@ _path() { esac } -# The use of -o filenames isn't strictly correct. The first completed world -# will actually just be a simple string, the sub-command to use. However in -# practice it doesn't matter as it's a fixed set of strings that won't be -# quoted anyway. -complete -F _path -o filenames path +complete -F _path path diff --git a/bash/bashrc.d/pd.bash b/bash/bashrc.d/pd.bash index 2a157b2a..1dbf7d39 100644 --- a/bash/bashrc.d/pd.bash +++ b/bash/bashrc.d/pd.bash @@ -16,7 +16,7 @@ pd() { ;; -*) shift - opts=("${opts[@]}" "$arg") + opts[${#opts[@]}]=$arg ;; *) break diff --git a/bash/bashrc.d/prompt.bash b/bash/bashrc.d/prompt.bash index e26460a4..12d68417 100644 --- a/bash/bashrc.d/prompt.bash +++ b/bash/bashrc.d/prompt.bash @@ -122,18 +122,18 @@ prompt() { # Build state array from status output flags local -a state if ((ready)) ; then - state=("${state[@]}" '+') + state[${#state[@]}]='+' fi if ((modified)) ; then - state=("${state[@]}" '!') + state[${#state[@]}]='!' fi if ((untracked)) ; then - state=("${state[@]}" '?') + state[${#state[@]}]='?' fi # Add another indicator if we have stashed changes if git rev-parse --verify refs/stash >/dev/null 2>&1 ; then - state=("${state[@]}" '^') + state[${#state[@]}]='^' fi # Print the status in brackets with a git: prefix @@ -167,10 +167,10 @@ prompt() { # Build state array from status output flags local -a state if ((modified)) ; then - state=("${state[@]}" '!') + state[${#state[@]}]='!' fi if ((untracked)) ; then - state=("${state[@]}" '?') + state[${#state[@]}]='?' fi # Print the status in brackets with an hg: prefix @@ -225,10 +225,10 @@ prompt() { # Add appropriate state flags local -a state if ((modified)) ; then - state=("${state[@]}" '!') + state[${#state[@]}]='!' fi if ((untracked)) ; then - state=("${state[@]}" '?') + state[${#state[@]}]='?' fi # Print the state in brackets with an svn: prefix diff --git a/bash/bashrc.d/sd.bash b/bash/bashrc.d/sd.bash index 70903246..eeb61fc1 100644 --- a/bash/bashrc.d/sd.bash +++ b/bash/bashrc.d/sd.bash @@ -45,7 +45,7 @@ sd() { ;; -*) shift - opts=("${opts[@]}" "$arg") + opts[${#opts[@]}]=$arg ;; *) break @@ -119,7 +119,7 @@ _sd() { # Build list of matching sibiling directories while IFS= read -d '' -r dirname ; do - COMPREPLY=("${COMPREPLY[@]}" "$dirname") + COMPREPLY[${#COMPREPLY[@]}]=$dirname done < <( # Set options to glob correctly @@ -137,7 +137,7 @@ _sd() { local dirname for dirname in "${dirnames[@]}" ; do [[ $dirname != "${PWD##*/}" ]] || continue - sibs=("${sibs[@]}" "$dirname") + sibs[${#sibs[@]}]=$dirname done # Bail if no results to prevent empty output diff --git a/bash/bashrc.d/ssh.bash b/bash/bashrc.d/ssh.bash index 67c2828a..40327b43 100644 --- a/bash/bashrc.d/ssh.bash +++ b/bash/bashrc.d/ssh.bash @@ -9,14 +9,14 @@ _ssh() { while read -r option value _ ; do [[ $option == Host ]] || continue [[ $value != *'*'* ]] || continue - hosts=("${hosts[@]}" "$value") + hosts[${#hosts[@]}]=$value done < "$config" done # Generate completion reply for host in "${hosts[@]}" ; do [[ $host == "${COMP_WORDS[COMP_CWORD]}"* ]] || continue - COMPREPLY=("${COMPREPLY[@]}" "$host") + COMPREPLY[${#COMPREPLY[@]}]=$host done } complete -F _ssh -o default ssh sftp ssh-copy-id diff --git a/bash/bashrc.d/ud.bash b/bash/bashrc.d/ud.bash index b05539ab..75768cc3 100644 --- a/bash/bashrc.d/ud.bash +++ b/bash/bashrc.d/ud.bash @@ -13,7 +13,7 @@ ud() { ;; -*) shift - opts=("${opts[@]}" "$arg") + opts[${#opts[@]}]=$arg ;; *) break @@ -58,7 +58,7 @@ _ud() { # Iterate through directories, null-separated, add them to completions local dirname while IFS= read -d '' -r dirname ; do - COMPREPLY=("${COMPREPLY[@]}" "$dirname") + COMPREPLY[${#COMPREPLY[@]}]=$dirname done < <( # Set options to glob correctly diff --git a/bash/bashrc.d/vis.bash b/bash/bashrc.d/vis.bash index 02981afe..93b4098c 100644 --- a/bash/bashrc.d/vis.bash +++ b/bash/bashrc.d/vis.bash @@ -5,7 +5,7 @@ _vis() { vispath=${VISPATH:-$HOME/.local/bin} [[ -d $vispath ]] || return while IFS= read -d '' -r executable ; do - COMPREPLY=("${COMPREPLY[@]}" "$executable") + COMPREPLY[${#COMPREPLY[@]}]=$executable done < <( shopt -s dotglob nullglob declare -a files @@ -13,7 +13,7 @@ _vis() { declare -a executables for file in "${files[@]}" ; do [[ -f $file && -x $file ]] || continue - executables=("${executables[@]}" "${file##*/}") + executables[${#executables[@]}]=${file##*/} done ((${#executables[@]})) || exit 1 printf '%q\0' "${executables[@]}" -- cgit v1.2.3