aboutsummaryrefslogtreecommitdiff
path: root/bash/bashrc.d/man.bash
blob: 562b0625ecbe37ae0a8bbb543b11b624334dc1ec (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# Autocompletion for man(1)
_man() {

    # Don't even bother if we don't have manpath(1)
    hash manpath || return 1

    # Snarf the word
    local word
    word=${COMP_WORDS[COMP_CWORD]}

    # If this is the second word, and the previous word started with a number,
    # we'll assume that's the section to search
    local section subdir
    if ((COMP_CWORD > 1)) && [[ ${COMP_WORDS[COMP_CWORD-1]} == [0-9]* ]] ; then
        section=${COMP_WORDS[COMP_CWORD-1]}
        subdir=man${section%%[^0-9]*}
    fi

    # 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
        shopt -u dotglob
        shopt -s extglob nullglob

        # Start an array of pages
        declare -a pages

        # Break manpath(1) output into an array of paths
        IFS=: read -a manpaths -r < <(manpath 2>/dev/null)

        # Iterate through the manual page paths and add every manual page we find
        for manpath in "${manpaths[@]}" ; do
            [[ $manpath ]] || continue
            if [[ $section ]] ; then
                for page in "$manpath"/"$subdir"/"$word"*."$section"?(.[glx]z|.bz2|.lzma|.Z) ; do
                    pages[${#pages[@]}]=$page
                done
            else
                for page in "$manpath"/man[0-9]*/"$word"*.* ; do
                    pages[${#pages[@]}]=$page
                done
            fi
        done

        # Strip paths, .gz suffixes, and finally .<section> suffixes
        pages=("${pages[@]##*/}")
        pages=("${pages[@]%.@([glx]z|bz2|lzma|Z)}")
        pages=("${pages[@]%.[0-9]*}")

        # Bail out if we ended up with no pages somehow to prevent us from
        # printing
        ((${#pages[@]})) || exit 1

        # Print the pages array to stdout, quoted and null-delimited
        printf '%q\0' "${pages[@]}"
    )
}
complete -F _man -o default man