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[-]\([a-z-]*\)[(].*,\1,' ) )
# 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 -aU available_session_options
available_session_options=( ${${${(f)"$($tmux show-options -g)"}:#@*}%%(\[<->\])# *} )
typeset -a supported_server_options
supported_server_options=( ${"${tmux_server_options[@]}"%%:*} )
typeset -aU available_server_options
available_server_options=( ${${${(f)"$($tmux show-options -s -g)"}:#@*}%%(\[<->\])# *} )
typeset -a supported_window_options
supported_window_options=( ${"${tmux_window_options[@]}"%%:*} )
typeset -aU available_window_options
available_window_options=( ${${${(f)"$($tmux show-options -w -g)"}:#@*}%%(\[<->\])# *} )
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
|