summaryrefslogtreecommitdiff
path: root/autoload/tools/man.kak
blob: 2fcc98142b6838cc8d661994954436ca15b7c0c9 (plain)
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
declare-option -docstring "name of the client in which documentation is to be displayed" \
    str docsclient

declare-option -hidden str-list manpage

hook -group man-highlight global WinSetOption filetype=man %{
    add-highlighter window/man-highlight group
    # Sections
    add-highlighter window/man-highlight/ regex ^\S.*?$ 0:title
    # Subsections
    add-highlighter window/man-highlight/ regex '^ {3}\S.*?$' 0:default+b
    # Command line options
    add-highlighter window/man-highlight/ regex '^ {7}-[^\s,]+(,\s+-[^\s,]+)*' 0:list
    # References to other manpages
    add-highlighter window/man-highlight/ regex [-a-zA-Z0-9_.]+\([a-z0-9]+\) 0:header

    map window normal <ret> :man-jump<ret>

    hook -once -always window WinSetOption filetype=.* %{
      remove-highlighter window/man-highlight
      unmap window normal <ret>
    }
}

hook global WinSetOption filetype=man %{
    hook -group man-hooks window WinResize .* %{ man-impl %opt{manpage} }
    hook -once -always window WinSetOption filetype=.* %{ remove-hooks window man-hooks }
}

define-command -hidden -params ..3 man-impl %{ evaluate-commands %sh{
    buffer_name="$1"
    if [ -z "${buffer_name}" ]; then
        exit
    fi
    shift
    manout=$(mktemp "${TMPDIR:-/tmp}"/kak-man.XXXXXX)
    manerr=$(mktemp "${TMPDIR:-/tmp}"/kak-man.XXXXXX)
    colout=$(mktemp "${TMPDIR:-/tmp}"/kak-man.XXXXXX)
    env MANWIDTH=${kak_window_range##* } man "$@" > "$manout" 2> "$manerr"
    retval=$?
    if command -v col >/dev/null; then
        col -b -x > ${colout} < ${manout}
    else
        sed 's/.//g' > ${colout} < ${manout}
    fi
    rm ${manout}

    if [ "${retval}" -eq 0 ]; then
        printf %s\\n "
                edit -scratch %{*$buffer_name ${*}*}
                execute-keys '%|cat<space>${colout}<ret>gk'
                nop %sh{ rm ${colout}; rm ${manerr} }
                set-option buffer filetype man
                set-option window manpage $buffer_name $*
        "
    else
        printf '
            fail %%{%s}
            nop %%sh{ rm "%s"; rm "%s" }
        ' "$(cat "$manerr")" "${colout}" "${manerr}"
    fi
} }

define-command -params ..1 \
    -shell-script-candidates %{
        find /usr/share/man/ $(printf %s "${MANPATH}" |
            sed 's/:/ /') -name '*.[1-8]*' |
            sed 's,^.*/\(.*\)\.\([1-8][a-zA-Z]*\).*$,\1(\2),'
    } \
    -docstring %{
        man [<page>]: manpage viewer wrapper
        If no argument is passed to the command, the selection will be used as page
        The page can be a word, or a word directly followed by a section number between parenthesis, e.g. kak(1)
    } man %{ evaluate-commands %sh{
    subject=${1-$kak_selection}

    ## The completion suggestions display the page number, strip them if present
    case "${subject}" in
        *\([1-8]*\))
            pagenum="${subject##*\(}"
            pagenum="${pagenum%\)}"
            subject="${subject%%\(*}"
            ;;
        *)
            pagenum=""
            ;;
    esac

    printf %s\\n "evaluate-commands -try-client %opt{docsclient} man-impl man $pagenum $subject"
} }



# The following section of code enables a user
# to go to next or previous man page links and to follow man page links,
# for example, apropos(1), that would normally appear in SEE ALSO sections.
# The user would position the cursor on any character of the link
# and then press <ret> to change to a buffer showing the man page.

# Regex pattern defining a man page link.
# Used for determining if a selection, which may just be a link, is a link.
declare-option -hidden regex man_link1 \
  [\w_.:-]+\(\d[a-z]*\)

# Same as above but with lookbehind and lookahead patterns.
# Used for searching for a man page link.
declare-option -hidden regex man_link2 \
  "(?:^|(?<=\W))%opt{man_link1}(?=\W)"

# Define a useful command sequence for searching a given regex
# and a given sequence of search keys.
define-command -hidden man-search -params 2 %{
    set-register / %arg[1]
    try %{
        execute-keys %arg[2]
    } catch %{
        fail "Could not find man page link"
    }
}

define-command -docstring 'Go to next man page link' \
man-link-next %{ man-search %opt[man_link2] n }

define-command -docstring 'Go to previous man page link' \
man-link-prev %{ man-search %opt[man_link2] <a-n> }

define-command -docstring 'Try to jump to a man page' \
man-jump %{
  try %{ execute-keys <a-a><a-w> s %opt[man_link1] <ret> } catch %{ fail 'Not a valid man page link' }
  try %{ man } catch %{ fail 'No man page link to follow' }
}

# Suggested keymaps for a user mode
declare-user-mode man

map global man 'g' -docstring 'Jump to a man page using selected man page link' :man-jump<ret>
map global man 'j' -docstring 'Go to next man page link'                        :man-link-next<ret>
map global man 'k' -docstring 'Go to previous man page link'                    :man-link-prev<ret>
map global man 'm' -docstring 'Look up a man page'                              :man<space>