-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathjj.kak
281 lines (261 loc) · 9.61 KB
/
jj.kak
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# Jujutsu - https://martinvonz.github.io/jj
declare-option -hidden str jj_source %val{source}
hook global WinSetOption filetype=jj-diff %{
map buffer normal <ret> %{:git-diff-goto-source<ret>} -docstring 'Jump to source from git diff'
hook -once -always -first window WinSetOption filetype=.* %{
# TODO this only works in colocated repos
unmap buffer normal <ret> %{:git-diff-goto-source<ret>}
}
}
define-command -override jj -params 1.. \
-docstring %{
jj [<arguments>]: Jujutsu wrapper
All optional arguments are forwarded to the jj utility
See ':doc jj' for help.
Available commands:
abandon
absorb
backout
describe
diff - compare file contents between two revisions
edit
log
new
parallelize
rebase
show
squash
split - split the selected lines into a separate commit
status
undo
} %{ evaluate-commands %sh{
kakquote() {
printf "%s" "$1" | sed "s/'/''/g; 1s/^/'/; \$s/\$/'/"
}
trace() {
# Tracing output.
printf 'echo -debug -- $ jj'
for arg; do
printf ' %s' "$(kakquote "$arg")"
done
printf '\n'
}
generic_jj() {
trace "$@"
if ! output=$(JJ_EDITOR=true jj "$@" 2>&1); then {
printf %s "fail failed to run jj $1, see the *debug* buffer"
exec >&2
printf '$ jj'
for arg
do
printf ' '
kakquote "$arg"
done
printf '\n'
printf '%s\n' "$output"
} fi
}
# TODO handle errors
show_jj_cmd_output() {
output=$(mktemp -d "${TMPDIR:-/tmp}"/kak-jj.XXXXXXXX)/fifo
mkfifo ${output}
color=
render_ansi=
if [ -n "$kak_opt_ansi_filter" ]; then
color=--color=always
render_ansi='
ansi-enable
hook -once buffer BufReadFifo .* %exp{
execute-keys -client %val{client} gk
}
'
fi
trace "$@"
( trap - INT QUIT; jj $color "$@" > ${output} 2>&1 & ) > /dev/null 2>&1 < /dev/null
printf %s "evaluate-commands -try-client '$kak_opt_docsclient' '
edit! -fifo ${output} *jj*
$render_ansi
set-option buffer filetype ${filetype}
hook -always -once buffer BufCloseFifo .* ''
nop %sh{ rm -r $(dirname ${output}) }
''
'"
}
with_revisions_around_cursor() {
revisions=$(revisions_around_cursor)
generic_jj "$@" $revisions
}
with_dash_revision_around_cursor() {
revision=
if ! printf '%s\n' "$@" | grep -qE '^(-r|--revisions)'; then
revision=$(revisions_around_cursor)
fi
generic_jj "$@" ${revision:+"--revision=${revision}"}
}
with_dash_revisions_around_cursor() {
revisions=
if ! printf '%s\n' "$@" | grep -qE '^(-r|--revisions)'; then
revisions=$(revisions_around_cursor)
fi
generic_jj "$@" ${revisions:+"--revisions=$(printf %s\\n ${revisions} | paste -d '|' -s)"}
}
revisions_around_cursor() {
echo >${kak_command_fifo} "jj-revisions-around-cursor ${kak_response_fifo}"
cat ${kak_response_fifo}
}
jj_describe() {
revisions=$(revisions_around_cursor)
msgfile=$(mktemp "${TMPDIR:-/tmp}"/kak-jj-describe.XXXXXXXX)
JJ_EDITOR=cat jj describe $revisions "$@" >"$msgfile" 2>/dev/null
printf %s "edit $msgfile
set-option buffer filetype jj-describe
hook buffer BufWritePost .* %{ evaluate-commands %sh{
jj describe $revisions $* --message=\"\$(grep -v ^JJ $msgfile)\"
} }
hook buffer BufClose .* %{ nop %sh{ rm -f $msgfile } }
"
}
jj_diff() {
filetype=git-diff
show_jj_cmd_output diff "$@"
}
jj_log() {
filetype=jj-log
echo "
hook -once global BufCloseFifo .* %{
execute-keys -client ${kak_client} %{/@ <ret>}
hook -once buffer NormalIdle .* %{
execute-keys -client ${kak_client} vv
}
}
"
show_jj_cmd_output log "$@"
}
jj_status() {
filetype=git-status
show_jj_cmd_output status "$@"
}
jj_show() {
filetype=git-diff
revision=$(revisions_around_cursor)
# Don't pass revision if given as arg.
if ! jj show $revision "$@" >/dev/null 2>&1; then
revision=
fi
show_jj_cmd_output show $revision "$@"
}
jj_squash() {
if ! printf '%s\n' "$@" | grep -qE '^(-r|--revisions)'; then
from=$(printf '%s\n' "$@" | grep -oE '^(--from|-f)')
into=$(printf '%s\n' "$@" | grep -oE '^(--into|-t)')
revisions=$(revisions_around_cursor)
joined_revisions=${revisions:+"$(printf %s\\n ${revisions} | paste -d '|' -s)"}
case ${from}${into} in
( --from | -f )
generic_jj squash "$@" ${revisions:+"--into=${joined_revisions}"}
return
;;
( --into | -t )
generic_jj squash "$@" ${revisions:+"--from=${joined_revisions}"}
return
;;
esac
if [ -n "$revisions" ]; then
for revision in $revisions
do
generic_jj squash "$@" ${revision:+"--revision=${revision}"}
done
return
fi
fi
generic_jj squash "$@"
}
jj_split() {
echo >${kak_command_fifo} "
evaluate-commands -draft %{
try %{
execute-keys %{<a-/>^(?:commit|Change ID:) \S+<ret>}
execute-keys %{1s^(?:commit|Change ID:) (\S+)<ret>}
echo -to-file ${kak_response_fifo} -- %exp{--revision=%val{selection}}
} catch %{
echo -to-file ${kak_response_fifo}
}
}
"
revision=$(cat ${kak_response_fifo})
echo "require-module patch"
printf %s "patch JJ_EDITOR=true \
jj split $revision --tool=${kak_opt_jj_source%/*}/jj-split-tool"
if [ $# -ge 2 ]; then
printf ' %%arg{%s}' $(seq 2 $#)
fi
echo
if [ -n "$revision" ] && ! printf '%s\n' "$@" | grep -qE '^(-p|--parallel\b)'; then {
revision=${revision#--revision=}
echo "evaluate-commands -draft -save-regs | %{
try %{
execute-keys %{<a-/>^Change ID: \S+<ret>}
execute-keys %{1s^Change ID: (\S+)<ret>}
set-register | %{
jj log --no-graph --ignore-working-copy -r ${revision}+ -T change_id
}
execute-keys |<ret>
}
}"
} fi
}
cmd=$1
shift
case "$cmd" in
(abandon) with_revisions_around_cursor abandon "$@" ;;
(absorb) generic_jj absorb "$@" ;;
(backout) with_dash_revisions_around_cursor backout "$@" ;;
(bookmark) generic_jj bookmark "$@" ;;
(describe) jj_describe "$@" ;;
(diff) jj_diff "$@" ;;
(edit) with_revisions_around_cursor edit "$@" ;;
(log) jj_log "$@" ;;
(new) generic_jj new "$@" ;;
(parallelize) with_revisions_around_cursor parallelize "$@" ;;
(rebase) with_dash_revisions_around_cursor rebase "$@" ;;
(show) jj_show "$@" ;;
(squash) jj_squash "$@" ;;
(split) jj_split "$@" ;;
(status) jj_status "$@" ;;
(undo) generic_jj undo "$@" ;;
(*) printf "fail unknown jj command '%s'\n" "$cmd"
esac
}
}
complete-command jj shell-script-candidates %{
printf %s\\n \
abandon \
backout \
describe \
diff \
edit \
log \
new \
parallelize \
rebase \
show \
squash \
split \
status \
undo \
}
define-command -override jj-revisions-around-cursor -params 1 %{
evaluate-commands -draft %{
try %{
execute-keys %{<a-/>^(?:commit|Change ID:) \S+<ret>}
execute-keys %{1s^(?:commit|Change ID:) (\S+)<ret>}
echo -to-file %arg{1} %val{selection}
} catch %{
execute-keys %{<a-s><a-l><semicolon><a-/>^\h*(?:│ )*[@◆○×](?:\h*│)*\h*\b[a-z]+<ret>}
execute-keys %{1s^\h*(?:│ )*[@◆○×](?:\h*│)*\h*\b([a-z]+)<ret>}
echo -to-file %arg{1} %val{selections}
} catch %{
echo -to-file %arg{1}
}
}
}