[arch-projects] [initscripts] simple rc.d bash completion script

Auguste Pop auguste at gmail.com
Wed May 18 14:07:04 EDT 2011


On Thu, May 19, 2011 at 1:13 AM, Dave Reisner <d at falconindy.com> wrote:
> On Thu, May 19, 2011 at 12:53:13AM +0800, Auguste Pop wrote:
>> i have made a small patch to initscripts to allow for a simple bash
>> completion function.
>>
>> i am not familiar with git, i made the patch by git clone, git branch,
>> git commit, and git show.
>>
>> the patch is at http://paste.pocoo.org/show/391299/ and also
>> copy-pasted as follows:
>>
>> commit a430fcfb8fcd1e268609473c9a722e1cae1a66f0
>> Author: Auguste Pop <auguste at gmail.com>
>> Date:   Thu May 19 00:36:44 2011 +0800
>>
>>    add a simple bash completion file
>>
>> diff --git a/Makefile b/Makefile
>> index 6923840..15df4cf 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -1,5 +1,5 @@
>>  VER  := $(shell git describe)
>> -DIRS := /etc/rc.d /etc/conf.d /etc/rc.d/functions.d /etc/cron.hourly /sbin
>> +DIRS := /etc/rc.d /etc/conf.d /etc/rc.d/functions.d /etc/cron.hourly
>> /sbin /etc/bash_completion.d
>>
>>  minilogd: minilogd.o
>>
>> @@ -13,6 +13,7 @@ install: minilogd installdirs
>>        install -m755 -t $(DESTDIR)/etc/cron.hourly adjtime
>>        install -m755 -t $(DESTDIR)/etc/rc.d functions hwclock network netfs
>>        install -m755 -t $(DESTDIR)/sbin minilogd rc.d
>> +       install -m644 bash_completion $(DESTDIR)/etc/bash_completion.d/rc.d
>>
>>  clean:
>>        rm -f minilogd minilogd.o
>> diff --git a/bash_completion b/bash_completion
>> new file mode 100644
>> index 0000000..a3bd8ed
>> --- /dev/null
>> +++ b/bash_completion
>> @@ -0,0 +1,55 @@
>> +#!/bin/bash
>> +
>> +_rc.d_getdaemons ()
>> +{
>> +    /usr/bin/find "$1" -mindepth 1 -maxdepth 1 -type f -printf '%f\n'
>> +}
>
> It would be nice to avoid the fork here. This can easily be accomplished
> as:
>
>  local -a files=("$1"/*)
>  printf '%s\n' "${files[@]##*/}"
>
> Also, please avoid using '.' in bash functions names. While bash will
> allow you to set this, it's technically wrong, and unset will not allow
> you to remove the function from your environment.
>
>> +_rc.d_arraydiff ()
>> +{
>> +    local arr
>> +    declare -A arr
>> +
>> +    for elem in "${!1}"
>> +    do
>> +        arr[$elem]=1
>> +    done
>> +    for elem in "${!2}"
>> +    do
>> +        unset arr[$elem]
>> +    done
>> +    echo "${!arr[@]}"
>> +}
>
> We use 'for i in group; do' and 'if commands; then' everywhere else
> in our code.
>
>> +
>> +_rc.d ()
>> +{
>> +    local command commands available started
>> +    local cur words cword
>> +
>> +    commands="list help start stop restart"
>> +    available=($(_rc.d_getdaemons /etc/rc.d))
>> +    started=($(_rc.d_getdaemons /run/daemons))
>> +
>> +    _get_comp_words_by_ref -n =: cur words cword
>> +    [ $cword -gt 1 ] && command=${words[1]}
>> +
>> +    if [ -z "$command" ]
>
> This is Bash, not posix. Please use [[.
>
>> +    then
>> +        COMPREPLY=($(compgen -W "$commands" -- $cur))
>> +    else
>> +        case "$command" in
>> +            start)
>> +                COMPREPLY=($(compgen -W "$(_rc.d_arraydiff \
>> +                    available[@] started[@])" -- $cur))
>> +                ;;
>> +            stop|restart)
>> +                COMPREPLY=($(compgen -W "$(echo ${started[@]})" -- $cur))
>> +                ;;
>> +            list|help|*)
>> +                COMPREPLY=()
>> +                ;;
>> +        esac
>> +    fi
>> +}
>> +
>> +complete -F _rc.d rc.d
>

here is the new patch that has changed find to simple glob, changed
format according to arch convention, and subsituted all dots in
function name into _.

i originally used find to avoid selecting functions.d as a daemon.
it's now simply excluded with functions by -X "functions*".

here's the patch:

commit 960641f72da1fae3183878f4752711d801b36fc9
Author: Auguste Pop <auguste at gmail.com>
Date:   Thu May 19 00:36:44 2011 +0800

    add a simple bash completion file

diff --git a/Makefile b/Makefile
index 6923840..15df4cf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 VER  := $(shell git describe)
-DIRS := /etc/rc.d /etc/conf.d /etc/rc.d/functions.d /etc/cron.hourly /sbin
+DIRS := /etc/rc.d /etc/conf.d /etc/rc.d/functions.d /etc/cron.hourly
/sbin /etc/bash_completion.d

 minilogd: minilogd.o

@@ -13,6 +13,7 @@ install: minilogd installdirs
 	install -m755 -t $(DESTDIR)/etc/cron.hourly adjtime
 	install -m755 -t $(DESTDIR)/etc/rc.d functions hwclock network netfs
 	install -m755 -t $(DESTDIR)/sbin minilogd rc.d
+	install -m644 bash_completion $(DESTDIR)/etc/bash_completion.d/rc.d

 clean:
 	rm -f minilogd minilogd.o
diff --git a/bash_completion b/bash_completion
new file mode 100644
index 0000000..69b1983
--- /dev/null
+++ b/bash_completion
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+_rc_d_getdaemons ()
+{
+    local -a files=("$1"/*)
+    echo "${files[@]##*/}"
+}
+
+_rc_d_arraydiff ()
+{
+    local -A arr
+
+    for elem in "${!1}"; do
+        arr[$elem]=1
+    done
+    for elem in "${!2}"; do
+        unset arr[$elem]
+    done
+    echo "${!arr[@]}"
+}
+
+_rc_d ()
+{
+    local command commands available started
+    local cur words cword
+
+    commands="list help start stop restart"
+    available=($(_rc_d_getdaemons /etc/rc.d))
+    started=($(_rc_d_getdaemons /run/daemons))
+
+    _get_comp_words_by_ref -n =: cur words cword
+    [[ $cword -gt 1 ]] && command=${words[1]}
+
+    if [[ -z "$command" ]]; then
+        COMPREPLY=($(compgen -W "$commands" -- $cur))
+    else
+        case "$command" in
+            start)
+                COMPREPLY=($(compgen -W "$(_rc_d_arraydiff \
+                    available[@] started[@])" -X "functions*" -- $cur))
+                ;;
+            stop|restart)
+                COMPREPLY=($(compgen -W "$(echo ${started[@]})" -- $cur))
+                ;;
+            list|help|*)
+                COMPREPLY=()
+                ;;
+        esac
+    fi
+}
+
+complete -F _rc_d rc.d


More information about the arch-projects mailing list