fix(tui): follow symlinks in fuzzy autocomplete closes #3507
This commit is contained in:
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed `@` autocomplete fuzzy search to follow symlinked directories and include symlinked paths in results ([#3507](https://github.com/badlogic/pi-mono/issues/3507))
|
||||||
|
|
||||||
## [0.68.0] - 2026-04-20
|
## [0.68.0] - 2026-04-20
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ async function walkDirectoryWithFd(
|
|||||||
"f",
|
"f",
|
||||||
"--type",
|
"--type",
|
||||||
"d",
|
"d",
|
||||||
|
"--follow",
|
||||||
"--hidden",
|
"--hidden",
|
||||||
"--exclude",
|
"--exclude",
|
||||||
".git",
|
".git",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import assert from "node:assert";
|
import assert from "node:assert";
|
||||||
import { spawnSync } from "node:child_process";
|
import { spawnSync } from "node:child_process";
|
||||||
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
import { mkdirSync, mkdtempSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
||||||
import { tmpdir } from "node:os";
|
import { tmpdir } from "node:os";
|
||||||
import { dirname, join } from "node:path";
|
import { dirname, join } from "node:path";
|
||||||
import { afterEach, beforeEach, describe, it, test } from "node:test";
|
import { afterEach, beforeEach, describe, it, test } from "node:test";
|
||||||
@@ -300,6 +300,61 @@ describe("CombinedAutocompleteProvider", () => {
|
|||||||
assert.ok(!values.some((value) => value === "@.git" || value.startsWith("@.git/")));
|
assert.ok(!values.some((value) => value === "@.git" || value.startsWith("@.git/")));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("follows symlinked directories for fuzzy @ search", async () => {
|
||||||
|
setupFolder(baseDir, {
|
||||||
|
files: {
|
||||||
|
"dir/some_file.txt": "real",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
setupFolder(outsideDir, {
|
||||||
|
files: {
|
||||||
|
"some_file.txt": "symlinked",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
symlinkSync("../outside", join(baseDir, "symlinked_dir"));
|
||||||
|
|
||||||
|
const provider = new CombinedAutocompleteProvider([], baseDir, requireFdPath());
|
||||||
|
const line = "@some";
|
||||||
|
const result = await getSuggestions(provider, [line], 0, line.length);
|
||||||
|
|
||||||
|
const values = result?.items.map((item) => item.value) ?? [];
|
||||||
|
assert.ok(values.includes("@dir/some_file.txt"));
|
||||||
|
assert.ok(values.includes("@symlinked_dir/some_file.txt"));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("returns symlinked directories when matching their name", async () => {
|
||||||
|
setupFolder(outsideDir, {
|
||||||
|
files: {
|
||||||
|
"nested/file.txt": "symlinked",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
symlinkSync("../outside", join(baseDir, "symlinked_dir"));
|
||||||
|
|
||||||
|
const provider = new CombinedAutocompleteProvider([], baseDir, requireFdPath());
|
||||||
|
const line = "@symlinked";
|
||||||
|
const result = await getSuggestions(provider, [line], 0, line.length);
|
||||||
|
|
||||||
|
const values = result?.items.map((item) => item.value) ?? [];
|
||||||
|
assert.ok(values.includes("@symlinked_dir/"));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("returns symlinked files without requiring type l", async () => {
|
||||||
|
setupFolder(baseDir, {
|
||||||
|
files: {
|
||||||
|
"original.txt": "content",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const linkPath = join(baseDir, "link.txt");
|
||||||
|
symlinkSync("original.txt", linkPath);
|
||||||
|
|
||||||
|
const provider = new CombinedAutocompleteProvider([], baseDir, requireFdPath());
|
||||||
|
const line = "@link";
|
||||||
|
const result = await getSuggestions(provider, [line], 0, line.length);
|
||||||
|
|
||||||
|
const values = result?.items.map((item) => item.value) ?? [];
|
||||||
|
assert.ok(values.includes("@link.txt"));
|
||||||
|
});
|
||||||
|
|
||||||
test("returns the same @ suggestions when the cwd path contains the query", async () => {
|
test("returns the same @ suggestions when the cwd path contains the query", async () => {
|
||||||
const normalBaseDir = join(rootDir, "cwd-normal");
|
const normalBaseDir = join(rootDir, "cwd-normal");
|
||||||
const queryInPathBaseDir = join(rootDir, "cwd-plan-repro");
|
const queryInPathBaseDir = join(rootDir, "cwd-plan-repro");
|
||||||
|
|||||||
Reference in New Issue
Block a user