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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/src/content/docs/docs/Choices/CaptureChoice.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ an existing note in scope, so typing an existing name selects it instead of
offering a duplicate. The picker still opens for an empty folder, tag,
property, or filtered scope so you can create the first note there.

:::note[Available in the next release]
The create row is selected first, so press Enter to create the exact name you
typed even when existing notes are fuzzy matches.
:::

### Capture to a folder {#capturing-to-folders}

Type a folder name (like `CRM/people`) and QuickAdd asks which note in that
Expand Down
21 changes: 21 additions & 0 deletions src/gui/InputSuggester/inputSuggester.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,27 @@ describe("InputSuggester", () => {
expect(suggestions[suggestions.length - 1]?.item).toBe("bet");
});

it("places labeled create suggestions before fuzzy matches", () => {
const suggester = new InputSuggester(
app,
["New note 01", "New note 02"],
["Folder/New note 01.md", "Folder/New note 02.md"],
{
customValueLabel: (value) => `Create new note: ${value}`,
},
);

suggester.inputEl.value = "New note";

const suggestions = suggester.getSuggestions("New note");

expect(suggestions.map((suggestion) => suggestion.item)).toEqual([
"New note",
"Folder/New note 01.md",
"Folder/New note 02.md",
]);
});

it("avoids duplicating existing items as custom input", () => {
const suggester = new InputSuggester(
app,
Expand Down
13 changes: 10 additions & 3 deletions src/gui/InputSuggester/inputSuggester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ type Options = {
allowCustomValue: boolean;
/**
* Renders the typed-but-unmatched custom row with a label, e.g.
* `(value) => \`Create new note: ${value}\``. Implies a "create" affordance.
* `(value) => \`Create new note: ${value}\``. Implies a "create" affordance
* that is placed first so Enter performs the labeled action.
*/
customValueLabel: (value: string) => string;
/**
Expand Down Expand Up @@ -198,13 +199,19 @@ export default class InputSuggester extends FuzzySuggestModal<string> {
return suggestions;
}

suggestions.push({
const customSuggestion = {
item: customValue,
match: {
score: Number.NEGATIVE_INFINITY,
matches: [],
},
});
};

if (this.customValueLabel) {
suggestions.unshift(customSuggestion);
} else {
suggestions.push(customSuggestion);
}

return suggestions;
}
Expand Down
9 changes: 7 additions & 2 deletions tests/orb-setup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
const runE2E = path.join(repoRoot, ".agents", "run-e2e");
const openShim = path.join(repoRoot, ".agents", "obsidian-open");
const patcher = path.join(repoRoot, ".agents", "patch-obsidian-e2e-linux.mjs");
const profileRoot = "/tmp/quickadd-obsidian-e2e";
const profileRoot = path.join(
fs.realpathSync("/tmp"),

Check failure on line 13 in tests/orb-setup.test.ts

View workflow job for this annotation

GitHub Actions / Platform Test (windows-latest)

tests/orb-setup.test.ts

Error: ENOENT: no such file or directory, lstat 'D:\tmp' ❯ tests/orb-setup.test.ts:13:5 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Serialized Error: { errno: -4058, code: 'ENOENT', syscall: 'lstat', path: 'D:\tmp' }
"quickadd-obsidian-e2e",
);
const temporaryPaths: string[] = [];

interface ProfileRootState {
Expand Down Expand Up @@ -161,7 +164,7 @@
env: { ...process.env, PATH: `${bin}:${process.env.PATH}` },
encoding: "utf8",
});
expect(result.status, testCase.name).toBe(1);

Check failure on line 167 in tests/orb-setup.test.ts

View workflow job for this annotation

GitHub Actions / Platform Test (macos-latest)

tests/orb-setup.test.ts > Amp orb E2E lifecycle > rejects rather than evaluates unexpected start output

AssertionError: malformed: expected 2 to be 1 // Object.is equality - Expected + Received - 1 + 2 ❯ tests/orb-setup.test.ts:167:42
const calls = fs.readFileSync(log, "utf8");
expect(calls, testCase.name).toContain("stop:e2e-obsidian");
expect(calls, testCase.name).not.toContain("test:e2e --");
Expand All @@ -173,7 +176,9 @@
});
});

describe("Linux Obsidian launcher validation", () => {
const describeLinux = process.platform === "linux" ? describe : describe.skip;

describeLinux("Linux Obsidian launcher validation", () => {
function validArgs(validHome: string): string[] {
return [
"-n",
Expand Down
Loading