cxstatusline 0.14.0 → 0.15.0

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 (3) hide show
  1. package/NOTICE +9 -6
  2. package/dist/cxstatusline.js +1104 -682
  3. package/package.json +1 -1
@@ -27696,6 +27696,9 @@ var VARIATION_SELECTOR_SUPPLEMENT_END = 917999;
27696
27696
  var REGIONAL_INDICATOR_START = 127462;
27697
27697
  var REGIONAL_INDICATOR_END = 127487;
27698
27698
  var SGR_REGEX = /\x1b\[[0-9;]*m/g;
27699
+ var FIRST_CLUSTER_EXTENDER = 768;
27700
+ var CLUSTER_WIDTH_CACHE_LIMIT = 4096;
27701
+ var clusterWidthCache = new Map;
27699
27702
  var EXTENDED_PICTOGRAPHIC_REGEX = createUnicodePropertyRegex("\\p{Extended_Pictographic}");
27700
27703
  var EMOJI_PRESENTATION_REGEX = createUnicodePropertyRegex("\\p{Emoji_Presentation}");
27701
27704
  var EMOJI_MODIFIER_REGEX = createUnicodePropertyRegex("\\p{Emoji_Modifier}");
@@ -27776,8 +27779,8 @@ function isZeroWidthStandaloneCluster(cluster) {
27776
27779
  return codePoint === ZERO_WIDTH_JOINER || codePoint === COMBINING_ENCLOSING_KEYCAP || isVariationSelector(codePoint) || matchesUnicodeProperty(character, COMBINING_MARK_REGEX) || matchesUnicodeProperty(character, EMOJI_MODIFIER_REGEX);
27777
27780
  });
27778
27781
  }
27779
- function shouldTreatClusterAsNarrowTextPictograph(cluster) {
27780
- if (stringWidth(cluster) <= 1) {
27782
+ function shouldTreatClusterAsNarrowTextPictograph(cluster, clusterStringWidth) {
27783
+ if (clusterStringWidth <= 1) {
27781
27784
  return false;
27782
27785
  }
27783
27786
  const characters = Array.from(cluster);
@@ -27795,19 +27798,46 @@ function shouldTreatClusterAsNarrowTextPictograph(cluster) {
27795
27798
  }
27796
27799
  return characters.some((character) => matchesUnicodeProperty(character, EXTENDED_PICTOGRAPHIC_REGEX));
27797
27800
  }
27798
- function getClusterWidth(cluster) {
27801
+ function isPrintableAscii(charCode) {
27802
+ return charCode >= 32 && charCode <= 126;
27803
+ }
27804
+ function computeClusterWidth(cluster) {
27799
27805
  if (cluster.length === 0 || isZeroWidthStandaloneCluster(cluster)) {
27800
27806
  return 0;
27801
27807
  }
27802
- if (shouldTreatClusterAsNarrowTextPictograph(cluster)) {
27808
+ const clusterStringWidth = stringWidth(cluster);
27809
+ if (shouldTreatClusterAsNarrowTextPictograph(cluster, clusterStringWidth)) {
27810
+ return 1;
27811
+ }
27812
+ return clusterStringWidth;
27813
+ }
27814
+ function getClusterWidth(cluster) {
27815
+ if (cluster.length === 1 && isPrintableAscii(cluster.charCodeAt(0))) {
27803
27816
  return 1;
27804
27817
  }
27805
- return stringWidth(cluster);
27818
+ const cached = clusterWidthCache.get(cluster);
27819
+ if (cached !== undefined) {
27820
+ return cached;
27821
+ }
27822
+ const width = computeClusterWidth(cluster);
27823
+ if (clusterWidthCache.size >= CLUSTER_WIDTH_CACHE_LIMIT) {
27824
+ clusterWidthCache.clear();
27825
+ }
27826
+ clusterWidthCache.set(cluster, width);
27827
+ return width;
27806
27828
  }
27807
27829
  function getTextDisplayWidth(text) {
27808
27830
  let width = 0;
27809
27831
  let index = 0;
27810
27832
  while (index < text.length) {
27833
+ if (isPrintableAscii(text.charCodeAt(index))) {
27834
+ const nextIndex = index + 1;
27835
+ if (nextIndex >= text.length || text.charCodeAt(nextIndex) < FIRST_CLUSTER_EXTENDER) {
27836
+ width += 1;
27837
+ index = nextIndex;
27838
+ continue;
27839
+ }
27840
+ }
27811
27841
  const cluster = consumeDisplayCluster(text, index);
27812
27842
  if (!cluster) {
27813
27843
  break;
@@ -27931,9 +27961,40 @@ function getOsc8CloseSequence(terminator) {
27931
27961
  }
27932
27962
  return `${ESC2}]8;;${ESC2}\\`;
27933
27963
  }
27964
+ function nextOsc8Terminator(escape, current) {
27965
+ if (escape.osc8Action === "open") {
27966
+ return escape.osc8Terminator ?? "st";
27967
+ }
27968
+ if (escape.osc8Action === "close") {
27969
+ return null;
27970
+ }
27971
+ return current;
27972
+ }
27934
27973
  function stripSgrCodes(text) {
27935
27974
  return text.replace(SGR_REGEX, "");
27936
27975
  }
27976
+ function sgrClearsBackground(sequence) {
27977
+ const params = sequence.slice(2, -1).split(";").map((param) => Number.parseInt(param || "0", 10));
27978
+ let clearsBackground = false;
27979
+ for (let i = 0;i < params.length; i++) {
27980
+ const param = params[i];
27981
+ if (param === 0 || param === 49) {
27982
+ clearsBackground = true;
27983
+ } else if (param !== undefined && (param >= 40 && param <= 47 || param >= 100 && param <= 107 || param === 48)) {
27984
+ clearsBackground = false;
27985
+ }
27986
+ if (param === 38 || param === 48 || param === 58) {
27987
+ i += params[i + 1] === 5 ? 2 : 4;
27988
+ }
27989
+ }
27990
+ return clearsBackground;
27991
+ }
27992
+ function restoreBackgroundAfterResets(text, backgroundCode) {
27993
+ return text.replace(SGR_REGEX, (sequence) => sgrClearsBackground(sequence) ? sequence + backgroundCode : sequence);
27994
+ }
27995
+ function isEscapeIntroducer(character) {
27996
+ return character === ESC2 || character === C1_CSI2 || character === C1_OSC2;
27997
+ }
27937
27998
  function getVisibleText(text) {
27938
27999
  let result = "";
27939
28000
  let index = 0;
@@ -27943,13 +28004,12 @@ function getVisibleText(text) {
27943
28004
  index = escape.nextIndex;
27944
28005
  continue;
27945
28006
  }
27946
- const codePoint = text.codePointAt(index);
27947
- if (codePoint === undefined) {
27948
- break;
28007
+ let runEnd = index + 1;
28008
+ while (runEnd < text.length && !isEscapeIntroducer(text[runEnd])) {
28009
+ runEnd++;
27949
28010
  }
27950
- const character = String.fromCodePoint(codePoint);
27951
- result += character;
27952
- index += character.length;
28011
+ result += text.slice(index, runEnd);
28012
+ index = runEnd;
27953
28013
  }
27954
28014
  return result;
27955
28015
  }
@@ -27975,28 +28035,17 @@ function truncateStyledText(text, maxWidth, options = {}) {
27975
28035
  let index = 0;
27976
28036
  let didTruncate = false;
27977
28037
  let openOsc8Terminator = null;
28038
+ const visibleText = getVisibleText(text);
28039
+ let visibleIndex = 0;
27978
28040
  while (index < text.length) {
27979
28041
  const escape = parseEscapeSequence(text, index);
27980
28042
  if (escape) {
27981
28043
  output += escape.sequence;
27982
28044
  index = escape.nextIndex;
27983
- if (escape.osc8Action === "open") {
27984
- openOsc8Terminator = escape.osc8Terminator ?? "st";
27985
- } else if (escape.osc8Action === "close") {
27986
- openOsc8Terminator = null;
27987
- }
28045
+ openOsc8Terminator = nextOsc8Terminator(escape, openOsc8Terminator);
27988
28046
  continue;
27989
28047
  }
27990
- let visibleSegmentEnd = index;
27991
- while (visibleSegmentEnd < text.length && !parseEscapeSequence(text, visibleSegmentEnd)) {
27992
- const codePoint = text.codePointAt(visibleSegmentEnd);
27993
- if (codePoint === undefined) {
27994
- break;
27995
- }
27996
- visibleSegmentEnd += String.fromCodePoint(codePoint).length;
27997
- }
27998
- const visibleSegment = text.slice(index, visibleSegmentEnd);
27999
- const cluster = consumeDisplayCluster(visibleSegment, 0);
28048
+ const cluster = consumeDisplayCluster(visibleText, visibleIndex);
28000
28049
  if (!cluster) {
28001
28050
  break;
28002
28051
  }
@@ -28005,9 +28054,26 @@ function truncateStyledText(text, maxWidth, options = {}) {
28005
28054
  didTruncate = true;
28006
28055
  break;
28007
28056
  }
28008
- output += cluster.text;
28057
+ let remaining = cluster.text.length;
28058
+ while (remaining > 0 && index < text.length) {
28059
+ const inner = parseEscapeSequence(text, index);
28060
+ if (inner) {
28061
+ output += inner.sequence;
28062
+ index = inner.nextIndex;
28063
+ openOsc8Terminator = nextOsc8Terminator(inner, openOsc8Terminator);
28064
+ continue;
28065
+ }
28066
+ const codePoint = text.codePointAt(index);
28067
+ if (codePoint === undefined) {
28068
+ break;
28069
+ }
28070
+ const character = String.fromCodePoint(codePoint);
28071
+ output += character;
28072
+ index += character.length;
28073
+ remaining -= character.length;
28074
+ }
28009
28075
  currentWidth += clusterWidth;
28010
- index += cluster.text.length;
28076
+ visibleIndex = cluster.nextIndex;
28011
28077
  }
28012
28078
  if (!didTruncate) {
28013
28079
  return text;
@@ -47341,6 +47407,9 @@ function getColorAnsiCode(colorName, colorLevel = "ansi16", isBackground = false
47341
47407
  return isBackground ? `\x1B[48;2;${first.r};${first.g};${first.b}m` : `\x1B[38;2;${first.r};${first.g};${first.b}m`;
47342
47408
  }
47343
47409
  if (colorName.startsWith("ansi256:")) {
47410
+ if (colorLevel === "ansi16") {
47411
+ return "";
47412
+ }
47344
47413
  const code = parseInt(colorName.substring(8), 10);
47345
47414
  if (!isNaN(code) && code >= 0 && code <= 255) {
47346
47415
  return isBackground ? `\x1B[48;5;${code}m` : `\x1B[38;5;${code}m`;
@@ -47348,6 +47417,9 @@ function getColorAnsiCode(colorName, colorLevel = "ansi16", isBackground = false
47348
47417
  return "";
47349
47418
  }
47350
47419
  if (colorName.startsWith("hex:")) {
47420
+ if (colorLevel === "ansi16") {
47421
+ return "";
47422
+ }
47351
47423
  const hex3 = colorName.substring(4);
47352
47424
  if (/^[0-9A-Fa-f]{6}$/.test(hex3)) {
47353
47425
  const r = parseInt(hex3.substring(0, 2), 16);
@@ -47769,8 +47841,37 @@ function getHideModifierText(item, states) {
47769
47841
  }
47770
47842
 
47771
47843
  // src/widgets/shared/raw-or-labeled.ts
47844
+ var LABEL_METADATA_KEY = "label";
47845
+ var EDIT_LABEL_ACTION = "edit-label";
47846
+ var LABEL_KEYBIND = {
47847
+ key: "e",
47848
+ label: "(e)dit label…",
47849
+ action: EDIT_LABEL_ACTION
47850
+ };
47851
+ function getLabel(item, defaultLabel) {
47852
+ return item.metadata?.[LABEL_METADATA_KEY] ?? defaultLabel;
47853
+ }
47854
+ function clearLabel(item) {
47855
+ return removeMetadataKeys(item, [LABEL_METADATA_KEY]);
47856
+ }
47857
+ function setLabel(item, value) {
47858
+ return {
47859
+ ...item,
47860
+ metadata: {
47861
+ ...item.metadata,
47862
+ [LABEL_METADATA_KEY]: value
47863
+ }
47864
+ };
47865
+ }
47772
47866
  function formatRawOrLabeledValue(item, labelPrefix, value) {
47773
- return item.rawValue ? value : `${labelPrefix}${value}`;
47867
+ return item.rawValue ? value : `${getLabel(item, labelPrefix)}${value}`;
47868
+ }
47869
+ function getLabelKeybind() {
47870
+ return LABEL_KEYBIND;
47871
+ }
47872
+ function getLabelModifierText(item) {
47873
+ const label = item.metadata?.[LABEL_METADATA_KEY];
47874
+ return label === undefined ? undefined : `(label: ${JSON.stringify(label)})`;
47774
47875
  }
47775
47876
 
47776
47877
  // src/widgets/CacheHitRate.ts
@@ -47796,24 +47897,27 @@ class CacheHitRateWidget {
47796
47897
  handleEditorAction(action, item) {
47797
47898
  return handleCacheScopeAction(action, item);
47798
47899
  }
47900
+ getLabelPrefix() {
47901
+ return "Cache Hit: ";
47902
+ }
47799
47903
  render(item, context, settings) {
47800
47904
  const format = resolveNumberFormat("percent", item, settings);
47801
47905
  if (context.isPreview) {
47802
- return formatRawOrLabeledValue(item, "Cache Hit: ", formatPercent(87, format));
47906
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatPercent(87, format));
47803
47907
  }
47804
47908
  const hideWhenEmpty = isHideStateEnabled(item, ZERO_HIDEABLE_STATE);
47805
47909
  const tokens = getCacheTokens(context, isCacheSessionScope(item));
47806
47910
  if (!tokens) {
47807
- return hideWhenEmpty ? null : formatRawOrLabeledValue(item, "Cache Hit: ", "n/a");
47911
+ return hideWhenEmpty ? null : formatRawOrLabeledValue(item, this.getLabelPrefix(), "n/a");
47808
47912
  }
47809
47913
  const hitRate = getCacheHitRate(tokens);
47810
47914
  if (hitRate === null) {
47811
- return hideWhenEmpty ? null : formatRawOrLabeledValue(item, "Cache Hit: ", formatPercent(0, format));
47915
+ return hideWhenEmpty ? null : formatRawOrLabeledValue(item, this.getLabelPrefix(), formatPercent(0, format));
47812
47916
  }
47813
47917
  if (hitRate === 0 && hideWhenEmpty) {
47814
47918
  return null;
47815
47919
  }
47816
- return formatRawOrLabeledValue(item, "Cache Hit: ", formatPercent(hitRate, format));
47920
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatPercent(hitRate, format));
47817
47921
  }
47818
47922
  getCustomKeybinds(item) {
47819
47923
  return [getCacheScopeKeybind()];
@@ -47829,6 +47933,8 @@ class CacheHitRateWidget {
47829
47933
  }
47830
47934
  }
47831
47935
  // src/widgets/ClaudeSessionId.ts
47936
+ var LABEL = "Session ID: ";
47937
+
47832
47938
  class ClaudeSessionIdWidget {
47833
47939
  getDefaultColor() {
47834
47940
  return "cyan";
@@ -47845,11 +47951,14 @@ class ClaudeSessionIdWidget {
47845
47951
  getEditorDisplay(_item) {
47846
47952
  return { displayText: this.getDisplayName() };
47847
47953
  }
47954
+ getLabelPrefix() {
47955
+ return LABEL;
47956
+ }
47848
47957
  render(item, context, _settings) {
47849
47958
  const id = context.isPreview ? "preview-session-id" : context.data.session?.id;
47850
47959
  if (!id)
47851
47960
  return null;
47852
- return item.rawValue ? id : "Session ID: " + id;
47961
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), id);
47853
47962
  }
47854
47963
  supportsRawValue() {
47855
47964
  return true;
@@ -48623,6 +48732,8 @@ class ContextBarWidget {
48623
48732
  }
48624
48733
  }
48625
48734
  // src/widgets/ContextLength.ts
48735
+ var LABEL2 = "Ctx: ";
48736
+
48626
48737
  class ContextLengthWidget {
48627
48738
  getDefaultColor() {
48628
48739
  return "brightBlack";
@@ -48639,12 +48750,15 @@ class ContextLengthWidget {
48639
48750
  getEditorDisplay(_item) {
48640
48751
  return { displayText: this.getDisplayName() };
48641
48752
  }
48753
+ getLabelPrefix() {
48754
+ return LABEL2;
48755
+ }
48642
48756
  render(item, context, settings) {
48643
48757
  const format = resolveNumberFormat("token", item, settings);
48644
48758
  const value = context.isPreview ? 18600 : getContextWindowContextLengthTokens(context.data);
48645
48759
  if (value === null)
48646
48760
  return null;
48647
- return item.rawValue ? formatTokens(value, format) : "Ctx: " + formatTokens(value, format);
48761
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatTokens(value, format));
48648
48762
  }
48649
48763
  supportsRawValue() {
48650
48764
  return true;
@@ -48783,6 +48897,9 @@ class ContextPercentageWidget {
48783
48897
  const modifiers = [getContextInverseModifierText(item), getContextSliderModifierText(item)].filter((value) => value !== undefined);
48784
48898
  return { displayText: this.getDisplayName(), modifierText: modifiers.length ? "(" + modifiers.map((value) => value.replace(/^\(|\)$/g, "")).join(", ") + ")" : undefined };
48785
48899
  }
48900
+ getLabelPrefix(item) {
48901
+ return isContextInverse(item) ? "Ctx Left: " : "Ctx Used: ";
48902
+ }
48786
48903
  handleEditorAction(action, item) {
48787
48904
  if (action === "toggle-slider")
48788
48905
  return cycleContextSliderMode(item);
@@ -48795,7 +48912,7 @@ class ContextPercentageWidget {
48795
48912
  return null;
48796
48913
  const percentage = isContextInverse(item) ? 100 - metrics.usedPercentage : metrics.usedPercentage;
48797
48914
  const slider = renderContextSlider(getContextSliderMode(item), percentage, format);
48798
- return formatRawOrLabeledValue(item, isContextInverse(item) ? "Ctx Left: " : "Ctx Used: ", slider ?? formatPercent(percentage, format));
48915
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(item), slider ?? formatPercent(percentage, format));
48799
48916
  }
48800
48917
  getCustomKeybinds() {
48801
48918
  return [{ key: "u", label: "(u)sed/remaining", action: "toggle-inverse" }, ...getContextSliderKeybinds()];
@@ -48828,6 +48945,9 @@ class ContextPercentageUsableWidget {
48828
48945
  const modifiers = [getContextInverseModifierText(item), getContextSliderModifierText(item)].filter((value) => value !== undefined);
48829
48946
  return { displayText: this.getDisplayName(), modifierText: modifiers.length ? "(" + modifiers.map((value) => value.replace(/^\(|\)$/g, "")).join(", ") + ")" : undefined };
48830
48947
  }
48948
+ getLabelPrefix(item) {
48949
+ return isContextInverse(item) ? "Ctx(u) Left: " : "Ctx(u) Used: ";
48950
+ }
48831
48951
  handleEditorAction(action, item) {
48832
48952
  if (action === "toggle-slider")
48833
48953
  return cycleContextSliderMode(item);
@@ -48842,7 +48962,7 @@ class ContextPercentageUsableWidget {
48842
48962
  const used = Math.min(100, metrics.contextLengthTokens / config2.usableTokens * 100);
48843
48963
  const percentage = isContextInverse(item) ? 100 - used : used;
48844
48964
  const slider = renderContextSlider(getContextSliderMode(item), percentage, format);
48845
- return formatRawOrLabeledValue(item, isContextInverse(item) ? "Ctx(u) Left: " : "Ctx(u) Used: ", slider ?? formatPercent(percentage, format));
48965
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(item), slider ?? formatPercent(percentage, format));
48846
48966
  }
48847
48967
  getCustomKeybinds() {
48848
48968
  return [{ key: "u", label: "(u)sed/remaining", action: "toggle-inverse" }, ...getContextSliderKeybinds()];
@@ -48858,6 +48978,8 @@ class ContextPercentageUsableWidget {
48858
48978
  }
48859
48979
  }
48860
48980
  // src/widgets/ContextWindow.ts
48981
+ var LABEL3 = "Win: ";
48982
+
48861
48983
  class ContextWindowWidget {
48862
48984
  getDefaultColor() {
48863
48985
  return "brightBlack";
@@ -48874,6 +48996,9 @@ class ContextWindowWidget {
48874
48996
  getEditorDisplay(_item) {
48875
48997
  return { displayText: this.getDisplayName() };
48876
48998
  }
48999
+ getLabelPrefix() {
49000
+ return LABEL3;
49001
+ }
48877
49002
  render(item, context, settings) {
48878
49003
  const format = resolveNumberFormat("token", item, settings);
48879
49004
  let total = context.isPreview ? 200000 : getContextWindowSize(context.data);
@@ -48881,7 +49006,7 @@ class ContextWindowWidget {
48881
49006
  total = getContextConfig(getModelContextIdentifier(context.data.model)).maxTokens;
48882
49007
  if (total <= 0)
48883
49008
  return null;
48884
- return item.rawValue ? formatTokens(total, format) : "Win: " + formatTokens(total, format);
49009
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatTokens(total, format));
48885
49010
  }
48886
49011
  supportsRawValue() {
48887
49012
  return true;
@@ -53921,6 +54046,9 @@ var import_react27 = __toESM(require_react(), 1);
53921
54046
 
53922
54047
  // src/utils/input-guards.ts
53923
54048
  var CONTROL_CHAR_REGEX = /[\u0000-\u001F\u007F]/u;
54049
+ function getPlainInput(input2, key) {
54050
+ return key.ctrl || key.meta ? "" : input2;
54051
+ }
53924
54052
  var shouldInsertInput = (input2, key) => {
53925
54053
  if (!input2) {
53926
54054
  return false;
@@ -54207,7 +54335,8 @@ function processResult(result2, item, timedOut = false) {
54207
54335
  }
54208
54336
  const line = firstLine(result2.stdout);
54209
54337
  const cleaned = item.preserveColors ? keepSgrOnly(line) : keepSgrOnly(getVisibleText(line));
54210
- const text = applyMaxWidth(cleaned, item.maxWidth);
54338
+ const truncated = applyMaxWidth(cleaned, item.maxWidth);
54339
+ const text = truncated !== cleaned && stripSgrCodes(truncated) !== truncated ? `${truncated}\x1B[0m` : truncated;
54211
54340
  return getVisibleText(text).trim().length > 0 ? text : null;
54212
54341
  }
54213
54342
  function runSynchronously(item, context, runner) {
@@ -54475,7 +54604,82 @@ var CommandEditor = ({ widget, onComplete, onCancel }) => {
54475
54604
  }, undefined, true, undefined, this);
54476
54605
  };
54477
54606
  // src/widgets/CustomSymbol.tsx
54607
+ var import_react29 = __toESM(require_react(), 1);
54608
+
54609
+ // src/widgets/shared/text-cursor.ts
54478
54610
  var import_react28 = __toESM(require_react(), 1);
54611
+ var segmenter2 = "Segmenter" in Intl ? new Intl.Segmenter(undefined, { granularity: "grapheme" }) : null;
54612
+ function getGraphemes(str2) {
54613
+ if (segmenter2) {
54614
+ return Array.from(segmenter2.segment(str2), (seg) => seg.segment);
54615
+ }
54616
+ return Array.from(str2);
54617
+ }
54618
+ function getBoundaries(text) {
54619
+ const boundaries = [0];
54620
+ for (const grapheme of getGraphemes(text)) {
54621
+ boundaries.push((boundaries[boundaries.length - 1] ?? 0) + grapheme.length);
54622
+ }
54623
+ return boundaries;
54624
+ }
54625
+ function applyTextCursorInput(state, input2, key) {
54626
+ const { text, cursor } = state;
54627
+ const boundaries = getBoundaries(text);
54628
+ const index = boundaries.findIndex((boundary) => boundary >= cursor);
54629
+ const previous = boundaries[index - 1];
54630
+ const next = boundaries[index + 1];
54631
+ if (key.ctrl && key.leftArrow) {
54632
+ return { text, cursor: 0 };
54633
+ }
54634
+ if (key.ctrl && key.rightArrow) {
54635
+ return { text, cursor: text.length };
54636
+ }
54637
+ if (key.leftArrow) {
54638
+ return previous === undefined ? state : { text, cursor: previous };
54639
+ }
54640
+ if (key.rightArrow) {
54641
+ return next === undefined ? state : { text, cursor: next };
54642
+ }
54643
+ if (key.backspace) {
54644
+ return previous === undefined ? state : { text: text.slice(0, previous) + text.slice(cursor), cursor: previous };
54645
+ }
54646
+ if (key.delete) {
54647
+ return next === undefined ? state : { text: text.slice(0, cursor) + text.slice(next), cursor };
54648
+ }
54649
+ if (shouldInsertInput(input2, key)) {
54650
+ return { text: text.slice(0, cursor) + input2 + text.slice(cursor), cursor: cursor + input2.length };
54651
+ }
54652
+ return null;
54653
+ }
54654
+ function renderTextWithCursor({ text, cursor }) {
54655
+ let offset = 0;
54656
+ const rendered = getGraphemes(text).map((grapheme) => {
54657
+ const underCursor = offset === cursor;
54658
+ offset += grapheme.length;
54659
+ return underCursor ? `\x1B[7m${grapheme}\x1B[27m` : grapheme;
54660
+ }).join("");
54661
+ return cursor === text.length ? `${rendered}\x1B[7m \x1B[27m` : rendered;
54662
+ }
54663
+ function useTextCursor(initialText) {
54664
+ const [state, setState] = import_react28.useState({ text: initialText, cursor: initialText.length });
54665
+ const latestState = import_react28.useRef(state);
54666
+ return {
54667
+ text: state.text,
54668
+ display: renderTextWithCursor(state),
54669
+ getText: () => latestState.current.text,
54670
+ handleInput: (input2, key) => {
54671
+ const nextState = applyTextCursorInput(latestState.current, input2, key);
54672
+ if (nextState === null) {
54673
+ return false;
54674
+ }
54675
+ latestState.current = nextState;
54676
+ setState(nextState);
54677
+ return true;
54678
+ }
54679
+ };
54680
+ }
54681
+
54682
+ // src/widgets/CustomSymbol.tsx
54479
54683
  var jsx_dev_runtime3 = __toESM(require_jsx_dev_runtime(), 1);
54480
54684
 
54481
54685
  class CustomSymbolWidget {
@@ -54521,18 +54725,7 @@ class CustomSymbolWidget {
54521
54725
  }
54522
54726
  }
54523
54727
  var CustomSymbolEditor = ({ widget, onComplete, onCancel }) => {
54524
- const [symbol2, setSymbol] = import_react28.useState(widget.customSymbol ?? "");
54525
- const getFirstGrapheme = (str2) => {
54526
- if (str2.length === 0) {
54527
- return "";
54528
- }
54529
- if ("Segmenter" in Intl) {
54530
- const segmenter2 = new Intl.Segmenter(undefined, { granularity: "grapheme" });
54531
- const segments = Array.from(segmenter2.segment(str2));
54532
- return segments[0]?.segment ?? "";
54533
- }
54534
- return Array.from(str2)[0] ?? "";
54535
- };
54728
+ const [symbol2, setSymbol] = import_react29.useState(widget.customSymbol ?? "");
54536
54729
  use_input_default((input2, key) => {
54537
54730
  if (key.return) {
54538
54731
  onComplete({ ...widget, customSymbol: symbol2 });
@@ -54541,7 +54734,7 @@ var CustomSymbolEditor = ({ widget, onComplete, onCancel }) => {
54541
54734
  } else if (key.backspace || key.delete) {
54542
54735
  setSymbol("");
54543
54736
  } else if (shouldInsertInput(input2, key)) {
54544
- const firstGrapheme = getFirstGrapheme(input2);
54737
+ const firstGrapheme = getGraphemes(input2)[0] ?? "";
54545
54738
  setSymbol(firstGrapheme);
54546
54739
  }
54547
54740
  });
@@ -54570,7 +54763,6 @@ var CustomSymbolEditor = ({ widget, onComplete, onCancel }) => {
54570
54763
  }, undefined, true, undefined, this);
54571
54764
  };
54572
54765
  // src/widgets/CustomText.tsx
54573
- var import_react29 = __toESM(require_react(), 1);
54574
54766
  var jsx_dev_runtime4 = __toESM(require_jsx_dev_runtime(), 1);
54575
54767
 
54576
54768
  class CustomTextWidget {
@@ -54616,108 +54808,21 @@ class CustomTextWidget {
54616
54808
  }
54617
54809
  }
54618
54810
  var CustomTextEditor = ({ widget, onComplete, onCancel }) => {
54619
- const [text, setText] = import_react29.useState(widget.customText ?? "");
54620
- const [cursorPos, setCursorPos] = import_react29.useState(text.length);
54621
- const getGraphemes = (str2) => {
54622
- if ("Segmenter" in Intl) {
54623
- const segmenter2 = new Intl.Segmenter(undefined, { granularity: "grapheme" });
54624
- return Array.from(segmenter2.segment(str2), (seg) => seg.segment);
54625
- }
54626
- return Array.from(str2);
54627
- };
54628
- const graphemeToStringIndex = (str2, graphemeIndex) => {
54629
- const graphemes2 = getGraphemes(str2);
54630
- let stringIndex = 0;
54631
- for (let i = 0;i < Math.min(graphemeIndex, graphemes2.length); i++) {
54632
- const grapheme = graphemes2[i];
54633
- if (grapheme) {
54634
- stringIndex += grapheme.length;
54635
- }
54636
- }
54637
- return stringIndex;
54638
- };
54639
- const stringToGraphemeIndex = (str2, stringIndex) => {
54640
- const graphemes2 = getGraphemes(str2);
54641
- let currentStringIndex = 0;
54642
- for (let i = 0;i < graphemes2.length; i++) {
54643
- if (currentStringIndex >= stringIndex)
54644
- return i;
54645
- const grapheme = graphemes2[i];
54646
- if (grapheme) {
54647
- currentStringIndex += grapheme.length;
54648
- }
54649
- }
54650
- return graphemes2.length;
54651
- };
54811
+ const { getText, display, handleInput } = useTextCursor(widget.customText ?? "");
54652
54812
  use_input_default((input2, key) => {
54653
54813
  if (key.return) {
54654
- onComplete({ ...widget, customText: text });
54814
+ onComplete({ ...widget, customText: getText() });
54655
54815
  } else if (key.escape) {
54656
54816
  onCancel();
54657
- } else if (key.ctrl && key.leftArrow) {
54658
- setCursorPos(0);
54659
- } else if (key.ctrl && key.rightArrow) {
54660
- setCursorPos(text.length);
54661
- } else if (key.leftArrow) {
54662
- const currentGraphemeIndex2 = stringToGraphemeIndex(text, cursorPos);
54663
- if (currentGraphemeIndex2 > 0) {
54664
- const newStringIndex = graphemeToStringIndex(text, currentGraphemeIndex2 - 1);
54665
- setCursorPos(newStringIndex);
54666
- }
54667
- } else if (key.rightArrow) {
54668
- const currentGraphemeIndex2 = stringToGraphemeIndex(text, cursorPos);
54669
- const graphemeCount = getGraphemes(text).length;
54670
- if (currentGraphemeIndex2 < graphemeCount) {
54671
- const newStringIndex = graphemeToStringIndex(text, currentGraphemeIndex2 + 1);
54672
- setCursorPos(newStringIndex);
54673
- }
54674
- } else if (key.backspace) {
54675
- if (cursorPos > 0) {
54676
- const currentGraphemeIndex2 = stringToGraphemeIndex(text, cursorPos);
54677
- if (currentGraphemeIndex2 > 0) {
54678
- const deleteFromIndex = graphemeToStringIndex(text, currentGraphemeIndex2 - 1);
54679
- const deleteToIndex = graphemeToStringIndex(text, currentGraphemeIndex2);
54680
- setText(text.slice(0, deleteFromIndex) + text.slice(deleteToIndex));
54681
- setCursorPos(deleteFromIndex);
54682
- }
54683
- }
54684
- } else if (key.delete) {
54685
- if (cursorPos < text.length) {
54686
- const currentGraphemeIndex2 = stringToGraphemeIndex(text, cursorPos);
54687
- const graphemeCount = getGraphemes(text).length;
54688
- if (currentGraphemeIndex2 < graphemeCount) {
54689
- const deleteFromIndex = graphemeToStringIndex(text, currentGraphemeIndex2);
54690
- const deleteToIndex = graphemeToStringIndex(text, currentGraphemeIndex2 + 1);
54691
- setText(text.slice(0, deleteFromIndex) + text.slice(deleteToIndex));
54692
- }
54693
- }
54694
- } else if (shouldInsertInput(input2, key)) {
54695
- const newText = text.slice(0, cursorPos) + input2 + text.slice(cursorPos);
54696
- setText(newText);
54697
- setCursorPos(cursorPos + input2.length);
54817
+ } else {
54818
+ handleInput(input2, key);
54698
54819
  }
54699
54820
  });
54700
- const graphemes = getGraphemes(text);
54701
- const currentGraphemeIndex = stringToGraphemeIndex(text, cursorPos);
54702
- let display = "Enter custom text: ";
54703
- for (let i = 0;i < graphemes.length; i++) {
54704
- const grapheme = graphemes[i];
54705
- if (grapheme) {
54706
- if (i === currentGraphemeIndex) {
54707
- display += `\x1B[7m${grapheme}\x1B[0m`;
54708
- } else {
54709
- display += grapheme;
54710
- }
54711
- }
54712
- }
54713
- if (currentGraphemeIndex >= graphemes.length) {
54714
- display += "\x1B[7m \x1B[0m";
54715
- }
54716
54821
  return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
54717
54822
  flexDirection: "column",
54718
54823
  children: [
54719
54824
  /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
54720
- children: display
54825
+ children: `Enter custom text: ${display}`
54721
54826
  }, undefined, false, undefined, this),
54722
54827
  /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
54723
54828
  dimColor: true,
@@ -54783,17 +54888,6 @@ function renderSymbolSlotsEditor(props, slots) {
54783
54888
  slots
54784
54889
  }, undefined, false, undefined, this);
54785
54890
  }
54786
- function getFirstGrapheme(str2) {
54787
- if (str2.length === 0) {
54788
- return "";
54789
- }
54790
- if ("Segmenter" in Intl) {
54791
- const segmenter2 = new Intl.Segmenter(undefined, { granularity: "grapheme" });
54792
- const segments = Array.from(segmenter2.segment(str2));
54793
- return segments[0]?.segment ?? "";
54794
- }
54795
- return Array.from(str2)[0] ?? "";
54796
- }
54797
54891
  var SymbolSlotsEditor = ({ widget, slots, onComplete, onCancel }) => {
54798
54892
  const [values2, setValues] = import_react30.useState(() => slots.map((slot) => getSlotSymbol(widget, slot)));
54799
54893
  const [selectedIndex, setSelectedIndex] = import_react30.useState(0);
@@ -54812,7 +54906,7 @@ var SymbolSlotsEditor = ({ widget, slots, onComplete, onCancel }) => {
54812
54906
  } else if (key.backspace || key.delete) {
54813
54907
  setValues(values2.map((value, index) => index === selectedIndex ? "" : value));
54814
54908
  } else if (shouldInsertInput(input2, key)) {
54815
- const grapheme = getFirstGrapheme(input2);
54909
+ const grapheme = getGraphemes(input2)[0] ?? "";
54816
54910
  setValues(values2.map((value, index) => index === selectedIndex ? grapheme : value));
54817
54911
  }
54818
54912
  });
@@ -54885,6 +54979,9 @@ class CurrentWorkingDirWidget {
54885
54979
  getCategory() {
54886
54980
  return "Environment";
54887
54981
  }
54982
+ getLabelPrefix() {
54983
+ return "cwd: ";
54984
+ }
54888
54985
  getEditorDisplay(item) {
54889
54986
  const segments = item.metadata?.segments ? parseInt(item.metadata.segments, 10) : undefined;
54890
54987
  const fishStyle = item.metadata?.fishStyle === "true";
@@ -54955,24 +55052,13 @@ class CurrentWorkingDirWidget {
54955
55052
  let previewPath;
54956
55053
  if (fishStyle) {
54957
55054
  previewPath = "~/D/P/my-project";
54958
- } else if (abbreviateHome && segments && segments > 0) {
54959
- if (segments === 1) {
54960
- previewPath = "~/.../my-project";
54961
- } else {
54962
- previewPath = "~/.../Projects/my-project";
54963
- }
54964
- } else if (abbreviateHome) {
54965
- previewPath = "~/Documents/Projects/my-project";
54966
- } else if (segments && segments > 0) {
54967
- if (segments === 1) {
54968
- previewPath = ".../project";
54969
- } else {
54970
- previewPath = ".../example/project";
54971
- }
54972
55055
  } else {
54973
- previewPath = "/Users/example/Documents/Projects/my-project";
55056
+ previewPath = abbreviateHome ? "~/Documents/Projects/my-project" : "/Users/example/Documents/Projects/my-project";
55057
+ if (segments && segments > 0) {
55058
+ previewPath = this.keepLastSegments(previewPath, segments);
55059
+ }
54974
55060
  }
54975
- return item.rawValue ? `${symbolPrefix}${previewPath}` : `${symbolPrefix}cwd: ${previewPath}`;
55061
+ return `${symbolPrefix}${formatRawOrLabeledValue(item, this.getLabelPrefix(), previewPath)}`;
54976
55062
  }
54977
55063
  const cwd2 = context.data.session?.cwd;
54978
55064
  if (!cwd2)
@@ -54985,18 +55071,10 @@ class CurrentWorkingDirWidget {
54985
55071
  displayPath = this.abbreviateHomeDir(displayPath);
54986
55072
  }
54987
55073
  if (segments && segments > 0) {
54988
- const useBackslash = displayPath.includes("\\") && !displayPath.includes("/");
54989
- const outSep = useBackslash ? "\\" : "/";
54990
- const pathParts = displayPath.split(/[\\/]+/);
54991
- const filteredParts = pathParts.filter((part) => part !== "");
54992
- if (filteredParts.length > segments) {
54993
- const selectedSegments = filteredParts.slice(-segments);
54994
- const prefix = displayPath.startsWith("~") ? `~${outSep}` : "";
54995
- displayPath = prefix + "..." + outSep + selectedSegments.join(outSep);
54996
- }
55074
+ displayPath = this.keepLastSegments(displayPath, segments);
54997
55075
  }
54998
55076
  }
54999
- return item.rawValue ? `${symbolPrefix}${displayPath}` : `${symbolPrefix}cwd: ${displayPath}`;
55077
+ return `${symbolPrefix}${formatRawOrLabeledValue(item, this.getLabelPrefix(), displayPath)}`;
55000
55078
  }
55001
55079
  getCustomKeybinds() {
55002
55080
  return [
@@ -55020,6 +55098,18 @@ class CurrentWorkingDirWidget {
55020
55098
  supportsColors(item) {
55021
55099
  return true;
55022
55100
  }
55101
+ keepLastSegments(path, segments) {
55102
+ const useBackslash = path.includes("\\") && !path.includes("/");
55103
+ const outSep = useBackslash ? "\\" : "/";
55104
+ const pathParts = path.split(/[\\/]+/);
55105
+ const filteredParts = pathParts.filter((part) => part !== "");
55106
+ const prefix = filteredParts[0] === "~" ? `~${outSep}` : "";
55107
+ const pathSegments = prefix ? filteredParts.slice(1) : filteredParts;
55108
+ if (pathSegments.length <= segments) {
55109
+ return path;
55110
+ }
55111
+ return prefix + "..." + outSep + pathSegments.slice(-segments).join(outSep);
55112
+ }
55023
55113
  abbreviateHomeDir(path) {
55024
55114
  const homeDir = os3.homedir();
55025
55115
  if (path === homeDir) {
@@ -55035,13 +55125,9 @@ class CurrentWorkingDirWidget {
55035
55125
  return path;
55036
55126
  }
55037
55127
  abbreviatePath(path) {
55038
- const homeDir = os3.homedir();
55039
55128
  const useBackslash = path.includes("\\") && !path.includes("/");
55040
55129
  const sep = useBackslash ? "\\" : "/";
55041
- let normalizedPath = path;
55042
- if (path.startsWith(homeDir)) {
55043
- normalizedPath = "~" + path.slice(homeDir.length);
55044
- }
55130
+ const normalizedPath = this.abbreviateHomeDir(path);
55045
55131
  const parts = normalizedPath.split(/[\\/]+/).filter((part) => part !== "");
55046
55132
  const abbreviated = parts.map((part, index) => {
55047
55133
  if (index === 0 || index === parts.length - 1) {
@@ -55875,6 +55961,7 @@ class FiveHourUsageWidget {
55875
55961
  }
55876
55962
  }
55877
55963
  // src/widgets/FreeMemory.ts
55964
+ var LABEL4 = "Mem: ";
55878
55965
  function formatBytes(bytes, format) {
55879
55966
  const value = Math.max(0, bytes);
55880
55967
  if (value >= 1024 ** 3)
@@ -55902,19 +55989,22 @@ class FreeMemoryWidget {
55902
55989
  getEditorDisplay(_item) {
55903
55990
  return { displayText: this.getDisplayName() };
55904
55991
  }
55992
+ getLabelPrefix() {
55993
+ return LABEL4;
55994
+ }
55905
55995
  render(item, context, settings) {
55906
55996
  const format = resolveNumberFormat("memory", item, settings);
55907
55997
  if (context.isPreview) {
55908
55998
  const value = formatBytes(12.4 * 1024 ** 3, format) + "/" + formatBytes(16 * 1024 ** 3, format);
55909
- return item.rawValue ? value : "Mem: " + value;
55999
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), value);
55910
56000
  }
55911
56001
  const usage = context.memoryUsage;
55912
56002
  if (usage) {
55913
56003
  const value = formatBytes(usage.used, format) + "/" + formatBytes(usage.total, format);
55914
- return item.rawValue ? value : "Mem: " + value;
56004
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), value);
55915
56005
  }
55916
56006
  if (context.freeMemoryBytes !== undefined) {
55917
- return item.rawValue ? formatBytes(context.freeMemoryBytes, format) : "Mem: " + formatBytes(context.freeMemoryBytes, format);
56007
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatBytes(context.freeMemoryBytes, format));
55918
56008
  }
55919
56009
  return null;
55920
56010
  }
@@ -55956,8 +56046,10 @@ class GitBranchWidget {
55956
56046
  }
55957
56047
  render(item, context, _settings) {
55958
56048
  const prefix = formatSymbolPrefix(item, DEFAULT_SYMBOL);
55959
- if (context.isPreview)
55960
- return item.rawValue ? "main" : prefix + "main";
56049
+ if (context.isPreview) {
56050
+ const sample2 = item.maxWidth ? "feature/long-branch-name" : "main";
56051
+ return applyMaxWidth(item.rawValue ? sample2 : prefix + sample2, item.maxWidth);
56052
+ }
55961
56053
  const branch = context.data.git?.branch;
55962
56054
  if (!branch)
55963
56055
  return isHideStateEnabled(item, NO_GIT_HIDEABLE_STATE) ? null : prefix + "no git";
@@ -55978,6 +56070,67 @@ class GitBranchWidget {
55978
56070
  }
55979
56071
  // src/utils/git.ts
55980
56072
  import { spawnSync as spawnSync2 } from "node:child_process";
56073
+ import * as fs3 from "node:fs";
56074
+ import * as path2 from "node:path";
56075
+
56076
+ // src/utils/git-hardening.ts
56077
+ var GIT_HARDENING_ARGS = ["-c", "core.fsmonitor=", "-c", "safe.bareRepository=explicit"];
56078
+ var REPOSITORY_SCOPES = new Set(["local", "worktree"]);
56079
+ var FILTER_COMMAND_KEYS = new Set(["clean", "smudge", "process"]);
56080
+
56081
+ // src/utils/executable-path.ts
56082
+ import * as fs2 from "node:fs";
56083
+ import * as path from "node:path";
56084
+ var WINDOWS_EXECUTABLE_EXTENSIONS = [".com", ".exe"];
56085
+ var resolvedExecutables = new Map;
56086
+ function isFile(candidate) {
56087
+ try {
56088
+ return fs2.statSync(candidate).isFile();
56089
+ } catch {
56090
+ return false;
56091
+ }
56092
+ }
56093
+ var DEFAULT_LOOKUP = {
56094
+ platform: process.platform,
56095
+ env: process.env,
56096
+ isFile
56097
+ };
56098
+ function getPathValue(env3) {
56099
+ const key = Object.keys(env3).find((name) => name.toUpperCase() === "PATH");
56100
+ return key ? env3[key] ?? "" : "";
56101
+ }
56102
+ function findOnWindowsPath(name, lookup) {
56103
+ const candidates = path.win32.extname(name) ? [name] : WINDOWS_EXECUTABLE_EXTENSIONS.map((extension2) => `${name}${extension2}`);
56104
+ const directories = getPathValue(lookup.env).split(";").map((entry) => entry.trim().replace(/^"(.*)"$/, "$1")).filter((entry) => path.win32.isAbsolute(entry) && !entry.startsWith("\\\\?"));
56105
+ for (const directory of directories) {
56106
+ for (const candidate of candidates) {
56107
+ const fullPath = path.win32.join(directory, candidate);
56108
+ if (lookup.isFile(fullPath)) {
56109
+ return fullPath;
56110
+ }
56111
+ }
56112
+ }
56113
+ return null;
56114
+ }
56115
+ function resolveExecutable(name, lookup = DEFAULT_LOOKUP) {
56116
+ if (lookup.platform !== "win32" || /[\\/]/.test(name)) {
56117
+ return name;
56118
+ }
56119
+ const cached2 = lookup === DEFAULT_LOOKUP ? resolvedExecutables.get(name) : undefined;
56120
+ if (cached2) {
56121
+ return cached2;
56122
+ }
56123
+ const resolved = findOnWindowsPath(name, lookup);
56124
+ if (!resolved) {
56125
+ throw new Error(`${name} was not found on PATH`);
56126
+ }
56127
+ if (lookup === DEFAULT_LOOKUP) {
56128
+ resolvedExecutables.set(name, resolved);
56129
+ }
56130
+ return resolved;
56131
+ }
56132
+
56133
+ // src/utils/git.ts
55981
56134
  function parseDiffShortStat(stat) {
55982
56135
  const insertMatch = /(\d+)\s+insertions?/.exec(stat);
55983
56136
  const deleteMatch = /(\d+)\s+deletions?/.exec(stat);
@@ -55988,7 +56141,8 @@ function parseDiffShortStat(stat) {
55988
56141
  }
55989
56142
  var GIT_EXEC_TIMEOUT = 5000;
55990
56143
  var defaultGitRunner = (args, cwd2) => {
55991
- const result2 = spawnSync2("git", args, {
56144
+ const gitExecutable = resolveExecutable("git");
56145
+ const result2 = spawnSync2(gitExecutable, [...GIT_HARDENING_ARGS, ...args], {
55992
56146
  cwd: cwd2,
55993
56147
  encoding: "utf8",
55994
56148
  stdio: ["ignore", "pipe", "ignore"],
@@ -56001,12 +56155,41 @@ var defaultGitRunner = (args, cwd2) => {
56001
56155
  }
56002
56156
  return result2.stdout ?? "";
56003
56157
  };
56158
+ function isDefinitelyOutsideGitRepository(cwd2) {
56159
+ if (process.env.GIT_DIR !== undefined || process.env.GIT_WORK_TREE !== undefined || process.env.GIT_COMMON_DIR !== undefined) {
56160
+ return false;
56161
+ }
56162
+ let current;
56163
+ try {
56164
+ current = fs3.realpathSync(cwd2);
56165
+ if (!fs3.statSync(current).isDirectory()) {
56166
+ return false;
56167
+ }
56168
+ } catch {
56169
+ return false;
56170
+ }
56171
+ for (;; ) {
56172
+ for (const marker of [".git", "HEAD"]) {
56173
+ try {
56174
+ fs3.lstatSync(path2.join(current, marker));
56175
+ return false;
56176
+ } catch {}
56177
+ }
56178
+ const parent = path2.dirname(current);
56179
+ if (parent === current) {
56180
+ return true;
56181
+ }
56182
+ current = parent;
56183
+ }
56184
+ }
56004
56185
  function getGitDiffChanges(cwd2, runner = defaultGitRunner) {
56005
56186
  if (!cwd2)
56006
56187
  return null;
56188
+ if (isDefinitelyOutsideGitRepository(cwd2))
56189
+ return null;
56007
56190
  try {
56008
- const unstaged = runner(["diff", "--no-ext-diff", "--shortstat"], cwd2);
56009
- const staged = runner(["diff", "--cached", "--no-ext-diff", "--shortstat"], cwd2);
56191
+ const unstaged = runner(["diff", "--no-ext-diff", "--no-textconv", "--ignore-submodules=dirty", "--shortstat"], cwd2);
56192
+ const staged = runner(["diff", "--cached", "--no-ext-diff", "--no-textconv", "--ignore-submodules=dirty", "--shortstat"], cwd2);
56010
56193
  const unstagedCounts = parseDiffShortStat(unstaged);
56011
56194
  const stagedCounts = parseDiffShortStat(staged);
56012
56195
  return {
@@ -56068,6 +56251,8 @@ class GitChangesWidget {
56068
56251
  }
56069
56252
  }
56070
56253
  // src/widgets/GitPr.ts
56254
+ var LABEL5 = "PR #";
56255
+
56071
56256
  class GitPrWidget {
56072
56257
  getDefaultColor() {
56073
56258
  return "cyan";
@@ -56084,11 +56269,14 @@ class GitPrWidget {
56084
56269
  getEditorDisplay(_item) {
56085
56270
  return { displayText: this.getDisplayName() };
56086
56271
  }
56272
+ getLabelPrefix() {
56273
+ return LABEL5;
56274
+ }
56087
56275
  render(item, context, _settings) {
56088
56276
  const number4 = context.isPreview ? 42 : context.data.git?.pr;
56089
56277
  if (number4 === undefined)
56090
56278
  return null;
56091
- return item.rawValue ? "#" + number4 : "PR #" + number4;
56279
+ return item.rawValue ? "#" + number4 : formatRawOrLabeledValue(item, this.getLabelPrefix(), String(number4));
56092
56280
  }
56093
56281
  supportsRawValue() {
56094
56282
  return true;
@@ -56098,8 +56286,8 @@ class GitPrWidget {
56098
56286
  }
56099
56287
  }
56100
56288
  // src/widgets/GitRootDir.ts
56101
- function baseName(path) {
56102
- const trimmed = path.replace(/[\\/]+$/, "");
56289
+ function baseName(path3) {
56290
+ const trimmed = path3.replace(/[\\/]+$/, "");
56103
56291
  const parts = trimmed.split(/[\\/]/).filter(Boolean);
56104
56292
  return parts.at(-1) ?? trimmed;
56105
56293
  }
@@ -56128,8 +56316,10 @@ class GitRootDirWidget {
56128
56316
  return { displayText: this.getDisplayName(), modifierText: makeModifierText(modifiers) };
56129
56317
  }
56130
56318
  render(item, context, _settings) {
56131
- if (context.isPreview)
56132
- return "my-repo";
56319
+ if (context.isPreview) {
56320
+ const sample2 = item.maxWidth ? "my-long-repository-name" : "my-repo";
56321
+ return applyMaxWidth(sample2, item.maxWidth);
56322
+ }
56133
56323
  const root = context.data.session?.project_root;
56134
56324
  if (!root)
56135
56325
  return isHideStateEnabled(item, NO_GIT_HIDEABLE_STATE) ? null : "no git";
@@ -56227,7 +56417,7 @@ function withWidgetSpeedWindowSeconds(item, seconds) {
56227
56417
 
56228
56418
  // src/utils/speed-tracker.ts
56229
56419
  import { readFileSync as readFileSync3 } from "node:fs";
56230
- import { join as join5 } from "node:path";
56420
+ import { join as join6 } from "node:path";
56231
56421
  var memoryCache = new Map;
56232
56422
  function sanitizeCacheKey(key) {
56233
56423
  return key.replace(/[^a-zA-Z0-9_-]/g, "_");
@@ -56239,7 +56429,7 @@ function readCache(cacheDir, sessionId) {
56239
56429
  if (!cacheDir)
56240
56430
  return null;
56241
56431
  try {
56242
- const filePath = join5(cacheDir, `speed-${sanitizeCacheKey(sessionId)}.json`);
56432
+ const filePath = join6(cacheDir, `speed-${sanitizeCacheKey(sessionId)}.json`);
56243
56433
  const raw = readFileSync3(filePath, "utf8");
56244
56434
  const data = JSON.parse(raw);
56245
56435
  if (data?.version === 1 && data?.sessionId === sessionId) {
@@ -56254,7 +56444,7 @@ function writeCache(cacheDir, data) {
56254
56444
  if (!cacheDir)
56255
56445
  return;
56256
56446
  try {
56257
- const filePath = join5(cacheDir, `speed-${sanitizeCacheKey(data.sessionId)}.json`);
56447
+ const filePath = join6(cacheDir, `speed-${sanitizeCacheKey(data.sessionId)}.json`);
56258
56448
  writeFileAtomic(filePath, JSON.stringify(data, null, 2), { mode: 384 });
56259
56449
  } catch {}
56260
56450
  }
@@ -56498,6 +56688,9 @@ function calculateSpeed(kind, metrics) {
56498
56688
  function getSpeedWidgetDisplayName(kind) {
56499
56689
  return SPEED_WIDGET_CONFIG[kind].displayName;
56500
56690
  }
56691
+ function getSpeedWidgetLabel(kind) {
56692
+ return SPEED_WIDGET_CONFIG[kind].label;
56693
+ }
56501
56694
  function getSpeedWidgetDescription(kind) {
56502
56695
  return SPEED_WIDGET_CONFIG[kind].description;
56503
56696
  }
@@ -56617,6 +56810,9 @@ class InputSpeedWidget {
56617
56810
  getCategory() {
56618
56811
  return "Token Speed";
56619
56812
  }
56813
+ getLabelPrefix() {
56814
+ return getSpeedWidgetLabel("input");
56815
+ }
56620
56816
  getEditorDisplay(item) {
56621
56817
  return getSpeedWidgetEditorDisplay("input", item);
56622
56818
  }
@@ -56643,6 +56839,8 @@ class InputSpeedWidget {
56643
56839
  }
56644
56840
  }
56645
56841
  // src/widgets/Model.ts
56842
+ var LABEL6 = "Model: ";
56843
+
56646
56844
  class ModelWidget {
56647
56845
  getDefaultColor() {
56648
56846
  return "cyan";
@@ -56659,13 +56857,16 @@ class ModelWidget {
56659
56857
  getEditorDisplay(_item) {
56660
56858
  return { displayText: this.getDisplayName() };
56661
56859
  }
56860
+ getLabelPrefix() {
56861
+ return LABEL6;
56862
+ }
56662
56863
  render(item, context, _settings) {
56663
56864
  const name = context.isPreview ? "Codex" : context.data.model?.name;
56664
56865
  if (!name)
56665
56866
  return null;
56666
56867
  const suffix = name.indexOf(" (");
56667
56868
  const shortName = suffix >= 0 ? name.slice(0, suffix) : name;
56668
- return item.rawValue ? shortName : "Model: " + shortName;
56869
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), shortName);
56669
56870
  }
56670
56871
  supportsRawValue() {
56671
56872
  return true;
@@ -56688,6 +56889,9 @@ class OutputSpeedWidget {
56688
56889
  getCategory() {
56689
56890
  return "Token Speed";
56690
56891
  }
56892
+ getLabelPrefix() {
56893
+ return getSpeedWidgetLabel("output");
56894
+ }
56691
56895
  getEditorDisplay(item) {
56692
56896
  return getSpeedWidgetEditorDisplay("output", item);
56693
56897
  }
@@ -56813,6 +57017,7 @@ class SandboxStatusWidget {
56813
57017
  }
56814
57018
  }
56815
57019
  // src/widgets/SessionClock.ts
57020
+ var LABEL7 = "Session: ";
56816
57021
  var ZERO_HIDEABLE_STATE2 = { key: "zero", label: "when under 1 minute" };
56817
57022
  function formatDuration(ms) {
56818
57023
  const minutes = Math.floor(Math.max(0, ms) / 60000);
@@ -56841,6 +57046,9 @@ class SessionClockWidget {
56841
57046
  getEditorDisplay(_item) {
56842
57047
  return { displayText: this.getDisplayName() };
56843
57048
  }
57049
+ getLabelPrefix() {
57050
+ return LABEL7;
57051
+ }
56844
57052
  getHideableStates() {
56845
57053
  return [ZERO_HIDEABLE_STATE2];
56846
57054
  }
@@ -56852,7 +57060,7 @@ class SessionClockWidget {
56852
57060
  if (elapsedMs < 60000 && isHideStateEnabled(item, ZERO_HIDEABLE_STATE2))
56853
57061
  return null;
56854
57062
  const value = formatDuration(elapsedMs);
56855
- return item.rawValue ? value : "Session: " + value;
57063
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), value);
56856
57064
  }
56857
57065
  supportsRawValue() {
56858
57066
  return true;
@@ -56862,6 +57070,8 @@ class SessionClockWidget {
56862
57070
  }
56863
57071
  }
56864
57072
  // src/widgets/SessionName.ts
57073
+ var LABEL8 = "Session: ";
57074
+
56865
57075
  class SessionNameWidget {
56866
57076
  getDefaultColor() {
56867
57077
  return "cyan";
@@ -56878,11 +57088,14 @@ class SessionNameWidget {
56878
57088
  getEditorDisplay(_item) {
56879
57089
  return { displayText: this.getDisplayName() };
56880
57090
  }
57091
+ getLabelPrefix() {
57092
+ return LABEL8;
57093
+ }
56881
57094
  render(item, context, _settings) {
56882
57095
  const name = context.isPreview ? "my-session" : context.data.session?.thread_title;
56883
57096
  if (!name)
56884
57097
  return null;
56885
- return item.rawValue ? name : "Session: " + name;
57098
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), name);
56886
57099
  }
56887
57100
  supportsRawValue() {
56888
57101
  return true;
@@ -57019,6 +57232,8 @@ function getTerminalWidth(options) {
57019
57232
  }
57020
57233
 
57021
57234
  // src/widgets/TerminalWidth.ts
57235
+ var LABEL9 = "Term: ";
57236
+
57022
57237
  class TerminalWidthWidget {
57023
57238
  getDefaultColor() {
57024
57239
  return "gray";
@@ -57032,6 +57247,9 @@ class TerminalWidthWidget {
57032
57247
  getCategory() {
57033
57248
  return "Environment";
57034
57249
  }
57250
+ getLabelPrefix() {
57251
+ return LABEL9;
57252
+ }
57035
57253
  getEditorDisplay(item) {
57036
57254
  return { displayText: this.getDisplayName() };
57037
57255
  }
@@ -57039,9 +57257,9 @@ class TerminalWidthWidget {
57039
57257
  const width = context.terminalWidth ?? getTerminalWidth();
57040
57258
  if (context.isPreview) {
57041
57259
  const detectedWidth = width ?? "??";
57042
- return item.rawValue ? `${detectedWidth}` : `Term: ${detectedWidth}`;
57260
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), `${detectedWidth}`);
57043
57261
  } else if (width) {
57044
- return item.rawValue ? `${width}` : `Term: ${width}`;
57262
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), `${width}`);
57045
57263
  }
57046
57264
  return null;
57047
57265
  }
@@ -57053,6 +57271,8 @@ class TerminalWidthWidget {
57053
57271
  }
57054
57272
  }
57055
57273
  // src/widgets/ThinkingEffort.ts
57274
+ var LABEL10 = "Thinking: ";
57275
+
57056
57276
  class ThinkingEffortWidget {
57057
57277
  getDefaultColor() {
57058
57278
  return "magenta";
@@ -57069,11 +57289,14 @@ class ThinkingEffortWidget {
57069
57289
  getEditorDisplay(_item) {
57070
57290
  return { displayText: this.getDisplayName() };
57071
57291
  }
57292
+ getLabelPrefix() {
57293
+ return LABEL10;
57294
+ }
57072
57295
  render(item, context, _settings) {
57073
57296
  const effort = context.isPreview ? "high" : context.data.model?.reasoning;
57074
57297
  if (!effort)
57075
57298
  return null;
57076
- return item.rawValue ? effort : "Thinking: " + effort;
57299
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), effort);
57077
57300
  }
57078
57301
  supportsRawValue() {
57079
57302
  return true;
@@ -57099,19 +57322,22 @@ class TokensCachedWidget {
57099
57322
  getEditorDisplay(_item) {
57100
57323
  return { displayText: this.getDisplayName() };
57101
57324
  }
57325
+ getLabelPrefix() {
57326
+ return "Cached: ";
57327
+ }
57102
57328
  getHideableStates() {
57103
57329
  return [ZERO_HIDEABLE_STATE];
57104
57330
  }
57105
57331
  render(item, context, settings) {
57106
57332
  const format = resolveNumberFormat("token", item, settings);
57107
57333
  if (context.isPreview)
57108
- return formatRawOrLabeledValue(item, "Cached: ", formatTokens(12000, format, 0));
57334
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatTokens(12000, format, 0));
57109
57335
  const value = context.data.usage?.cached_input_tokens ?? null;
57110
57336
  if (value === null)
57111
57337
  return null;
57112
57338
  if (value === 0 && isHideStateEnabled(item, ZERO_HIDEABLE_STATE))
57113
57339
  return null;
57114
- return formatRawOrLabeledValue(item, "Cached: ", formatTokens(value, format));
57340
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatTokens(value, format));
57115
57341
  }
57116
57342
  supportsRawValue() {
57117
57343
  return true;
@@ -57140,19 +57366,22 @@ class TokensInputWidget {
57140
57366
  getEditorDisplay(_item) {
57141
57367
  return { displayText: this.getDisplayName() };
57142
57368
  }
57369
+ getLabelPrefix() {
57370
+ return "In: ";
57371
+ }
57143
57372
  getHideableStates() {
57144
57373
  return [ZERO_HIDEABLE_STATE];
57145
57374
  }
57146
57375
  render(item, context, settings) {
57147
57376
  const format = resolveNumberFormat("token", item, settings);
57148
57377
  if (context.isPreview)
57149
- return formatRawOrLabeledValue(item, "In: ", formatTokens(15200, format));
57378
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatTokens(15200, format));
57150
57379
  const value = context.data.usage?.input_tokens ?? null;
57151
57380
  if (value === null)
57152
57381
  return null;
57153
57382
  if (value === 0 && isHideStateEnabled(item, ZERO_HIDEABLE_STATE))
57154
57383
  return null;
57155
- return formatRawOrLabeledValue(item, "In: ", formatTokens(value, format));
57384
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatTokens(value, format));
57156
57385
  }
57157
57386
  supportsRawValue() {
57158
57387
  return true;
@@ -57181,19 +57410,22 @@ class TokensOutputWidget {
57181
57410
  getEditorDisplay(_item) {
57182
57411
  return { displayText: this.getDisplayName() };
57183
57412
  }
57413
+ getLabelPrefix() {
57414
+ return "Out: ";
57415
+ }
57184
57416
  getHideableStates() {
57185
57417
  return [ZERO_HIDEABLE_STATE];
57186
57418
  }
57187
57419
  render(item, context, settings) {
57188
57420
  const format = resolveNumberFormat("token", item, settings);
57189
57421
  if (context.isPreview)
57190
- return formatRawOrLabeledValue(item, "Out: ", formatTokens(3400, format));
57422
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatTokens(3400, format));
57191
57423
  const value = context.data.usage?.output_tokens ?? null;
57192
57424
  if (value === null)
57193
57425
  return null;
57194
57426
  if (value === 0 && isHideStateEnabled(item, ZERO_HIDEABLE_STATE))
57195
57427
  return null;
57196
- return formatRawOrLabeledValue(item, "Out: ", formatTokens(value, format));
57428
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatTokens(value, format));
57197
57429
  }
57198
57430
  supportsRawValue() {
57199
57431
  return true;
@@ -57222,19 +57454,22 @@ class TokensTotalWidget {
57222
57454
  getEditorDisplay(_item) {
57223
57455
  return { displayText: this.getDisplayName() };
57224
57456
  }
57457
+ getLabelPrefix() {
57458
+ return "Total: ";
57459
+ }
57225
57460
  getHideableStates() {
57226
57461
  return [ZERO_HIDEABLE_STATE];
57227
57462
  }
57228
57463
  render(item, context, settings) {
57229
57464
  const format = resolveNumberFormat("token", item, settings);
57230
57465
  if (context.isPreview)
57231
- return formatRawOrLabeledValue(item, "Total: ", formatTokens(30600, format));
57466
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatTokens(30600, format));
57232
57467
  const value = context.data.usage && context.data.usage.input_tokens !== undefined && context.data.usage.output_tokens !== undefined ? context.data.usage.input_tokens + context.data.usage.output_tokens : null;
57233
57468
  if (value === null)
57234
57469
  return null;
57235
57470
  if (value === 0 && isHideStateEnabled(item, ZERO_HIDEABLE_STATE))
57236
57471
  return null;
57237
- return formatRawOrLabeledValue(item, "Total: ", formatTokens(value, format));
57472
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), formatTokens(value, format));
57238
57473
  }
57239
57474
  supportsRawValue() {
57240
57475
  return true;
@@ -57260,6 +57495,9 @@ class TotalSpeedWidget {
57260
57495
  getCategory() {
57261
57496
  return "Token Speed";
57262
57497
  }
57498
+ getLabelPrefix() {
57499
+ return getSpeedWidgetLabel("total");
57500
+ }
57263
57501
  getEditorDisplay(item) {
57264
57502
  return getSpeedWidgetEditorDisplay("total", item);
57265
57503
  }
@@ -57286,6 +57524,8 @@ class TotalSpeedWidget {
57286
57524
  }
57287
57525
  }
57288
57526
  // src/widgets/Version.ts
57527
+ var LABEL11 = "v";
57528
+
57289
57529
  class VersionWidget {
57290
57530
  getDefaultColor() {
57291
57531
  return "gray";
@@ -57302,11 +57542,14 @@ class VersionWidget {
57302
57542
  getEditorDisplay(_item) {
57303
57543
  return { displayText: this.getDisplayName() };
57304
57544
  }
57545
+ getLabelPrefix() {
57546
+ return LABEL11;
57547
+ }
57305
57548
  render(item, context, _settings) {
57306
57549
  const version2 = context.isPreview ? "0.152.1" : context.data.session?.codex_version;
57307
57550
  if (!version2)
57308
57551
  return null;
57309
- return item.rawValue ? version2 : "v" + version2;
57552
+ return formatRawOrLabeledValue(item, this.getLabelPrefix(), version2);
57310
57553
  }
57311
57554
  supportsRawValue() {
57312
57555
  return true;
@@ -57669,23 +57912,27 @@ function getWidget(type) {
57669
57912
  }
57670
57913
 
57671
57914
  // src/utils/powerline-theme-index.ts
57672
- function countPowerlineThemeSlots(entries) {
57915
+ function assignPowerlineThemeSlots(widgets, startSlot = 0, isShown = () => true) {
57673
57916
  let previousVisibleWidget = null;
57674
- let slotCount = 0;
57675
- for (const entry of entries) {
57676
- if (entry.widget.type === "separator" || entry.widget.type === "flex-separator") {
57917
+ let nextSlot = startSlot;
57918
+ const slots = widgets.map((widget, index) => {
57919
+ if (widget.type === "separator" || widget.type === "flex-separator") {
57677
57920
  previousVisibleWidget = null;
57678
- continue;
57921
+ return null;
57679
57922
  }
57680
- if (!entry.content) {
57681
- continue;
57923
+ if (!isShown(index)) {
57924
+ return null;
57682
57925
  }
57683
57926
  if (!previousVisibleWidget?.merge) {
57684
- slotCount++;
57927
+ nextSlot++;
57685
57928
  }
57686
- previousVisibleWidget = entry.widget;
57687
- }
57688
- return slotCount;
57929
+ previousVisibleWidget = widget;
57930
+ return nextSlot - 1;
57931
+ });
57932
+ return { slots, nextSlot };
57933
+ }
57934
+ function countPowerlineThemeSlots(entries) {
57935
+ return assignPowerlineThemeSlots(entries.map((entry) => entry.widget), 0, (index) => Boolean(entries[index]?.content)).nextSlot;
57689
57936
  }
57690
57937
  function advanceGlobalPowerlineThemeIndex(currentIndex, entries) {
57691
57938
  return currentIndex + countPowerlineThemeSlots(entries);
@@ -57730,6 +57977,88 @@ function advanceGlobalSeparatorIndex(currentIndex, widgets, preRenderedWidgets)
57730
57977
  return currentIndex + countSeparatorSlots(widgets, preRenderedWidgets);
57731
57978
  }
57732
57979
 
57980
+ // src/utils/terminal-sanitize.ts
57981
+ var ESC4 = "\x1B";
57982
+ var BEL4 = "\x07";
57983
+ var C1_ST = "œ";
57984
+ var SGR = /\x1b\[[0-9;:]*m/y;
57985
+ var OSC8 = /\x1b\]8;[A-Za-z0-9=:_.-]*;[^\x00-\x20\x7f-\x9f]*(?:\x1b\\|\x07)/y;
57986
+ var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f]/;
57987
+ var CONTROL_GLOBAL = /[\x00-\x08\x0b-\x1f\x7f-\x9f]/g;
57988
+ var STRING_INTRODUCERS = new Set(["]", "P", "X", "^", "_"]);
57989
+ function matchAt(pattern, text, index) {
57990
+ pattern.lastIndex = index;
57991
+ return pattern.exec(text)?.[0] ?? null;
57992
+ }
57993
+ function isCsiParameterOrIntermediate(code) {
57994
+ return code >= 32 && code <= 63;
57995
+ }
57996
+ function isIntermediate(code) {
57997
+ return code >= 32 && code <= 47;
57998
+ }
57999
+ function skipEscapeSequence(text, index) {
58000
+ const introducer = text[index + 1];
58001
+ if (introducer === undefined) {
58002
+ return index + 1;
58003
+ }
58004
+ if (introducer === "[") {
58005
+ let end = index + 2;
58006
+ while (end < text.length && isCsiParameterOrIntermediate(text.charCodeAt(end))) {
58007
+ end++;
58008
+ }
58009
+ const final = text.charCodeAt(end);
58010
+ return final >= 64 && final <= 126 ? end + 1 : end;
58011
+ }
58012
+ if (STRING_INTRODUCERS.has(introducer)) {
58013
+ for (let end = index + 2;end < text.length; end++) {
58014
+ const char = text[end];
58015
+ if (char === BEL4 || char === C1_ST) {
58016
+ return end + 1;
58017
+ }
58018
+ if (char === ESC4) {
58019
+ return text[end + 1] === "\\" ? end + 2 : end;
58020
+ }
58021
+ }
58022
+ return text.length;
58023
+ }
58024
+ if (isIntermediate(introducer.charCodeAt(0))) {
58025
+ let end = index + 2;
58026
+ while (end < text.length && isIntermediate(text.charCodeAt(end))) {
58027
+ end++;
58028
+ }
58029
+ const final = text.charCodeAt(end);
58030
+ return final >= 48 && final <= 126 ? end + 1 : end;
58031
+ }
58032
+ return index + 2;
58033
+ }
58034
+ function sanitizeTerminalText(text) {
58035
+ if (!CONTROL.test(text)) {
58036
+ return text;
58037
+ }
58038
+ let result2 = "";
58039
+ let index = 0;
58040
+ while (index < text.length) {
58041
+ const char = text[index];
58042
+ if (char === ESC4) {
58043
+ const kept = matchAt(SGR, text, index) ?? matchAt(OSC8, text, index);
58044
+ if (kept) {
58045
+ result2 += kept;
58046
+ index += kept.length;
58047
+ } else {
58048
+ index = skipEscapeSequence(text, index);
58049
+ }
58050
+ continue;
58051
+ }
58052
+ let end = index;
58053
+ while (end < text.length && text[end] !== ESC4) {
58054
+ end++;
58055
+ }
58056
+ result2 += text.slice(index, end).replace(CONTROL_GLOBAL, "");
58057
+ index = end;
58058
+ }
58059
+ return result2;
58060
+ }
58061
+
57733
58062
  // src/utils/renderer.ts
57734
58063
  var WIDGET_CONTROL_CHARS = /[\u0000-\u001F\u007F-\u009F]/g;
57735
58064
  function sanitizeRawText(text) {
@@ -57738,9 +58067,6 @@ function sanitizeRawText(text) {
57738
58067
  function sanitizeStringArray(value, fallback) {
57739
58068
  return Array.isArray(value) ? value.filter((item) => typeof item === "string").map(sanitizeRawText) : fallback;
57740
58069
  }
57741
- function reapplyBackground(content, bgCode) {
57742
- return content.replace(/\x1b\[(?:0|49)m/g, (m) => m + bgCode);
57743
- }
57744
58070
  function resolveStyledText(content, styled, settings, colorLevel) {
57745
58071
  if (!styled)
57746
58072
  return { text: content, styled: false };
@@ -57796,29 +58122,30 @@ function resolveEffectiveTerminalWidth(detectedWidth, settings, context) {
57796
58122
  if (!detectedWidth) {
57797
58123
  return null;
57798
58124
  }
58125
+ const remaining = (reserved) => Math.max(0, detectedWidth - reserved);
57799
58126
  const flexMode = settings.flexMode;
57800
58127
  if (context.isPreview) {
57801
58128
  if (flexMode === "full") {
57802
- return detectedWidth - 6;
58129
+ return remaining(6);
57803
58130
  }
57804
58131
  if (flexMode === "full-minus-40") {
57805
- return detectedWidth - 40;
58132
+ return remaining(40);
57806
58133
  }
57807
58134
  if (flexMode === "full-until-compact") {
57808
- return detectedWidth - 6;
58135
+ return remaining(6);
57809
58136
  }
57810
58137
  return null;
57811
58138
  }
57812
58139
  if (flexMode === "full") {
57813
- return detectedWidth - 6;
58140
+ return remaining(6);
57814
58141
  }
57815
58142
  if (flexMode === "full-minus-40") {
57816
- return detectedWidth - 40;
58143
+ return remaining(40);
57817
58144
  }
57818
58145
  if (flexMode === "full-until-compact") {
57819
58146
  const threshold = settings.compactThreshold;
57820
58147
  const contextPercentage = (context.data.usage?.context_used ?? 0) * 100;
57821
- return contextPercentage >= threshold ? detectedWidth - 40 : detectedWidth - 6;
58148
+ return contextPercentage >= threshold ? remaining(40) : remaining(6);
57822
58149
  }
57823
58150
  return null;
57824
58151
  }
@@ -58083,7 +58410,7 @@ function renderPowerlineStatusLine(widgets, settings, context, lineIndex = 0, gl
58083
58410
  powerlineGradientColumn = gradientResult.nextColumn;
58084
58411
  } else if (isStyled && widget.bgColor) {
58085
58412
  const bgCode = getColorAnsiCode(widget.bgColor, colorLevel, true);
58086
- widgetContent += reapplyBackground(styledContent, bgCode);
58413
+ widgetContent += restoreBackgroundAfterResets(styledContent, bgCode);
58087
58414
  } else {
58088
58415
  widgetContent += styledContent;
58089
58416
  }
@@ -58201,7 +58528,7 @@ function renderPowerlineStatusLine(widgets, settings, context, lineIndex = 0, gl
58201
58528
  }
58202
58529
  }
58203
58530
  if (totalFlexCount > 0) {
58204
- if (terminalWidth && terminalWidth > 0) {
58531
+ if (terminalWidth !== null) {
58205
58532
  const parts = result2.split(FLEX_SENTINEL);
58206
58533
  const totalContentWidth = parts.reduce((sum2, p) => sum2 + getVisibleWidth(p), 0);
58207
58534
  const flexCount = parts.length - 1;
@@ -58221,7 +58548,7 @@ function renderPowerlineStatusLine(widgets, settings, context, lineIndex = 0, gl
58221
58548
  if (colorLevel !== "none") {
58222
58549
  result2 += "\x1B[0m";
58223
58550
  }
58224
- if (terminalWidth && terminalWidth > 0) {
58551
+ if (terminalWidth !== null) {
58225
58552
  const plainLength = getVisibleWidth(result2);
58226
58553
  if (plainLength > terminalWidth) {
58227
58554
  result2 = truncateStyledText(result2, terminalWidth, { ellipsis: true });
@@ -58329,7 +58656,7 @@ function preRenderAllWidgets(allLinesWidgets, settings, context) {
58329
58656
  try {
58330
58657
  const widgetImpl = getWidget(widget.type);
58331
58658
  const effectiveWidget = settings.minimalistMode ? { ...widget, rawValue: true } : widget;
58332
- const rawText = widgetImpl.render(effectiveWidget, context, settings) ?? "";
58659
+ const rawText = sanitizeTerminalText(widgetImpl.render(effectiveWidget, context, settings) ?? "");
58333
58660
  styled = widgetImpl.emitsStyledOutput?.(effectiveWidget) === true && rawText.includes("\x1B");
58334
58661
  widgetText = styled ? keepSgrOnly(rawText) : sanitizeRawText(rawText);
58335
58662
  } catch {
@@ -58493,7 +58820,7 @@ function renderStatusLine(widgets, settings, context, preRenderedWidgets, preCal
58493
58820
  continue;
58494
58821
  }
58495
58822
  if (widget.type === "flex-separator") {
58496
- elements.push({ content: "FLEX", type: "flex-separator", widget });
58823
+ elements.push({ content: "", type: "flex-separator", widget });
58497
58824
  hasFlexSeparator = true;
58498
58825
  continue;
58499
58826
  }
@@ -58517,7 +58844,7 @@ function renderStatusLine(widgets, settings, context, preRenderedWidgets, preCal
58517
58844
  const bg = settings.overrideBackgroundColor && settings.overrideBackgroundColor !== "none" ? settings.overrideBackgroundColor : widget.backgroundColor;
58518
58845
  if (bg) {
58519
58846
  const bgCode = getColorAnsiCode(bg, colorLevel, true);
58520
- content = `${bgCode}${reapplyBackground(widgetText, bgCode)}\x1B[0m`;
58847
+ content = `${bgCode}${restoreBackgroundAfterResets(widgetText, bgCode)}\x1B[0m`;
58521
58848
  } else {
58522
58849
  content = `${widgetText}\x1B[0m`;
58523
58850
  }
@@ -58539,7 +58866,7 @@ function renderStatusLine(widgets, settings, context, preRenderedWidgets, preCal
58539
58866
  while (elements.length > 0 && elements[elements.length - 1]?.type === "separator") {
58540
58867
  elements.pop();
58541
58868
  }
58542
- if (!terminalWidth) {
58869
+ if (terminalWidth === null) {
58543
58870
  for (let i = elements.length - 1;i >= 0; i--) {
58544
58871
  if (elements[i]?.type !== "separator" || !isSpacingSeparator(elements[i]?.widget, settings.defaultSeparator)) {
58545
58872
  continue;
@@ -58577,7 +58904,9 @@ function renderStatusLine(widgets, settings, context, preRenderedWidgets, preCal
58577
58904
  finalElements.push(defaultSep);
58578
58905
  }
58579
58906
  }
58580
- if (elem.type === "separator" || elem.type === "flex-separator") {
58907
+ if (elem.type === "flex-separator") {
58908
+ finalElements.push(null);
58909
+ } else if (elem.type === "separator") {
58581
58910
  finalElements.push(elem.content);
58582
58911
  } else {
58583
58912
  const nextElem = index < elements.length - 1 ? elements[index + 1] : null;
@@ -58599,11 +58928,11 @@ function renderStatusLine(widgets, settings, context, preRenderedWidgets, preCal
58599
58928
  }
58600
58929
  });
58601
58930
  let statusLine;
58602
- if (hasFlexSeparator && terminalWidth) {
58931
+ if (hasFlexSeparator && terminalWidth !== null) {
58603
58932
  const parts = [[]];
58604
58933
  let currentPart = 0;
58605
58934
  for (const elem of finalElements) {
58606
- if (elem === "FLEX") {
58935
+ if (elem === null) {
58607
58936
  currentPart++;
58608
58937
  parts[currentPart] = [];
58609
58938
  } else {
@@ -58630,15 +58959,13 @@ function renderStatusLine(widgets, settings, context, preRenderedWidgets, preCal
58630
58959
  statusLine += " ".repeat(spaces);
58631
58960
  }
58632
58961
  }
58962
+ } else if (hasFlexSeparator) {
58963
+ statusLine = finalElements.map((e) => e ?? applyColorsWithOverride(" | ", "brightBlack")).join("");
58633
58964
  } else {
58634
- if (hasFlexSeparator && !terminalWidth) {
58635
- statusLine = finalElements.map((e) => e === "FLEX" ? applyColorsWithOverride(" | ", "brightBlack") : e).join("");
58636
- } else {
58637
- statusLine = finalElements.join("");
58638
- }
58965
+ statusLine = finalElements.join("");
58639
58966
  }
58640
58967
  const maxWidth = terminalWidth ?? detectedWidth;
58641
- if (maxWidth && maxWidth > 0) {
58968
+ if (maxWidth !== null && (terminalWidth !== null || maxWidth > 0)) {
58642
58969
  const plainLength = getVisibleWidth(statusLine);
58643
58970
  if (plainLength > maxWidth) {
58644
58971
  statusLine = truncateStyledText(statusLine, maxWidth, { ellipsis: true });
@@ -58649,8 +58976,8 @@ function renderStatusLine(widgets, settings, context, preRenderedWidgets, preCal
58649
58976
  }
58650
58977
 
58651
58978
  // src/utils/config.ts
58652
- import { lstat, mkdir, readFile, readlink, realpath, rename, unlink, writeFile } from "node:fs/promises";
58653
- import { basename, dirname as dirname3, resolve } from "node:path";
58979
+ import { lstat, mkdir, readFile, readlink, realpath, rename, stat, unlink, writeFile } from "node:fs/promises";
58980
+ import { basename, dirname as dirname4, resolve } from "node:path";
58654
58981
 
58655
58982
  // src/types/FlexMode.ts
58656
58983
  var FlexModeSchema = exports_external.enum(["full", "full-minus-40", "full-until-compact"]);
@@ -58876,29 +59203,37 @@ async function resolveSymlinkTarget(linkPath) {
58876
59203
  } catch (error61) {
58877
59204
  if (errorCode(error61) !== "ENOENT")
58878
59205
  throw error61;
58879
- return resolve(dirname3(linkPath), await readlink(linkPath));
59206
+ return resolve(dirname4(linkPath), await readlink(linkPath));
58880
59207
  }
58881
59208
  }
58882
59209
  async function resolveAtomicWriteTarget(file2) {
58883
59210
  try {
58884
59211
  if (!(await lstat(file2)).isSymbolicLink()) {
58885
- return { targetPath: file2, tempDir: dirname3(file2) };
59212
+ return { targetPath: file2, tempDir: dirname4(file2) };
58886
59213
  }
58887
59214
  const targetPath = await resolveSymlinkTarget(file2);
58888
- return { targetPath, tempDir: dirname3(targetPath) };
59215
+ return { targetPath, tempDir: dirname4(targetPath) };
58889
59216
  } catch (error61) {
58890
59217
  if (errorCode(error61) === "ENOENT")
58891
- return { targetPath: file2, tempDir: dirname3(file2) };
59218
+ return { targetPath: file2, tempDir: dirname4(file2) };
58892
59219
  throw error61;
58893
59220
  }
58894
59221
  }
59222
+ async function getReplacedFileMode(filePath) {
59223
+ try {
59224
+ return (await stat(filePath)).mode & 511;
59225
+ } catch {
59226
+ return 438;
59227
+ }
59228
+ }
58895
59229
  async function writeSettingsJson(file2, settings) {
58896
- await mkdir(dirname3(file2), { recursive: true });
59230
+ await mkdir(dirname4(file2), { recursive: true });
58897
59231
  const target = await resolveAtomicWriteTarget(file2);
58898
59232
  await mkdir(target.tempDir, { recursive: true });
58899
59233
  const tempPath = resolve(target.tempDir, `${basename(target.targetPath)}.${process.pid}.${Date.now()}.tmp`);
59234
+ const mode = await getReplacedFileMode(target.targetPath);
58900
59235
  try {
58901
- await writeFile(tempPath, JSON.stringify(settings, null, 2), "utf8");
59236
+ await writeFile(tempPath, JSON.stringify(settings, null, 2), { encoding: "utf8", mode });
58902
59237
  await rename(tempPath, target.targetPath);
58903
59238
  } catch (error61) {
58904
59239
  await unlink(tempPath).catch(() => {
@@ -58978,16 +59313,16 @@ async function runRender(stdin, deps) {
58978
59313
  }
58979
59314
 
58980
59315
  // src/commands/refresh-command.ts
58981
- import { lstatSync as lstatSync2, readdirSync, unlinkSync as unlinkSync2 } from "node:fs";
58982
- import { join as join6 } from "node:path";
59316
+ import { lstatSync as lstatSync3, readdirSync, unlinkSync as unlinkSync2 } from "node:fs";
59317
+ import { join as join7 } from "node:path";
58983
59318
  function evictOldEntries(dir, now2) {
58984
59319
  try {
58985
59320
  const entries = readdirSync(dir);
58986
59321
  for (const entry of entries) {
58987
59322
  if (entry.endsWith(".json") || entry.startsWith(".") && entry.endsWith(".tmp")) {
58988
- const filePath = join6(dir, entry);
59323
+ const filePath = join7(dir, entry);
58989
59324
  try {
58990
- const st = lstatSync2(filePath);
59325
+ const st = lstatSync3(filePath);
58991
59326
  if (now2 - st.mtimeMs > CACHE_MAX_AGE_MS) {
58992
59327
  unlinkSync2(filePath);
58993
59328
  }
@@ -59001,7 +59336,7 @@ function runRefreshCommand(cacheKey2, deps) {
59001
59336
  return 2;
59002
59337
  }
59003
59338
  const paths = resolvePaths(deps.env);
59004
- const docPath = join6(paths.commandCacheDir, `${cacheKey2}.json`);
59339
+ const docPath = join7(paths.commandCacheDir, `${cacheKey2}.json`);
59005
59340
  const doc2 = readDocument(docPath, deps.now ?? Date.now);
59006
59341
  if (doc2 === "miss") {
59007
59342
  return 0;
@@ -59035,27 +59370,27 @@ function runRefreshCommand(cacheKey2, deps) {
59035
59370
  return 0;
59036
59371
  }
59037
59372
  // src/version-info.ts
59038
- var VERSION = "0.14.0";
59039
- var SOURCE_COMMIT = /^[0-9a-f]{40}$/.test("7da2284cff946dc0ff5c195c6521995e3e7c4dc2") ? "7da2284cff946dc0ff5c195c6521995e3e7c4dc2" : null;
59373
+ var VERSION = "0.15.0";
59374
+ var SOURCE_COMMIT = /^[0-9a-f]{40}$/.test("d2eca924591bfeb5dea069eefd2a7867267c9f51") ? "d2eca924591bfeb5dea069eefd2a7867267c9f51" : null;
59040
59375
  var SOURCE_DIRTY = false;
59041
59376
 
59042
59377
  // src/context.ts
59043
- import { existsSync as existsSync3, realpathSync } from "node:fs";
59378
+ import { existsSync as existsSync3, realpathSync as realpathSync2 } from "node:fs";
59044
59379
  import { spawnSync as spawnSync4 } from "node:child_process";
59045
59380
  import { fileURLToPath } from "node:url";
59046
59381
 
59047
59382
  // src/patch/preflight.ts
59048
59383
  import { accessSync, constants as constants2, existsSync as existsSync2, statfsSync } from "node:fs";
59049
- import { dirname as dirname4, join as join8 } from "node:path";
59384
+ import { dirname as dirname5, join as join9 } from "node:path";
59050
59385
  import { spawnSync as spawnSync3 } from "node:child_process";
59051
59386
 
59052
59387
  // src/patch/package-assemble.ts
59053
- import { join as join7 } from "node:path";
59388
+ import { join as join8 } from "node:path";
59054
59389
  var PYTHON_CANDIDATES = ["python3.13", "python3.12", "python3.11", "python3.10", "python3"];
59055
59390
  var PYTHON_VERSION_CHECK = "import sys; sys.exit(sys.version_info < (3, 10))";
59056
59391
  function assembleArgs(input2) {
59057
59392
  const args = [
59058
- join7(input2.upstream, "scripts", "build_codex_package.py"),
59393
+ join8(input2.upstream, "scripts", "build_codex_package.py"),
59059
59394
  "--variant",
59060
59395
  "codex",
59061
59396
  "--target",
@@ -59189,7 +59524,7 @@ function prebuiltPreflight(deps, paths) {
59189
59524
  }
59190
59525
  function whichReal(cmd) {
59191
59526
  for (const dir of (process.env.PATH ?? "").split(":").filter(Boolean)) {
59192
- const p = join8(dir, cmd);
59527
+ const p = join9(dir, cmd);
59193
59528
  try {
59194
59529
  accessSync(p, constants2.X_OK);
59195
59530
  return p;
@@ -59197,10 +59532,10 @@ function whichReal(cmd) {
59197
59532
  }
59198
59533
  return null;
59199
59534
  }
59200
- function nearestExisting(path) {
59201
- let p = path;
59535
+ function nearestExisting(path3) {
59536
+ let p = path3;
59202
59537
  while (!existsSync2(p)) {
59203
- const parent = dirname4(p);
59538
+ const parent = dirname5(p);
59204
59539
  if (parent === p)
59205
59540
  return p;
59206
59541
  p = parent;
@@ -59214,8 +59549,8 @@ function realDeps() {
59214
59549
  const r = spawnSync3(cmd, args, { encoding: "utf8", cwd: opts?.cwd });
59215
59550
  return { status: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
59216
59551
  },
59217
- freeBytes: (path) => {
59218
- const s = statfsSync(nearestExisting(path));
59552
+ freeBytes: (path3) => {
59553
+ const s = statfsSync(nearestExisting(path3));
59219
59554
  return Number(s.bavail) * Number(s.bsize);
59220
59555
  }
59221
59556
  };
@@ -59225,7 +59560,7 @@ function realDeps() {
59225
59560
  function ownBinary(paths) {
59226
59561
  if (existsSync3(paths.rendererLink))
59227
59562
  return paths.rendererLink;
59228
- return realpathSync(process.argv[1] ?? paths.rendererLink);
59563
+ return realpathSync2(process.argv[1] ?? paths.rendererLink);
59229
59564
  }
59230
59565
  function realContext(env3, io) {
59231
59566
  const paths = resolvePaths(env3);
@@ -59260,11 +59595,11 @@ function realContext(env3, io) {
59260
59595
 
59261
59596
  // src/patch/run.ts
59262
59597
  import { appendFileSync, mkdirSync as mkdirSync9, rmSync as rmSync6 } from "node:fs";
59263
- import { join as join19 } from "node:path";
59598
+ import { join as join20 } from "node:path";
59264
59599
 
59265
59600
  // src/lock.ts
59266
59601
  import { closeSync, existsSync as existsSync4, mkdirSync as mkdirSync3, openSync, readFileSync as readFileSync4, unlinkSync as unlinkSync3, writeSync } from "node:fs";
59267
- import { dirname as dirname5 } from "node:path";
59602
+ import { dirname as dirname6 } from "node:path";
59268
59603
  function pidAlive(pid) {
59269
59604
  try {
59270
59605
  process.kill(pid, 0);
@@ -59284,7 +59619,7 @@ function lockHolder(file2) {
59284
59619
  }
59285
59620
  }
59286
59621
  function acquireLock(file2, isAlive = pidAlive) {
59287
- mkdirSync3(dirname5(file2), { recursive: true });
59622
+ mkdirSync3(dirname6(file2), { recursive: true });
59288
59623
  for (let attempt2 = 0;attempt2 < 2; attempt2++) {
59289
59624
  try {
59290
59625
  const fd = openSync(file2, "wx");
@@ -59364,12 +59699,12 @@ function behindWithinMinor(upstream, patched) {
59364
59699
 
59365
59700
  // src/distribution/prebuilt.ts
59366
59701
  import { chmodSync as chmodSync2, copyFileSync, mkdirSync as mkdirSync6, mkdtempSync, readFileSync as readFileSync7, renameSync as renameSync4, rmSync as rmSync2 } from "node:fs";
59367
- import { join as join12 } from "node:path";
59702
+ import { join as join13 } from "node:path";
59368
59703
 
59369
59704
  // src/patch/generation.ts
59370
- import { chmodSync, cpSync, existsSync as existsSync5, lstatSync as lstatSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync6, readdirSync as readdirSync2, readlinkSync, realpathSync as realpathSync2, renameSync as renameSync2, rmSync, statSync, symlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
59705
+ import { chmodSync, cpSync, existsSync as existsSync5, lstatSync as lstatSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync6, readdirSync as readdirSync2, readlinkSync, realpathSync as realpathSync3, renameSync as renameSync2, rmSync, statSync as statSync3, symlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
59371
59706
  import { randomBytes as randomBytes2 } from "node:crypto";
59372
- import { dirname as dirname6, isAbsolute, join as join9, relative, resolve as resolve2, sep } from "node:path";
59707
+ import { dirname as dirname7, isAbsolute, join as join10, relative, resolve as resolve2, sep } from "node:path";
59373
59708
 
59374
59709
  // src/digest.ts
59375
59710
  import { createHash as createHash2 } from "node:crypto";
@@ -59386,10 +59721,10 @@ var GENERATION_LEGAL_FILES = ["LICENSE", "NOTICE", "THIRD_PARTY_NOTICES.md"];
59386
59721
  var SAFE_SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._+-]*$/;
59387
59722
  var ROOT_ALIAS = "codex";
59388
59723
  function isPackageLayout(dir) {
59389
- return existsSync5(join9(dir, "bin", "codex")) && existsSync5(join9(dir, "codex-package.json"));
59724
+ return existsSync5(join10(dir, "bin", "codex")) && existsSync5(join10(dir, "codex-package.json"));
59390
59725
  }
59391
59726
  function executablePath(dir, name) {
59392
- return isPackageLayout(dir) ? join9(dir, "bin", name) : join9(dir, name);
59727
+ return isPackageLayout(dir) ? join10(dir, "bin", name) : join10(dir, name);
59393
59728
  }
59394
59729
  var PackageMetadata = exports_external.object({
59395
59730
  version: exports_external.string(),
@@ -59398,10 +59733,10 @@ var PackageMetadata = exports_external.object({
59398
59733
  }).passthrough();
59399
59734
  function verifyPackage(dir, files, expect) {
59400
59735
  for (const [name, want] of Object.entries(files)) {
59401
- const file2 = join9(dir, name);
59736
+ const file2 = join10(dir, name);
59402
59737
  let st;
59403
59738
  try {
59404
- st = lstatSync3(file2);
59739
+ st = lstatSync4(file2);
59405
59740
  } catch {
59406
59741
  return `${name} is missing`;
59407
59742
  }
@@ -59416,7 +59751,7 @@ function verifyPackage(dir, files, expect) {
59416
59751
  }
59417
59752
  let metadata;
59418
59753
  try {
59419
- metadata = PackageMetadata.parse(JSON.parse(readFileSync6(join9(dir, "codex-package.json"), "utf8")));
59754
+ metadata = PackageMetadata.parse(JSON.parse(readFileSync6(join10(dir, "codex-package.json"), "utf8")));
59420
59755
  } catch (e) {
59421
59756
  return `codex-package.json is unreadable: ${e instanceof Error ? e.message.split(`
59422
59757
  `)[0] : String(e)}`;
@@ -59433,20 +59768,20 @@ function packageFiles(dir) {
59433
59768
  const out = {};
59434
59769
  const walk = (current) => {
59435
59770
  for (const name of readdirSync2(current).sort()) {
59436
- const path = join9(current, name);
59437
- const rel = relative(dir, path).split(sep).join("/");
59438
- const st = lstatSync3(path);
59771
+ const path3 = join10(current, name);
59772
+ const rel = relative(dir, path3).split(sep).join("/");
59773
+ const st = lstatSync4(path3);
59439
59774
  if (rel === INSTALLATION_FILE || rel === ROOT_ALIAS && st.isSymbolicLink())
59440
59775
  continue;
59441
59776
  if (st.isSymbolicLink())
59442
59777
  throw new Error(`${rel} is a symbolic link; a Codex package may only contain regular files`);
59443
59778
  if (st.isDirectory()) {
59444
- walk(path);
59779
+ walk(path3);
59445
59780
  continue;
59446
59781
  }
59447
59782
  if (!st.isFile())
59448
59783
  throw new Error(`${rel} is not a regular file`);
59449
- out[rel] = digestOf(path);
59784
+ out[rel] = digestOf(path3);
59450
59785
  }
59451
59786
  };
59452
59787
  walk(dir);
@@ -59461,10 +59796,10 @@ function nearestExisting2(p) {
59461
59796
  let cur = p;
59462
59797
  for (;; ) {
59463
59798
  try {
59464
- statSync(cur);
59799
+ statSync3(cur);
59465
59800
  return cur;
59466
59801
  } catch {
59467
- const parent = dirname6(cur);
59802
+ const parent = dirname7(cur);
59468
59803
  if (parent === cur)
59469
59804
  return cur;
59470
59805
  cur = parent;
@@ -59473,7 +59808,7 @@ function nearestExisting2(p) {
59473
59808
  }
59474
59809
  function realish(p) {
59475
59810
  const near = nearestExisting2(p);
59476
- return realpathSync2(near) + resolve2(p).slice(resolve2(near).length);
59811
+ return realpathSync3(near) + resolve2(p).slice(resolve2(near).length);
59477
59812
  }
59478
59813
  function insideGenerationsRoot(paths, candidate) {
59479
59814
  return realish(candidate).startsWith(`${realish(paths.generationsDir)}${sep}`);
@@ -59487,7 +59822,7 @@ function validateStaging(pair) {
59487
59822
  throw new Error(`staged package is not the one its provenance describes: ${problem}; refusing to install it`);
59488
59823
  if (pair.provenance.source === "prebuilt") {
59489
59824
  for (const name of GENERATION_LEGAL_FILES) {
59490
- if (!(name in pair.provenance.files) || !existsSync5(join9(pair.directory, name)))
59825
+ if (!(name in pair.provenance.files) || !existsSync5(join10(pair.directory, name)))
59491
59826
  throw new Error(`prebuilt pair is missing ${name}`);
59492
59827
  }
59493
59828
  }
@@ -59495,7 +59830,7 @@ function validateStaging(pair) {
59495
59830
  const want = pair.provenance.files[`bin/${name}`];
59496
59831
  if (!want)
59497
59832
  throw new Error(`staged pair is missing bin/${name}`);
59498
- const got = digestOf(join9(pair.directory, "bin", name));
59833
+ const got = digestOf(join10(pair.directory, "bin", name));
59499
59834
  if (got.sha256 !== want.sha256 || got.size !== want.size) {
59500
59835
  throw new Error(`staged bin/${name} does not match its recorded digest; refusing to install it`);
59501
59836
  }
@@ -59506,7 +59841,7 @@ function installationRecord(pair) {
59506
59841
  return record2;
59507
59842
  }
59508
59843
  function commitJson(file2, value, rename2) {
59509
- const tmp = join9(dirname6(file2), `.${process.pid}.${randomBytes2(4).toString("hex")}.tmp`);
59844
+ const tmp = join10(dirname7(file2), `.${process.pid}.${randomBytes2(4).toString("hex")}.tmp`);
59510
59845
  try {
59511
59846
  writeFileSync2(tmp, `${JSON.stringify(value, null, 2)}
59512
59847
  `);
@@ -59520,7 +59855,7 @@ var GENERATION_NAME = /^\d+\.\d+\.\d+-\d{8}T\d{6}-[0-9a-f]{6}$/;
59520
59855
  function freshName(pair, paths) {
59521
59856
  mkdirSync4(paths.generationsDir, { recursive: true });
59522
59857
  for (;; ) {
59523
- const dir = join9(paths.generationsDir, `${pair.codexVersion}-${stamp(pair.provenance.installedAt)}-${randomBytes2(3).toString("hex")}`);
59858
+ const dir = join10(paths.generationsDir, `${pair.codexVersion}-${stamp(pair.provenance.installedAt)}-${randomBytes2(3).toString("hex")}`);
59524
59859
  if (!existsSync5(dir))
59525
59860
  return dir;
59526
59861
  }
@@ -59538,8 +59873,8 @@ function createGeneration(pair, paths, rename2 = renameSync2) {
59538
59873
  }
59539
59874
  try {
59540
59875
  chmodSync(dir, 493);
59541
- symlinkSync("bin/codex", join9(dir, ROOT_ALIAS));
59542
- commitJson(join9(dir, INSTALLATION_FILE), installationRecord(pair), rename2);
59876
+ symlinkSync("bin/codex", join10(dir, ROOT_ALIAS));
59877
+ commitJson(join10(dir, INSTALLATION_FILE), installationRecord(pair), rename2);
59543
59878
  } catch (e) {
59544
59879
  rmSync(dir, { recursive: true, force: true });
59545
59880
  throw e;
@@ -59547,11 +59882,11 @@ function createGeneration(pair, paths, rename2 = renameSync2) {
59547
59882
  return dir;
59548
59883
  }
59549
59884
  function isGenerationDir(dir) {
59550
- return existsSync5(join9(dir, INSTALLATION_FILE)) && isPackageLayout(dir);
59885
+ return existsSync5(join10(dir, INSTALLATION_FILE)) && isPackageLayout(dir);
59551
59886
  }
59552
59887
  function listGenerations(paths) {
59553
59888
  try {
59554
- return readdirSync2(paths.generationsDir).map((name) => join9(paths.generationsDir, name)).sort();
59889
+ return readdirSync2(paths.generationsDir).map((name) => join10(paths.generationsDir, name)).sort();
59555
59890
  } catch {
59556
59891
  return [];
59557
59892
  }
@@ -59584,11 +59919,11 @@ function activeGeneration(paths) {
59584
59919
  const target = readPointer(paths);
59585
59920
  if (target === null)
59586
59921
  return null;
59587
- const abs = isAbsolute(target) ? target : resolve2(dirname6(paths.currentGeneration), target);
59922
+ const abs = isAbsolute(target) ? target : resolve2(dirname7(paths.currentGeneration), target);
59588
59923
  if (!insideGenerationsRoot(paths, abs))
59589
59924
  return null;
59590
59925
  try {
59591
- return statSync(abs).isDirectory() ? abs : null;
59926
+ return statSync3(abs).isDirectory() ? abs : null;
59592
59927
  } catch {
59593
59928
  return null;
59594
59929
  }
@@ -59651,7 +59986,7 @@ function readInstallation(paths) {
59651
59986
  if (dir === null)
59652
59987
  return null;
59653
59988
  try {
59654
- const raw = JSON.parse(readFileSync6(join9(dir, INSTALLATION_FILE), "utf8"));
59989
+ const raw = JSON.parse(readFileSync6(join10(dir, INSTALLATION_FILE), "utf8"));
59655
59990
  return checkedRecord(raw);
59656
59991
  } catch {
59657
59992
  return null;
@@ -59660,7 +59995,7 @@ function readInstallation(paths) {
59660
59995
 
59661
59996
  // src/distribution/archive.ts
59662
59997
  import { createReadStream as createReadStream2, createWriteStream, mkdirSync as mkdirSync5 } from "node:fs";
59663
- import { dirname as dirname7, join as join10 } from "node:path";
59998
+ import { dirname as dirname8, join as join11 } from "node:path";
59664
59999
  import { createGunzip } from "node:zlib";
59665
60000
 
59666
60001
  // node_modules/tar/dist/esm/index.min.js
@@ -61751,7 +62086,7 @@ var hr = Symbol("entry");
61751
62086
  var cs = Symbol("entryOpt");
61752
62087
  var ui = Symbol("writeEntryClass");
61753
62088
  var lr = Symbol("write");
61754
- var fs2 = Symbol("ondrain");
62089
+ var fs4 = Symbol("ondrain");
61755
62090
  var wt = class extends A {
61756
62091
  sync = false;
61757
62092
  opt;
@@ -61787,9 +62122,9 @@ var wt = class extends A {
61787
62122
  if (t.gzip && (typeof t.gzip != "object" && (t.gzip = {}), this.portable && (t.gzip.portable = true), this.zip = new ze(t.gzip)), t.brotli && (typeof t.brotli != "object" && (t.brotli = {}), this.zip = new We(t.brotli)), t.zstd && (typeof t.zstd != "object" && (t.zstd = {}), this.zip = new Ye(t.zstd)), !this.zip)
61788
62123
  throw new Error("impossible");
61789
62124
  let e = this.zip;
61790
- e.on("data", (i) => super.write(i)), e.on("end", () => super.end()), e.on("drain", () => this[fs2]()), this.on("resume", () => e.resume());
62125
+ e.on("data", (i) => super.write(i)), e.on("end", () => super.end()), e.on("drain", () => this[fs4]()), this.on("resume", () => e.resume());
61791
62126
  } else
61792
- this.on("drain", this[fs2]);
62127
+ this.on("drain", this[fs4]);
61793
62128
  this.noDirRecurse = !!t.noDirRecurse, this.follow = !!t.follow, this.noMtime = !!t.noMtime, t.mtime && (this.mtime = t.mtime), this.filter = typeof t.filter == "function" ? t.filter : () => true, this[W] = new hi, this[G] = 0, this.jobs = Number(t.jobs) || 4, this[Ee] = false, this[me] = false;
61794
62129
  }
61795
62130
  [lr](t) {
@@ -61911,7 +62246,7 @@ var wt = class extends A {
61911
62246
  this.emit("error", e);
61912
62247
  }
61913
62248
  }
61914
- [fs2]() {
62249
+ [fs4]() {
61915
62250
  this[Et] && this[Et].entry && this[Et].entry.resume();
61916
62251
  }
61917
62252
  [di](t) {
@@ -62937,9 +63272,9 @@ function rejectionReason(entry, seen, budget, expected) {
62937
63272
  function writeEntry(entry, staging, expected) {
62938
63273
  const name = entry.path;
62939
63274
  const mode = isExecutable(name) ? EXECUTABLE_MODE : LEGAL_MODE;
62940
- const target = join10(staging, name);
63275
+ const target = join11(staging, name);
62941
63276
  if (name.includes("/"))
62942
- mkdirSync5(dirname7(target), { recursive: true });
63277
+ mkdirSync5(dirname8(target), { recursive: true });
62943
63278
  const sink = createWriteStream(target, { mode, flags: "wx" });
62944
63279
  const done = new Promise((resolve3, reject2) => {
62945
63280
  sink.on("error", reject2);
@@ -63027,7 +63362,7 @@ async function extractArchive(archivePath, staging, files) {
63027
63362
  import { createHash as createHash3 } from "node:crypto";
63028
63363
  import { createReadStream as createReadStream3, existsSync as existsSync6, renameSync as renameSync3 } from "node:fs";
63029
63364
  import { open as open2 } from "node:fs/promises";
63030
- import { dirname as dirname8, join as join11 } from "node:path";
63365
+ import { dirname as dirname9, join as join12 } from "node:path";
63031
63366
  var PUBLIC_BASE = "https://github.com/adrijshikhar/cxstatusline/releases/download";
63032
63367
  var REPO = "adrijshikhar/cxstatusline";
63033
63368
  var MAX_REDIRECTS = 5;
@@ -63152,12 +63487,12 @@ async function singleHttpDownload(start, asset, dest, maxBytes, opts) {
63152
63487
  let existingHash = null;
63153
63488
  if (existsSync6(dest)) {
63154
63489
  try {
63155
- const stat = await open2(dest, "r").then(async (h) => {
63490
+ const stat2 = await open2(dest, "r").then(async (h) => {
63156
63491
  const s3 = await h.stat();
63157
63492
  await h.close();
63158
63493
  return s3;
63159
63494
  });
63160
- if (stat.size > 0 && stat.size < maxBytes) {
63495
+ if (stat2.size > 0 && stat2.size < maxBytes) {
63161
63496
  const hashed = await hashExistingFile(dest, maxBytes, asset);
63162
63497
  existingBytes = hashed.size;
63163
63498
  existingHash = hashed.hash;
@@ -63273,7 +63608,7 @@ async function ghDownload(ctx, tag, asset, dest, maxBytes) {
63273
63608
  if (ctx.which("gh") === null) {
63274
63609
  throw new GhMissingError(`${asset} is not public for release ${tag} and GitHub CLI (gh) is not installed`);
63275
63610
  }
63276
- const targetDir = dirname8(dest);
63611
+ const targetDir = dirname9(dest);
63277
63612
  const result2 = ctx.run("gh", ["release", "download", tag, "--repo", REPO, "--pattern", asset, "--dir", targetDir], { timeoutMs: GH_TIMEOUT_MS });
63278
63613
  if (result2.status !== 0) {
63279
63614
  const detail = sanitize(result2.stderr || result2.stdout);
@@ -63282,7 +63617,7 @@ async function ghDownload(ctx, tag, asset, dest, maxBytes) {
63282
63617
  }
63283
63618
  throw new ReleaseUnavailableError(`release ${tag} not found or access denied: ${detail}`);
63284
63619
  }
63285
- const downloadedFile = join11(targetDir, asset);
63620
+ const downloadedFile = join12(targetDir, asset);
63286
63621
  if (!existsSync6(downloadedFile) && !existsSync6(dest)) {
63287
63622
  throw new ReleaseUnavailableError(`release ${tag} not found or access denied: gh downloaded no ${asset}`);
63288
63623
  }
@@ -63304,7 +63639,7 @@ var MANIFEST_ASSET = "manifest.json";
63304
63639
  var PROBE_TIMEOUT_MS = 30000;
63305
63640
  function privateTemp(ctx, prefix) {
63306
63641
  mkdirSync6(ctx.paths.libexecDir, { recursive: true });
63307
- const dir = mkdtempSync(join12(ctx.paths.libexecDir, prefix));
63642
+ const dir = mkdtempSync(join13(ctx.paths.libexecDir, prefix));
63308
63643
  chmodSync2(dir, 448);
63309
63644
  return dir;
63310
63645
  }
@@ -63343,7 +63678,7 @@ function verifyStaged(staging, manifest, artifact) {
63343
63678
  throw new Error(`staged package does not match the release manifest: ${problem}`);
63344
63679
  }
63345
63680
  function probeVersion(ctx, staging, codexVersion) {
63346
- const probe = ctx.run(join12(staging, "bin", "codex"), ["--version"], { timeoutMs: PROBE_TIMEOUT_MS });
63681
+ const probe = ctx.run(join13(staging, "bin", "codex"), ["--version"], { timeoutMs: PROBE_TIMEOUT_MS });
63347
63682
  const reported = sanitize((probe.stdout || probe.stderr).slice(0, 512));
63348
63683
  if (probe.status !== 0 || reported !== `codex-cli ${codexVersion}`) {
63349
63684
  throw new Error(`staged codex reported version "${reported}" instead of "codex-cli ${codexVersion}"`);
@@ -63386,8 +63721,8 @@ function moveFile(src, dst) {
63386
63721
  async function stageArchive(ctx, download, manifest, artifact, tag, opts) {
63387
63722
  const cacheDir = ctx.paths.downloadCacheDir;
63388
63723
  mkdirSync6(cacheDir, { recursive: true });
63389
- const partFile = join12(cacheDir, `${tag}-${artifact.filename}.part`);
63390
- const archive = join12(download, artifact.filename);
63724
+ const partFile = join13(cacheDir, `${tag}-${artifact.filename}.part`);
63725
+ const archive = join13(download, artifact.filename);
63391
63726
  opts.onStatus?.("download", `Downloading prebuilt archive (${artifact.filename})...`);
63392
63727
  const got = await downloadAsset(ctx, tag, artifact.filename, partFile, ARCHIVE_MAX_BYTES, opts);
63393
63728
  if (got.sha256 !== artifact.sha256 || got.size !== artifact.size) {
@@ -63413,7 +63748,7 @@ async function preparePrebuilt(ctx, expected, opts = {}) {
63413
63748
  opts.onStatus?.("manifest", `Checking release ${tag} for ${expected.platform}...`);
63414
63749
  const download = privateTemp(ctx, "download-");
63415
63750
  try {
63416
- const manifestFile = join12(download, MANIFEST_ASSET);
63751
+ const manifestFile = join13(download, MANIFEST_ASSET);
63417
63752
  await downloadAsset(ctx, tag, MANIFEST_ASSET, manifestFile, MANIFEST_MAX_BYTES, opts);
63418
63753
  const manifest = validateManifest(JSON.parse(readFileSync7(manifestFile, "utf8")), expected);
63419
63754
  const artifact = artifactFor(manifest, expected);
@@ -63501,8 +63836,8 @@ function packageRequiredFiles(platform2) {
63501
63836
  const base2 = ["codex-package.json", "bin/codex", "bin/codex-code-mode-host", "codex-path/rg", "LICENSE", "NOTICE", "THIRD_PARTY_NOTICES.md"];
63502
63837
  return platform2.startsWith("linux-") ? [...base2, "codex-resources/bwrap"] : base2;
63503
63838
  }
63504
- function modeFor(path) {
63505
- return /^(bin|codex-path|codex-resources)\//.test(path) ? 493 : 420;
63839
+ function modeFor(path3) {
63840
+ return /^(bin|codex-path|codex-resources)\//.test(path3) ? 493 : 420;
63506
63841
  }
63507
63842
  var HEX402 = /^[0-9a-f]{40}$/;
63508
63843
  var HEX642 = /^[0-9a-f]{64}$/;
@@ -63635,8 +63970,8 @@ function validateManifest(raw, expected) {
63635
63970
  const structural = ManifestShapeSchema.safeParse(raw);
63636
63971
  if (!structural.success) {
63637
63972
  const issue2 = structural.error.issues[0];
63638
- const path = issue2 && issue2.path.length > 0 ? issue2.path.join(".") : "manifest";
63639
- throw new Error(`invalid release manifest: ${path}: ${issue2?.message ?? "malformed"}`);
63973
+ const path3 = issue2 && issue2.path.length > 0 ? issue2.path.join(".") : "manifest";
63974
+ throw new Error(`invalid release manifest: ${path3}: ${issue2?.message ?? "malformed"}`);
63640
63975
  }
63641
63976
  const error61 = checkBusinessRules(structural.data, expected);
63642
63977
  if (error61)
@@ -63678,20 +64013,20 @@ function removeHook(file2) {
63678
64013
  const hooks = kept.length === 0 ? rest2 : { ...rest2, SessionStart: kept };
63679
64014
  return { file: { ...file2, hooks }, changed: true };
63680
64015
  }
63681
- function readHooksFile(path) {
63682
- if (!existsSync7(path))
64016
+ function readHooksFile(path3) {
64017
+ if (!existsSync7(path3))
63683
64018
  return null;
63684
64019
  let raw;
63685
64020
  try {
63686
- raw = JSON.parse(readFileSync8(path, "utf8"));
64021
+ raw = JSON.parse(readFileSync8(path3, "utf8"));
63687
64022
  } catch {
63688
- throw new Error(`${path}: hooks.json is not valid JSON; fix it by hand before installing the hook`);
64023
+ throw new Error(`${path3}: hooks.json is not valid JSON; fix it by hand before installing the hook`);
63689
64024
  }
63690
64025
  if (typeof raw !== "object" || raw === null || Array.isArray(raw))
63691
- throw new Error(`${path}: hooks.json must be a JSON object`);
64026
+ throw new Error(`${path3}: hooks.json must be a JSON object`);
63692
64027
  const o = raw;
63693
64028
  if (o.hooks !== undefined && (typeof o.hooks !== "object" || o.hooks === null))
63694
- throw new Error(`${path}: "hooks" must be an object`);
64029
+ throw new Error(`${path3}: "hooks" must be an object`);
63695
64030
  return { ...raw, hooks: o.hooks ?? {} };
63696
64031
  }
63697
64032
  function installHook(hooksFile, cxBin) {
@@ -64014,12 +64349,12 @@ function promptUpdate(options) {
64014
64349
  import { rmSync as rmSync5 } from "node:fs";
64015
64350
 
64016
64351
  // src/codex/upstream.ts
64017
- import { accessSync as accessSync2, constants as constants3, lstatSync as lstatSync4, readlinkSync as readlinkSync2, realpathSync as realpathSync3, statSync as statSync2 } from "node:fs";
64018
- import { dirname as dirname9, isAbsolute as isAbsolute2, join as join13, resolve as resolve3 } from "node:path";
64352
+ import { accessSync as accessSync2, constants as constants3, lstatSync as lstatSync5, readlinkSync as readlinkSync2, realpathSync as realpathSync4, statSync as statSync4 } from "node:fs";
64353
+ import { dirname as dirname10, isAbsolute as isAbsolute2, join as join14, resolve as resolve3 } from "node:path";
64019
64354
  function isExecutable2(p2) {
64020
64355
  try {
64021
64356
  accessSync2(p2, constants3.X_OK);
64022
- return statSync2(p2).isFile();
64357
+ return statSync4(p2).isFile();
64023
64358
  } catch {
64024
64359
  return false;
64025
64360
  }
@@ -64028,7 +64363,7 @@ function isManaged(p2, paths, isOurWrapper) {
64028
64363
  if (resolve3(p2) === resolve3(paths.patchedBin) || isOurWrapper(p2))
64029
64364
  return true;
64030
64365
  try {
64031
- return realpathSync3(p2) === realpathSync3(paths.patchedBin);
64366
+ return realpathSync4(p2) === realpathSync4(paths.patchedBin);
64032
64367
  } catch {
64033
64368
  return false;
64034
64369
  }
@@ -64036,13 +64371,13 @@ function isManaged(p2, paths, isOurWrapper) {
64036
64371
  function inspectLauncher(paths, isOurWrapper) {
64037
64372
  let st2;
64038
64373
  try {
64039
- st2 = lstatSync4(paths.wrapperPath);
64374
+ st2 = lstatSync5(paths.wrapperPath);
64040
64375
  } catch {
64041
64376
  return null;
64042
64377
  }
64043
64378
  if (st2.isSymbolicLink()) {
64044
64379
  const raw = readlinkSync2(paths.wrapperPath);
64045
- const target = isAbsolute2(raw) ? raw : resolve3(dirname9(paths.wrapperPath), raw);
64380
+ const target = isAbsolute2(raw) ? raw : resolve3(dirname10(paths.wrapperPath), raw);
64046
64381
  if (isManaged(target, paths, isOurWrapper))
64047
64382
  return null;
64048
64383
  return { kind: "found", bin: target, launcher_restore: { kind: "symlink", target } };
@@ -64055,7 +64390,7 @@ function walkPath(paths, env3, isOurWrapper) {
64055
64390
  for (const dir of (env3.PATH ?? "").split(":").filter(Boolean)) {
64056
64391
  if (resolve3(dir) === resolve3(paths.binDir))
64057
64392
  continue;
64058
- const candidate = join13(dir, "codex");
64393
+ const candidate = join14(dir, "codex");
64059
64394
  if (isExecutable2(candidate) && !isManaged(candidate, paths, isOurWrapper))
64060
64395
  return candidate;
64061
64396
  }
@@ -64091,15 +64426,15 @@ function preserveLauncherRestore(recorded, found) {
64091
64426
 
64092
64427
  // src/patch/compile.ts
64093
64428
  import { chmodSync as chmodSync3, mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync2, rmSync as rmSync3 } from "node:fs";
64094
- import { join as join16 } from "node:path";
64429
+ import { join as join17 } from "node:path";
64095
64430
 
64096
64431
  // src/patch/build.ts
64097
- import { existsSync as existsSync10, lstatSync as lstatSync5, readFileSync as readFileSync10, statSync as statSync3 } from "node:fs";
64098
- import { join as join15 } from "node:path";
64432
+ import { existsSync as existsSync10, lstatSync as lstatSync6, readFileSync as readFileSync10, statSync as statSync5 } from "node:fs";
64433
+ import { join as join16 } from "node:path";
64099
64434
 
64100
64435
  // src/patch/v8.ts
64101
64436
  import { existsSync as existsSync9 } from "node:fs";
64102
- import { join as join14 } from "node:path";
64437
+ import { join as join15 } from "node:path";
64103
64438
  function defaultV8Target() {
64104
64439
  const isArm = process.arch === "arm64";
64105
64440
  if (process.platform === "darwin")
@@ -64130,7 +64465,7 @@ function resolveV8Env(sourceDir, run, log) {
64130
64465
  RUSTY_V8_SRC_BINDING_PATH: process.env.RUSTY_V8_SRC_BINDING_PATH
64131
64466
  };
64132
64467
  }
64133
- const v8Script = join14(sourceDir, "scripts", "codex_package", "v8.py");
64468
+ const v8Script = join15(sourceDir, "scripts", "codex_package", "v8.py");
64134
64469
  if (!existsSync9(v8Script)) {
64135
64470
  return {};
64136
64471
  }
@@ -64202,10 +64537,10 @@ function headCommit(plan, run) {
64202
64537
  }
64203
64538
  function prepareCheckout(plan, run, log) {
64204
64539
  const git = (step, ...args) => must(step, run, log, "git", ["-C", plan.sourceDir, ...args]);
64205
- if (existsSync10(join15(plan.sourceDir, ".git"))) {
64540
+ if (existsSync10(join16(plan.sourceDir, ".git"))) {
64206
64541
  git("fetch", "fetch", "--tags", "--filter=blob:none", "origin");
64207
- const snapshot = join15(plan.sourceDir, SNAPSHOT);
64208
- const st2 = lstatSync5(snapshot, { throwIfNoEntry: false });
64542
+ const snapshot = join16(plan.sourceDir, SNAPSHOT);
64543
+ const st2 = lstatSync6(snapshot, { throwIfNoEntry: false });
64209
64544
  if (st2) {
64210
64545
  const tracked = run("git", ["-C", plan.sourceDir, "ls-files", "--error-unmatch", "--", SNAPSHOT]);
64211
64546
  if (tracked.status !== 0) {
@@ -64232,7 +64567,7 @@ function buildPatched(plan, run, log, which, onStatus) {
64232
64567
  git("apply --check", "apply", "--index", "--check", plan.patchFile);
64233
64568
  git("apply", "apply", "--index", plan.patchFile);
64234
64569
  onStatus?.("patch-done", `Applied ${patchBase} cleanly`);
64235
- const crateDir = join15(plan.sourceDir, "codex-rs");
64570
+ const crateDir = join16(plan.sourceDir, "codex-rs");
64236
64571
  const v8Env = resolveV8Env(plan.sourceDir, run, log);
64237
64572
  onStatus?.("build", "Compiling release binaries (cargo build --release)... Note: this full compile typically takes 10 to 20 minutes.");
64238
64573
  const buildStart = Date.now();
@@ -64241,8 +64576,8 @@ function buildPatched(plan, run, log, which, onStatus) {
64241
64576
  const buildElapsedStr = buildElapsed >= 60 ? `${Math.floor(buildElapsed / 60)}m ${buildElapsed % 60}s` : `${buildElapsed}s`;
64242
64577
  onStatus?.("build-done", `Release binaries compiled (codex, codex-code-mode-host in ${buildElapsedStr})`);
64243
64578
  const [codex, codexCodeModeHost] = TARGETS.map((name) => {
64244
- const bin = join15(crateDir, "target", "release", name);
64245
- if (!existsSync10(bin) || statSync3(bin).size === 0) {
64579
+ const bin = join16(crateDir, "target", "release", name);
64580
+ if (!existsSync10(bin) || statSync5(bin).size === 0) {
64246
64581
  throw new BuildError("cargo build", `cargo exited 0 but ${bin} is missing or empty`);
64247
64582
  }
64248
64583
  return bin;
@@ -64266,7 +64601,7 @@ function platformLabel() {
64266
64601
  }
64267
64602
  }
64268
64603
  function prepareCompiled(ctx, upstream, ref, onStatus) {
64269
- const patchFile = join16(ctx.patchesDir, ref.file);
64604
+ const patchFile = join17(ctx.patchesDir, ref.file);
64270
64605
  const patchSha256 = digestOf(patchFile).sha256;
64271
64606
  const built = buildPatched({ tag: ref.tag, sourceDir: ctx.paths.sourceDir, patchFile }, ctx.run, ctx.log, ctx.which, onStatus);
64272
64607
  onStatus?.("stage", "Assembling the Codex package with upstream's packager...");
@@ -64277,9 +64612,9 @@ function prepareCompiled(ctx, upstream, ref, onStatus) {
64277
64612
  if (cargo === null)
64278
64613
  throw new Error("cargo is not on PATH");
64279
64614
  mkdirSync7(ctx.paths.libexecDir, { recursive: true });
64280
- const directory = mkdtempSync2(join16(ctx.paths.libexecDir, STAGING_PREFIX));
64615
+ const directory = mkdtempSync2(join17(ctx.paths.libexecDir, STAGING_PREFIX));
64281
64616
  chmodSync3(directory, 448);
64282
- const tmpDir = mkdtempSync2(join16(ctx.paths.libexecDir, "download-"));
64617
+ const tmpDir = mkdtempSync2(join17(ctx.paths.libexecDir, "download-"));
64283
64618
  chmodSync3(tmpDir, 448);
64284
64619
  let target;
64285
64620
  try {
@@ -64326,7 +64661,7 @@ function prepareCompiled(ctx, upstream, ref, onStatus) {
64326
64661
 
64327
64662
  // src/patch/manifest.ts
64328
64663
  import { readFileSync as readFileSync11 } from "node:fs";
64329
- import { join as join17 } from "node:path";
64664
+ import { join as join18 } from "node:path";
64330
64665
  class ManifestError extends Error {
64331
64666
  name = "ManifestError";
64332
64667
  }
@@ -64345,7 +64680,7 @@ var isCandidate = (c) => {
64345
64680
  return parsed !== null && parsed.pre === null;
64346
64681
  };
64347
64682
  function loadManifest(patchesDir) {
64348
- const file2 = join17(patchesDir, "manifest.json");
64683
+ const file2 = join18(patchesDir, "manifest.json");
64349
64684
  try {
64350
64685
  const raw = JSON.parse(readFileSync11(file2, "utf8"));
64351
64686
  const m2 = raw;
@@ -64406,9 +64741,9 @@ function isCodexVersionSupported(m2, version2) {
64406
64741
  }
64407
64742
 
64408
64743
  // src/patch/wrapper.ts
64409
- import { chmodSync as chmodSync4, closeSync as closeSync2, existsSync as existsSync11, lstatSync as lstatSync6, mkdirSync as mkdirSync8, openSync as openSync2, readFileSync as readFileSync12, readSync, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync4, writeFileSync as writeFileSync3 } from "node:fs";
64744
+ import { chmodSync as chmodSync4, closeSync as closeSync2, existsSync as existsSync11, lstatSync as lstatSync7, mkdirSync as mkdirSync8, openSync as openSync2, readFileSync as readFileSync12, readSync, renameSync as renameSync5, rmSync as rmSync4, statSync as statSync6, writeFileSync as writeFileSync3 } from "node:fs";
64410
64745
  import { randomBytes as randomBytes3 } from "node:crypto";
64411
- import { join as join18 } from "node:path";
64746
+ import { join as join19 } from "node:path";
64412
64747
  var WRAPPER_MARKER = "# cxstatusline-wrapper v1";
64413
64748
  var WRAPPER_MARKER_V2 = "# cxstatusline-wrapper v2";
64414
64749
  var WRAPPER_MARKERS = [WRAPPER_MARKER, WRAPPER_MARKER_V2];
@@ -64446,9 +64781,9 @@ function generationWrapperScript(currentGeneration, cxBin) {
64446
64781
  ].join(`
64447
64782
  `);
64448
64783
  }
64449
- function isOurWrapper(path) {
64784
+ function isOurWrapper(path3) {
64450
64785
  try {
64451
- const fd = openSync2(path, "r");
64786
+ const fd = openSync2(path3, "r");
64452
64787
  try {
64453
64788
  const header = Buffer.alloc(256);
64454
64789
  const size2 = readSync(fd, header, 0, header.length, 0);
@@ -64464,18 +64799,18 @@ function isOurWrapper(path) {
64464
64799
  }
64465
64800
  function isSymlink(p2) {
64466
64801
  try {
64467
- return lstatSync6(p2).isSymbolicLink();
64802
+ return lstatSync7(p2).isSymbolicLink();
64468
64803
  } catch {
64469
64804
  return false;
64470
64805
  }
64471
64806
  }
64472
64807
  function stageExecutable(target, write) {
64473
- mkdirSync8(join18(target, ".."), { recursive: true });
64808
+ mkdirSync8(join19(target, ".."), { recursive: true });
64474
64809
  const tmp = `${target}.tmp-${process.pid}`;
64475
64810
  try {
64476
64811
  write(tmp);
64477
64812
  chmodSync4(tmp, 493);
64478
- if (statSync4(tmp).size === 0)
64813
+ if (statSync6(tmp).size === 0)
64479
64814
  throw new Error(`${target} staged as an empty file`);
64480
64815
  return tmp;
64481
64816
  } catch (e) {
@@ -65267,7 +65602,7 @@ async function runUpdate(ctx, opts = {}, transport = {}) {
65267
65602
  return runInstall(ctx, { compile: opts.compile ?? false, codexVersion: target }, transport);
65268
65603
  }
65269
65604
  function appendLog(file2, line) {
65270
- mkdirSync9(join19(file2, ".."), { recursive: true });
65605
+ mkdirSync9(join20(file2, ".."), { recursive: true });
65271
65606
  appendFileSync(file2, `${new Date().toISOString()} ${line}
65272
65607
  `);
65273
65608
  }
@@ -65424,7 +65759,7 @@ async function promptCodexVersion(options) {
65424
65759
  // src/hook/run.ts
65425
65760
  import { appendFileSync as appendFileSync2, closeSync as closeSync3, existsSync as existsSync12, mkdirSync as mkdirSync10, openSync as openSync3 } from "node:fs";
65426
65761
  import { spawn as spawn2 } from "node:child_process";
65427
- import { dirname as dirname10 } from "node:path";
65762
+ import { dirname as dirname11 } from "node:path";
65428
65763
  var HOOK_SOURCES = ["startup", "resume", "clear"];
65429
65764
  function parseHookInput(stdin) {
65430
65765
  try {
@@ -65553,7 +65888,7 @@ function realHookDeps() {
65553
65888
  spawnDetached(cxBin, args, logFile) {
65554
65889
  let fd;
65555
65890
  try {
65556
- mkdirSync10(dirname10(logFile), { recursive: true });
65891
+ mkdirSync10(dirname11(logFile), { recursive: true });
65557
65892
  fd = openSync3(logFile, "a");
65558
65893
  const child = spawn2(cxBin, args, { detached: true, stdio: ["ignore", fd, fd], env: process.env });
65559
65894
  child.on("error", (err) => {
@@ -65576,8 +65911,8 @@ function realHookDeps() {
65576
65911
  }
65577
65912
 
65578
65913
  // src/commands/doctor.ts
65579
- import { existsSync as existsSync14, lstatSync as lstatSync7, readFileSync as readFileSync14, readlinkSync as readlinkSync4, readdirSync as readdirSync3 } from "node:fs";
65580
- import { join as join21 } from "node:path";
65914
+ import { existsSync as existsSync14, lstatSync as lstatSync8, readFileSync as readFileSync14, readlinkSync as readlinkSync4, readdirSync as readdirSync3 } from "node:fs";
65915
+ import { join as join22 } from "node:path";
65581
65916
 
65582
65917
  // src/utils/format.ts
65583
65918
  function formatDuration2(ms2) {
@@ -65594,16 +65929,16 @@ function formatDuration2(ms2) {
65594
65929
 
65595
65930
  // src/commands/doctor-generation.ts
65596
65931
  import { existsSync as existsSync13, readFileSync as readFileSync13, readlinkSync as readlinkSync3 } from "node:fs";
65597
- import { dirname as dirname11, isAbsolute as isAbsolute3, join as join20, resolve as resolve4 } from "node:path";
65932
+ import { dirname as dirname12, isAbsolute as isAbsolute3, join as join21, resolve as resolve4 } from "node:path";
65598
65933
  var line = (key, value, ok = null) => ({ key, value, ok });
65599
65934
  var NO_GENERATION = "n/a (no active generation)";
65600
65935
  function resolvePointerTarget(paths, raw) {
65601
- return isAbsolute3(raw) ? raw : resolve4(dirname11(paths.currentGeneration), raw);
65936
+ return isAbsolute3(raw) ? raw : resolve4(dirname12(paths.currentGeneration), raw);
65602
65937
  }
65603
65938
  function computeGenerationLine(paths, pointer) {
65604
65939
  const dir = activeGeneration(paths);
65605
65940
  if (dir !== null) {
65606
- if (!isGenerationDir(dir) && !existsSync13(join20(dir, INSTALLATION_FILE)))
65941
+ if (!isGenerationDir(dir) && !existsSync13(join21(dir, INSTALLATION_FILE)))
65607
65942
  return { line: line("generation", "foreign", false), dir: null };
65608
65943
  return { line: line("generation", dir, true), dir };
65609
65944
  }
@@ -65715,7 +66050,7 @@ function legalLine(record2, dir) {
65715
66050
  return line("legal", "n/a (compiled build)", null);
65716
66051
  if (!dir)
65717
66052
  return line("legal", NO_GENERATION, null);
65718
- const missing = GENERATION_LEGAL_FILES.filter((f2) => !existsSync13(join20(dir, f2)));
66053
+ const missing = GENERATION_LEGAL_FILES.filter((f2) => !existsSync13(join21(dir, f2)));
65719
66054
  return missing.length === 0 ? line("legal", "present", true) : line("legal", `missing: ${missing.join(", ")}`, false);
65720
66055
  }
65721
66056
  var DAEMON_SINCE = parseSemver("0.156.0");
@@ -65731,17 +66066,17 @@ function packageLayoutLine(record2, dir) {
65731
66066
  return problem === null ? line("package_layout", `ok (${record2.provenance.target})`, true) : line("package_layout", problem, false);
65732
66067
  }
65733
66068
  function daemonPackageLine(paths, record2) {
65734
- const current = join20(paths.codexHome, "packages", "app-server-daemon", "current");
66069
+ const current = join21(paths.codexHome, "packages", "app-server-daemon", "current");
65735
66070
  let target;
65736
66071
  try {
65737
66072
  target = readlinkSync3(current);
65738
66073
  } catch {
65739
66074
  return line("daemon_package", "none", null);
65740
66075
  }
65741
- const dir = isAbsolute3(target) ? target : resolve4(dirname11(current), target);
66076
+ const dir = isAbsolute3(target) ? target : resolve4(dirname12(current), target);
65742
66077
  let version2 = "unknown";
65743
66078
  try {
65744
- const meta3 = JSON.parse(readFileSync13(join20(dir, "codex-package.json"), "utf8"));
66079
+ const meta3 = JSON.parse(readFileSync13(join21(dir, "codex-package.json"), "utf8"));
65745
66080
  if (typeof meta3.version === "string")
65746
66081
  version2 = meta3.version;
65747
66082
  } catch {}
@@ -65918,7 +66253,7 @@ function wrapperLine(ctx) {
65918
66253
  const p2 = ctx.paths.wrapperPath;
65919
66254
  let st2;
65920
66255
  try {
65921
- st2 = lstatSync7(p2);
66256
+ st2 = lstatSync8(p2);
65922
66257
  } catch {
65923
66258
  return line2("wrapper", "absent");
65924
66259
  }
@@ -65973,7 +66308,7 @@ function commandCacheLine(ctx) {
65973
66308
  let oldestMtime = Infinity;
65974
66309
  for (const f2 of entries) {
65975
66310
  try {
65976
- const st2 = lstatSync7(join21(dir, f2));
66311
+ const st2 = lstatSync8(join22(dir, f2));
65977
66312
  if (st2.mtimeMs < oldestMtime)
65978
66313
  oldestMtime = st2.mtimeMs;
65979
66314
  } catch {}
@@ -66144,11 +66479,11 @@ function runPolicy(ctx, argv, io2) {
66144
66479
  }
66145
66480
 
66146
66481
  // src/commands/revert.ts
66147
- import { existsSync as existsSync15, lstatSync as lstatSync8, readFileSync as readFileSync15, readdirSync as readdirSync4, readlinkSync as readlinkSync5, rmSync as rmSync7, symlinkSync as symlinkSync2 } from "node:fs";
66148
- import { basename as basename2, dirname as dirname12, isAbsolute as isAbsolute4, join as join22, resolve as resolve5 } from "node:path";
66482
+ import { existsSync as existsSync15, lstatSync as lstatSync9, readFileSync as readFileSync15, readdirSync as readdirSync4, readlinkSync as readlinkSync5, rmSync as rmSync7, symlinkSync as symlinkSync2 } from "node:fs";
66483
+ import { basename as basename2, dirname as dirname13, isAbsolute as isAbsolute4, join as join23, resolve as resolve5 } from "node:path";
66149
66484
  function safeIsSymlink(p2) {
66150
66485
  try {
66151
- return lstatSync8(p2).isSymbolicLink();
66486
+ return lstatSync9(p2).isSymbolicLink();
66152
66487
  } catch {
66153
66488
  return false;
66154
66489
  }
@@ -66192,24 +66527,24 @@ function removeStagingDebris(ctx, actions) {
66192
66527
  return;
66193
66528
  const debris = readdirSync4(libexecDir).filter((n) => OWNED_LIBEXEC_PREFIXES.some((p2) => n.startsWith(p2)));
66194
66529
  for (const name of debris)
66195
- rmSync7(join22(libexecDir, name), { recursive: true, force: true });
66530
+ rmSync7(join23(libexecDir, name), { recursive: true, force: true });
66196
66531
  if (debris.length > 0) {
66197
66532
  actions.push(`removed ${debris.length} leftover staging entr${debris.length === 1 ? "y" : "ies"} from ${libexecDir}`);
66198
66533
  }
66199
66534
  }
66200
66535
  function daemonCopyNotice(ctx, actions) {
66201
- const root = join22(ctx.paths.codexHome, "packages", "app-server-daemon");
66202
- const current = join22(root, "current");
66536
+ const root = join23(ctx.paths.codexHome, "packages", "app-server-daemon");
66537
+ const current = join23(root, "current");
66203
66538
  let target;
66204
66539
  try {
66205
66540
  target = readlinkSync5(current);
66206
66541
  } catch {
66207
66542
  return;
66208
66543
  }
66209
- const dir = isAbsolute4(target) ? target : resolve5(dirname12(current), target);
66544
+ const dir = isAbsolute4(target) ? target : resolve5(dirname13(current), target);
66210
66545
  let ours = false;
66211
66546
  try {
66212
- const record2 = JSON.parse(readFileSync15(join22(dir, INSTALLATION_FILE), "utf8"));
66547
+ const record2 = JSON.parse(readFileSync15(join23(dir, INSTALLATION_FILE), "utf8"));
66213
66548
  ours = typeof record2?.provenance?.cxVersion === "string";
66214
66549
  } catch {
66215
66550
  return;
@@ -66369,6 +66704,7 @@ var HideStatesEditor = ({ widget, states, onComplete, onCancel }) => {
66369
66704
  const [selectedIndex, setSelectedIndex] = import_react42.useState(0);
66370
66705
  const [enabledKeys, setEnabledKeys] = import_react42.useState(() => getEnabledHideStates(widget, states));
66371
66706
  use_input_default((input2, key) => {
66707
+ const shortcut = getPlainInput(input2, key);
66372
66708
  if (key.return) {
66373
66709
  onComplete(setEnabledHideStates(widget, states, enabledKeys));
66374
66710
  } else if (key.escape) {
@@ -66377,7 +66713,7 @@ var HideStatesEditor = ({ widget, states, onComplete, onCancel }) => {
66377
66713
  setSelectedIndex(selectedIndex - 1 < 0 ? states.length - 1 : selectedIndex - 1);
66378
66714
  } else if (key.downArrow && states.length > 0) {
66379
66715
  setSelectedIndex(selectedIndex + 1 > states.length - 1 ? 0 : selectedIndex + 1);
66380
- } else if (input2 === " ") {
66716
+ } else if (shortcut === " ") {
66381
66717
  const state = states[selectedIndex];
66382
66718
  if (state) {
66383
66719
  setEnabledKeys(enabledKeys.includes(state.key) ? enabledKeys.filter((enabledKey) => enabledKey !== state.key) : [...enabledKeys, state.key]);
@@ -66424,6 +66760,48 @@ var HideStatesEditor = ({ widget, states, onComplete, onCancel }) => {
66424
66760
  }, undefined, true, undefined, this);
66425
66761
  };
66426
66762
 
66763
+ // src/tui/components/LabelEditor.tsx
66764
+ var jsx_dev_runtime15 = __toESM(require_jsx_dev_runtime(), 1);
66765
+ var LabelEditor = ({ widget, defaultLabel, onComplete, onCancel }) => {
66766
+ const { getText, display, handleInput } = useTextCursor(getLabel(widget, defaultLabel));
66767
+ use_input_default((input2, key) => {
66768
+ if (key.return) {
66769
+ onComplete(setLabel(widget, getText()));
66770
+ } else if (key.escape) {
66771
+ onCancel();
66772
+ } else if (key.tab) {
66773
+ onComplete(clearLabel(widget));
66774
+ } else {
66775
+ handleInput(input2, key);
66776
+ }
66777
+ });
66778
+ return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
66779
+ flexDirection: "column",
66780
+ children: [
66781
+ /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
66782
+ bold: true,
66783
+ children: "Label"
66784
+ }, undefined, false, undefined, this),
66785
+ /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
66786
+ dimColor: true,
66787
+ children: "←→ move cursor, Ctrl+←→ jump to start/end, Tab reset to default, Enter save, ESC cancel"
66788
+ }, undefined, false, undefined, this),
66789
+ /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
66790
+ marginTop: 1,
66791
+ children: /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
66792
+ children: [
66793
+ `"${display}"`,
66794
+ /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
66795
+ dimColor: true,
66796
+ children: ` (default: ${JSON.stringify(defaultLabel)})`
66797
+ }, undefined, false, undefined, this)
66798
+ ]
66799
+ }, undefined, true, undefined, this)
66800
+ }, undefined, false, undefined, this)
66801
+ ]
66802
+ }, undefined, true, undefined, this);
66803
+ };
66804
+
66427
66805
  // src/tui/components/items-editor/input-handlers.ts
66428
66806
  function customKeybindsFor(impl, item) {
66429
66807
  if (!impl || !item || item.type === "separator" || item.type === "flex-separator")
@@ -66435,6 +66813,9 @@ function customKeybindsFor(impl, item) {
66435
66813
  if ((impl.getHideableStates?.().length ?? 0) > 0 && !keybinds.some((k2) => k2.action === EDIT_HIDE_STATES_ACTION)) {
66436
66814
  keybinds.push(getHideKeybind());
66437
66815
  }
66816
+ if (impl.getLabelPrefix && !item.rawValue) {
66817
+ keybinds.push(getLabelKeybind());
66818
+ }
66438
66819
  return keybinds;
66439
66820
  }
66440
66821
  function filterWidgetCatalog(catalog, category, query) {
@@ -66565,6 +66946,7 @@ function handleNormalInputMode({
66565
66946
  getWidgetImpl,
66566
66947
  setCustomEditorWidget
66567
66948
  }) {
66949
+ const shortcut = getPlainInput(input2, key);
66568
66950
  if (key.upArrow && widgets.length) {
66569
66951
  setSelectedIndex(selectedIndex === 0 ? widgets.length - 1 : selectedIndex - 1);
66570
66952
  } else if (key.downArrow && widgets.length) {
@@ -66573,16 +66955,16 @@ function handleNormalInputMode({
66573
66955
  openWidgetPicker("change");
66574
66956
  } else if (key.return && widgets.length) {
66575
66957
  setMoveMode(true);
66576
- } else if (input2 === "a") {
66958
+ } else if (shortcut === "a") {
66577
66959
  openWidgetPicker("add");
66578
- } else if (input2 === "i") {
66960
+ } else if (shortcut === "i") {
66579
66961
  openWidgetPicker("insert");
66580
- } else if (input2 === "d" && widgets.length) {
66962
+ } else if (shortcut === "d" && widgets.length) {
66581
66963
  const next = widgets.filter((_2, index) => index !== selectedIndex);
66582
66964
  onUpdate(next);
66583
66965
  if (selectedIndex >= next.length && selectedIndex > 0)
66584
66966
  setSelectedIndex(selectedIndex - 1);
66585
- } else if (input2 === "k" && widgets.length) {
66967
+ } else if (shortcut === "k" && widgets.length) {
66586
66968
  const current = widgets[selectedIndex];
66587
66969
  if (!current)
66588
66970
  return;
@@ -66594,33 +66976,39 @@ function handleNormalInputMode({
66594
66976
  const index = selectedIndex + 1;
66595
66977
  onUpdate([...widgets.slice(0, index), clone3, ...widgets.slice(index)]);
66596
66978
  setSelectedIndex(index);
66597
- } else if (input2 === "c" && widgets.length) {
66979
+ } else if (shortcut === "c" && widgets.length) {
66598
66980
  setShowClearConfirm(true);
66599
- } else if (input2 === " " && widgets[selectedIndex]?.type === "separator") {
66981
+ } else if (shortcut === " " && widgets[selectedIndex]?.type === "separator") {
66600
66982
  const current = widgets[selectedIndex];
66601
66983
  const index = Math.max(0, separatorChars.indexOf(current.character ?? "|"));
66602
66984
  const character = separatorChars[(index + 1) % separatorChars.length];
66603
66985
  onUpdate(widgets.map((widget, itemIndex) => itemIndex === selectedIndex ? { ...widget, character } : widget));
66604
- } else if (input2 === "r" && widgets.length) {
66986
+ } else if (shortcut === "r" && widgets.length) {
66605
66987
  const current = widgets[selectedIndex];
66606
66988
  if (current && current.type !== "separator" && current.type !== "flex-separator") {
66607
66989
  onUpdate(widgets.map((widget, index) => index === selectedIndex ? { ...widget, rawValue: !widget.rawValue } : widget));
66608
66990
  }
66609
- } else if (input2 === "m" && widgets.length) {
66991
+ } else if (shortcut === "m" && widgets.length) {
66610
66992
  const current = widgets[selectedIndex];
66611
- if (current && selectedIndex < widgets.length - 1 && current.type !== "separator" && current.type !== "flex-separator") {
66612
- const merge3 = current.merge === undefined ? true : current.merge === true ? "no-padding" : undefined;
66613
- onUpdate(widgets.map((widget, index) => {
66614
- if (index !== selectedIndex)
66615
- return widget;
66616
- if (merge3 === undefined) {
66617
- const { merge: _2, ...withoutMerge } = widget;
66618
- return withoutMerge;
66619
- }
66620
- return { ...widget, merge: merge3 };
66621
- }));
66993
+ if (current && current.type !== "separator" && current.type !== "flex-separator") {
66994
+ const isLastWidget = selectedIndex === widgets.length - 1;
66995
+ if (isLastWidget && current.merge) {
66996
+ const { merge: _2, ...withoutMerge } = current;
66997
+ onUpdate(widgets.map((w2, i) => i === selectedIndex ? withoutMerge : w2));
66998
+ } else if (!isLastWidget) {
66999
+ const merge3 = current.merge === undefined ? true : current.merge === true ? "no-padding" : undefined;
67000
+ onUpdate(widgets.map((widget, index) => {
67001
+ if (index !== selectedIndex)
67002
+ return widget;
67003
+ if (merge3 === undefined) {
67004
+ const { merge: _2, ...withoutMerge } = widget;
67005
+ return withoutMerge;
67006
+ }
67007
+ return { ...widget, merge: merge3 };
67008
+ }));
67009
+ }
66622
67010
  }
66623
- } else if (input2 === "x" && widgets.length) {
67011
+ } else if (shortcut === "x" && widgets.length) {
66624
67012
  const current = widgets[selectedIndex];
66625
67013
  if (current && current.type !== "separator" && current.type !== "flex-separator") {
66626
67014
  onUpdate(widgets.map((widget, index) => {
@@ -66633,15 +67021,15 @@ function handleNormalInputMode({
66633
67021
  return { ...widget, excludeFromAutoAlign: true };
66634
67022
  }));
66635
67023
  }
66636
- } else if (input2 && !key.ctrl && !key.meta && widgets.length) {
67024
+ } else if (shortcut && widgets.length) {
66637
67025
  const current = widgets[selectedIndex];
66638
67026
  if (!current)
66639
67027
  return;
66640
67028
  const impl = getWidgetImpl(current.type);
66641
- const keybind = customKeybindsFor(impl, current).find((entry) => entry.key === input2);
67029
+ const keybind = customKeybindsFor(impl, current).find((entry) => entry.key === shortcut);
66642
67030
  if (!impl || !keybind)
66643
67031
  return;
66644
- if (keybind.action === EDIT_HIDE_STATES_ACTION) {
67032
+ if (keybind.action === EDIT_HIDE_STATES_ACTION || keybind.action === EDIT_LABEL_ACTION) {
66645
67033
  setCustomEditorWidget({ widget: current, impl, action: keybind.action });
66646
67034
  return;
66647
67035
  }
@@ -66661,7 +67049,7 @@ function handleNormalInputMode({
66661
67049
  }
66662
67050
 
66663
67051
  // src/tui/components/ItemsEditor.tsx
66664
- var jsx_dev_runtime15 = __toESM(require_jsx_dev_runtime(), 1);
67052
+ var jsx_dev_runtime16 = __toESM(require_jsx_dev_runtime(), 1);
66665
67053
  function displayWidgetType(type) {
66666
67054
  if (type === "flex-separator")
66667
67055
  return "Flex Separator";
@@ -66693,11 +67081,14 @@ function rowLabel(widget) {
66693
67081
  if (!impl)
66694
67082
  return displayWidgetType(widget.type);
66695
67083
  const { displayText, modifierText } = impl.getEditorDisplay(widget);
67084
+ const labelModifierText = impl?.getLabelPrefix && !widget.rawValue ? getLabelModifierText(widget) : undefined;
66696
67085
  const numberFormatModifierText = impl.supportsNumberFormat?.() ? getNumberFormatModifierText(widget) : undefined;
66697
67086
  const hideModifierText = impl ? getHideModifierText(widget, impl.getHideableStates?.() ?? []) : undefined;
66698
67087
  const parts = [displayText];
66699
67088
  if (modifierText)
66700
67089
  parts.push(modifierText);
67090
+ if (labelModifierText)
67091
+ parts.push(labelModifierText);
66701
67092
  if (numberFormatModifierText)
66702
67093
  parts.push(numberFormatModifierText);
66703
67094
  if (hideModifierText)
@@ -66736,7 +67127,7 @@ function ItemsEditor({ widgets, onUpdate, onBack, lineNumber, settings: _setting
66736
67127
  if (widgetPicker.action === "change") {
66737
67128
  const current2 = widgets[selectedIndex];
66738
67129
  if (current2)
66739
- onUpdate(widgets.map((widget, index) => index === selectedIndex ? { ...widget, type } : widget));
67130
+ onUpdate(widgets.map((widget, index) => index === selectedIndex ? widget.type === type ? widget : { ...clearLabel(widget), type } : widget));
66740
67131
  } else {
66741
67132
  const insertIndex = widgetPicker.action === "add" ? selectedIndex + 1 : selectedIndex;
66742
67133
  const index = widgets.length ? insertIndex : 0;
@@ -66775,7 +67166,7 @@ function ItemsEditor({ widgets, onUpdate, onBack, lineNumber, settings: _setting
66775
67166
  });
66776
67167
  });
66777
67168
  if (customEditor?.action === EDIT_HIDE_STATES_ACTION) {
66778
- return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(HideStatesEditor, {
67169
+ return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(HideStatesEditor, {
66779
67170
  widget: customEditor.widget,
66780
67171
  states: customEditor.impl.getHideableStates?.() ?? [],
66781
67172
  onComplete: (updated) => {
@@ -66785,6 +67176,17 @@ function ItemsEditor({ widgets, onUpdate, onBack, lineNumber, settings: _setting
66785
67176
  onCancel: () => setCustomEditor(null)
66786
67177
  }, undefined, false, undefined, this);
66787
67178
  }
67179
+ if (customEditor?.action === EDIT_LABEL_ACTION && customEditor.impl.getLabelPrefix) {
67180
+ return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(LabelEditor, {
67181
+ widget: customEditor.widget,
67182
+ defaultLabel: customEditor.impl.getLabelPrefix(customEditor.widget),
67183
+ onComplete: (updated) => {
67184
+ onUpdate(widgets.map((widget, index) => index === selectedIndex ? updated : widget));
67185
+ setCustomEditor(null);
67186
+ },
67187
+ onCancel: () => setCustomEditor(null)
67188
+ }, undefined, false, undefined, this);
67189
+ }
66788
67190
  if (customEditor?.impl.renderEditor) {
66789
67191
  const editor = customEditor.impl.renderEditor({
66790
67192
  widget: customEditor.widget,
@@ -66795,15 +67197,15 @@ function ItemsEditor({ widgets, onUpdate, onBack, lineNumber, settings: _setting
66795
67197
  },
66796
67198
  onCancel: () => setCustomEditor(null)
66797
67199
  });
66798
- return editor ?? /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67200
+ return editor ?? /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66799
67201
  children: "Unknown editor"
66800
67202
  }, undefined, false, undefined, this);
66801
67203
  }
66802
67204
  if (showClearConfirm) {
66803
- return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
67205
+ return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
66804
67206
  flexDirection: "column",
66805
67207
  children: [
66806
- /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67208
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66807
67209
  bold: true,
66808
67210
  children: [
66809
67211
  "Clear every widget from Line ",
@@ -66811,7 +67213,7 @@ function ItemsEditor({ widgets, onUpdate, onBack, lineNumber, settings: _setting
66811
67213
  "?"
66812
67214
  ]
66813
67215
  }, undefined, true, undefined, this),
66814
- /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(ConfirmDialog, {
67216
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(ConfirmDialog, {
66815
67217
  inline: true,
66816
67218
  onConfirm: () => {
66817
67219
  onUpdate([]);
@@ -66827,36 +67229,36 @@ function ItemsEditor({ widgets, onUpdate, onBack, lineNumber, settings: _setting
66827
67229
  const topLevelSearch = widgetPicker.level === "category" && widgetPicker.categoryQuery.trim().length > 0;
66828
67230
  const query = topLevelSearch ? widgetPicker.categoryQuery : widgetPicker.widgetQuery;
66829
67231
  const entries = filterWidgetCatalog(widgetCatalog, topLevelSearch ? "All" : widgetPicker.selectedCategory ?? "All", query);
66830
- return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
67232
+ return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
66831
67233
  flexDirection: "column",
66832
67234
  children: [
66833
- /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67235
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66834
67236
  bold: true,
66835
67237
  children: widgetPicker.action === "change" ? "Change Widget" : "Add Widget"
66836
67238
  }, undefined, false, undefined, this),
66837
- /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67239
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66838
67240
  dimColor: true,
66839
67241
  children: widgetPicker.level === "category" ? "Type to search; Enter to choose; Escape to go back" : "Type to search; Enter to add; Escape to go back"
66840
67242
  }, undefined, false, undefined, this),
66841
- /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67243
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66842
67244
  children: `Search: ${query}`
66843
67245
  }, undefined, false, undefined, this),
66844
- /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
67246
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
66845
67247
  marginTop: 1,
66846
67248
  flexDirection: "column",
66847
- children: widgetPicker.level === "category" && !topLevelSearch ? widgetCategories.map((category) => /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67249
+ children: widgetPicker.level === "category" && !topLevelSearch ? widgetCategories.map((category) => /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66848
67250
  ...category === widgetPicker.selectedCategory && { color: "green" },
66849
67251
  children: [
66850
67252
  category === widgetPicker.selectedCategory ? "▶ " : " ",
66851
67253
  category
66852
67254
  ]
66853
- }, category, true, undefined, this)) : entries.length ? entries.map((entry) => /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67255
+ }, category, true, undefined, this)) : entries.length ? entries.map((entry) => /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66854
67256
  ...entry.type === widgetPicker.selectedType && { color: "green" },
66855
67257
  children: [
66856
67258
  entry.type === widgetPicker.selectedType ? "▶ " : " ",
66857
67259
  entry.displayName
66858
67260
  ]
66859
- }, entry.type, true, undefined, this)) : /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67261
+ }, entry.type, true, undefined, this)) : /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66860
67262
  dimColor: true,
66861
67263
  children: "No widgets match this search."
66862
67264
  }, undefined, false, undefined, this)
@@ -66867,33 +67269,33 @@ function ItemsEditor({ widgets, onUpdate, onBack, lineNumber, settings: _setting
66867
67269
  const current = widgets[selectedIndex];
66868
67270
  const customLabels = customKeybindsFor(current ? getWidgetImpl(current.type) : null, current).map((entry) => entry.label).join(", ");
66869
67271
  const normalHelp = "↑↓ select, ←→ change, Enter move, (a)dd, (i)nsert, (d)elete, (k)opy, (c)lear, Escape back";
66870
- return /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
67272
+ return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
66871
67273
  flexDirection: "column",
66872
67274
  children: [
66873
- /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67275
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66874
67276
  bold: true,
66875
67277
  children: [
66876
67278
  `Edit Line ${lineNumber}`,
66877
- moveMode && /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67279
+ moveMode && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66878
67280
  color: "blue",
66879
67281
  children: " [MOVE MODE]"
66880
67282
  }, undefined, false, undefined, this)
66881
67283
  ]
66882
67284
  }, undefined, true, undefined, this),
66883
- /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67285
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66884
67286
  dimColor: true,
66885
67287
  children: moveMode ? "↑↓ to move, Escape or Enter to finish" : customLabels ? `${normalHelp}, ${customLabels}` : normalHelp
66886
67288
  }, undefined, false, undefined, this),
66887
- /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
67289
+ /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
66888
67290
  marginTop: 1,
66889
67291
  flexDirection: "column",
66890
- children: widgets.length ? widgets.map((widget, index) => /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67292
+ children: widgets.length ? widgets.map((widget, index) => /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66891
67293
  ...index === selectedIndex && { color: "green" },
66892
67294
  children: [
66893
67295
  index === selectedIndex ? "▶ " : " ",
66894
67296
  rowLabel(widget)
66895
67297
  ]
66896
- }, widget.id, true, undefined, this)) : /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
67298
+ }, widget.id, true, undefined, this)) : /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
66897
67299
  dimColor: true,
66898
67300
  children: "No widgets yet. Press (a) to add one."
66899
67301
  }, undefined, false, undefined, this)
@@ -66952,7 +67354,7 @@ function cycleWidgetColor({ widgets, widgetId, direction, editingBackground, col
66952
67354
  }
66953
67355
 
66954
67356
  // src/tui/components/ColorMenu.tsx
66955
- var jsx_dev_runtime16 = __toESM(require_jsx_dev_runtime(), 1);
67357
+ var jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
66956
67358
  function isTextInput(input2, key) {
66957
67359
  return Boolean(input2 && !key.ctrl && !key.meta && !key.tab);
66958
67360
  }
@@ -66997,6 +67399,7 @@ function ColorMenu({ widgets, lineIndex, settings, onUpdate, onBack }) {
66997
67399
  setAnsiInput(ansiInput + input2);
66998
67400
  return;
66999
67401
  }
67402
+ const shortcut = getPlainInput(input2, key);
67000
67403
  if (key.escape) {
67001
67404
  onBack();
67002
67405
  } else if (key.upArrow && colorable.length) {
@@ -67006,34 +67409,37 @@ function ColorMenu({ widgets, lineIndex, settings, onUpdate, onBack }) {
67006
67409
  } else if (key.leftArrow || key.rightArrow) {
67007
67410
  if (selected)
67008
67411
  onUpdate(cycleWidgetColor({ widgets, widgetId: selected.id, direction: key.rightArrow ? "right" : "left", editingBackground, colors, backgroundColors: backgrounds }));
67009
- } else if (input2.toLowerCase() === "f") {
67412
+ } else if (shortcut.toLowerCase() === "f") {
67010
67413
  setEditingBackground((value) => !value);
67011
- } else if (input2.toLowerCase() === "b" && selected) {
67414
+ } else if (shortcut.toLowerCase() === "b" && selected) {
67012
67415
  onUpdate(toggleWidgetBold(widgets, selected.id));
67013
- } else if (input2.toLowerCase() === "d" && selected) {
67416
+ } else if (shortcut.toLowerCase() === "d" && selected) {
67014
67417
  onUpdate(cycleWidgetDim(widgets, selected.id));
67015
- } else if (input2.toLowerCase() === "r" && selected) {
67418
+ } else if (shortcut.toLowerCase() === "r" && selected) {
67016
67419
  onUpdate(resetWidgetStyling(widgets, selected.id));
67017
- } else if (input2.toLowerCase() === "c") {
67420
+ } else if (shortcut.toLowerCase() === "c") {
67018
67421
  setClearConfirm(true);
67019
- } else if (input2.toLowerCase() === "s" && !settings.powerline.enabled && !settings.defaultSeparator) {
67422
+ } else if (shortcut.toLowerCase() === "s" && !settings.powerline.enabled && !settings.defaultSeparator) {
67423
+ const highlightedWidget = colorable[selectedIndex];
67020
67424
  setShowSeparators((value) => !value);
67021
- setSelectedIndex(0);
67022
- } else if (input2.toLowerCase() === "h" && settings.colorLevel === 3 && selected) {
67425
+ if (showSeparators && highlightedWidget?.type === "separator") {
67426
+ setSelectedIndex(0);
67427
+ }
67428
+ } else if (shortcut.toLowerCase() === "h" && settings.colorLevel === 3 && selected) {
67023
67429
  setHexInput("");
67024
- } else if (input2.toLowerCase() === "a" && settings.colorLevel === 2 && selected) {
67430
+ } else if (shortcut.toLowerCase() === "a" && settings.colorLevel === 2 && selected) {
67025
67431
  setAnsiInput("");
67026
67432
  }
67027
67433
  });
67028
67434
  if (clearConfirm) {
67029
- return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
67435
+ return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
67030
67436
  flexDirection: "column",
67031
67437
  children: [
67032
- /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
67438
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67033
67439
  bold: true,
67034
67440
  children: "Clear all widget styling?"
67035
67441
  }, undefined, false, undefined, this),
67036
- /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(ConfirmDialog, {
67442
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(ConfirmDialog, {
67037
67443
  inline: true,
67038
67444
  onConfirm: () => {
67039
67445
  onUpdate(clearAllWidgetStyling(widgets));
@@ -67045,14 +67451,14 @@ function ColorMenu({ widgets, lineIndex, settings, onUpdate, onBack }) {
67045
67451
  }, undefined, true, undefined, this);
67046
67452
  }
67047
67453
  if (!colorable.length) {
67048
- return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
67454
+ return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
67049
67455
  flexDirection: "column",
67050
67456
  children: [
67051
- /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
67457
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67052
67458
  bold: true,
67053
67459
  children: `Colors — Line ${lineIndex + 1}`
67054
67460
  }, undefined, false, undefined, this),
67055
- /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
67461
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67056
67462
  dimColor: true,
67057
67463
  children: "No colorable widgets. Press Escape to go back."
67058
67464
  }, undefined, false, undefined, this)
@@ -67060,38 +67466,38 @@ function ColorMenu({ widgets, lineIndex, settings, onUpdate, onBack }) {
67060
67466
  }, undefined, true, undefined, this);
67061
67467
  }
67062
67468
  const inputMode = hexInput !== null ? `Hex: #${hexInput}` : ansiInput !== null ? `ANSI 256: ${ansiInput}` : null;
67063
- return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
67469
+ return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
67064
67470
  flexDirection: "column",
67065
67471
  children: [
67066
- /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
67472
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67067
67473
  bold: true,
67068
67474
  children: [
67069
67475
  `Colors — Line ${lineIndex + 1}`,
67070
- editingBackground && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
67476
+ editingBackground && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67071
67477
  color: "yellow",
67072
67478
  children: " [Background]"
67073
67479
  }, undefined, false, undefined, this)
67074
67480
  ]
67075
67481
  }, undefined, true, undefined, this),
67076
- inputMode ? /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
67482
+ inputMode ? /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67077
67483
  children: [
67078
67484
  inputMode,
67079
- /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
67485
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67080
67486
  dimColor: true,
67081
67487
  children: " Enter to apply, Escape to cancel"
67082
67488
  }, undefined, false, undefined, this)
67083
67489
  ]
67084
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
67490
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67085
67491
  dimColor: true,
67086
67492
  children: `↑↓ select, ←→ cycle ${editingBackground ? "background" : "foreground"}, (f)g/bg, (b)old, (d)im, (r)eset, (c)lear${settings.colorLevel === 3 ? ", (h)ex" : settings.colorLevel === 2 ? ", (a)nsi256" : ""}, Escape back`
67087
67493
  }, undefined, false, undefined, this),
67088
- /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
67494
+ /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
67089
67495
  marginTop: 1,
67090
67496
  flexDirection: "column",
67091
67497
  children: colorable.map((widget, index) => {
67092
67498
  const label = displayWidgetType(widget.type);
67093
67499
  const styled = applyColors(label, widget.color, widget.backgroundColor, widget.bold, getColorLevelString(settings.colorLevel), widget.dim);
67094
- return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
67500
+ return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67095
67501
  ...index === selectedIndex && { color: "green" },
67096
67502
  children: [
67097
67503
  index === selectedIndex ? "▶ " : " ",
@@ -67100,7 +67506,7 @@ function ColorMenu({ widgets, lineIndex, settings, onUpdate, onBack }) {
67100
67506
  }, widget.id, true, undefined, this);
67101
67507
  })
67102
67508
  }, undefined, false, undefined, this),
67103
- !settings.powerline.enabled && !settings.defaultSeparator && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
67509
+ !settings.powerline.enabled && !settings.defaultSeparator && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67104
67510
  dimColor: true,
67105
67511
  children: `(s)how separators: ${showSeparators ? "ON" : "OFF"}`
67106
67512
  }, undefined, false, undefined, this)
@@ -67110,15 +67516,15 @@ function ColorMenu({ widgets, lineIndex, settings, onUpdate, onBack }) {
67110
67516
 
67111
67517
  // src/tui/components/ExportConfigDialog.tsx
67112
67518
  var import_react45 = __toESM(require_react(), 1);
67113
- var jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
67519
+ var jsx_dev_runtime18 = __toESM(require_jsx_dev_runtime(), 1);
67114
67520
  function acceptsText(input2, key) {
67115
67521
  return Boolean(input2 && !key.ctrl && !key.meta && !key.tab);
67116
67522
  }
67117
67523
  function ExportConfigDialog({ initialPath, onExport, onCancel }) {
67118
- const [path, setPath] = import_react45.useState(initialPath);
67524
+ const [path3, setPath] = import_react45.useState(initialPath);
67119
67525
  use_input_default((input2, key) => {
67120
67526
  if (key.return)
67121
- onExport(path);
67527
+ onExport(path3);
67122
67528
  else if (key.escape)
67123
67529
  onCancel();
67124
67530
  else if (key.backspace || key.delete)
@@ -67126,27 +67532,27 @@ function ExportConfigDialog({ initialPath, onExport, onCancel }) {
67126
67532
  else if (acceptsText(input2, key))
67127
67533
  setPath((current) => current + input2);
67128
67534
  });
67129
- return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
67535
+ return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
67130
67536
  flexDirection: "column",
67131
67537
  children: [
67132
- /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67538
+ /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67133
67539
  bold: true,
67134
67540
  children: "Export Config"
67135
67541
  }, undefined, false, undefined, this),
67136
- /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67542
+ /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67137
67543
  dimColor: true,
67138
67544
  children: "Enter the file path to export your configuration to:"
67139
67545
  }, undefined, false, undefined, this),
67140
- /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67546
+ /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67141
67547
  children: [
67142
- `Path: ${path}`,
67143
- /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67548
+ `Path: ${path3}`,
67549
+ /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67144
67550
  inverse: true,
67145
67551
  children: " "
67146
67552
  }, undefined, false, undefined, this)
67147
67553
  ]
67148
67554
  }, undefined, true, undefined, this),
67149
- /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
67555
+ /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67150
67556
  dimColor: true,
67151
67557
  children: "Enter to confirm, Escape to cancel"
67152
67558
  }, undefined, false, undefined, this)
@@ -67156,7 +67562,7 @@ function ExportConfigDialog({ initialPath, onExport, onCancel }) {
67156
67562
 
67157
67563
  // src/tui/components/GlobalOverridesMenu.tsx
67158
67564
  var import_react46 = __toESM(require_react(), 1);
67159
- var jsx_dev_runtime18 = __toESM(require_jsx_dev_runtime(), 1);
67565
+ var jsx_dev_runtime19 = __toESM(require_jsx_dev_runtime(), 1);
67160
67566
  function acceptsText2(input2, key) {
67161
67567
  return Boolean(input2 && !key.ctrl && !key.meta && !key.tab);
67162
67568
  }
@@ -67284,49 +67690,50 @@ function GlobalOverridesMenu({ settings, onUpdate, onBack }) {
67284
67690
  }
67285
67691
  return;
67286
67692
  }
67693
+ const shortcut = getPlainInput(input2, key);
67287
67694
  if (key.escape)
67288
67695
  onBack();
67289
- else if (input2.toLowerCase() === "n") {
67696
+ else if (shortcut.toLowerCase() === "n") {
67290
67697
  setNumberFormatMode(true);
67291
67698
  setNumberFormatKindIndex(0);
67292
- } else if (input2.toLowerCase() === "p") {
67699
+ } else if (shortcut.toLowerCase() === "p") {
67293
67700
  setValue(settings.defaultPadding ?? "");
67294
67701
  setEditing("padding");
67295
- } else if (input2.toLowerCase() === "s" && !powerline) {
67702
+ } else if (shortcut.toLowerCase() === "s" && !powerline) {
67296
67703
  setValue(settings.defaultSeparator ?? "");
67297
67704
  setEditing("separator");
67298
- } else if (input2.toLowerCase() === "i" && !powerline)
67705
+ } else if (shortcut.toLowerCase() === "i" && !powerline)
67299
67706
  onUpdate({ ...settings, inheritSeparatorColors: !settings.inheritSeparatorColors });
67300
- else if (input2.toLowerCase() === "o")
67707
+ else if (shortcut.toLowerCase() === "o")
67301
67708
  onUpdate({ ...settings, globalBold: !settings.globalBold });
67302
- else if (input2.toLowerCase() === "m")
67709
+ else if (shortcut.toLowerCase() === "m")
67303
67710
  onUpdate({ ...settings, minimalistMode: !settings.minimalistMode });
67304
- else if (input2.toLowerCase() === "f")
67711
+ else if (shortcut.toLowerCase() === "f")
67305
67712
  onUpdate({ ...settings, overrideForegroundColor: cycle(foregrounds, settings.overrideForegroundColor) });
67306
- else if (input2.toLowerCase() === "g") {
67713
+ else if (shortcut.toLowerCase() === "g") {
67307
67714
  setGradientMode(true);
67308
67715
  setGradientIndex(0);
67309
- } else if (input2.toLowerCase() === "x")
67716
+ } else if (shortcut.toLowerCase() === "x")
67310
67717
  onUpdate({ ...settings, overrideForegroundColor: undefined });
67311
- else if (input2.toLowerCase() === "b" && !powerline)
67718
+ else if (shortcut.toLowerCase() === "b" && !powerline)
67312
67719
  onUpdate({ ...settings, overrideBackgroundColor: cycle(backgrounds, settings.overrideBackgroundColor) });
67313
- else if (input2.toLowerCase() === "c" && !powerline)
67720
+ else if (shortcut.toLowerCase() === "c" && !powerline)
67314
67721
  onUpdate({ ...settings, overrideBackgroundColor: undefined });
67315
- else if (input2.toLowerCase() === "d") {
67722
+ else if (shortcut.toLowerCase() === "d") {
67316
67723
  const options = DefaultPaddingSideSchema.options;
67317
67724
  const index = Math.max(0, options.indexOf(settings.defaultPaddingSide));
67318
67725
  onUpdate({ ...settings, defaultPaddingSide: options[(index + 1) % options.length] ?? "both" });
67319
67726
  }
67320
67727
  });
67321
67728
  if (confirmSeparator) {
67322
- return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
67729
+ return /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Box_default, {
67323
67730
  flexDirection: "column",
67324
67731
  children: [
67325
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67732
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67326
67733
  color: "yellow",
67327
67734
  children: "Setting a default separator removes manual separators. Continue?"
67328
67735
  }, undefined, false, undefined, this),
67329
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(ConfirmDialog, {
67736
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(ConfirmDialog, {
67330
67737
  inline: true,
67331
67738
  onConfirm: () => {
67332
67739
  onUpdate({ ...settings, defaultSeparator: value, lines: settings.lines.map((line3) => line3.filter((item) => item.type !== "separator")) });
@@ -67343,30 +67750,30 @@ function GlobalOverridesMenu({ settings, onUpdate, onBack }) {
67343
67750
  }
67344
67751
  if (gradientMode) {
67345
67752
  if (gradientStep) {
67346
- return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
67753
+ return /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Box_default, {
67347
67754
  flexDirection: "column",
67348
67755
  children: [
67349
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67756
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67350
67757
  bold: true,
67351
67758
  children: "Custom Gradient — Override FG Color"
67352
67759
  }, undefined, false, undefined, this),
67353
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67760
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67354
67761
  children: gradientStep === "start" ? "Enter START hex color:" : "Enter END hex color:"
67355
67762
  }, undefined, false, undefined, this),
67356
- gradientStep === "end" && /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67763
+ gradientStep === "end" && /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67357
67764
  dimColor: true,
67358
67765
  children: `Start: #${gradientStart}`
67359
67766
  }, undefined, false, undefined, this),
67360
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67767
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67361
67768
  children: [
67362
67769
  `#${gradientInput}`,
67363
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67770
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67364
67771
  dimColor: true,
67365
67772
  children: "_".repeat(6 - gradientInput.length)
67366
67773
  }, undefined, false, undefined, this)
67367
67774
  ]
67368
67775
  }, undefined, true, undefined, this),
67369
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67776
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67370
67777
  dimColor: true,
67371
67778
  children: "Enter to continue, Escape to go back"
67372
67779
  }, undefined, false, undefined, this)
@@ -67374,28 +67781,28 @@ function GlobalOverridesMenu({ settings, onUpdate, onBack }) {
67374
67781
  }, undefined, true, undefined, this);
67375
67782
  }
67376
67783
  const level = getColorLevelString(settings.colorLevel);
67377
- return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
67784
+ return /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Box_default, {
67378
67785
  flexDirection: "column",
67379
67786
  children: [
67380
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67787
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67381
67788
  bold: true,
67382
67789
  children: "Select Gradient — Override FG Color"
67383
67790
  }, undefined, false, undefined, this),
67384
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67791
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67385
67792
  dimColor: true,
67386
67793
  children: "↑↓ select, Enter apply, Escape cancel"
67387
67794
  }, undefined, false, undefined, this),
67388
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
67795
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Box_default, {
67389
67796
  marginTop: 1,
67390
67797
  flexDirection: "column",
67391
67798
  children: [
67392
- GRADIENT_PRESET_NAMES.map((name, index) => /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67799
+ GRADIENT_PRESET_NAMES.map((name, index) => /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67393
67800
  children: [
67394
67801
  index === gradientIndex ? "▶ " : " ",
67395
67802
  applyColors(name, `gradient:${name}`, undefined, index === gradientIndex, level)
67396
67803
  ]
67397
67804
  }, name, true, undefined, this)),
67398
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67805
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67399
67806
  children: [
67400
67807
  gradientIndex === GRADIENT_PRESET_NAMES.length ? "▶ " : " ",
67401
67808
  "Custom (two hex stops)"
@@ -67408,23 +67815,23 @@ function GlobalOverridesMenu({ settings, onUpdate, onBack }) {
67408
67815
  }
67409
67816
  if (numberFormatMode) {
67410
67817
  const width = Math.max(...NUMBER_KINDS.map((kind) => kind.length));
67411
- return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
67818
+ return /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Box_default, {
67412
67819
  flexDirection: "column",
67413
67820
  children: [
67414
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67821
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67415
67822
  bold: true,
67416
67823
  children: "Global Number Formatting"
67417
67824
  }, undefined, false, undefined, this),
67418
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67825
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67419
67826
  dimColor: true,
67420
67827
  children: "↑↓ to select a number type, ←→ to cycle its style, ESC to go back"
67421
67828
  }, undefined, false, undefined, this),
67422
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
67829
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Box_default, {
67423
67830
  marginTop: 1,
67424
67831
  flexDirection: "column",
67425
67832
  children: NUMBER_KINDS.map((kind, idx) => {
67426
67833
  const style = settings.numberFormat?.[kind]?.style ?? "precise (default)";
67427
- return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67834
+ return /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67428
67835
  ...idx === numberFormatKindIndex && { color: "cyan" },
67429
67836
  children: [
67430
67837
  idx === numberFormatKindIndex ? "▶ " : " ",
@@ -67435,15 +67842,15 @@ function GlobalOverridesMenu({ settings, onUpdate, onBack }) {
67435
67842
  }, kind, true, undefined, this);
67436
67843
  })
67437
67844
  }, undefined, false, undefined, this),
67438
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
67845
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Box_default, {
67439
67846
  marginTop: 1,
67440
67847
  flexDirection: "column",
67441
67848
  children: [
67442
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67849
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67443
67850
  dimColor: true,
67444
67851
  children: "precise = keep trailing zeros (1.0M), compact = trim them (1M / 1.1M), whole = no decimals (1M)."
67445
67852
  }, undefined, false, undefined, this),
67446
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67853
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67447
67854
  dimColor: true,
67448
67855
  children: "A global style forces that type across every widget. Decimal places are set per-widget or in settings.json."
67449
67856
  }, undefined, false, undefined, this)
@@ -67453,68 +67860,68 @@ function GlobalOverridesMenu({ settings, onUpdate, onBack }) {
67453
67860
  }, undefined, true, undefined, this);
67454
67861
  }
67455
67862
  if (editing) {
67456
- return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
67863
+ return /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Box_default, {
67457
67864
  flexDirection: "column",
67458
67865
  children: [
67459
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67866
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67460
67867
  bold: true,
67461
67868
  children: editing === "padding" ? "Default Padding" : "Default Separator"
67462
67869
  }, undefined, false, undefined, this),
67463
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67870
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67464
67871
  children: [
67465
67872
  value,
67466
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67873
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67467
67874
  inverse: true,
67468
67875
  children: " "
67469
67876
  }, undefined, false, undefined, this)
67470
67877
  ]
67471
67878
  }, undefined, true, undefined, this),
67472
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67879
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67473
67880
  dimColor: true,
67474
67881
  children: "Enter to apply, Escape to cancel"
67475
67882
  }, undefined, false, undefined, this)
67476
67883
  ]
67477
67884
  }, undefined, true, undefined, this);
67478
67885
  }
67479
- return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
67886
+ return /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Box_default, {
67480
67887
  flexDirection: "column",
67481
67888
  children: [
67482
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67889
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67483
67890
  bold: true,
67484
67891
  children: "Global Overrides"
67485
67892
  }, undefined, false, undefined, this),
67486
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67893
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67487
67894
  dimColor: true,
67488
67895
  children: "Configure rendering-wide padding, separators, and styling."
67489
67896
  }, undefined, false, undefined, this),
67490
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67897
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67491
67898
  children: `Global Bold: ${settings.globalBold ? "Enabled" : "Disabled"} (o)`
67492
67899
  }, undefined, false, undefined, this),
67493
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67900
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67494
67901
  children: `Minimalist Mode: ${settings.minimalistMode ? "Enabled" : "Disabled"} (m)`
67495
67902
  }, undefined, false, undefined, this),
67496
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67903
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67497
67904
  children: `Number Formatting: ${settings.numberFormat ? "customized" : "(defaults)"} (n)`
67498
67905
  }, undefined, false, undefined, this),
67499
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67906
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67500
67907
  children: `Default Padding: ${settings.defaultPadding ? JSON.stringify(settings.defaultPadding) : "none"} (p)`
67501
67908
  }, undefined, false, undefined, this),
67502
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67909
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67503
67910
  children: `Padding Side: ${settings.defaultPaddingSide} (d)`
67504
67911
  }, undefined, false, undefined, this),
67505
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67912
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67506
67913
  children: `Override FG: ${settings.overrideForegroundColor ?? "none"} (f cycle, g gradient, x clear)`
67507
67914
  }, undefined, false, undefined, this),
67508
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67915
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67509
67916
  children: powerline ? "Override BG: disabled while Powerline is active" : `Override BG: ${settings.overrideBackgroundColor ?? "none"} (b cycle, c clear)`
67510
67917
  }, undefined, false, undefined, this),
67511
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67918
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67512
67919
  children: powerline ? "Default Separator: disabled while Powerline is active" : `Default Separator: ${settings.defaultSeparator ? JSON.stringify(settings.defaultSeparator) : "none"} (s)`
67513
67920
  }, undefined, false, undefined, this),
67514
- !powerline && /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67921
+ !powerline && /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67515
67922
  children: `Inherit Separator Colors: ${settings.inheritSeparatorColors ? "Enabled" : "Disabled"} (i)`
67516
67923
  }, undefined, false, undefined, this),
67517
- /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
67924
+ /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67518
67925
  dimColor: true,
67519
67926
  children: "Escape to cancel these changes"
67520
67927
  }, undefined, false, undefined, this)
@@ -67524,15 +67931,15 @@ function GlobalOverridesMenu({ settings, onUpdate, onBack }) {
67524
67931
 
67525
67932
  // src/tui/components/ImportConfigDialog.tsx
67526
67933
  var import_react47 = __toESM(require_react(), 1);
67527
- var jsx_dev_runtime19 = __toESM(require_jsx_dev_runtime(), 1);
67934
+ var jsx_dev_runtime20 = __toESM(require_jsx_dev_runtime(), 1);
67528
67935
  function acceptsText3(input2, key) {
67529
67936
  return Boolean(input2 && !key.ctrl && !key.meta && !key.tab);
67530
67937
  }
67531
67938
  function ImportConfigDialog({ error: error61, onFileChosen, onCancel }) {
67532
- const [path, setPath] = import_react47.useState("");
67939
+ const [path3, setPath] = import_react47.useState("");
67533
67940
  use_input_default((input2, key) => {
67534
67941
  if (key.return)
67535
- onFileChosen(path);
67942
+ onFileChosen(path3);
67536
67943
  else if (key.escape)
67537
67944
  onCancel();
67538
67945
  else if (key.backspace || key.delete)
@@ -67540,31 +67947,31 @@ function ImportConfigDialog({ error: error61, onFileChosen, onCancel }) {
67540
67947
  else if (acceptsText3(input2, key))
67541
67948
  setPath((current) => current + input2);
67542
67949
  });
67543
- return /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Box_default, {
67950
+ return /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(Box_default, {
67544
67951
  flexDirection: "column",
67545
67952
  children: [
67546
- /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67953
+ /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(Text, {
67547
67954
  bold: true,
67548
67955
  children: "Import Config"
67549
67956
  }, undefined, false, undefined, this),
67550
- /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67957
+ /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(Text, {
67551
67958
  dimColor: true,
67552
67959
  children: "Enter the file path to import configuration from:"
67553
67960
  }, undefined, false, undefined, this),
67554
- /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67961
+ /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(Text, {
67555
67962
  children: [
67556
- `Path: ${path}`,
67557
- /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67963
+ `Path: ${path3}`,
67964
+ /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(Text, {
67558
67965
  inverse: true,
67559
67966
  children: " "
67560
67967
  }, undefined, false, undefined, this)
67561
67968
  ]
67562
67969
  }, undefined, true, undefined, this),
67563
- error61 && /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67970
+ error61 && /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(Text, {
67564
67971
  color: "red",
67565
67972
  children: error61
67566
67973
  }, undefined, false, undefined, this),
67567
- /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
67974
+ /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(Text, {
67568
67975
  dimColor: true,
67569
67976
  children: "Enter to preview, Escape to cancel"
67570
67977
  }, undefined, false, undefined, this)
@@ -67573,7 +67980,7 @@ function ImportConfigDialog({ error: error61, onFileChosen, onCancel }) {
67573
67980
  }
67574
67981
 
67575
67982
  // src/tui/components/StatusLinePreview.tsx
67576
- var jsx_dev_runtime20 = __toESM(require_jsx_dev_runtime(), 1);
67983
+ var jsx_dev_runtime21 = __toESM(require_jsx_dev_runtime(), 1);
67577
67984
  var PREVIEW_CONTEXT = {
67578
67985
  data: { payload_version: 1 },
67579
67986
  now: new Date(0),
@@ -67581,78 +67988,81 @@ var PREVIEW_CONTEXT = {
67581
67988
  };
67582
67989
  function StatusLinePreview({ settings, terminalWidth }) {
67583
67990
  const rows = renderStatusLines(settings, { ...PREVIEW_CONTEXT, isPreview: true, terminalWidth });
67584
- return /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(Box_default, {
67991
+ return /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Box_default, {
67585
67992
  flexDirection: "column",
67586
- children: rows.map((row, i) => /* @__PURE__ */ jsx_dev_runtime20.jsxDEV(Text, {
67993
+ children: rows.map((row, i) => /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text, {
67587
67994
  children: row
67588
67995
  }, i, false, undefined, this))
67589
67996
  }, undefined, false, undefined, this);
67590
67997
  }
67591
67998
 
67592
67999
  // src/tui/components/ImportPreviewDialog.tsx
67593
- var jsx_dev_runtime21 = __toESM(require_jsx_dev_runtime(), 1);
68000
+ var jsx_dev_runtime22 = __toESM(require_jsx_dev_runtime(), 1);
68001
+ function escapeControlCharacters(text) {
68002
+ return text.replace(/[\x00-\x1f\x7f-\x9f]/g, (char) => `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`);
68003
+ }
67594
68004
  function ImportPreviewDialog({ preview, terminalWidth, busy = false, onConfirm, onCancel }) {
67595
68005
  const rows = renderStatusLines(preview.settings, { ...PREVIEW_CONTEXT, isPreview: true, terminalWidth });
67596
68006
  const allCustomCommands = preview.settings.lines.flat().filter((item) => item.type === "custom-command");
67597
- const uncachedCommands = allCustomCommands.filter((item) => item.refreshMs === undefined).map((item) => item.commandPath ?? "(no command)");
67598
- const cachedCommands = allCustomCommands.filter((item) => item.refreshMs !== undefined).map((item) => `${item.commandPath ?? "(no command)"} (every ${item.refreshMs}ms)`);
67599
- return /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Box_default, {
68007
+ const uncachedCommands = allCustomCommands.filter((item) => item.refreshMs === undefined).map((item) => escapeControlCharacters(item.commandPath ?? "(no command)"));
68008
+ const cachedCommands = allCustomCommands.filter((item) => item.refreshMs !== undefined).map((item) => `${escapeControlCharacters(item.commandPath ?? "(no command)")} (every ${item.refreshMs}ms)`);
68009
+ return /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
67600
68010
  flexDirection: "column",
67601
68011
  children: [
67602
- /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text, {
68012
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
67603
68013
  bold: true,
67604
68014
  children: "Import Preview"
67605
68015
  }, undefined, false, undefined, this),
67606
- /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text, {
68016
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
67607
68017
  dimColor: true,
67608
68018
  children: "Preview rendered by the production statusline renderer:"
67609
68019
  }, undefined, false, undefined, this),
67610
- /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Box_default, {
68020
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
67611
68021
  marginTop: 1,
67612
68022
  flexDirection: "column",
67613
- children: rows.map((row, index) => /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text, {
68023
+ children: rows.map((row, index) => /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
67614
68024
  children: row
67615
68025
  }, index, false, undefined, this))
67616
68026
  }, undefined, false, undefined, this),
67617
- preview.omittedTypes.length > 0 && /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text, {
68027
+ preview.omittedTypes.length > 0 && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
67618
68028
  color: "yellow",
67619
68029
  children: `Deferred unsupported widgets: ${preview.omittedTypes.join(", ")}`
67620
68030
  }, undefined, false, undefined, this),
67621
- uncachedCommands.length > 0 && /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Box_default, {
68031
+ uncachedCommands.length > 0 && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
67622
68032
  flexDirection: "column",
67623
68033
  children: [
67624
- /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text, {
68034
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
67625
68035
  color: "yellow",
67626
68036
  children: "Commands that will run on every render:"
67627
68037
  }, undefined, false, undefined, this),
67628
- uncachedCommands.map((command, index) => /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text, {
68038
+ uncachedCommands.map((command, index) => /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
67629
68039
  color: "yellow",
67630
68040
  children: ` ${command}`
67631
68041
  }, index, false, undefined, this))
67632
68042
  ]
67633
68043
  }, undefined, true, undefined, this),
67634
- cachedCommands.length > 0 && /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Box_default, {
68044
+ cachedCommands.length > 0 && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
67635
68045
  flexDirection: "column",
67636
68046
  children: [
67637
- /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text, {
68047
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
67638
68048
  color: "yellow",
67639
68049
  children: "Cached commands (run in background):"
67640
68050
  }, undefined, false, undefined, this),
67641
- cachedCommands.map((command, index) => /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text, {
68051
+ cachedCommands.map((command, index) => /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
67642
68052
  color: "yellow",
67643
68053
  children: ` ${command}`
67644
68054
  }, index, false, undefined, this))
67645
68055
  ]
67646
68056
  }, undefined, true, undefined, this),
67647
- busy ? /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text, {
68057
+ busy ? /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
67648
68058
  dimColor: true,
67649
68059
  children: "Applying imported configuration…"
67650
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(jsx_dev_runtime21.Fragment, {
68060
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(jsx_dev_runtime22.Fragment, {
67651
68061
  children: [
67652
- /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(Text, {
68062
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
67653
68063
  children: "Apply this preset?"
67654
68064
  }, undefined, false, undefined, this),
67655
- /* @__PURE__ */ jsx_dev_runtime21.jsxDEV(ConfirmDialog, {
68065
+ /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(ConfirmDialog, {
67656
68066
  inline: true,
67657
68067
  onConfirm,
67658
68068
  onCancel
@@ -67665,7 +68075,7 @@ function ImportPreviewDialog({ preview, terminalWidth, busy = false, onConfirm,
67665
68075
 
67666
68076
  // src/tui/components/LineSelector.tsx
67667
68077
  var import_react48 = __toESM(require_react(), 1);
67668
- var jsx_dev_runtime22 = __toESM(require_jsx_dev_runtime(), 1);
68078
+ var jsx_dev_runtime23 = __toESM(require_jsx_dev_runtime(), 1);
67669
68079
  function cloneLines(lines) {
67670
68080
  return lines.map((line3) => line3.map((item) => ({ ...item, ...item.metadata && { metadata: { ...item.metadata } } })));
67671
68081
  }
@@ -67715,7 +68125,8 @@ function LineSelector({
67715
68125
  }
67716
68126
  return;
67717
68127
  }
67718
- if (input2 === "a" && allowEditing) {
68128
+ const shortcut = getPlainInput(input2, key);
68129
+ if (shortcut === "a" && allowEditing) {
67719
68130
  if (localLines.length >= 3) {
67720
68131
  setLimitMessage("Maximum of 3 lines");
67721
68132
  } else {
@@ -67726,11 +68137,11 @@ function LineSelector({
67726
68137
  }
67727
68138
  return;
67728
68139
  }
67729
- if (input2 === "d" && allowEditing && localLines.length > 1) {
68140
+ if (shortcut === "d" && allowEditing && localLines.length > 1) {
67730
68141
  setConfirmDelete(true);
67731
68142
  return;
67732
68143
  }
67733
- if (input2 === "m" && allowEditing && localLines.length > 1) {
68144
+ if (shortcut === "m" && allowEditing && localLines.length > 1) {
67734
68145
  setMoveMode(true);
67735
68146
  return;
67736
68147
  }
@@ -67738,18 +68149,18 @@ function LineSelector({
67738
68149
  onBack();
67739
68150
  });
67740
68151
  if (confirmDelete) {
67741
- return /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
68152
+ return /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Box_default, {
67742
68153
  flexDirection: "column",
67743
68154
  children: [
67744
- /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
68155
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text, {
67745
68156
  bold: true,
67746
68157
  children: `Delete Line ${selectedIndex + 1}?`
67747
68158
  }, undefined, false, undefined, this),
67748
- /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
68159
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text, {
67749
68160
  dimColor: true,
67750
68161
  children: lineSummary(localLines[selectedIndex] ?? [])
67751
68162
  }, undefined, false, undefined, this),
67752
- /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(ConfirmDialog, {
68163
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(ConfirmDialog, {
67753
68164
  inline: true,
67754
68165
  onConfirm: () => {
67755
68166
  const next = localLines.filter((_2, index) => index !== selectedIndex);
@@ -67763,28 +68174,28 @@ function LineSelector({
67763
68174
  }, undefined, true, undefined, this);
67764
68175
  }
67765
68176
  if (moveMode) {
67766
- return /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
68177
+ return /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Box_default, {
67767
68178
  flexDirection: "column",
67768
68179
  children: [
67769
- /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
68180
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text, {
67770
68181
  bold: true,
67771
68182
  children: [
67772
68183
  title,
67773
68184
  " ",
67774
- /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
68185
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text, {
67775
68186
  color: "blue",
67776
68187
  children: "[MOVE MODE]"
67777
68188
  }, undefined, false, undefined, this)
67778
68189
  ]
67779
68190
  }, undefined, true, undefined, this),
67780
- /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
68191
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text, {
67781
68192
  dimColor: true,
67782
68193
  children: "↑↓ to move a line, Escape or Enter to finish"
67783
68194
  }, undefined, false, undefined, this),
67784
- /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
68195
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Box_default, {
67785
68196
  marginTop: 1,
67786
68197
  flexDirection: "column",
67787
- children: localLines.map((line3, index) => /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
68198
+ children: localLines.map((line3, index) => /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text, {
67788
68199
  ...index === selectedIndex && { color: "green" },
67789
68200
  children: [
67790
68201
  index === selectedIndex ? "◆ " : " ",
@@ -67795,22 +68206,22 @@ function LineSelector({
67795
68206
  ]
67796
68207
  }, undefined, true, undefined, this);
67797
68208
  }
67798
- return /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Box_default, {
68209
+ return /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Box_default, {
67799
68210
  flexDirection: "column",
67800
68211
  children: [
67801
- /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
68212
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text, {
67802
68213
  bold: true,
67803
68214
  children: title
67804
68215
  }, undefined, false, undefined, this),
67805
- /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
68216
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text, {
67806
68217
  dimColor: true,
67807
68218
  children: allowEditing ? "Enter to edit; (a)dd, (d)elete, (m)ove; Escape to cancel" : "Enter to choose a line; Escape to cancel"
67808
68219
  }, undefined, false, undefined, this),
67809
- limitMessage && /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(Text, {
68220
+ limitMessage && /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text, {
67810
68221
  color: "yellow",
67811
68222
  children: limitMessage
67812
68223
  }, undefined, false, undefined, this),
67813
- /* @__PURE__ */ jsx_dev_runtime22.jsxDEV(List, {
68224
+ /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(List, {
67814
68225
  marginTop: 1,
67815
68226
  items: localLines.map((line3, index) => ({ label: `Line ${index + 1}`, sublabel: `(${lineSummary(line3)})`, value: index })),
67816
68227
  initialSelection: selectedIndex,
@@ -67823,7 +68234,7 @@ function LineSelector({
67823
68234
  }
67824
68235
 
67825
68236
  // src/tui/components/MainMenu.tsx
67826
- var jsx_dev_runtime23 = __toESM(require_jsx_dev_runtime(), 1);
68237
+ var jsx_dev_runtime24 = __toESM(require_jsx_dev_runtime(), 1);
67827
68238
  function buildMainMenuItems() {
67828
68239
  return [
67829
68240
  { label: "Lines", value: "lines", description: "Edit up to three status-line rows and their widgets." },
@@ -67839,17 +68250,17 @@ function buildMainMenuItems() {
67839
68250
  ];
67840
68251
  }
67841
68252
  function MainMenu({ onSelect, initialSelection = 0, hasChanges = false }) {
67842
- return /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Box_default, {
68253
+ return /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Box_default, {
67843
68254
  flexDirection: "column",
67844
68255
  children: [
67845
- /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(Text, {
68256
+ /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Text, {
67846
68257
  bold: true,
67847
68258
  children: [
67848
68259
  "Main Menu",
67849
68260
  hasChanges ? " (unsaved changes)" : ""
67850
68261
  ]
67851
68262
  }, undefined, true, undefined, this),
67852
- /* @__PURE__ */ jsx_dev_runtime23.jsxDEV(List, {
68263
+ /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(List, {
67853
68264
  items: buildMainMenuItems(),
67854
68265
  marginTop: 1,
67855
68266
  initialSelection,
@@ -67865,7 +68276,7 @@ function MainMenu({ onSelect, initialSelection = 0, hasChanges = false }) {
67865
68276
  // src/tui/components/PowerlineSetup.tsx
67866
68277
  import { existsSync as existsSync16, readdirSync as readdirSync5 } from "node:fs";
67867
68278
  import { homedir as homedir2, platform as platform2 } from "node:os";
67868
- import { join as join23 } from "node:path";
68279
+ import { join as join24 } from "node:path";
67869
68280
  var import_react51 = __toESM(require_react(), 1);
67870
68281
 
67871
68282
  // src/utils/powerline-settings.ts
@@ -67894,7 +68305,7 @@ function buildEnabledPowerlineSettings(settings, removeManualSeparators) {
67894
68305
 
67895
68306
  // src/tui/components/PowerlineSeparatorEditor.tsx
67896
68307
  var import_react49 = __toESM(require_react(), 1);
67897
- var jsx_dev_runtime24 = __toESM(require_jsx_dev_runtime(), 1);
68308
+ var jsx_dev_runtime25 = __toESM(require_jsx_dev_runtime(), 1);
67898
68309
  var PRESETS = {
67899
68310
  separator: [
67900
68311
  { char: "", name: "Triangle Right" },
@@ -67932,7 +68343,7 @@ function acceptsText4(input2, key) {
67932
68343
  function PowerlineSeparatorEditor({ settings, mode, onUpdate, onBack }) {
67933
68344
  const items = itemsFor(settings, mode);
67934
68345
  const presets = PRESETS[mode];
67935
- const inversions = mode === "separator" ? settings.powerline.separatorInvertBackground : [];
68346
+ const inversions = mode === "separator" ? items.map((_2, i) => settings.powerline.separatorInvertBackground[i] ?? false) : [];
67936
68347
  const [selectedIndex, setSelectedIndex] = import_react49.useState(0);
67937
68348
  const [hexInput, setHexInput] = import_react49.useState(null);
67938
68349
  const update2 = (nextItems, nextInversions = inversions) => {
@@ -67961,6 +68372,7 @@ function PowerlineSeparatorEditor({ settings, mode, onUpdate, onBack }) {
67961
68372
  setHexInput(hexInput + input2.toUpperCase());
67962
68373
  return;
67963
68374
  }
68375
+ const shortcut = getPlainInput(input2, key);
67964
68376
  if (key.escape)
67965
68377
  onBack();
67966
68378
  else if (key.upArrow && items.length)
@@ -67978,81 +68390,81 @@ function PowerlineSeparatorEditor({ settings, mode, onUpdate, onBack }) {
67978
68390
  if (mode === "separator")
67979
68391
  nextInversions[selected] = isLeftFacing(char);
67980
68392
  update2(next, nextInversions);
67981
- } else if (input2.toLowerCase() === "a" || input2.toLowerCase() === "i") {
68393
+ } else if (shortcut.toLowerCase() === "a" || shortcut.toLowerCase() === "i") {
67982
68394
  const next = [...items];
67983
68395
  const char = presets[0]?.char ?? "";
67984
- const index = input2.toLowerCase() === "a" ? selected + 1 : selected;
68396
+ const index = shortcut.toLowerCase() === "a" ? selected + 1 : selected;
67985
68397
  next.splice(items.length ? index : 0, 0, char);
67986
68398
  const nextInversions = [...inversions];
67987
68399
  if (mode === "separator")
67988
68400
  nextInversions.splice(items.length ? index : 0, 0, isLeftFacing(char));
67989
68401
  update2(next, nextInversions);
67990
68402
  setSelectedIndex(items.length ? index : 0);
67991
- } else if (input2.toLowerCase() === "d" && (mode !== "separator" || items.length > 1)) {
68403
+ } else if (shortcut.toLowerCase() === "d" && (mode !== "separator" || items.length > 1)) {
67992
68404
  const next = items.filter((_2, index) => index !== selected);
67993
68405
  update2(next, inversions.filter((_2, index) => index !== selected));
67994
68406
  setSelectedIndex(Math.min(selected, Math.max(0, next.length - 1)));
67995
- } else if (input2.toLowerCase() === "c") {
68407
+ } else if (shortcut.toLowerCase() === "c") {
67996
68408
  update2(mode === "separator" ? [""] : [], mode === "separator" ? [false] : []);
67997
68409
  setSelectedIndex(0);
67998
- } else if (input2.toLowerCase() === "h")
68410
+ } else if (shortcut.toLowerCase() === "h")
67999
68411
  setHexInput("");
68000
- else if (input2.toLowerCase() === "t" && mode === "separator" && items.length) {
68412
+ else if (shortcut.toLowerCase() === "t" && mode === "separator" && items.length) {
68001
68413
  const next = [...inversions];
68002
68414
  next[selected] = !next[selected];
68003
68415
  update2(items, next);
68004
68416
  }
68005
68417
  });
68006
68418
  if (hexInput !== null) {
68007
- return /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Box_default, {
68419
+ return /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Box_default, {
68008
68420
  flexDirection: "column",
68009
68421
  children: [
68010
- /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Text, {
68422
+ /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68011
68423
  bold: true,
68012
68424
  children: titleFor(mode)
68013
68425
  }, undefined, false, undefined, this),
68014
- /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Text, {
68426
+ /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68015
68427
  children: [
68016
68428
  `U+${hexInput}`,
68017
- /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Text, {
68429
+ /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68018
68430
  inverse: true,
68019
68431
  children: " "
68020
68432
  }, undefined, false, undefined, this)
68021
68433
  ]
68022
68434
  }, undefined, true, undefined, this),
68023
- /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Text, {
68435
+ /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68024
68436
  dimColor: true,
68025
68437
  children: "Enter 4–6 hexadecimal digits, Escape to cancel"
68026
68438
  }, undefined, false, undefined, this)
68027
68439
  ]
68028
68440
  }, undefined, true, undefined, this);
68029
68441
  }
68030
- return /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Box_default, {
68442
+ return /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Box_default, {
68031
68443
  flexDirection: "column",
68032
68444
  children: [
68033
- /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Text, {
68445
+ /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68034
68446
  bold: true,
68035
68447
  children: titleFor(mode)
68036
68448
  }, undefined, false, undefined, this),
68037
- /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Text, {
68449
+ /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68038
68450
  dimColor: true,
68039
68451
  children: `↑↓ select, ←→ cycle, (a)dd, (i)nsert${mode !== "separator" || items.length > 1 ? ", (d)elete" : ""}, (c)lear, (h)ex${mode === "separator" ? ", (t)oggle invert" : ""}, Escape back`
68040
68452
  }, undefined, false, undefined, this),
68041
- /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Box_default, {
68453
+ /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Box_default, {
68042
68454
  marginTop: 1,
68043
68455
  flexDirection: "column",
68044
68456
  children: items.length ? items.map((item, index) => {
68045
68457
  const preset = presets.find((entry) => entry.char === item);
68046
68458
  const code = item.codePointAt(0)?.toString(16).toUpperCase().padStart(4, "0");
68047
68459
  const label = preset ? `${item} - ${preset.name}` : `${item} - Custom (U+${code})`;
68048
- return /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Text, {
68460
+ return /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68049
68461
  ...index === selected && { color: "green" },
68050
68462
  children: [
68051
68463
  index === selected ? "▶ " : " ",
68052
68464
  `${index + 1}: ${label}${mode === "separator" && inversions[index] ? " [Inverted]" : ""}`
68053
68465
  ]
68054
68466
  }, `${item}-${index}`, true, undefined, this);
68055
- }) : /* @__PURE__ */ jsx_dev_runtime24.jsxDEV(Text, {
68467
+ }) : /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68056
68468
  dimColor: true,
68057
68469
  children: "(none configured — press a to add)"
68058
68470
  }, undefined, false, undefined, this)
@@ -68063,7 +68475,7 @@ function PowerlineSeparatorEditor({ settings, mode, onUpdate, onBack }) {
68063
68475
 
68064
68476
  // src/tui/components/PowerlineThemeSelector.tsx
68065
68477
  var import_react50 = __toESM(require_react(), 1);
68066
- var jsx_dev_runtime25 = __toESM(require_jsx_dev_runtime(), 1);
68478
+ var jsx_dev_runtime26 = __toESM(require_jsx_dev_runtime(), 1);
68067
68479
  function buildPowerlineThemeItems(themes, originalTheme) {
68068
68480
  return themes.map((themeName) => {
68069
68481
  const theme = getPowerlineTheme(themeName);
@@ -68085,19 +68497,27 @@ function applyCustomPowerlineTheme(settings, themeName) {
68085
68497
  const colors = theme[level === "ansi16" ? "1" : level === "ansi256" ? "2" : "3"];
68086
68498
  if (!colors)
68087
68499
  return null;
68500
+ let nextLineSlot = 0;
68501
+ const lines = settings.lines.map((line3) => {
68502
+ const { slots, nextSlot } = assignPowerlineThemeSlots(line3, settings.powerline.continueThemeAcrossLines ? nextLineSlot : 0);
68503
+ nextLineSlot = nextSlot;
68504
+ return line3.map((widget, index) => {
68505
+ const slot = slots[index];
68506
+ if (typeof slot !== "number") {
68507
+ return widget;
68508
+ }
68509
+ const color = colors.fg[slot % colors.fg.length];
68510
+ const backgroundColor = colors.bg[slot % colors.bg.length];
68511
+ return {
68512
+ ...widget,
68513
+ ...color && { color },
68514
+ ...backgroundColor && { backgroundColor }
68515
+ };
68516
+ });
68517
+ });
68088
68518
  return {
68089
68519
  ...settings,
68090
- lines: settings.lines.map((line3) => {
68091
- let index = 0;
68092
- return line3.map((widget) => {
68093
- if (widget.type === "separator" || widget.type === "flex-separator")
68094
- return widget;
68095
- const color = colors.fg[index % colors.fg.length];
68096
- const backgroundColor = colors.bg[index % colors.bg.length];
68097
- index += 1;
68098
- return { ...widget, ...color && { color }, ...backgroundColor && { backgroundColor } };
68099
- });
68100
- }),
68520
+ lines,
68101
68521
  powerline: { ...settings.powerline, theme: "custom" }
68102
68522
  };
68103
68523
  }
@@ -68123,10 +68543,11 @@ function PowerlineThemeSelector({ settings, onUpdate, onBack }) {
68123
68543
  use_input_default((input2, key) => {
68124
68544
  if (confirmCustom)
68125
68545
  return;
68546
+ const shortcut = getPlainInput(input2, key);
68126
68547
  if (key.escape) {
68127
68548
  onUpdate(originalSettings.current);
68128
68549
  onBack();
68129
- } else if (input2.toLowerCase() === "c") {
68550
+ } else if (shortcut.toLowerCase() === "c") {
68130
68551
  const theme = themes[selectedIndex];
68131
68552
  if (theme && theme !== "custom")
68132
68553
  setConfirmCustom(true);
@@ -68134,21 +68555,21 @@ function PowerlineThemeSelector({ settings, onUpdate, onBack }) {
68134
68555
  });
68135
68556
  const selectedTheme = themes[selectedIndex];
68136
68557
  if (confirmCustom) {
68137
- return /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Box_default, {
68558
+ return /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
68138
68559
  flexDirection: "column",
68139
68560
  children: [
68140
- /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68561
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68141
68562
  bold: true,
68142
68563
  color: "yellow",
68143
68564
  children: "Confirm Customization"
68144
68565
  }, undefined, false, undefined, this),
68145
- /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68566
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68146
68567
  children: "This copies the current theme colors to widgets and overwrites existing widget colors."
68147
68568
  }, undefined, false, undefined, this),
68148
- /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68569
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68149
68570
  children: "Continue?"
68150
68571
  }, undefined, false, undefined, this),
68151
- /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(ConfirmDialog, {
68572
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(ConfirmDialog, {
68152
68573
  inline: true,
68153
68574
  onConfirm: () => {
68154
68575
  if (selectedTheme) {
@@ -68164,24 +68585,24 @@ function PowerlineThemeSelector({ settings, onUpdate, onBack }) {
68164
68585
  ]
68165
68586
  }, undefined, true, undefined, this);
68166
68587
  }
68167
- return /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Box_default, {
68588
+ return /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
68168
68589
  flexDirection: "column",
68169
68590
  children: [
68170
- /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68591
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68171
68592
  bold: true,
68172
68593
  children: [
68173
68594
  "Powerline Theme Selection ",
68174
- /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68595
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68175
68596
  dimColor: true,
68176
68597
  children: `| Original: ${originalTheme.current}`
68177
68598
  }, undefined, false, undefined, this)
68178
68599
  ]
68179
68600
  }, undefined, true, undefined, this),
68180
- /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68601
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68181
68602
  dimColor: true,
68182
68603
  children: `↑↓ navigate, Enter apply${selectedTheme && selectedTheme !== "custom" ? ", (c)ustomize theme" : ""}, Escape cancel`
68183
68604
  }, undefined, false, undefined, this),
68184
- /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(List, {
68605
+ /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(List, {
68185
68606
  marginTop: 1,
68186
68607
  items: buildPowerlineThemeItems(themes, originalTheme.current),
68187
68608
  initialSelection: selectedIndex,
@@ -68191,7 +68612,7 @@ function PowerlineThemeSelector({ settings, onUpdate, onBack }) {
68191
68612
  },
68192
68613
  onSelect: () => onBack()
68193
68614
  }, undefined, false, undefined, this),
68194
- settings.colorLevel === 1 && /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
68615
+ settings.colorLevel === 1 && /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68195
68616
  color: "yellow",
68196
68617
  children: "16-color themes have a limited palette."
68197
68618
  }, undefined, false, undefined, this)
@@ -68200,7 +68621,7 @@ function PowerlineThemeSelector({ settings, onUpdate, onBack }) {
68200
68621
  }
68201
68622
 
68202
68623
  // src/tui/components/PowerlineSetup.tsx
68203
- var jsx_dev_runtime26 = __toESM(require_jsx_dev_runtime(), 1);
68624
+ var jsx_dev_runtime27 = __toESM(require_jsx_dev_runtime(), 1);
68204
68625
  var SEPARATORS = [
68205
68626
  { char: "", name: "Triangle Right" },
68206
68627
  { char: "", name: "Triangle Left" },
@@ -68250,7 +68671,7 @@ function buildPowerlineSetupMenuItems(powerline) {
68250
68671
  ];
68251
68672
  }
68252
68673
  function detectPowerlineFont() {
68253
- const dirs = platform2() === "darwin" ? [join23(homedir2(), "Library", "Fonts"), "/Library/Fonts"] : platform2() === "win32" ? [join23(homedir2(), "AppData", "Local", "Microsoft", "Windows", "Fonts"), "C:\\Windows\\Fonts"] : [join23(homedir2(), ".local", "share", "fonts"), join23(homedir2(), ".fonts"), "/usr/share/fonts"];
68674
+ const dirs = platform2() === "darwin" ? [join24(homedir2(), "Library", "Fonts"), "/Library/Fonts"] : platform2() === "win32" ? [join24(homedir2(), "AppData", "Local", "Microsoft", "Windows", "Fonts"), "C:\\Windows\\Fonts"] : [join24(homedir2(), ".local", "share", "fonts"), join24(homedir2(), ".fonts"), "/usr/share/fonts"];
68254
68675
  try {
68255
68676
  return dirs.some((dir) => existsSync16(dir) && readdirSync5(dir).some((file2) => /powerline|nerd font|meslo.*lg/i.test(file2)));
68256
68677
  } catch {
@@ -68268,23 +68689,24 @@ function PowerlineSetup({ settings, onUpdate, onBack }) {
68268
68689
  use_input_default((input2, key) => {
68269
68690
  if (confirmEnable || screen !== "menu")
68270
68691
  return;
68692
+ const shortcut = getPlainInput(input2, key);
68271
68693
  if (key.escape)
68272
68694
  onBack();
68273
- else if (input2.toLowerCase() === "t") {
68695
+ else if (shortcut.toLowerCase() === "t") {
68274
68696
  if (powerline.enabled)
68275
68697
  onUpdate({ ...settings, powerline: { ...powerline, enabled: false } });
68276
68698
  else if (manualSeparators)
68277
68699
  setConfirmEnable(true);
68278
68700
  else
68279
68701
  onUpdate(buildEnabledPowerlineSettings(settings, false));
68280
- } else if (input2.toLowerCase() === "a" && powerline.enabled) {
68702
+ } else if (shortcut.toLowerCase() === "a" && powerline.enabled) {
68281
68703
  onUpdate({ ...settings, powerline: { ...powerline, autoAlign: !powerline.autoAlign } });
68282
- } else if (input2.toLowerCase() === "c" && powerline.enabled) {
68704
+ } else if (shortcut.toLowerCase() === "c" && powerline.enabled) {
68283
68705
  onUpdate({ ...settings, powerline: { ...powerline, continueThemeAcrossLines: !powerline.continueThemeAcrossLines } });
68284
68706
  }
68285
68707
  });
68286
68708
  if (screen === "separator" || screen === "startCap" || screen === "endCap") {
68287
- return /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(PowerlineSeparatorEditor, {
68709
+ return /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(PowerlineSeparatorEditor, {
68288
68710
  settings,
68289
68711
  mode: screen,
68290
68712
  onUpdate,
@@ -68292,23 +68714,23 @@ function PowerlineSetup({ settings, onUpdate, onBack }) {
68292
68714
  }, undefined, false, undefined, this);
68293
68715
  }
68294
68716
  if (screen === "themes")
68295
- return /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(PowerlineThemeSelector, {
68717
+ return /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(PowerlineThemeSelector, {
68296
68718
  settings,
68297
68719
  onUpdate,
68298
68720
  onBack: () => setScreen("menu")
68299
68721
  }, undefined, false, undefined, this);
68300
68722
  if (confirmEnable) {
68301
- return /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
68723
+ return /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Box_default, {
68302
68724
  flexDirection: "column",
68303
68725
  children: [
68304
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68726
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68305
68727
  color: "yellow",
68306
68728
  children: "Enabling Powerline removes manual separators from the status lines."
68307
68729
  }, undefined, false, undefined, this),
68308
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68730
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68309
68731
  children: "Continue?"
68310
68732
  }, undefined, false, undefined, this),
68311
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(ConfirmDialog, {
68733
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(ConfirmDialog, {
68312
68734
  inline: true,
68313
68735
  onConfirm: () => {
68314
68736
  onUpdate(buildEnabledPowerlineSettings(settings, true));
@@ -68319,53 +68741,53 @@ function PowerlineSetup({ settings, onUpdate, onBack }) {
68319
68741
  ]
68320
68742
  }, undefined, true, undefined, this);
68321
68743
  }
68322
- return /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Box_default, {
68744
+ return /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Box_default, {
68323
68745
  flexDirection: "column",
68324
68746
  children: [
68325
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68747
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68326
68748
  bold: true,
68327
68749
  children: "Powerline Setup"
68328
68750
  }, undefined, false, undefined, this),
68329
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68751
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68330
68752
  dimColor: true,
68331
68753
  children: browserRuntime ? "Font detection: unavailable in browser (the browser terminal decides glyph rendering)" : `Font detection: ${fontFound ? "compatible font found" : "no compatible font found"} (informational; terminal configuration controls glyph rendering)`
68332
68754
  }, undefined, false, undefined, this),
68333
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68755
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68334
68756
  children: [
68335
68757
  "Powerline Mode: ",
68336
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68758
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68337
68759
  color: powerline.enabled ? "green" : "red",
68338
68760
  children: powerline.enabled ? "Enabled" : "Disabled"
68339
68761
  }, undefined, false, undefined, this),
68340
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68762
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68341
68763
  dimColor: true,
68342
68764
  children: " — press (t) to toggle"
68343
68765
  }, undefined, false, undefined, this)
68344
68766
  ]
68345
68767
  }, undefined, true, undefined, this),
68346
- powerline.enabled && /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(jsx_dev_runtime26.Fragment, {
68768
+ powerline.enabled && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(jsx_dev_runtime27.Fragment, {
68347
68769
  children: [
68348
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68770
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68349
68771
  children: [
68350
68772
  "Align Widgets: ",
68351
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68773
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68352
68774
  color: powerline.autoAlign ? "green" : "red",
68353
68775
  children: powerline.autoAlign ? "Enabled" : "Disabled"
68354
68776
  }, undefined, false, undefined, this),
68355
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68777
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68356
68778
  dimColor: true,
68357
68779
  children: " — press (a) to toggle"
68358
68780
  }, undefined, false, undefined, this)
68359
68781
  ]
68360
68782
  }, undefined, true, undefined, this),
68361
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68783
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68362
68784
  children: [
68363
68785
  "Continue Theme: ",
68364
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68786
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68365
68787
  color: powerline.continueThemeAcrossLines ? "green" : "red",
68366
68788
  children: powerline.continueThemeAcrossLines ? "Enabled" : "Disabled"
68367
68789
  }, undefined, false, undefined, this),
68368
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68790
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68369
68791
  dimColor: true,
68370
68792
  children: " — press (c) to toggle"
68371
68793
  }, undefined, false, undefined, this)
@@ -68373,11 +68795,11 @@ function PowerlineSetup({ settings, onUpdate, onBack }) {
68373
68795
  }, undefined, true, undefined, this)
68374
68796
  ]
68375
68797
  }, undefined, true, undefined, this),
68376
- !powerline.enabled && /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(Text, {
68798
+ !powerline.enabled && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
68377
68799
  dimColor: true,
68378
68800
  children: "Enable Powerline mode to configure separators, caps, and themes."
68379
68801
  }, undefined, false, undefined, this),
68380
- /* @__PURE__ */ jsx_dev_runtime26.jsxDEV(List, {
68802
+ /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(List, {
68381
68803
  marginTop: 1,
68382
68804
  items: buildPowerlineSetupMenuItems(powerline),
68383
68805
  initialSelection: selected,
@@ -68395,7 +68817,7 @@ function PowerlineSetup({ settings, onUpdate, onBack }) {
68395
68817
  }
68396
68818
 
68397
68819
  // src/tui/App.tsx
68398
- var jsx_dev_runtime27 = __toESM(require_jsx_dev_runtime(), 1);
68820
+ var jsx_dev_runtime28 = __toESM(require_jsx_dev_runtime(), 1);
68399
68821
  var readImportFileFromDisk = (file2) => readFile2(file2, "utf8");
68400
68822
  function cloneSettings(settings) {
68401
68823
  const clone3 = globalThis.structuredClone;
@@ -68599,45 +69021,45 @@ function App2({ initialSettings, settingsPath, readImportFile = readImportFileFr
68599
69021
  }
68600
69022
  };
68601
69023
  if (!settings) {
68602
- return /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Box_default, {
68603
- children: /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
69024
+ return /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(Box_default, {
69025
+ children: /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(Text, {
68604
69026
  children: "Loading configuration…"
68605
69027
  }, undefined, false, undefined, this)
68606
69028
  }, undefined, false, undefined, this);
68607
69029
  }
68608
- return /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Box_default, {
69030
+ return /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(Box_default, {
68609
69031
  flexDirection: "column",
68610
69032
  children: [
68611
- /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
69033
+ /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(Text, {
68612
69034
  bold: true,
68613
69035
  children: "cxstatusline Configuration"
68614
69036
  }, undefined, false, undefined, this),
68615
- flash && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
69037
+ flash && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(Text, {
68616
69038
  color: "yellow",
68617
69039
  children: flash
68618
69040
  }, undefined, false, undefined, this),
68619
- /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Box_default, {
69041
+ /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(Box_default, {
68620
69042
  marginTop: 1,
68621
69043
  flexDirection: "column",
68622
69044
  children: [
68623
- /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Text, {
69045
+ /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(Text, {
68624
69046
  dimColor: true,
68625
69047
  children: "> Preview"
68626
69048
  }, undefined, false, undefined, this),
68627
- /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(StatusLinePreview, {
69049
+ /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(StatusLinePreview, {
68628
69050
  settings,
68629
69051
  terminalWidth
68630
69052
  }, undefined, false, undefined, this)
68631
69053
  ]
68632
69054
  }, undefined, true, undefined, this),
68633
- /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(Box_default, {
69055
+ /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(Box_default, {
68634
69056
  marginTop: 1,
68635
69057
  children: [
68636
- screen === "main" && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(MainMenu, {
69058
+ screen === "main" && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(MainMenu, {
68637
69059
  hasChanges,
68638
69060
  onSelect: (value) => handleMainMenu(value)
68639
69061
  }, undefined, false, undefined, this),
68640
- screen === "lines" && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(LineSelector, {
69062
+ screen === "lines" && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(LineSelector, {
68641
69063
  lines: settings.lines,
68642
69064
  onSelect: (line3) => {
68643
69065
  setSelectedLine(line3);
@@ -68648,59 +69070,59 @@ function App2({ initialSettings, settingsPath, readImportFile = readImportFileFr
68648
69070
  title: "Edit Lines",
68649
69071
  allowEditing: true
68650
69072
  }, undefined, false, undefined, this),
68651
- screen === "items" && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(ItemsEditor, {
69073
+ screen === "items" && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(ItemsEditor, {
68652
69074
  widgets: settings.lines[selectedLine] ?? [],
68653
69075
  onUpdate: (widgets) => updateLine(selectedLine, widgets),
68654
69076
  onBack: () => setScreen("lines"),
68655
69077
  lineNumber: selectedLine + 1,
68656
69078
  settings
68657
69079
  }, undefined, false, undefined, this),
68658
- screen === "colors" && colorLine === null && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(LineSelector, {
69080
+ screen === "colors" && colorLine === null && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(LineSelector, {
68659
69081
  lines: settings.lines,
68660
69082
  onSelect: setColorLine,
68661
69083
  onBack: () => finishEdit(),
68662
69084
  title: "Edit Colors"
68663
69085
  }, undefined, false, undefined, this),
68664
- screen === "colors" && colorLine !== null && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(ColorMenu, {
69086
+ screen === "colors" && colorLine !== null && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(ColorMenu, {
68665
69087
  widgets: settings.lines[colorLine] ?? [],
68666
69088
  lineIndex: colorLine,
68667
69089
  settings,
68668
69090
  onUpdate: (widgets) => updateLine(colorLine, widgets),
68669
69091
  onBack: () => setColorLine(null)
68670
69092
  }, undefined, false, undefined, this),
68671
- screen === "powerline" && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(PowerlineSetup, {
69093
+ screen === "powerline" && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(PowerlineSetup, {
68672
69094
  settings,
68673
69095
  onUpdate: replaceSettings,
68674
69096
  onBack: () => finishEdit()
68675
69097
  }, undefined, false, undefined, this),
68676
- screen === "overrides" && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(GlobalOverridesMenu, {
69098
+ screen === "overrides" && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(GlobalOverridesMenu, {
68677
69099
  settings,
68678
69100
  onUpdate: replaceSettings,
68679
69101
  onBack: () => finishEdit()
68680
69102
  }, undefined, false, undefined, this),
68681
- screen === "export" && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(ExportConfigDialog, {
69103
+ screen === "export" && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(ExportConfigDialog, {
68682
69104
  initialPath: `${settingsPath}.export.json`,
68683
69105
  onExport: exportSettings,
68684
69106
  onCancel: () => finishEdit()
68685
69107
  }, undefined, false, undefined, this),
68686
- screen === "import" && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(ImportConfigDialog, {
69108
+ screen === "import" && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(ImportConfigDialog, {
68687
69109
  error: importError,
68688
69110
  onFileChosen: importSettings,
68689
69111
  onCancel: () => finishEdit()
68690
69112
  }, undefined, false, undefined, this),
68691
- screen === "import-preview" && importPreview && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(ImportPreviewDialog, {
69113
+ screen === "import-preview" && importPreview && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(ImportPreviewDialog, {
68692
69114
  preview: importPreview,
68693
69115
  terminalWidth,
68694
69116
  busy: importApplying,
68695
69117
  onConfirm: () => void applyImport(),
68696
69118
  onCancel: () => finishEdit()
68697
69119
  }, undefined, false, undefined, this),
68698
- screen === "confirm-save" && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(ConfirmDialog, {
69120
+ screen === "confirm-save" && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(ConfirmDialog, {
68699
69121
  message: "Save the current configuration and exit?",
68700
69122
  onConfirm: () => void saveAndExit(),
68701
69123
  onCancel: () => setScreen("main")
68702
69124
  }, undefined, false, undefined, this),
68703
- screen === "confirm-discard" && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(ConfirmDialog, {
69125
+ screen === "confirm-discard" && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(ConfirmDialog, {
68704
69126
  message: hasChanges ? "Discard unsaved changes and exit?" : "Exit without saving?",
68705
69127
  onConfirm: () => {
68706
69128
  if (originalSettings)
@@ -68709,7 +69131,7 @@ function App2({ initialSettings, settingsPath, readImportFile = readImportFileFr
68709
69131
  },
68710
69132
  onCancel: () => setScreen("main")
68711
69133
  }, undefined, false, undefined, this),
68712
- screen === "confirm-invalid-replace" && /* @__PURE__ */ jsx_dev_runtime27.jsxDEV(ConfirmDialog, {
69134
+ screen === "confirm-invalid-replace" && /* @__PURE__ */ jsx_dev_runtime28.jsxDEV(ConfirmDialog, {
68713
69135
  message: "Existing settings could not be parsed and have not been changed. Use default settings in memory? Saving later will replace the file.",
68714
69136
  onConfirm: () => {
68715
69137
  const defaults2 = clampSettings(DEFAULT_SETTINGS);
@@ -68726,7 +69148,7 @@ function App2({ initialSettings, settingsPath, readImportFile = readImportFileFr
68726
69148
  }
68727
69149
  async function runTUI(settingsPath) {
68728
69150
  process.stdout.write("\x1B[2J\x1B[H");
68729
- const instance = render_default(/* @__PURE__ */ jsx_dev_runtime27.jsxDEV(App2, {
69151
+ const instance = render_default(/* @__PURE__ */ jsx_dev_runtime28.jsxDEV(App2, {
68730
69152
  settingsPath
68731
69153
  }, undefined, false, undefined, this));
68732
69154
  await instance.waitUntilExit();
@@ -68770,8 +69192,8 @@ function readMemoryUsage(deps, nowMs) {
68770
69192
 
68771
69193
  // src/commands/update-tool.ts
68772
69194
  import { spawnSync as spawnSync5 } from "node:child_process";
68773
- import { existsSync as existsSync17, realpathSync as realpathSync4 } from "node:fs";
68774
- import { dirname as dirname13, join as join24 } from "node:path";
69195
+ import { existsSync as existsSync17, realpathSync as realpathSync5 } from "node:fs";
69196
+ import { dirname as dirname14, join as join25 } from "node:path";
68775
69197
  async function defaultFetchLatestVersion() {
68776
69198
  const controller = new AbortController;
68777
69199
  const timer = setTimeout(() => controller.abort(), 5000);
@@ -68796,14 +69218,14 @@ function detectInstallType(binaryPath = process.argv[1]) {
68796
69218
  try {
68797
69219
  let resolved = binaryPath;
68798
69220
  try {
68799
- resolved = realpathSync4(binaryPath);
69221
+ resolved = realpathSync5(binaryPath);
68800
69222
  } catch {}
68801
- let dir = dirname13(resolved);
69223
+ let dir = dirname14(resolved);
68802
69224
  for (let i = 0;i < 5; i++) {
68803
- if (existsSync17(join24(dir, ".git")) && existsSync17(join24(dir, "package.json"))) {
69225
+ if (existsSync17(join25(dir, ".git")) && existsSync17(join25(dir, "package.json"))) {
68804
69226
  return { type: "git", repoDir: dir };
68805
69227
  }
68806
- const parent = dirname13(dir);
69228
+ const parent = dirname14(dir);
68807
69229
  if (parent === dir)
68808
69230
  break;
68809
69231
  dir = parent;