feat(coding-agent): add treeFilterMode setting for /tree default filter (#1852)

Add configurable initial filter mode for the session tree navigator.
Users who always switch to a specific filter (e.g. no-tools via Ctrl+T)
can now set it as default in settings.

Same pattern as doubleEscapeAction (#404). Filter infra from #747.
This commit is contained in:
lajarre
2026-03-05 21:25:58 +00:00
committed by GitHub
parent a0d839ce84
commit 1f39cc776a
5 changed files with 39 additions and 2 deletions

View File

@@ -38,6 +38,7 @@ export interface SettingsConfig {
hideThinkingBlock: boolean;
collapseChangelog: boolean;
doubleEscapeAction: "fork" | "tree" | "none";
treeFilterMode: "default" | "no-tools" | "user-only" | "labeled-only" | "all";
showHardwareCursor: boolean;
editorPaddingX: number;
autocompleteMaxVisible: number;
@@ -60,6 +61,7 @@ export interface SettingsCallbacks {
onHideThinkingBlockChange: (hidden: boolean) => void;
onCollapseChangelogChange: (collapsed: boolean) => void;
onDoubleEscapeActionChange: (action: "fork" | "tree" | "none") => void;
onTreeFilterModeChange: (mode: "default" | "no-tools" | "user-only" | "labeled-only" | "all") => void;
onShowHardwareCursorChange: (enabled: boolean) => void;
onEditorPaddingXChange: (padding: number) => void;
onAutocompleteMaxVisibleChange: (maxVisible: number) => void;
@@ -200,6 +202,13 @@ export class SettingsSelectorComponent extends Container {
currentValue: config.doubleEscapeAction,
values: ["tree", "fork", "none"],
},
{
id: "tree-filter-mode",
label: "Tree filter mode",
description: "Default filter when opening /tree",
currentValue: config.treeFilterMode,
values: ["default", "no-tools", "user-only", "labeled-only", "all"],
},
{
id: "thinking",
label: "Thinking level",
@@ -379,6 +388,11 @@ export class SettingsSelectorComponent extends Container {
case "double-escape-action":
callbacks.onDoubleEscapeActionChange(newValue as "fork" | "tree");
break;
case "tree-filter-mode":
callbacks.onTreeFilterModeChange(
newValue as "default" | "no-tools" | "user-only" | "labeled-only" | "all",
);
break;
case "show-hardware-cursor":
callbacks.onShowHardwareCursorChange(newValue === "true");
break;

View File

@@ -37,7 +37,7 @@ interface FlatNode {
}
/** Filter mode for tree display */
type FilterMode = "default" | "no-tools" | "user-only" | "labeled-only" | "all";
export type FilterMode = "default" | "no-tools" | "user-only" | "labeled-only" | "all";
/**
* Tree list component with selection and ASCII art visualization
@@ -70,9 +70,11 @@ class TreeList implements Component {
currentLeafId: string | null,
maxVisibleLines: number,
initialSelectedId?: string,
initialFilterMode?: FilterMode,
) {
this.currentLeafId = currentLeafId;
this.maxVisibleLines = maxVisibleLines;
this.filterMode = initialFilterMode ?? "default";
this.multipleRoots = tree.length > 1;
this.flatNodes = this.flattenTree(tree);
this.buildActivePath();
@@ -1001,13 +1003,14 @@ export class TreeSelectorComponent extends Container implements Focusable {
onCancel: () => void,
onLabelChange?: (entryId: string, label: string | undefined) => void,
initialSelectedId?: string,
initialFilterMode?: FilterMode,
) {
super();
this.onLabelChangeCallback = onLabelChange;
const maxVisibleLines = Math.max(5, Math.floor(terminalHeight / 2));
this.treeList = new TreeList(tree, currentLeafId, maxVisibleLines, initialSelectedId);
this.treeList = new TreeList(tree, currentLeafId, maxVisibleLines, initialSelectedId, initialFilterMode);
this.treeList.onSelect = onSelect;
this.treeList.onCancel = onCancel;
this.treeList.onLabelEdit = (entryId, currentLabel) => this.showLabelInput(entryId, currentLabel);