tmux-fuzzy-motion 0.0.8 → 0.0.9
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.
- package/dist/cli.js +76 -17
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -4727,7 +4727,7 @@ const capturePane = async (tmux, paneId) => {
|
|
|
4727
4727
|
};
|
|
4728
4728
|
//#endregion
|
|
4729
4729
|
//#region src/core/width.ts
|
|
4730
|
-
const ANSI_PATTERN = /\u001B\[[0-9;]*m/gu;
|
|
4730
|
+
const ANSI_PATTERN$1 = /\u001B\[[0-9;]*m/gu;
|
|
4731
4731
|
const RESET$2 = "\x1B[0m";
|
|
4732
4732
|
const displayWidth = (value) => stringWidth(value);
|
|
4733
4733
|
const codeUnitIndexToColumn = (value, index) => stringWidth(value.slice(0, index));
|
|
@@ -4765,11 +4765,52 @@ const codeUnitRangeToColumns = (value, start, end) => {
|
|
|
4765
4765
|
}
|
|
4766
4766
|
return columns;
|
|
4767
4767
|
};
|
|
4768
|
+
const createCompactStyledDisplayCells = (value) => {
|
|
4769
|
+
const cells = [];
|
|
4770
|
+
let activeStyle = "";
|
|
4771
|
+
let pendingStyle = "";
|
|
4772
|
+
let styleOpen = false;
|
|
4773
|
+
let lastVisibleCellIndex = -1;
|
|
4774
|
+
let lastIndex = 0;
|
|
4775
|
+
const appendChunk = (chunk) => {
|
|
4776
|
+
for (const char of chunk) {
|
|
4777
|
+
const width = Math.max(1, stringWidth(char));
|
|
4778
|
+
const prefix = pendingStyle.length > 0 ? pendingStyle : !styleOpen && activeStyle.length > 0 ? activeStyle : "";
|
|
4779
|
+
cells.push(`${prefix}${char}`);
|
|
4780
|
+
if (prefix.length > 0) {
|
|
4781
|
+
pendingStyle = "";
|
|
4782
|
+
styleOpen = true;
|
|
4783
|
+
}
|
|
4784
|
+
lastVisibleCellIndex = cells.length - 1;
|
|
4785
|
+
for (let offset = 1; offset < width; offset += 1) cells.push("");
|
|
4786
|
+
}
|
|
4787
|
+
};
|
|
4788
|
+
const closeStyle = () => {
|
|
4789
|
+
if (styleOpen && lastVisibleCellIndex >= 0) cells[lastVisibleCellIndex] = `${cells[lastVisibleCellIndex]}${RESET$2}`;
|
|
4790
|
+
activeStyle = "";
|
|
4791
|
+
pendingStyle = "";
|
|
4792
|
+
styleOpen = false;
|
|
4793
|
+
};
|
|
4794
|
+
for (const match of value.matchAll(ANSI_PATTERN$1)) {
|
|
4795
|
+
const start = match.index ?? 0;
|
|
4796
|
+
appendChunk(value.slice(lastIndex, start));
|
|
4797
|
+
const sequence = match[0];
|
|
4798
|
+
if (sequence === RESET$2) closeStyle();
|
|
4799
|
+
else {
|
|
4800
|
+
activeStyle = `${activeStyle}${sequence}`;
|
|
4801
|
+
pendingStyle = `${pendingStyle}${sequence}`;
|
|
4802
|
+
}
|
|
4803
|
+
lastIndex = start + sequence.length;
|
|
4804
|
+
}
|
|
4805
|
+
appendChunk(value.slice(lastIndex));
|
|
4806
|
+
if (styleOpen) closeStyle();
|
|
4807
|
+
return cells;
|
|
4808
|
+
};
|
|
4768
4809
|
const createStyledDisplayCells = (value) => {
|
|
4769
4810
|
const cells = [];
|
|
4770
4811
|
let activeStyle = "";
|
|
4771
4812
|
let lastIndex = 0;
|
|
4772
|
-
for (const match of value.matchAll(ANSI_PATTERN)) {
|
|
4813
|
+
for (const match of value.matchAll(ANSI_PATTERN$1)) {
|
|
4773
4814
|
const start = match.index ?? 0;
|
|
4774
4815
|
const chunk = value.slice(lastIndex, start);
|
|
4775
4816
|
for (const char of chunk) {
|
|
@@ -4816,9 +4857,19 @@ const PATTERNS = [
|
|
|
4816
4857
|
}
|
|
4817
4858
|
];
|
|
4818
4859
|
const isContainedByHigherPriority = (current, others) => others.some((candidate) => candidate.line === current.line && candidate.priority < current.priority && candidate.startIndex <= current.startIndex && candidate.endIndex >= current.endIndex);
|
|
4860
|
+
const dedupeLineCandidates = (candidates) => {
|
|
4861
|
+
const byStartIndex = /* @__PURE__ */ new Map();
|
|
4862
|
+
for (const candidate of candidates) {
|
|
4863
|
+
const current = byStartIndex.get(candidate.startIndex);
|
|
4864
|
+
if (!current || candidate.priority < current.priority) byStartIndex.set(candidate.startIndex, candidate);
|
|
4865
|
+
}
|
|
4866
|
+
const deduped = [...byStartIndex.values()];
|
|
4867
|
+
return deduped.filter((candidate) => !isContainedByHigherPriority(candidate, deduped));
|
|
4868
|
+
};
|
|
4819
4869
|
const extractCandidates = (lines) => {
|
|
4820
4870
|
const collected = [];
|
|
4821
4871
|
lines.forEach((lineText, lineIndex) => {
|
|
4872
|
+
const lineCandidates = [];
|
|
4822
4873
|
PATTERNS.forEach(({ kind, pattern }, priority) => {
|
|
4823
4874
|
const regex = new RegExp(pattern.source, pattern.flags);
|
|
4824
4875
|
for (const match of lineText.matchAll(regex)) {
|
|
@@ -4829,7 +4880,7 @@ const extractCandidates = (lines) => {
|
|
|
4829
4880
|
if (width === 1 && kind !== "word") continue;
|
|
4830
4881
|
const col = codeUnitIndexToColumn(lineText, startIndex);
|
|
4831
4882
|
const charCol = codeUnitIndexToCharacterIndex(lineText, startIndex);
|
|
4832
|
-
|
|
4883
|
+
lineCandidates.push({
|
|
4833
4884
|
kind,
|
|
4834
4885
|
text,
|
|
4835
4886
|
line: lineIndex + 1,
|
|
@@ -4842,10 +4893,9 @@ const extractCandidates = (lines) => {
|
|
|
4842
4893
|
});
|
|
4843
4894
|
}
|
|
4844
4895
|
});
|
|
4896
|
+
collected.push(...dedupeLineCandidates(lineCandidates));
|
|
4845
4897
|
});
|
|
4846
|
-
return collected.
|
|
4847
|
-
return source.find((other) => other.line === candidate.line && other.startIndex === candidate.startIndex && other.priority <= candidate.priority) === candidate;
|
|
4848
|
-
}).filter((candidate, _, source) => !isContainedByHigherPriority(candidate, source)).sort((left, right) => left.line - right.line || left.col - right.col || left.priority - right.priority).map((candidate) => ({
|
|
4898
|
+
return collected.sort((left, right) => left.line - right.line || left.col - right.col || left.priority - right.priority).map((candidate) => ({
|
|
4849
4899
|
kind: candidate.kind,
|
|
4850
4900
|
text: candidate.text,
|
|
4851
4901
|
line: candidate.line,
|
|
@@ -5961,6 +6011,7 @@ const withRawMode = async (input, output, callback) => {
|
|
|
5961
6011
|
//#region src/commands/input.ts
|
|
5962
6012
|
const QUERY_STYLE = "\x1B[48;5;236;38;5;252m";
|
|
5963
6013
|
const RESET = "\x1B[0m";
|
|
6014
|
+
const ANSI_PATTERN = /\u001B\[[0-9;]*m/u;
|
|
5964
6015
|
const HINT_CHARS = /* @__PURE__ */ new Set("ASDFGHJKLQWERTYUIOPZXCVBNM");
|
|
5965
6016
|
const WORD_CHAR_PATTERN = /[a-z0-9_-]/u;
|
|
5966
6017
|
const parsePopupArgs = (args) => {
|
|
@@ -6036,9 +6087,14 @@ const fitBodyToHeight = (lines, height) => {
|
|
|
6036
6087
|
return next;
|
|
6037
6088
|
};
|
|
6038
6089
|
const renderQueryOnBottomLine = (line, width, query) => {
|
|
6090
|
+
if (query.length === 0) {
|
|
6091
|
+
const cells = createCompactStyledDisplayCells(line);
|
|
6092
|
+
while (cells.length < width) cells.push(" ");
|
|
6093
|
+
const rendered = cells.slice(0, width).join("");
|
|
6094
|
+
return ANSI_PATTERN.test(rendered) && !rendered.endsWith(RESET) ? `${rendered}${RESET}` : rendered;
|
|
6095
|
+
}
|
|
6039
6096
|
const cells = createStyledDisplayCells(line);
|
|
6040
6097
|
while (cells.length < width) cells.push(" ");
|
|
6041
|
-
if (query.length === 0) return cells.slice(0, width).join("");
|
|
6042
6098
|
const queryWidth = Math.min(width, stringWidth(query));
|
|
6043
6099
|
const start = Math.max(0, width - queryWidth);
|
|
6044
6100
|
const content = Array.from(query);
|
|
@@ -6055,7 +6111,7 @@ const renderQueryOnBottomLine = (line, width, query) => {
|
|
|
6055
6111
|
return cells.slice(0, width).join("");
|
|
6056
6112
|
};
|
|
6057
6113
|
const createFrame = (state, query, matches, renderOverlay) => {
|
|
6058
|
-
const body = fitBodyToHeight(query.length > 0 && matches.length > 0 ? renderOverlay(matches) : state.displayLines, state.height);
|
|
6114
|
+
const body = fitBodyToHeight(query.length > 0 && matches.length > 0 && renderOverlay ? renderOverlay(matches) : state.displayLines, state.height);
|
|
6059
6115
|
const lastLineIndex = Math.max(0, body.length - 1);
|
|
6060
6116
|
body[lastLineIndex] = renderQueryOnBottomLine(body[lastLineIndex] ?? "", state.width, query);
|
|
6061
6117
|
return { body };
|
|
@@ -6173,7 +6229,11 @@ const expectResponse = (response, type) => {
|
|
|
6173
6229
|
return response;
|
|
6174
6230
|
};
|
|
6175
6231
|
const runPopupJob = async (state, options) => {
|
|
6176
|
-
|
|
6232
|
+
let overlayRenderer = null;
|
|
6233
|
+
const getOverlayRenderer = () => {
|
|
6234
|
+
overlayRenderer ??= createOverlayRenderer(state.displayLines);
|
|
6235
|
+
return overlayRenderer;
|
|
6236
|
+
};
|
|
6177
6237
|
let query = "";
|
|
6178
6238
|
let previousHints = /* @__PURE__ */ new Map();
|
|
6179
6239
|
let matches = [];
|
|
@@ -6181,7 +6241,7 @@ const runPopupJob = async (state, options) => {
|
|
|
6181
6241
|
const output = process.stdout;
|
|
6182
6242
|
await withRawMode(input, output, async () => {
|
|
6183
6243
|
const reader = createByteReader(input);
|
|
6184
|
-
let previousFrame = renderFrame(output, createFrame(state, query, matches
|
|
6244
|
+
let previousFrame = renderFrame(output, createFrame(state, query, matches));
|
|
6185
6245
|
try {
|
|
6186
6246
|
while (true) {
|
|
6187
6247
|
const value = await reader.nextByte();
|
|
@@ -6224,7 +6284,7 @@ const runPopupJob = async (state, options) => {
|
|
|
6224
6284
|
}
|
|
6225
6285
|
matches = query.length === 0 ? [] : await options.onMatch(query, previousHints);
|
|
6226
6286
|
previousHints = new Map(matches.map((target) => [createTargetKey(target), target.hint]));
|
|
6227
|
-
previousFrame = renderFrame(output, createFrame(state, query, matches,
|
|
6287
|
+
previousFrame = renderFrame(output, createFrame(state, query, matches, matches.length > 0 ? getOverlayRenderer() : void 0), previousFrame);
|
|
6228
6288
|
}
|
|
6229
6289
|
} finally {
|
|
6230
6290
|
reader.close();
|
|
@@ -6542,7 +6602,7 @@ const composeDisplayLines = (panes, width, height, borderLines) => {
|
|
|
6542
6602
|
for (const pane of panes) pane.displayLines.forEach((line, lineIndex) => {
|
|
6543
6603
|
const row = rows[pane.top + lineIndex];
|
|
6544
6604
|
if (!row) return;
|
|
6545
|
-
|
|
6605
|
+
createCompactStyledDisplayCells(line).forEach((cell, cellIndex) => {
|
|
6546
6606
|
const column = pane.left + cellIndex;
|
|
6547
6607
|
if (column < 0 || column >= row.length) return;
|
|
6548
6608
|
row[column] = cell;
|
|
@@ -6581,10 +6641,9 @@ const buildAllPaneState = async (tmux, pane, paneId, clientTty) => {
|
|
|
6581
6641
|
right: Number.NEGATIVE_INFINITY,
|
|
6582
6642
|
bottom: Number.NEGATIVE_INFINITY
|
|
6583
6643
|
});
|
|
6584
|
-
const snapshots =
|
|
6585
|
-
for (const item of panes) {
|
|
6644
|
+
const snapshots = await Promise.all(panes.map(async (item) => {
|
|
6586
6645
|
const capture = fitCaptureToHeight(await capturePane(tmux, item.paneId), item.height);
|
|
6587
|
-
|
|
6646
|
+
return {
|
|
6588
6647
|
paneId: item.paneId,
|
|
6589
6648
|
inCopyMode: item.inCopyMode,
|
|
6590
6649
|
width: item.width,
|
|
@@ -6593,8 +6652,8 @@ const buildAllPaneState = async (tmux, pane, paneId, clientTty) => {
|
|
|
6593
6652
|
top: item.top - bounds.top,
|
|
6594
6653
|
plainLines: capture.lines,
|
|
6595
6654
|
displayLines: capture.displayLines
|
|
6596
|
-
}
|
|
6597
|
-
}
|
|
6655
|
+
};
|
|
6656
|
+
}));
|
|
6598
6657
|
const width = Math.max(0, bounds.right - bounds.left);
|
|
6599
6658
|
const height = Math.max(0, bounds.bottom - bounds.top);
|
|
6600
6659
|
const x = buildPopupRelativePosition("x", bounds.left);
|