bash complete でperldoc

bash-completionがないー

bash-completionが入ってない環境でBig Sky :: perldocのbash-completionが激しく便利でうれしょん出た。のようなことができたらいいなと思って試してみました.bashは':'をファイルセパレータに使っているのでHackが必要です.bash-completionのcontribにperl用のコマンドがあって,それを見ながら作ったのがこれ.

コード

function _myperldoc ()
{
    local mod cur word prev
    local cur=${COMP_WORDS[COMP_CWORD]}
    local prev=${COMP_WORDS[COMP_CWORD-1]}
    export mod=${COMP_LINE/perldoc/}

    case $prev in
        -f)
            COMPREPLY=( $( compgen -W 'chomp chop chr crypt hex index lc \
                lcfirst length oct ord pack q qq reverse rindex sprintf \
                substr tr uc ucfirst y m pos quotemeta s split study qr abs \
                atan2 cos exp hex int log oct rand sin sqrt srand pop push \
                shift splice unshift grep join map qw reverse sort unpack \
                delete each exists keys values binmode close closedir \
                dbmclose dbmopen die eof fileno flock format getc print \
                printf read readdir rewinddir seek seekdir select syscall \
                sysread sysseek syswrite tell telldir truncate warn write \
                pack read syscall sysread syswrite unpack vec -X chdir chmod \
                chown chroot fcntl glob ioctl link lstat mkdir open opendir \
                readlink rename rmdir stat symlink umask unlink utime caller \
                continue do dump eval exit goto last next redo return \
                sub wantarray caller import local my our package use defined \
                formline reset scalar undef \
                alarm exec fork getpgrp getppid getpriority kill pipe qx \
                setpgrp setpriority sleep system times wait waitpid \
                import no package require use bless dbmclose dbmopen package \
                ref tie tied untie use accept bind connect getpeername \
                getsockname getsockopt listen recv send setsockopt shutdown \
                socket socketpair msgctl msgget msgrcv msgsnd semctl semget \
                semop shmctl shmget shmread shmwrite endgrent endhostent \
                endnetent endpwent getgrent getgrgid getgrnam getlogin \
                getpwent getpwnam getpwuid setgrent setpwent endprotoent \
                endservent gethostbyaddr gethostbyname gethostent \
                getnetbyaddr getnetbyname getnetent getprotobyname \
                getprotobynumber getprotoent getservbyname getservbyport \
                getservent sethostent setnetent setprotoent setservent \
                gmtime localtime time times' -- "$cur" ) )
            return 0
            ;;
    esac

    if [[ "$cur" == -* ]]; then
        COMPREPLY=( $( compgen -W '-h -V -r -i -t -u -m -n -l -F -v -T -d -o -M -w -X -q'' -- "$cur" ))
    else


        word=" `perl -MExtUtils::Installed -le \
            '$n = $ENV{mod}; $n =~ s/\s+//; $i = ExtUtils::Installed->new; \
             @m = $i->modules; @m = grep{/^$n/}@m; @m = map{s/^$n//; $_}@m; print join q{ }, @m'` "
        COMPREPLY=( $( compgen -W "${word}" ) )
    fi
}
complete -F _myperldoc perldoc

モジュールと引数候補を出す所は作りましたが,関数一覧はcontribにあったものを使いました.一覧を作るにはどうするのがいいんでしょうね?

使い方

ちょっと時間はかかりますが,perldocと書いてからtabを3回押すと

$ perldoc 
Display all 451 possibilities? (y or n)

という感じで表示します.yを押すと一覧表示です.モジュールに関しては'::'まで入力してtabを2回押してください

$ perldoc IO::
All              Compress::Bzip2  Handle::Util     Socket::SSL      Stringy          Zlib
Compress::Base   Compress::Zlib   Prompt           String           Tty              
$ perldoc IO::

となります.下位のモジュールにアクセスする時も'::'まで書いてください.クラス名の補完は残念ながらできないです.私の場合は,.profileに

. ~/.myperldoc

という行を追加してみました.少し使ってみて使えるかどうか試してみようと思ってます.あ,まだgithubとかには上げてません.まだ安定してない感じです.もうshellでのプログラミング忘れてしまいました…