bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Programmable Completion Problem


From: Mark Johnson
Subject: Programmable Completion Problem
Date: Thu, 5 Dec 2002 19:10:41 +0000 (UTC)

When I try to complete man pages using programmable completion I have the
following problem:

$ man perlf<tab>
perlfaq     perlfaq3    perlfaq6    perlfaq9    perlform    
perlfaq1    perlfaq4    perlfaq7    perlfilter  perlfunc    
perlfaq2    perlfaq5    perlfaq8    perlfork    
$ man perlfaq<enter>
$ <enter>
>
> <^C>
[Exit 1]

Here's the completion function and support:

_mannames ()
{
        local path
        local name

        while read path
        do
                name="${path##*/}"
                echo "${name%.[0-9a-z]*}"
        done
}

#
# XXX: man pages like Gimp::Fu seem to confuse this.
#
_man_complete ()
{
        local cur prev section all f

        cur=${COMP_WORDS[COMP_CWORD]}
        prev=${COMP_WORDS[COMP_CWORD-1]}

        case "$prev" in
        [0-9]*)
                section="man$prev"
                ;;
        *)
                section=""
                ;;
        esac

        # Just use the caching layer when a section is not specified.
        if [[ -z $section ]]
        then
                cache_get allmanpages
                if [[ $? -ne 0 ]]
                then
                        all=$(
                                for f in $(echo $MANPATH | tr : ' ')
                                do
                                        find $f 2>/dev/null
                                done | _mannames
                        )
                        cache_put allmanpages all
                fi

                COMPREPLY=(
                        $(echo $all | tr ' ' '\n' | grep ^$cur)
                )
        else
                COMPREPLY=( 
                        $( 
                        for f in $(echo $MANPATH | tr : ' ')
                        do
                                find $f/$section 2>/dev/null
                        done | grep /$cur | _mannames | grep ^$cur
                        ) )
        fi
        # echo "[reply: ${COMPREPLY[@]}]"
}
complete -F _man_complete man

This was working before before I added the cache_[get|put] stuff.  The 
part that has me confused is that if supply the man page section (which
uses the old working code path) it works:

$ man -s 1 perlfaq
Reformatting page.  Please Wait... done

But, COMPREPLY in both cases is the same (as seen when that last echo is 
uncommented).  So what (obvious I'm sure) thing am I missing?

Also, is there a better way to print debugging info from completion
functions?

For completeness, here is the caching functions:

# cache.bash
#
# Author: Mark Johnson <mj@bror.org>
# Created: 2002-11-22
# Last Modified: 2002-12-02

# Commentary:

# These functions provide a caching mechanism for shell variables.
# These can be used to easily implement a caching layer for completion
# functions.  If a function needs to perform a costly opertation to
# generate possible completions it can store the results in a variable
# and use cache_put() to store the results avoiding the costly
# operation in the future.

# The cache id specifies a file that the variables will be dumped.
# The file is placed in the directory specified by the directory
# _cache_path (which defaults to $HOME/.bash/cache).

# These functions will only attempt storing and retrieving values if
# cache_use is set.  This way a function can call the caching layer
# without worrying if the user wants to use caching.

# Todo:

# Cache invalidation

[[ -z $_cache_path ]] && _cache_path=$HOME/.bash/cache

#:docstring cache_put:
# Usage: cache_put id var ...
#
# Cache a list of variables under id.
#
# If the return value is zero the storage was successful.
#:end docstring:

cache_put ()
{
        local id=$1
        local var
        shift

        [[ $cache_use ]] || return 1

        [[ -d "$_cache_path" ]] || mkdir -p "$_cache_path" || return 1

        for var in "$@"
        do
                echo $var=\"${!var}\"
        done > "$_cache_path/$id"

        return 0        
}

#:docstring cache_get:
# Usage: cache_get id
#
# Retrieve the information cached under id.
#
# Return 0 if successful.
#:end docstring:

cache_get ()
{
        local id=$1

        [[ $cache_use ]] || return 1

        [[ -f "$_cache_path/$id" ]] || return 1

        . "$_cache_path/$id"

        return 0
}

provide cache





reply via email to

[Prev in Thread] Current Thread [Next in Thread]