Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions plugins/statusline/assets/costs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@
# used to exercise the day/month rollover branches deterministically (e.g. the
# month-boundary transition). Unset in production; real `date` is used.

# Numeric formatting must be locale-independent. Under a comma-decimal locale
# (e.g. fr_FR) awk/printf emit "19,78"; interpolated into a downstream awk
# program that value is read as TWO arguments and the amount is truncated.
# Only the numeric category is forced, matching statusline-command.sh: LC_ALL=C
# would also pin LC_CTYPE, which breaks ${#s} width measurement. LC_ALL must be
# unset first — it outranks LC_NUMERIC when the environment sets it.
unset LC_ALL
export LC_NUMERIC=C

set -u

COST_LOG="${STATUSLINE_COST_LOG:-${HOME}/.claude/statusline-costs.jsonl}"
Expand Down
10 changes: 10 additions & 0 deletions plugins/statusline/assets/statusline-command.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@
# (test harnesses pointing at a working copy).
# Load order is dependency order: platform and palette own no dependencies,
# everything else builds on them.
# Numeric formatting must be locale-independent. Under a comma-decimal locale
# (e.g. fr_FR) awk/printf emit "19,78"; interpolated into a downstream awk
# program that value is read as TWO arguments and the amount is truncated.
# Only the numeric category may be forced: LC_ALL=C would also pin LC_CTYPE,
# and vislen() measures with ${#s}, which then counts UTF-8 bytes instead of
# columns (a 3-byte glyph reads as width 3). LC_ALL must be unset first —
# it outranks LC_NUMERIC when the environment sets it.
unset LC_ALL
export LC_NUMERIC=C

STATUSLINE_LIB="${STATUSLINE_LIB:-$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)/statusline-lib}"
for _mod in platform palette fit severity format config gitctx session_state layout render; do
if [ -r "${STATUSLINE_LIB}/${_mod}.sh" ]; then
Expand Down
7 changes: 5 additions & 2 deletions plugins/statusline/assets/statusline-lib/format.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ fmt_tokens() {

# fmt_usd — a dollar amount, thousands folded to "$1.2k".
fmt_usd() {
local v="$1"
LC_NUMERIC=C awk "BEGIN{ if($v>=1000) printf \"\$%.1fk\",$v/1000; else printf \"\$%.2f\",$v }"
# Value passed via -v, never interpolated into the program text: a stray
# comma decimal must not become an argument separator.
local v="${1:-0}"
v="${v/,/.}"
LC_ALL=C awk -v v="$v" 'BEGIN{ v=v+0; if (v>=1000) printf "$%.1fk", v/1000; else printf "$%.2f", v }'
}

# fmt_dur — compact duration: "Xh Ym" / "Xm Ys" / "Xs" from a seconds count.
Expand Down
4 changes: 2 additions & 2 deletions plugins/statusline/assets/statusline-lib/render.sh
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ render_session() {
# "main" so an understated number is never shown as if it were the total.
if [ "$RANK" -ge 1 ]; then
if [ -n "$cost_session" ]; then
cost_fmt=$(LC_NUMERIC=C awk "BEGIN{printf \"%.2f\",$cost_session}")
cost_fmt=$(LC_ALL=C awk -v v="${cost_session/,/.}" 'BEGIN{printf "%.2f", v+0}')
line="${line:+$line ${SEP} }${KEY}session ${SUBTEXT}${DOLLAR}${cost_fmt}${RESET}"
elif [ -n "$cost" ]; then
cost_fmt=$(LC_NUMERIC=C awk "BEGIN{printf \"%.2f\",$cost}")
cost_fmt=$(LC_ALL=C awk -v v="${cost/,/.}" 'BEGIN{printf "%.2f", v+0}')
line="${line:+$line ${SEP} }${KEY}session main ${SUBTEXT}${DOLLAR}${cost_fmt}${RESET}"
fi
fi
Expand Down