terminal-ai-helper 2.3.0 → 2.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +1 -1
- package/package.json +1 -1
- package/plugins/bash/keys.bash +22 -3
- package/plugins/zsh/menu.zsh +18 -0
- package/plugins/zsh/widgets.zsh +52 -0
- package/readme.md +1 -1
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.3.
|
|
1
|
+
2.3.2
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terminal-ai-helper",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "The terminal that knows your next command Bash/Zsh suggestions that learn from your own history Offline and private with no account required",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
package/plugins/bash/keys.bash
CHANGED
|
@@ -15,6 +15,12 @@ _tai_prompt() {
|
|
|
15
15
|
raw="${raw#"${raw%%[![:space:]]*}"}" # drop the leading indent
|
|
16
16
|
while [[ "$raw" == [0-9]* ]]; do raw="${raw#?}"; done # drop the history number
|
|
17
17
|
last_cmd="${raw#"${raw%%[![:space:]]*}"}" # drop the space after it
|
|
18
|
+
# A completion's own space rides the line into the history (`nano ` after a
|
|
19
|
+
# menu choice), and the store strips it — but this shell's next prediction
|
|
20
|
+
# looks the last command up in the sequence table by its exact text, and the
|
|
21
|
+
# table's keys are the stored, stripped rows. Trim here, once per command,
|
|
22
|
+
# so `nano ` predicts what followed `nano` and records the same row either way.
|
|
23
|
+
while [[ "$last_cmd" == *[[:space:]] ]]; do last_cmd="${last_cmd%?}"; done
|
|
18
24
|
if [[ -n "$last_cmd" && "$last_cmd" != "$_TAI_LAST" ]]; then
|
|
19
25
|
_TAI_LAST="$last_cmd"
|
|
20
26
|
# The unit cache pre-loads itself in the background after a command that
|
|
@@ -247,12 +253,25 @@ _tai_complete() {
|
|
|
247
253
|
# by both loops above — once as the file that is here, once as the line the
|
|
248
254
|
# history holds — and COMPREPLY holding it twice makes readline print it twice.
|
|
249
255
|
_tai_reply() {
|
|
250
|
-
local c
|
|
256
|
+
local c x
|
|
251
257
|
# A learned line carrying raw control bytes is not a completion it is this
|
|
252
258
|
# plugin's promise to never paint: what it would write is escape bytes.
|
|
253
259
|
[[ "$1" =~ [[:cntrl:]] ]] && return 0
|
|
254
|
-
|
|
255
|
-
|
|
260
|
+
c="$1"
|
|
261
|
+
# A completion that leaves the line one bare word is a command waiting for
|
|
262
|
+
# its arguments, and readline's own completion would have written the space
|
|
263
|
+
# between them (`cat tzz_solo `). `-o nospace` took that append away from
|
|
264
|
+
# every entry so a directory's slash could stand alone, so the entries that
|
|
265
|
+
# want the space carry it — measured on a real shell, a match holding a
|
|
266
|
+
# trailing space is inserted verbatim, and the common prefix of matches that
|
|
267
|
+
# disagree past the space is the prefix alone. Three shapes carry none: a
|
|
268
|
+
# directory's slash, which is the path still being typed; a whole learned
|
|
269
|
+
# line, which is the line the user ran, and whose space would ride the next
|
|
270
|
+
# Enter into the history as a row of its own; and a name that already holds
|
|
271
|
+
# a space, which is more than one shell word already.
|
|
272
|
+
if [[ -n "$c" && "$c" != */ && "$c" != *[[:space:]]* ]]; then c="$c "; fi
|
|
273
|
+
for x in "${COMPREPLY[@]}"; do [[ "$x" == "$c" ]] && return 0; done
|
|
274
|
+
COMPREPLY+=("$c")
|
|
256
275
|
}
|
|
257
276
|
complete -o nospace -F _tai_complete tai 2>/dev/null
|
|
258
277
|
# -o default is what makes Tab fall back to readline's own filename completion
|
package/plugins/zsh/menu.zsh
CHANGED
|
@@ -769,6 +769,24 @@ _tai_menu_commit() {
|
|
|
769
769
|
# slash from truncating what gets written.
|
|
770
770
|
(( ${_TAI_MENU_Q[_TAI_MENU_IDX]} )) && { _tai_quote "$entry"; entry="$_TAI_QUOTED" }
|
|
771
771
|
BUFFER="${BUFFER[1,$(( _TAI_MENU_FROM - 1 ))]}$entry${BUFFER[_TAI_MENU_TO + 1,-1]}"
|
|
772
|
+
# A completion that leaves the line one bare word is a command waiting for its
|
|
773
|
+
# arguments, and the space between them is written for the user — every
|
|
774
|
+
# shell's own completion does this, and readline's half of this plugin always
|
|
775
|
+
# did (`cat tzz_solo `). The report: choosing `nano` out of the menu put
|
|
776
|
+
# `nano` in the line, and the user typed the space by hand, once per line,
|
|
777
|
+
# every time. Three shapes write nothing after them: a directory's slash,
|
|
778
|
+
# which is the path still being typed; a whole learned line, which is the
|
|
779
|
+
# line the user ran, and whose space would ride the next Enter into the
|
|
780
|
+
# history as a row of its own; and a name that already holds a space, whose
|
|
781
|
+
# quoting is the shell word it is.
|
|
782
|
+
[[ "$entry" != */ && "$entry" != *[[:space:]]* ]] && BUFFER+=" "
|
|
783
|
+
# What the commit wrote is the line the user took. Without this, the space a
|
|
784
|
+
# bare-word commit writes is one deletion from the learned line itself, and
|
|
785
|
+
# the loose glimpse answered the very next redraw with the line just taken —
|
|
786
|
+
# `cd tzz_dir ` re-offering `cd tzz_dir` from under the cursor. The same
|
|
787
|
+
# dismiss an Up from a glimpse sets: while the text stands, the list does not
|
|
788
|
+
# spring back, and the next keystroke re-arms it.
|
|
789
|
+
_TAI_MENU_DISMISS="$BUFFER"
|
|
772
790
|
CURSOR=${#BUFFER}
|
|
773
791
|
_tai_menu_close
|
|
774
792
|
}
|
package/plugins/zsh/widgets.zsh
CHANGED
|
@@ -114,6 +114,26 @@ _tai_update() {
|
|
|
114
114
|
fi
|
|
115
115
|
return
|
|
116
116
|
fi
|
|
117
|
+
# The accept echo is the one redraw that paints nothing. When the line is
|
|
118
|
+
# accepted, zsh re-renders it as it will run, and that render fires this
|
|
119
|
+
# hook — which answered it like any keystroke: it ran the query for the
|
|
120
|
+
# line one last time and painted the hint back onto the row the shell was
|
|
121
|
+
# leaving. The report: Enters on an empty prompt stacked gray `cd …` lines
|
|
122
|
+
# that read as commands the user ran, and a scrollback reader believed
|
|
123
|
+
# them. So the accept path raises _TAI_ACCEPT, and this hook takes tai's
|
|
124
|
+
# own paint down and stands aside: the echo shows what was typed, and what
|
|
125
|
+
# tai drew goes down with the line it rode in on. line-init lowers the
|
|
126
|
+
# flag with everything else it resets — the next line paints as usual.
|
|
127
|
+
if (( _TAI_ACCEPT )); then
|
|
128
|
+
_TAI_SUGGESTION=""
|
|
129
|
+
(( _TAI_MENU_IDX )) && _tai_menu_close
|
|
130
|
+
if (( _TAI_DREW )); then
|
|
131
|
+
POSTDISPLAY=""
|
|
132
|
+
region_highlight=()
|
|
133
|
+
_TAI_DREW=0
|
|
134
|
+
fi
|
|
135
|
+
return
|
|
136
|
+
fi
|
|
117
137
|
local -i ours_was=$_TAI_DREW
|
|
118
138
|
# What the last widget was decides whether this buffer is typed. The hook
|
|
119
139
|
# runs after every widget, and the names here are the ones that mean an
|
|
@@ -348,10 +368,32 @@ tai-enter() {
|
|
|
348
368
|
# A glimpsed menu still swallows the selection; Enter at a disarmed menu is
|
|
349
369
|
# the line's Enter.
|
|
350
370
|
if (( _TAI_MENU_IDX )); then _tai_menu_close; POSTDISPLAY=""; region_highlight=(); fi
|
|
371
|
+
# What runs is what was typed, and the echo of it must say so. zsh's final
|
|
372
|
+
# render of the accepted line fires the redraw hook, which would answer it
|
|
373
|
+
# with a fresh query and paint the hint back onto the row being left; the
|
|
374
|
+
# flag stands the hook down for that one render. See _tai_update.
|
|
375
|
+
_TAI_ACCEPT=1
|
|
351
376
|
zle accept-line
|
|
352
377
|
}
|
|
353
378
|
zle -N tai-enter
|
|
354
379
|
|
|
380
|
+
# Enter is not the only door to a running line: TAI_NO_MENU=1 leaves ^M on
|
|
381
|
+
# stock accept-line, and so can a user binding of their own. The wrapper
|
|
382
|
+
# raises the same flag tai-enter raises, so the accept echo paints nothing
|
|
383
|
+
# in those shells either. It is registered only while the name is still the
|
|
384
|
+
# builtin — an accept-line another plugin wrapped is theirs, their clear
|
|
385
|
+
# already answers their own hint, and tai-enter raises the flag itself
|
|
386
|
+
# before it calls accept-line by name, so the hook stands down either way.
|
|
387
|
+
typeset -gi _TAI_ACCEPT=0
|
|
388
|
+
tai-accept-line() {
|
|
389
|
+
_TAI_ACCEPT=1
|
|
390
|
+
zle .accept-line
|
|
391
|
+
}
|
|
392
|
+
zle -N tai-accept-line
|
|
393
|
+
case "${widgets[accept-line]:-}" in
|
|
394
|
+
builtin*) zle -N accept-line tai-accept-line ;;
|
|
395
|
+
esac
|
|
396
|
+
|
|
355
397
|
# Right arrow accepts the suggestion at the end of the line, and moves the
|
|
356
398
|
# cursor one character anywhere else. Bound straight to tai-accept it took
|
|
357
399
|
# forward-char away entirely: with a ghost on screen there was then no key left
|
|
@@ -560,6 +602,10 @@ _tai_line_init() {
|
|
|
560
602
|
# exit hook, and a flag carried into the next line would stand tai down for
|
|
561
603
|
# every keystroke of it. The hook pair is the truth; this is the belt.
|
|
562
604
|
_TAI_ISEARCH=0
|
|
605
|
+
# Nor is a line still being accepted: the accept flag stands the redraw
|
|
606
|
+
# hook down for the echo of the line that is leaving, and a new line is
|
|
607
|
+
# painted on again from its first redraw.
|
|
608
|
+
_TAI_ACCEPT=0
|
|
563
609
|
region_highlight=()
|
|
564
610
|
_tai_menu_close
|
|
565
611
|
# The prophecy. _TAI_SEQ answers "what did I run after this", and the fresh
|
|
@@ -716,6 +762,12 @@ _tai_preexec() {
|
|
|
716
762
|
# resolved in the background write instead, which also means the repo, branch
|
|
717
763
|
# and cwd all describe the same moment. bash has always done it this way.
|
|
718
764
|
_TAI_CMD="$1"
|
|
765
|
+
# A completion's own space rides the line into preexec (`nano ` after a menu
|
|
766
|
+
# choice), and the store strips it on the way in — but this shell's next
|
|
767
|
+
# prediction looks the last command up in the sequence table by its exact
|
|
768
|
+
# text, and the table's keys are the stored, stripped rows. Trim here, once
|
|
769
|
+
# per command, so `nano ` predicts what followed `nano`.
|
|
770
|
+
while [[ "$_TAI_CMD" == *[[:space:]] ]]; do _TAI_CMD="${_TAI_CMD%?}"; done
|
|
719
771
|
# The directory the command was *run from*. A prompt-time $PWD comes after the
|
|
720
772
|
# command, so for `cd src` the recorded origin was the destination — and the
|
|
721
773
|
# path-liveness check judged the cd's argument against the place it had just
|
package/readme.md
CHANGED
|
@@ -38,7 +38,7 @@ exec zsh
|
|
|
38
38
|
✓ bash installed
|
|
39
39
|
|
|
40
40
|
1. Type a few letters — tai finishes the command in grey. → takes it.
|
|
41
|
-
2. Tab opens a menu of what fits. Enter picks; a second Enter runs.
|
|
41
|
+
2. Tab opens a menu of what fits. Enter picks, space after the command included; a second Enter runs.
|
|
42
42
|
3. It learns from your history — offline, private, no account.
|
|
43
43
|
|
|
44
44
|
Try it now: type "cd " and watch the grey.
|