fix(tui): preserve spaces in settings searches

This commit is contained in:
Armin Ronacher 2026-07-31 16:34:27 +02:00
parent 3c717842e8
commit bf4a90d819
4 changed files with 65 additions and 6 deletions

View file

@ -12,6 +12,7 @@
### Fixed
- Fixed spaces in `/settings` searches toggling the highlighted setting while typing multi-word queries such as **UI mode** or **Quiet startup**.
- Fixed custom editors not inheriting the default editor's autocomplete dropdown item limit ([#7333](https://github.com/earendil-works/pi/issues/7333)).
- Fixed malformed resource arrays in package manifests crashing session startup ([#7187](https://github.com/earendil-works/pi/issues/7187)).
- Fixed the DOOM overlay example downloading its shareware WAD from a dead URL.

View file

@ -6,6 +6,7 @@
- Fixed terminal width accounting for Indic conjunct grapheme clusters ([#6124](https://github.com/earendil-works/pi/issues/6124) by [@petrroll](https://github.com/petrroll)).
- Fixed phantom alternate-screen text selection from unmatched mouse events when changing terminal pane focus.
- Fixed spaces in searchable settings queries changing the selected value instead of filtering multi-word labels.
### Added

View file

@ -182,16 +182,15 @@ export class SettingsList implements Component {
} else if (kb.matches(data, "tui.select.down")) {
if (displayItems.length === 0) return;
this.selectedIndex = this.selectedIndex === displayItems.length - 1 ? 0 : this.selectedIndex + 1;
} else if (kb.matches(data, "tui.select.confirm") || data === " ") {
} else if (
kb.matches(data, "tui.select.confirm") ||
(data === " " && (!this.searchEnabled || this.searchInput?.getValue().length === 0))
) {
this.activateItem();
} else if (kb.matches(data, "tui.select.cancel")) {
this.onCancel();
} else if (this.searchEnabled && this.searchInput) {
const sanitized = data.replace(/ /g, "");
if (!sanitized) {
return;
}
this.searchInput.handleInput(sanitized);
this.searchInput.handleInput(data);
this.applyFilter(this.searchInput.getValue());
}
}

View file

@ -0,0 +1,58 @@
import assert from "node:assert";
import { describe, it } from "node:test";
import { SettingsList, type SettingsListTheme } from "../src/components/settings-list.ts";
const testTheme: SettingsListTheme = {
label: (text) => text,
value: (text) => text,
description: (text) => text,
cursor: "> ",
hint: (text) => text,
};
const items = [
{
id: "ui-mode",
label: "UI mode",
currentValue: "regular",
values: ["regular", "fullscreen"],
},
];
describe("SettingsList", () => {
it("includes spaces in an active search instead of changing the selected setting", () => {
const changes: Array<{ id: string; value: string }> = [];
const list = new SettingsList(
items.map((item) => ({ ...item })),
10,
testTheme,
(id, value) => changes.push({ id, value }),
() => {},
{ enableSearch: true },
);
for (const character of "UI mode") list.handleInput(character);
assert.deepStrictEqual(changes, []);
assert.match(list.render(80)[0] ?? "", /UI mode/);
list.handleInput("\r");
assert.deepStrictEqual(changes, [{ id: "ui-mode", value: "fullscreen" }]);
});
it("keeps Space as a change shortcut before a search query is entered", () => {
const changes: Array<{ id: string; value: string }> = [];
const list = new SettingsList(
items.map((item) => ({ ...item })),
10,
testTheme,
(id, value) => changes.push({ id, value }),
() => {},
{ enableSearch: true },
);
list.handleInput(" ");
assert.deepStrictEqual(changes, [{ id: "ui-mode", value: "fullscreen" }]);
});
});