mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 20:47:03 +01:00
Split calc-live.zsh: extract the qalc coprocess
266 -> 204, with the warmed qalc coprocess (its four _CALC_Q* state vars
and four functions) in calc-live-qalc.zsh at 74.
The source line uses ${0:A:h}, matching what the file already does for
_CALC_EVAL_PY. That is load-bearing here: this file is loaded as
~/.oh-my-zsh/custom/calc-live.zsh, a symlink into the repo, so a naive
$0 would look for the sibling in the oh-my-zsh custom dir, where it does
not exist -- and break every new shell, not just one script run.
So it is verified THROUGH the symlink, not the repo path: sources clean,
functions defined across the seam, and the qalc path in the new file
answers end to end ("=5 ft to cm" -> 152.4 cm). Seven expressions give
byte-identical results to HEAD, and _calc_is_expr still accepts "2+2"
while rejecting "ls -la".
zsh -n is the parse check here; shellcheck cannot read zsh and the
repo's hook excludes it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
This commit is contained in:
parent
a61d195a89
commit
1506371976
48
docs/superpowers/evidence/calc-live-split-2026-08-16.json
Normal file
48
docs/superpowers/evidence/calc-live-split-2026-08-16.json
Normal file
@ -0,0 +1,48 @@
|
||||
{
|
||||
"intent": "Bring calc-live.zsh under the 250-line cap by extracting the warmed qalc coprocess into a sibling file, without changing what the live prompt calculator computes.",
|
||||
"scope": [
|
||||
"linux_configuration/zsh/calc-live.zsh (266 -> 204 lines)",
|
||||
"New: linux_configuration/zsh/calc-live-qalc.zsh (74 lines)",
|
||||
"Non-goal: changing the evaluator, the expression heuristic, or the ZLE bindings"
|
||||
],
|
||||
"changes": [
|
||||
"Moved the qalc coprocess block -- its four _CALC_Q* state variables and _calc_qalc_line, _calc_qco_start, _calc_qco_stop, _calc_qalc_eval -- into calc-live-qalc.zsh, sourced from calc-live.zsh after _CALC_QALC_BIN and _CALC_TIMEOUT_BIN are set.",
|
||||
"The source line uses ${0:A:h}, the same idiom the file already relies on for _CALC_EVAL_PY. This matters here more than usual: the file is loaded as ~/.oh-my-zsh/custom/calc-live.zsh, a symlink into the repo, so a naive $0 would resolve into the oh-my-zsh custom directory where the sibling does not exist."
|
||||
],
|
||||
"verification": [
|
||||
{
|
||||
"command": "zsh -c 'source ~/.oh-my-zsh/custom/calc-live.zsh; ...' -- through the real symlink, not the repo path",
|
||||
"result": "pass",
|
||||
"evidence": "Sources without error, all five probed functions are defined across the seam, _calc_eval '10/4' returns 2.5, and the qalc path in the NEW file works end to end: _calc_qalc_line '=5 ft to cm' strips to '5 ft to cm' and _calc_qalc_eval returns '152.4 cm'. This is the check that matters, since the symlink is how the file is actually loaded."
|
||||
},
|
||||
{
|
||||
"command": "seven expressions evaluated under HEAD and under the split, compared",
|
||||
"result": "pass",
|
||||
"evidence": "Identical for all seven: 2+2=4, 1/3=0.333333333333, sqrt(2)*3=4.24264068712, sin(pi/2)=1, 2^10=1024, 10/4=2.5, factorial(5)=120. _calc_is_expr still accepts '2+2' and still rejects 'ls -la', so ordinary commands remain untouched."
|
||||
},
|
||||
{
|
||||
"command": "zsh -n on both files",
|
||||
"result": "pass",
|
||||
"evidence": "Both parse. zsh is the right parser here; shellcheck cannot read zsh syntax and the repo's shellcheck hook excludes zsh files, so the zsh-syntax hook is the gate."
|
||||
},
|
||||
{
|
||||
"command": "bash ~/utils/scripts/check_file_length.sh",
|
||||
"result": "pass",
|
||||
"evidence": "calc-live.zsh 204, calc-live-qalc.zsh 74. Neither appears in the violation list."
|
||||
},
|
||||
{
|
||||
"command": "function-set and line-set diff against HEAD",
|
||||
"result": "pass",
|
||||
"evidence": "All ten functions preserved and identical. Zero executable lines lost; the single addition is the source line."
|
||||
}
|
||||
],
|
||||
"risks": [
|
||||
"This is a live interactive component: a broken source line would break every new shell, not just a script run on demand. That is why it was verified through the oh-my-zsh symlink rather than the repo path -- the symlink is the only path that actually exercises ${0:A:h}.",
|
||||
"The coprocess variables are shared across the seam by design: calc-live-qalc.zsh sets _CALC_QRESULT and _CALC_QEXPR, which _calc_preview and _calc_accept_line in the main file read. This is a sourced-into-the-same-shell relationship, not two processes, and the end-to-end qalc test exercises exactly that path.",
|
||||
"Already-running shells keep the old single-file version in memory until they exit; nothing needs restarting, but a shell opened mid-commit could source a half-written pair. Both files were written before either was staged."
|
||||
],
|
||||
"rollback": [
|
||||
"git revert the commit; calc-live.zsh returns to its 266-line single-file form and the sibling disappears. No symlink change is needed -- the oh-my-zsh symlink points at calc-live.zsh either way.",
|
||||
"After rollback, open a new shell and type '2+2' to confirm the live preview still appears."
|
||||
]
|
||||
}
|
||||
74
linux_configuration/zsh/calc-live-qalc.zsh
Normal file
74
linux_configuration/zsh/calc-live-qalc.zsh
Normal file
@ -0,0 +1,74 @@
|
||||
# calc-live-qalc.zsh — the warmed qalc coprocess for "="-prefixed lines
|
||||
# ----------------------------------------------------------------------------
|
||||
# Sourced by calc-live.zsh; split out to keep both files under the 250-line
|
||||
# cap. Not standalone: it relies on _CALC_QALC_BIN and _CALC_TIMEOUT_BIN, which
|
||||
# calc-live.zsh sets above the source line.
|
||||
|
||||
# --- qalc (richer engine) for "="-prefixed lines: units, hex, percentages ----
|
||||
# qalc cold start is ~120 ms, far too slow per keystroke; but a warmed qalc
|
||||
# coprocess answers in ~1 ms, fast enough to evaluate live in the redraw hook.
|
||||
# So we keep ONE persistent qalc per shell, started lazily on first "=" line.
|
||||
#
|
||||
# IMPORTANT: the coprocess lives in the main shell. Its evaluator must NOT be
|
||||
# called via $(...) (that forks a subshell and loses the pipe) — it sets the
|
||||
# global _CALC_QRESULT instead.
|
||||
typeset -g _CALC_QCO_UP=0 # 1 once the qalc coprocess is running
|
||||
typeset -gi _CALC_QSEQ=0 # unique-sentinel counter (prevents desync)
|
||||
typeset -g _CALC_QEXPR= # stripped expression from the last "=" line
|
||||
typeset -g _CALC_QRESULT= # result from the last _calc_qalc_eval
|
||||
|
||||
# If the line is "=<expr>", set _CALC_QEXPR to the stripped <expr> and return 0.
|
||||
_calc_qalc_line() {
|
||||
emulate -L zsh
|
||||
setopt local_options extended_glob
|
||||
local s=$1
|
||||
_CALC_QEXPR=
|
||||
[[ $s == (#s)[[:space:]]#=* ]] || return 1
|
||||
s=${s##[[:space:]]#=[[:space:]]#} # drop leading spaces, the "=", trailing spaces
|
||||
[[ -n $s ]] || return 1
|
||||
_CALC_QEXPR=$s
|
||||
return 0
|
||||
}
|
||||
|
||||
# Start / stop the persistent qalc coprocess (no job-control chatter).
|
||||
_calc_qco_start() {
|
||||
setopt local_options no_monitor no_notify
|
||||
coproc "$_CALC_QALC_BIN" -t 2>/dev/null
|
||||
_CALC_QCO_PID=$!
|
||||
disown %+ 2>/dev/null
|
||||
_CALC_QCO_UP=1
|
||||
}
|
||||
_calc_qco_stop() {
|
||||
[[ ${_CALC_QCO_UP:-0} == 1 ]] || return 0
|
||||
kill "${_CALC_QCO_PID:-0}" 2>/dev/null
|
||||
_CALC_QCO_UP=0
|
||||
}
|
||||
|
||||
# Evaluate _CALC_QEXPR (arg) via the coprocess; sets _CALC_QRESULT ("" on fail).
|
||||
_calc_qalc_eval() {
|
||||
emulate -L zsh
|
||||
setopt local_options extended_glob no_monitor no_notify
|
||||
_CALC_QRESULT=
|
||||
[[ -n $_CALC_QALC_BIN ]] || return 0
|
||||
local expr=${1// of / * } # qalc mis-parses "A% of B"
|
||||
(( _CALC_QCO_UP )) || _calc_qco_start
|
||||
(( _CALC_QSEQ++ ))
|
||||
local sentinel="909090909${_CALC_QSEQ}" # unique per call, echoes itself
|
||||
if ! { print -p -- "$expr" && print -p -- "$sentinel" } 2>/dev/null; then
|
||||
_calc_qco_stop; _calc_qco_start # pipe broke -> restart once
|
||||
{ print -p -- "$expr" && print -p -- "$sentinel" } 2>/dev/null || return 0
|
||||
fi
|
||||
local line result='' saw=0
|
||||
integer guard=0
|
||||
while (( guard++ < 100 )) && read -rp -t 0.8 line 2>/dev/null; do
|
||||
line=${line//$'\e'\[[0-9;?]##[a-zA-Z]/} # strip color escapes
|
||||
line=${line##[[:space:]]##}; line=${line%%[[:space:]]##}
|
||||
[[ -z $line || $line == '>'* ]] && continue # blank / echoed input
|
||||
[[ $line == *$sentinel* ]] && { saw=1; break; } # our sentinel result
|
||||
result=$line
|
||||
done
|
||||
(( saw )) || { _CALC_QCO_UP=0; return 0 } # timed out/wedged -> reset
|
||||
# qalc echoes the input back when it cannot evaluate (e.g. "1 / 0").
|
||||
[[ -n $result && ${result// /} != ${expr// /} ]] && _CALC_QRESULT=$result
|
||||
return 0
|
||||
}
|
||||
@ -84,74 +84,12 @@ _calc_eval() {
|
||||
print -r -- "$out"
|
||||
}
|
||||
|
||||
# --- qalc (richer engine) for "="-prefixed lines: units, hex, percentages ----
|
||||
# qalc cold start is ~120 ms, far too slow per keystroke; but a warmed qalc
|
||||
# coprocess answers in ~1 ms, fast enough to evaluate live in the redraw hook.
|
||||
# So we keep ONE persistent qalc per shell, started lazily on first "=" line.
|
||||
#
|
||||
# IMPORTANT: the coprocess lives in the main shell. Its evaluator must NOT be
|
||||
# called via $(...) (that forks a subshell and loses the pipe) — it sets the
|
||||
# global _CALC_QRESULT instead.
|
||||
typeset -g _CALC_QCO_UP=0 # 1 once the qalc coprocess is running
|
||||
typeset -gi _CALC_QSEQ=0 # unique-sentinel counter (prevents desync)
|
||||
typeset -g _CALC_QEXPR= # stripped expression from the last "=" line
|
||||
typeset -g _CALC_QRESULT= # result from the last _calc_qalc_eval
|
||||
# --- qalc (richer engine) for "="-prefixed lines ------------------------------
|
||||
# Sourced after _CALC_QALC_BIN and _CALC_TIMEOUT_BIN above, which it reads.
|
||||
# ${0:A:h} follows the oh-my-zsh symlink back to the real directory in the repo,
|
||||
# the same idiom used for _CALC_EVAL_PY above.
|
||||
source ${0:A:h}/calc-live-qalc.zsh
|
||||
|
||||
# If the line is "=<expr>", set _CALC_QEXPR to the stripped <expr> and return 0.
|
||||
_calc_qalc_line() {
|
||||
emulate -L zsh
|
||||
setopt local_options extended_glob
|
||||
local s=$1
|
||||
_CALC_QEXPR=
|
||||
[[ $s == (#s)[[:space:]]#=* ]] || return 1
|
||||
s=${s##[[:space:]]#=[[:space:]]#} # drop leading spaces, the "=", trailing spaces
|
||||
[[ -n $s ]] || return 1
|
||||
_CALC_QEXPR=$s
|
||||
return 0
|
||||
}
|
||||
|
||||
# Start / stop the persistent qalc coprocess (no job-control chatter).
|
||||
_calc_qco_start() {
|
||||
setopt local_options no_monitor no_notify
|
||||
coproc "$_CALC_QALC_BIN" -t 2>/dev/null
|
||||
_CALC_QCO_PID=$!
|
||||
disown %+ 2>/dev/null
|
||||
_CALC_QCO_UP=1
|
||||
}
|
||||
_calc_qco_stop() {
|
||||
[[ ${_CALC_QCO_UP:-0} == 1 ]] || return 0
|
||||
kill "${_CALC_QCO_PID:-0}" 2>/dev/null
|
||||
_CALC_QCO_UP=0
|
||||
}
|
||||
|
||||
# Evaluate _CALC_QEXPR (arg) via the coprocess; sets _CALC_QRESULT ("" on fail).
|
||||
_calc_qalc_eval() {
|
||||
emulate -L zsh
|
||||
setopt local_options extended_glob no_monitor no_notify
|
||||
_CALC_QRESULT=
|
||||
[[ -n $_CALC_QALC_BIN ]] || return 0
|
||||
local expr=${1// of / * } # qalc mis-parses "A% of B"
|
||||
(( _CALC_QCO_UP )) || _calc_qco_start
|
||||
(( _CALC_QSEQ++ ))
|
||||
local sentinel="909090909${_CALC_QSEQ}" # unique per call, echoes itself
|
||||
if ! { print -p -- "$expr" && print -p -- "$sentinel" } 2>/dev/null; then
|
||||
_calc_qco_stop; _calc_qco_start # pipe broke -> restart once
|
||||
{ print -p -- "$expr" && print -p -- "$sentinel" } 2>/dev/null || return 0
|
||||
fi
|
||||
local line result='' saw=0
|
||||
integer guard=0
|
||||
while (( guard++ < 100 )) && read -rp -t 0.8 line 2>/dev/null; do
|
||||
line=${line//$'\e'\[[0-9;?]##[a-zA-Z]/} # strip color escapes
|
||||
line=${line##[[:space:]]##}; line=${line%%[[:space:]]##}
|
||||
[[ -z $line || $line == '>'* ]] && continue # blank / echoed input
|
||||
[[ $line == *$sentinel* ]] && { saw=1; break; } # our sentinel result
|
||||
result=$line
|
||||
done
|
||||
(( saw )) || { _CALC_QCO_UP=0; return 0 } # timed out/wedged -> reset
|
||||
# qalc echoes the input back when it cannot evaluate (e.g. "1 / 0").
|
||||
[[ -n $result && ${result// /} != ${expr// /} ]] && _CALC_QRESULT=$result
|
||||
return 0
|
||||
}
|
||||
|
||||
# --- Decide whether a line is a pure math expression worth evaluating --------
|
||||
# Conservative on purpose: must contain a digit and an operator (or a function
|
||||
|
||||
Loading…
Reference in New Issue
Block a user