On Wed, 8 Jun 2011 08:58:00 -0400, Dave Reisner wrote:
On Wed, Jun 08, 2011 at 01:32:36PM +0200, Andrwe wrote:
Hi,
I've improved the bash-completion of rc.d.
I created a patch for latest git
(https://github.com/seblu/arch-initscripts/tree/).
The patched version extracts all actions of an initscript and adds
them to the list of possible actions and only list initscripts
supporting the given action.
Kind regards,
Andrwe
diff --git a/bash-completion b/bash-completion
index 5151972..03ce0e6 100644
--- a/bash-completion
+++ b/bash-completion
@@ -1,22 +1,50 @@
-# rc.d bash completion by Seblu <[email protected]>
-
-_rc.d ()
+# rc.d completion
+#
+# Author: Andrwe Lord Weber
+# Mail: lord-weber-andrwe <at> andrwe <dot> org
+#
Ouch. Really? Not going to leave _any_ credit behind for the original
author?
Sorry, forgot to add credits but will definitely.
+which rc.d >/dev/null 2>&1 &&
'type -P', never which.
Thanks for this hint.
+_rc_d()
{
- local action="help list start stop reload restart"
- local cur="${COMP_WORDS[COMP_CWORD]}"
- local caction="${COMP_WORDS[1]}"
- if ((${COMP_CWORD} == 1)); then
- COMPREPLY=($(compgen -W "${action}" -- "$cur"))
- elif [[ "$caction" =~ help|list ]]; then
- COMPREPLY=()
- elif [[ "$caction" == start ]]; then
- COMPREPLY=($(comm -23 <(cd /etc/rc.d && compgen -f -X
'functions*' "$cur"|sort) <(cd /run/daemons/ && compgen -f
"$cur"|sort)))
- elif [[ "$caction" =~ stop|restart|reload ]]; then
- COMPREPLY=($(cd /run/daemons/ && compgen -f "$cur"|sort))
- elif ((${COMP_CWORD} > 1)); then
- COMPREPLY=($(cd /etc/rc.d && compgen -f -X 'functions*'
"$cur"|sort))
+ local cur prev initdir long_opts cmds shoptExtglob
+
+ shoptExtglob="$(shopt -p | grep extglob)"
No grep needed here:
shopt -p extglob
Thanks for this hint.
We don't use camel case, either.
Didn't know but will respect it now.
+ shopt -s extglob
+
+ long_opts='list help'
+ initdir=/etc/rc.d
+ cmds="$(sed '/#.*sh/,/^.*case\s*"*\${*1}*"*.*/ {
/^.*case\s*"*\${*1}*"*.*/!d
};s/^.*case\s*"*\${*1}*"*.*/;;/g;/;;/,/^\s*.*)\s*$/ !d;/^\s*.*)\s*$/
!d;/\*/d;/;;/d;s/\s*//g;s/)//g;s/|/ /g' ${initdir}/!(*functions*) |
LANG=C sort -u | tr '\n' ' ')"
The default IFS is '\n\t ', so the final tr isn't needed here. This
really should be an array, too.
Done.
+
+ _get_comp_words_by_ref cur prev
+
+ cmd="${COMP_WORDS[1]}"
+
+ if [[ "${cmd}" =~ ^(${cmds// /|}|${long_opts// /|})$ ]] && [ -n
"${cmd}" ]; then
+ daemons="$(ls -1 /run/daemons/ | tr '\n' '|')"
Never parse ls. The need for the pipe delimiter isn't obvious either.
pushd /run/daemons &>/dev/null && { daemons=(*); popd &>/dev/null;
}
If you really need the pipe delimiter, you can then later:
( IFS='|'; echo "${daemons[*]}" )
Is needed for the regex-based check whether it's a valid action and to
decrease the amount of listed initscripts.
For now I've removed this functionality.
+ case "${cmd}" in
+ start)
+ COMPREPLY+=( $( compgen -W '`grep -El "^[ ]*[^
]*${cmd}[|\)][^ ]*\)*[ ]*$" ${initdir}/* | sed 's#${initdir}/##' |
grep -vE "^(${daemons})$"`' -- "$cur" ) )
+ ;;
+ stop|restart|reload)
+ COMPREPLY+=( $( compgen -W '`grep -El "^[ ]*[^
]*${cmd}[|\)][^ ]*\)*[ ]*$" ${initdir}/* | sed 's#${initdir}/##' |
grep -E "^(${daemons})$"`' -- "$cur" ) )
+ ;;
+ *)
+ COMPREPLY+=( $( compgen -W '`grep -El "^[ ]*[^
]*${cmd}[|\)][^ ]*\)*[ ]*$" ${initdir}/* | sed 's#${initdir}/##'`' --
"$cur" ) )
We use $() for command substitution, not backticks.
Thanks for the hint.
+ ;;
+ esac
+ else
+ COMPREPLY=( $( compgen -W '${long_opts} ${cmds}' -- "$cur" ) )
fi
-}
-complete -F _rc.d rc.d
-# vim: set ts=2 sw=2 ft=sh noet:
+ ${shoptExtglob}
+ return 0
+} &&
+complete -F _rc_d rc.d
+
+# Local variables:
+# mode: shell-script
+# sh-basic-offset: 4
+# sh-indent-comment: t
+# indent-tabs-mode: nil
+# End:
+# vim: ts=2 sw=2 et filetype=sh
A general lack of commenting and an overbearing sense of
overcomplicating
things gets a NACK from me.
d
So here is a version which should satisfy your hints.
Why should I always use an array?
It's easier to manipulate a string using bash internals than
manipulating an array.
Because of that I had to remove a functionality of the script because I
don't know how I can merge two arrays by removing all elemts which can
be found in both arrays without using multiple for-loops.
Kind regards,
Andrwe
diff --git a/bash-completion b/bash-completion
index 5151972..e751c8c 100644
--- a/bash-completion
+++ b/bash-completion
@@ -1,22 +1,59 @@
-# rc.d bash completion by Seblu <[email protected]>
+# rc.d completion
+#
+# Author: Andrwe Lord Weber
+# Mail: lord-weber-andrwe <at> andrwe <dot> org
+# Credits: Seblu <[email protected]>
+#
-_rc.d ()
+# check wheather rc.d command exists
+type -P rc.d >/dev/null 2>&1 &&
+_rc_d()
{
- local action="help list start stop reload restart"
- local cur="${COMP_WORDS[COMP_CWORD]}"
- local caction="${COMP_WORDS[1]}"
- if ((${COMP_CWORD} == 1)); then
- COMPREPLY=($(compgen -W "${action}" -- "$cur"))
- elif [[ "$caction" =~ help|list ]]; then
- COMPREPLY=()
- elif [[ "$caction" == start ]]; then
- COMPREPLY=($(comm -23 <(cd /etc/rc.d && compgen -f -X 'functions*' "$cur"|sort) <(cd /run/daemons/ && compgen -f "$cur"|sort)))
- elif [[ "$caction" =~ stop|restart|reload ]]; then
- COMPREPLY=($(cd /run/daemons/ && compgen -f "$cur"|sort))
- elif ((${COMP_CWORD} > 1)); then
- COMPREPLY=($(cd /etc/rc.d && compgen -f -X 'functions*' "$cur"|sort))
+ local cur prev action actions shoptextglob
+
+ # get current extglob status
+ shoptextglob="$(shopt -p extglob)"
+ # set extglob for extended directory listing
+ shopt -s extglob
+
+ # get all possible actions also the initscript specific ones
+ pushd /etc/rc.d/ &>/dev/null && { actions=($(sed '/#.*sh/,/^.*case\s*"*\${*1}*"*.*/ { /^.*case\s*"*\${*1}*"*.*/!d };s/^.*case\s*"*\${*1}*"*.*/;;/g;/;;/,/^\s*.*)\s*$/ !d;/^\s*.*)\s*$/ !d;/\*/d;/;;/d;s/\s*//g;s/)//g;s/|/ /g' !(*functions*) | LANG=C sort -u) list help); popd &>/dev/null; }
+
+ _get_comp_words_by_ref cur prev
+
+ # get first argument to whether it's a valid action
+ action="${COMP_WORDS[1]}"
+
+ # check if action is is valid/completed
+ if ( IFS='|'; [[ "${action}" =~ ^(${actions[*]})$ ]] ) && [ -n "${action}" ]; then
+
+ # get all running daemons
+ pushd /run/daemons &>/dev/null && { daemons=(*); popd &>/dev/null; }
+
+ # get all initscripts supporting chosen action
+ pushd /etc/rc.d/&>/dev/null && { inits=($(grep -El "^[ ]*[^ ]*${action}[|\)][^ ]*\)*[ ]*$" !(*functions*))); popd &>/dev/null; }
+
+ # set completion list
+ COMPREPLY+=( $( compgen -W '${inits[*]}' -- "$cur" ) )
+
+ # if not complete using detected actions
+ else
+
+ # set completion list
+ COMPREPLY=( $( compgen -W '${actions[*]}' -- "$cur" ) )
+
fi
-}
-complete -F _rc.d rc.d
-# vim: set ts=2 sw=2 ft=sh noet:
+ # restore extglob status
+ ${shoptextglob}
+ return 0
+} &&
+complete -F _rc_d rc.d
+
+# Local variables:
+# mode: shell-script
+# sh-basic-offset: 4
+# sh-indent-comment: t
+# indent-tabs-mode: nil
+# End:
+# vim: ts=2 sw=2 et filetype=sh