tmux-fuzzy-motion 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +40 -49
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -40,19 +40,6 @@ const createTmuxClient = () => ({
40
40
  return (await runProcess("tmux", args)).stdout;
41
41
  }
42
42
  });
43
- const focusClientPane = async (tmux, paneId, clientTty) => {
44
- try {
45
- await tmux.run([
46
- "switch-client",
47
- "-c",
48
- clientTty,
49
- "-t",
50
- paneId
51
- ]);
52
- } catch (error) {
53
- throw new Error("tmux-fuzzy-motion: client not found", { cause: error });
54
- }
55
- };
56
43
  const enterCopyMode = async (tmux, paneId) => {
57
44
  try {
58
45
  await tmux.run([
@@ -117,20 +104,26 @@ const listWindowPanes = async (tmux, paneId) => {
117
104
  "-t",
118
105
  paneId,
119
106
  "-F",
120
- "#{pane_id} #{pane_in_mode} #{pane_width} #{pane_height} #{pane_current_path} #{pane_left} #{pane_top} #{?pane_active,1,0} #{window_zoomed_flag}"
107
+ "#{pane_id} #{pane_in_mode} #{pane_width} #{pane_height} #{pane_current_path} #{pane_left} #{pane_top} #{?pane_active,1,0} #{window_zoomed_flag} #{pane-border-lines}"
121
108
  ])).trim();
122
109
  } catch (error) {
123
110
  throw new Error("tmux-fuzzy-motion: pane not found", { cause: error });
124
111
  }
125
112
  const panes = output.split("\n").filter((line) => line.length > 0).map((line) => {
126
- const [resolvedPaneId, paneInMode, width, height, currentPath, left, top, active, zoomed] = line.split(" ");
113
+ const [resolvedPaneId, paneInMode, width, height, currentPath, left, top, active, zoomed, borderLines] = line.split(" ");
127
114
  const numeric = [
128
115
  width,
129
116
  height,
130
117
  left,
131
118
  top
132
119
  ].map((value) => Number(value));
133
- if (!resolvedPaneId || !paneInMode || !currentPath || [active, zoomed].some((value) => value === void 0) || numeric.some((value) => !Number.isFinite(value))) throw new Error("tmux-fuzzy-motion: failed to resolve window panes");
120
+ if (!resolvedPaneId || !paneInMode || !currentPath || [
121
+ active,
122
+ zoomed,
123
+ borderLines
124
+ ].some((value) => value === void 0) || numeric.some((value) => !Number.isFinite(value))) throw new Error("tmux-fuzzy-motion: failed to resolve window panes");
125
+ if (borderLines !== "single" && borderLines !== "double" && borderLines !== "heavy" && borderLines !== "simple" && borderLines !== "number" && borderLines !== "spaces") throw new Error("tmux-fuzzy-motion: failed to resolve window panes");
126
+ const resolvedBorderLines = borderLines;
134
127
  return {
135
128
  paneId: resolvedPaneId,
136
129
  inCopyMode: paneInMode === "1",
@@ -140,6 +133,7 @@ const listWindowPanes = async (tmux, paneId) => {
140
133
  left: Number(left),
141
134
  top: Number(top),
142
135
  active: active === "1",
136
+ borderLines: resolvedBorderLines,
143
137
  zoomed: zoomed === "1"
144
138
  };
145
139
  });
@@ -150,23 +144,6 @@ const listWindowPanes = async (tmux, paneId) => {
150
144
  return rest;
151
145
  });
152
146
  };
153
- const getPaneBorderLines = async (tmux, paneId) => {
154
- let output = "";
155
- try {
156
- output = (await tmux.capture([
157
- "show-options",
158
- "-A",
159
- "-wv",
160
- "-t",
161
- paneId,
162
- "pane-border-lines"
163
- ])).trim();
164
- } catch (error) {
165
- throw new Error("tmux-fuzzy-motion: failed to resolve pane border lines", { cause: error });
166
- }
167
- if (output === "single" || output === "double" || output === "heavy" || output === "simple" || output === "number" || output === "spaces") return output;
168
- throw new Error("tmux-fuzzy-motion: failed to resolve pane border lines");
169
- };
170
147
  const getTmuxVersion = async () => {
171
148
  return (await runProcess("tmux", ["-V"])).stdout.trim();
172
149
  };
@@ -5901,10 +5878,19 @@ const measureCellWidth = (cells, start) => {
5901
5878
  return width;
5902
5879
  };
5903
5880
  const createOverlayRenderer = (lines) => {
5904
- const baseCellsByLine = lines.map((line) => createStyledDisplayCells(line));
5905
- const baseLines = baseCellsByLine.map((cells) => cells.join(""));
5881
+ const baseLines = [...lines];
5882
+ const baseCellsByLine = /* @__PURE__ */ new Map();
5906
5883
  const targetLine = (target) => (target.screenLine ?? target.line) - 1;
5907
5884
  const targetCol = (target) => target.screenCol ?? target.col;
5885
+ const baseCellsForLine = (lineIndex) => {
5886
+ const line = lines[lineIndex];
5887
+ if (line === void 0) return;
5888
+ const existing = baseCellsByLine.get(lineIndex);
5889
+ if (existing) return existing;
5890
+ const cells = createStyledDisplayCells(line);
5891
+ baseCellsByLine.set(lineIndex, cells);
5892
+ return cells;
5893
+ };
5908
5894
  return (targets) => {
5909
5895
  const rendered = [...baseLines];
5910
5896
  const mutableCells = /* @__PURE__ */ new Map();
@@ -5913,7 +5899,7 @@ const createOverlayRenderer = (lines) => {
5913
5899
  const sorted = [...targets].sort((left, right) => targetLine(left) - targetLine(right) || targetCol(left) + left.primary - (targetCol(right) + right.primary));
5914
5900
  for (const target of sorted) {
5915
5901
  const lineIndex = targetLine(target);
5916
- const baseCells = baseCellsByLine[lineIndex];
5902
+ const baseCells = baseCellsForLine(lineIndex);
5917
5903
  if (!baseCells) continue;
5918
5904
  let cells = mutableCells.get(lineIndex);
5919
5905
  if (!cells) {
@@ -6116,10 +6102,15 @@ const createFrame = (state, query, matches, renderOverlay) => {
6116
6102
  body[lastLineIndex] = renderQueryOnBottomLine(body[lastLineIndex] ?? "", state.width, query);
6117
6103
  return { body };
6118
6104
  };
6105
+ const createInitialFrameOutput = (frame) => {
6106
+ const full = frame.body.map((line) => line.trimEnd()).join("\n");
6107
+ const sparse = frame.body.map((line, index) => [index, line.trimEnd()]).filter(([, line]) => line.length > 0).map(([index, line]) => `\u001B[${index + 1};1H${line}`).join("");
6108
+ return sparse.length < full.length ? sparse : full;
6109
+ };
6119
6110
  const writeFullFrame = (output, frame) => {
6120
6111
  output.write("\x1B[?7l");
6121
6112
  clearScreen(output);
6122
- output.write(frame.body.join("\n"));
6113
+ output.write(createInitialFrameOutput(frame));
6123
6114
  output.write("\x1B[H\x1B[?7h");
6124
6115
  };
6125
6116
  const renderFrame = (output, frame, previousFrame) => {
@@ -6609,7 +6600,7 @@ const composeDisplayLines = (panes, width, height, borderLines) => {
6609
6600
  });
6610
6601
  });
6611
6602
  drawPaneBorders(rows, occupied, borderLines);
6612
- return rows.map((row) => row.join(""));
6603
+ return rows.map((row) => row.join("").trimEnd());
6613
6604
  };
6614
6605
  const buildCurrentState = async (tmux, pane, paneId, clientTty) => {
6615
6606
  if (!pane.inCopyMode) await enterCopyMode(tmux, paneId);
@@ -6627,9 +6618,11 @@ const buildCurrentState = async (tmux, pane, paneId, clientTty) => {
6627
6618
  }
6628
6619
  };
6629
6620
  };
6630
- const buildAllPaneState = async (tmux, pane, paneId, clientTty) => {
6621
+ const buildAllPaneState = async (tmux, paneId, clientTty) => {
6631
6622
  const panes = await listWindowPanes(tmux, paneId);
6632
- const borderLines = await getPaneBorderLines(tmux, paneId);
6623
+ const targetPane = panes.find((item) => item.paneId === paneId) ?? panes.find((item) => item.active) ?? panes[0];
6624
+ if (!targetPane) throw new Error("tmux-fuzzy-motion: pane not found");
6625
+ const borderLines = targetPane.borderLines;
6633
6626
  const bounds = panes.reduce((accumulator, item) => ({
6634
6627
  left: Math.min(accumulator.left, item.left),
6635
6628
  top: Math.min(accumulator.top, item.top),
@@ -6663,11 +6656,11 @@ const buildAllPaneState = async (tmux, pane, paneId, clientTty) => {
6663
6656
  paneId,
6664
6657
  clientTty,
6665
6658
  targetPane: {
6666
- paneId: pane.paneId,
6667
- width: pane.width,
6668
- height: pane.height,
6669
- inCopyMode: pane.inCopyMode,
6670
- currentPath: pane.currentPath
6659
+ paneId: targetPane.paneId,
6660
+ width: targetPane.width,
6661
+ height: targetPane.height,
6662
+ inCopyMode: targetPane.inCopyMode,
6663
+ currentPath: targetPane.currentPath
6671
6664
  },
6672
6665
  bounds,
6673
6666
  size: {
@@ -6690,7 +6683,7 @@ const buildAllPaneState = async (tmux, pane, paneId, clientTty) => {
6690
6683
  }))
6691
6684
  });
6692
6685
  return {
6693
- currentPath: pane.currentPath,
6686
+ currentPath: targetPane.currentPath,
6694
6687
  x,
6695
6688
  y,
6696
6689
  state: {
@@ -6724,9 +6717,7 @@ const runStart = async (args) => {
6724
6717
  const resultFile = join(tempDir, "result.json");
6725
6718
  const socketPath = createDaemonSocketPath();
6726
6719
  try {
6727
- const pane = await getPaneStartContext(tmux, paneId);
6728
- await focusClientPane(tmux, paneId, clientTty);
6729
- const popupState = scope === "all" ? await buildAllPaneState(tmux, pane, paneId, clientTty) : await buildCurrentState(tmux, pane, paneId, clientTty);
6720
+ const popupState = scope === "all" ? await buildAllPaneState(tmux, paneId, clientTty) : await buildCurrentState(tmux, await getPaneStartContext(tmux, paneId), paneId, clientTty);
6730
6721
  const state = popupState.state;
6731
6722
  await writeFile(stateFile, JSON.stringify(state), "utf8");
6732
6723
  await ensureDaemon(socketPath);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmux-fuzzy-motion",
3
- "version": "0.0.9",
3
+ "version": "0.0.10",
4
4
  "description": "Fuzzy hint motion for tmux copy-mode",
5
5
  "type": "module",
6
6
  "files": [