shellwise 0.2.9 → 0.2.10

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli/init.ts +53 -21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shellwise",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
4
4
  "description": "Smart command history with inline auto-suggest and fuzzy search for your terminal",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli/init.ts CHANGED
@@ -25,25 +25,48 @@ typeset -ga __sw_suggestions=()
25
25
  typeset -g __sw_selected=0
26
26
  typeset -g __sw_fd=""
27
27
  typeset -g __sw_ready=0
28
+ typeset -g __sw_port=0
29
+
30
+ # ─── Daemon connection (self-healing) ──────────────────────
31
+ # The daemon idle-exits after inactivity and the TCP port is
32
+ # deterministic, so the shell must be able to reconnect on
33
+ # demand — otherwise a long-idle pane loses suggest forever.
34
+
35
+ # Read daemon port from PID file (line 2). No fork (\$(<file) is builtin).
36
+ __sw_read_port() {
37
+ local pf="/tmp/shellwise-\${UID}.pid"
38
+ [[ -f "\$pf" ]] || return 1
39
+ local lines=("\${(@f)\$(<\$pf)}")
40
+ __sw_port=\${lines[2]:-0}
41
+ [[ \$__sw_port -gt 0 ]]
42
+ }
43
+
44
+ # Is the daemon process alive? No fork (kill -0 is a builtin).
45
+ __sw_daemon_alive() {
46
+ local pf="/tmp/shellwise-\${UID}.pid"
47
+ [[ -f "\$pf" ]] || return 1
48
+ local lines=("\${(@f)\$(<\$pf)}")
49
+ kill -0 \${lines[1]:-0} 2>/dev/null
50
+ }
51
+
52
+ # (Re)establish the persistent TCP connection. No fork while typing.
53
+ __sw_connect() {
54
+ __sw_ready=0
55
+ [[ -n "\$__sw_fd" ]] && { ztcp -c \$__sw_fd 2>/dev/null; __sw_fd="" }
56
+ [[ \$__sw_port -gt 0 ]] || __sw_read_port || return 1
57
+ ztcp 127.0.0.1 \$__sw_port 2>/dev/null || return 1
58
+ __sw_fd=\$REPLY
59
+ __sw_ready=1
60
+ }
28
61
 
29
62
  # Load TCP module + connect at shell startup
30
63
  zmodload zsh/net/tcp 2>/dev/null && {
31
- # Read daemon port from PID file
32
- local __sw_pidfile="/tmp/shellwise-\${UID}.pid"
33
- if [[ ! -f "\$__sw_pidfile" ]]; then
64
+ if [[ ! -f "/tmp/shellwise-\${UID}.pid" ]]; then
34
65
  # Start daemon in background (non-blocking)
35
66
  command ${bin} daemon start &>/dev/null &!
36
67
  sleep 0.3
37
68
  fi
38
- if [[ -f "\$__sw_pidfile" ]]; then
39
- local __sw_port=\${"\$(sed -n 2p "\$__sw_pidfile")":-0}
40
- if [[ \$__sw_port -gt 0 ]]; then
41
- ztcp 127.0.0.1 \$__sw_port 2>/dev/null && {
42
- __sw_fd=\$REPLY
43
- __sw_ready=1
44
- }
45
- fi
46
- fi
69
+ __sw_connect
47
70
  }
48
71
 
49
72
  # ─── Persistent TCP query (no connect/disconnect overhead) ─
@@ -52,14 +75,19 @@ typeset -ga __sw_tcp_result=()
52
75
 
53
76
  __sw_tcp_query() {
54
77
  __sw_tcp_result=()
55
- [[ \$__sw_ready -ne 1 ]] && return 1
56
78
 
57
- # Send request
58
- print -u \$__sw_fd "\$1" 2>/dev/null || {
59
- # Connection broken — mark unavailable
60
- __sw_ready=0
61
- return 1
62
- }
79
+ # Neutralize SIGPIPE: writing to a daemon that has idle-exited must return
80
+ # a recoverable error, never raise a signal that freezes the line editor.
81
+ setopt local_options local_traps
82
+ trap '' PIPE
83
+
84
+ # (Re)connect if needed — daemon may have idle-exited or restarted
85
+ [[ \$__sw_ready -ne 1 ]] && { __sw_connect || return 1 }
86
+
87
+ # Send request; one transparent reconnect+retry on a stale connection
88
+ if ! print -u \$__sw_fd "\$1" 2>/dev/null; then
89
+ __sw_connect && print -u \$__sw_fd "\$1" 2>/dev/null || { __sw_ready=0; return 1 }
90
+ fi
63
91
 
64
92
  # Read response lines until empty line
65
93
  local line
@@ -87,8 +115,11 @@ __sw_precmd() {
87
115
  duration=\${duration%%.*}
88
116
  fi
89
117
 
90
- # Save via persistent TCP (instant) or fallback to background process
91
- __sw_tcp_query "ADD\\t\$__SW_COMMAND\\t\$PWD\\t\$exit_code\\t\$duration\\t\$SW_SESSION_ID\\tzsh" || \\
118
+ # Save via persistent TCP (instant). On failure, restart a dead daemon
119
+ # (a fork between commands is fine) so the next keystroke can reconnect,
120
+ # and fall back to a direct write for this command.
121
+ if ! __sw_tcp_query "ADD\\t\$__SW_COMMAND\\t\$PWD\\t\$exit_code\\t\$duration\\t\$SW_SESSION_ID\\tzsh"; then
122
+ __sw_daemon_alive || command ${bin} daemon start &>/dev/null &!
92
123
  command ${bin} add \\
93
124
  --command "\$__SW_COMMAND" \\
94
125
  --cwd "\$PWD" \\
@@ -96,6 +127,7 @@ __sw_precmd() {
96
127
  --duration "\$duration" \\
97
128
  --session "\$SW_SESSION_ID" \\
98
129
  --shell "zsh" &!
130
+ fi
99
131
 
100
132
  # Show update notice if available
101
133
  local __sw_line