summary refs log tree commit diff
path: root/Util/check-tmux-state
blob: 2c6106203f313322cc3ccdaf54beff1ffa7163d3 (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
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/bin/zsh -f

# Tmux has lots of options and sub-commands. It's very tedious to manually
# check if the actual command's idea of all this matches the completion
# function. So this is a helper script that automates checking the state of
# _tmux.
#
# You need to call it like this, with a running tmux server:
#
# zsh -f check-tmux-state <path-to-tmux-binary> <path-to-_tmux-function>
#
# The script will tell you the differences in available and supported
# sub-commands, command aliases, server options, session options and
# window-options.
#
# It also checks if options have moved from one scope to another. If this
# happens, then the option in question also appears in the "new/old" listings
# of the involved scopes. First fix the scope changes, then the "new/old" lists
# are accurate.

emulate zsh
setopt extended_glob null_glob no_octal_zeroes

if (( $#argv != 2 )); then
    printf 'usage: zsh -f check-tmux-state <tmux-binary> <_tmux-function>\n'
    exit 1
fi

printf ' -!- Checking status of _tmux completion function definition -!-\n'

autoload -Uz colors
colors

tmux=$1
func=$2

differences=none

# We'll source the _tmux file and call a bunch of its functions to gather
# information. For that, we need to put a few stubs into place so sourcing the
# file doesn't blow up in our face.

# We need to disable the new "local" keyword to make our data retrieval trick
# work:
disable -r local

function _arguments () { }
function _describe () { }
function local () { }

typeset -A rev

source $func
__tmux-server-options
__tmux-session-options
__tmux-window-options

# Subcommand helper functions are defined like "function _tmux-foo() {"
# in the _tmux function definition file.
typeset -a supported_commands
supported_commands=( $( grep '^_tmux-[^(]*() *{$' $func |
                        sed -e 's,^.*\<_tmux-,,' -e 's,(.*$,,' ) )

# Ask tmux for available commands:
typeset -a available_commands
available_commands=( $( $tmux list-commands | cut -f1 -d' ' ) )

# Ask tmux for available aliases:
typeset -A available_aliases
available_aliases=( $( $tmux list-commands |
                       grep '^[a-z-]* *(' |
                       sed -e 's,^\([a-z-]*\) *(\([a-z-]*\))\(.*\)$,\2 \1,' ) )

# Gather information about options:
typeset -a supported_session_options
supported_session_options=( ${"${tmux_session_options[@]}"%%:*} )
typeset -a available_session_options
available_session_options=( $( $tmux show-options -g | cut -f1 -d' ' ) )

typeset -a available_server_options
supported_server_options=( ${"${tmux_server_options[@]}"%%:*} )
typeset -a supported_server_options
available_server_options=( $( $tmux show-options -s -g | cut -f1 -d' ' ) )

typeset -a supported_window_options
supported_window_options=( ${"${tmux_window_options[@]}"%%:*} )
typeset -a available_window_options
available_window_options=( $( $tmux show-options -w -g | cut -f1 -d' ' ) )

typeset -a supported available

function find_new () {
    local i
    new=()
    for i in "${available[@]}"; do
        [[ -z ${supported[(r)$i]} ]] && new+=( $i )
    done
}

function find_old () {
    local i
    old=()
    for i in "${supported[@]}"; do
        [[ -z ${available[(r)$i]} ]] && old+=( $i )
    done
}

function compare_sets() {
    name=$1
    local -a old new
    new=()
    old=()
    find_old
    find_new
    if (( $#old > 0 )) || (( $#new > 0 )); then
        printf '\n%sDifferences with %s:%s\n' ${fg[yellow]} $name $reset_color
        differences=some
        if (( $#new > 0 )); then
            printf '%sNew:%s' ${fg[green]} $reset_color
            printf ' %s' "${new[@]}"
            printf '\n'
        fi
        if (( $#old > 0 )); then
            printf '%sOld:%s' ${fg[red]} $reset_color
            printf ' %s' "${old[@]}"
            printf '\n'
        fi
    fi
}

function find_changed_scope() {
    name=$1
    local -a changes
    local i av
    changes=()
    for i in "${supported[@]}"; do
        av=${available[(r)$i]}
        [[ -n $av ]] && changes+=( $av )
    done
    if (( $#changes > 0 )); then
        differences=some
        printf '\n%sDifferences with scope %s:%s\n' \
               ${fg[yellow]} $name $reset_color
        printf '%sChanged:%s' ${fg[green]} $reset_color
        printf ' %s' "${changes[@]}"
        printf '\n'
    fi
}

supported=( "${supported_session_options[@]}" )
available=( "${available_server_options[@]}" )
find_changed_scope 'session=>server'

supported=( "${supported_server_options[@]}" )
available=( "${available_session_options[@]}" )
find_changed_scope 'server=>session'

supported=( "${supported_window_options[@]}" )
available=( "${available_session_options[@]}" )
find_changed_scope 'window=>session'

supported=( "${supported_session_options[@]}" )
available=( "${available_window_options[@]}" )
find_changed_scope 'session=>window'

supported=( "${supported_window_options[@]}" )
available=( "${available_server_options[@]}" )
find_changed_scope 'window=>server'

supported=( "${supported_server_options[@]}" )
available=( "${available_window_options[@]}" )
find_changed_scope 'server=>window'

supported=( "${supported_commands[@]}" )
available=( "${available_commands[@]}" )
compare_sets commands

supported=( "${supported_session_options[@]}" )
available=( "${available_session_options[@]}" )
compare_sets session_options

supported=( "${supported_server_options[@]}" )
available=( "${available_server_options[@]}" )
compare_sets server_options

supported=( "${supported_window_options[@]}" )
available=( "${available_window_options[@]}" )
compare_sets window_options

typeset -a alias_messages
for i in "${(k)_tmux_aliasmap[@]}"; do
    su=${_tmux_aliasmap[$i]}
    av=${available_aliases[$i]}
    if [[ -z $av ]]; then
        alias_messages+=( "${fg[red]}Old alias${reset_color}: $i ($su)" )
    elif [[ $av != $su ]]; then
        alias_messages+=( "Changed alias $i: is ($av) was ($su)" )
    fi
done
for i in "${(k)available_aliases[@]}"; do
    su=${_tmux_aliasmap[$i]}
    av=${available_aliases[$i]}
    if [[ -z $su ]]; then
        alias_messages+=( "${fg[green]}New alias${reset_color}: $i ($av)" )
    fi
done
if (( $#alias_messages > 0 )); then
    differences=some
    printf '\n%sDifferences with %s:%s\n' ${fg[yellow]} "aliases" $reset_color
    for i in "${alias_messages[@]}"; do
        printf '%s\n' $i
    done
fi

if [[ $differences == none ]]; then
    printf '\n... _tmux seems to be up to date!\n'
else
    printf '\n'
fi
exit 0