Skip to content

Commit 02f236f

Browse files
lambdalisueclaude
andcommitted
feat: add buffer info refiner for filtering by buffer properties
Implements a refiner that filters items based on buffer information such as modification status, visibility, file type, and buffer properties. Supports filtering by line count, buffer types, and special buffer exclusion. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 2bbd819 commit 02f236f

File tree

1 file changed

+185
-0
lines changed

1 file changed

+185
-0
lines changed

builtin/refiner/buffer_info.ts

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
import * as fn from "@denops/std/function";
2+
import { defineRefiner, type Refiner } from "../../refiner.ts";
3+
4+
type Detail = {
5+
bufnr: number;
6+
};
7+
8+
export type BufferInfoRefinerOptions = {
9+
/**
10+
* Filter by buffer modification status.
11+
*/
12+
modified?: boolean;
13+
14+
/**
15+
* Filter by buffer listed status.
16+
*/
17+
listed?: boolean;
18+
19+
/**
20+
* Filter by buffer loaded status.
21+
*/
22+
loaded?: boolean;
23+
24+
/**
25+
* Filter by buffer visibility (visible in any window).
26+
*/
27+
visible?: boolean;
28+
29+
/**
30+
* Filter by file types.
31+
* If provided, only buffers with these filetypes will pass.
32+
*/
33+
filetypes?: string[];
34+
35+
/**
36+
* Filter by buffer types.
37+
* Common values: "", "help", "quickfix", "terminal", "prompt", "popup", "nofile", "nowrite", "acwrite"
38+
*/
39+
buftypes?: string[];
40+
41+
/**
42+
* Whether to include unnamed buffers.
43+
* @default true
44+
*/
45+
includeUnnamed?: boolean;
46+
47+
/**
48+
* Whether to include special buffers (help, quickfix, etc).
49+
* @default true
50+
*/
51+
includeSpecial?: boolean;
52+
53+
/**
54+
* Minimum line count for the buffer.
55+
*/
56+
minLines?: number;
57+
58+
/**
59+
* Maximum line count for the buffer.
60+
*/
61+
maxLines?: number;
62+
};
63+
64+
/**
65+
* Creates a Refiner that filters items based on buffer information.
66+
*
67+
* This Refiner can filter buffers based on various criteria such as
68+
* modification status, visibility, file type, and buffer properties.
69+
*
70+
* @param options - Options to customize buffer filtering.
71+
* @returns A Refiner that filters items based on buffer information.
72+
*/
73+
export function bufferInfo(
74+
options: Readonly<BufferInfoRefinerOptions> = {},
75+
): Refiner<Detail> {
76+
const modified = options.modified;
77+
const listed = options.listed;
78+
const loaded = options.loaded;
79+
const visible = options.visible;
80+
const filetypes = options.filetypes;
81+
const buftypes = options.buftypes;
82+
const includeUnnamed = options.includeUnnamed ?? true;
83+
const includeSpecial = options.includeSpecial ?? true;
84+
const minLines = options.minLines;
85+
const maxLines = options.maxLines;
86+
87+
return defineRefiner(async (denops, { items }) => {
88+
// Get all buffer info at once for efficiency
89+
const allBufinfo = await fn.getbufinfo(denops);
90+
const bufInfoMap = new Map(
91+
allBufinfo.map((info) => [info.bufnr, info]),
92+
);
93+
94+
// Process items and filter
95+
const results = await Promise.all(
96+
items.map(async (item) => {
97+
const { bufnr } = item.detail;
98+
const bufinfo = bufInfoMap.get(bufnr);
99+
100+
if (!bufinfo) {
101+
return null;
102+
}
103+
104+
// Check modification status
105+
if (modified !== undefined && bufinfo.changed !== (modified ? 1 : 0)) {
106+
return null;
107+
}
108+
109+
// Check listed status
110+
if (listed !== undefined && bufinfo.listed !== (listed ? 1 : 0)) {
111+
return null;
112+
}
113+
114+
// Check loaded status
115+
if (loaded !== undefined && bufinfo.loaded !== (loaded ? 1 : 0)) {
116+
return null;
117+
}
118+
119+
// Check visibility
120+
if (visible !== undefined) {
121+
const isVisible = bufinfo.windows && bufinfo.windows.length > 0;
122+
if (visible !== isVisible) {
123+
return null;
124+
}
125+
}
126+
127+
// Check unnamed buffers
128+
if (!includeUnnamed && !bufinfo.name) {
129+
return null;
130+
}
131+
132+
// Check line count
133+
if (minLines !== undefined && bufinfo.linecount < minLines) {
134+
return null;
135+
}
136+
if (maxLines !== undefined && bufinfo.linecount > maxLines) {
137+
return null;
138+
}
139+
140+
// Check filetype
141+
if (filetypes && filetypes.length > 0) {
142+
const filetype = await denops.eval(
143+
`getbufvar(${bufnr}, "&filetype")`,
144+
) as string;
145+
if (!filetypes.includes(filetype)) {
146+
return null;
147+
}
148+
}
149+
150+
// Check buftype
151+
if (buftypes && buftypes.length > 0) {
152+
const buftype = await denops.eval(
153+
`getbufvar(${bufnr}, "&buftype")`,
154+
) as string;
155+
if (!buftypes.includes(buftype)) {
156+
return null;
157+
}
158+
}
159+
160+
// Check special buffers
161+
if (!includeSpecial) {
162+
const buftype = await denops.eval(
163+
`getbufvar(${bufnr}, "&buftype")`,
164+
) as string;
165+
if (buftype && buftype !== "") {
166+
return null;
167+
}
168+
169+
// Also check for help buffers
170+
const filetype = await denops.eval(
171+
`getbufvar(${bufnr}, "&filetype")`,
172+
) as string;
173+
if (filetype === "help") {
174+
return null;
175+
}
176+
}
177+
178+
return item;
179+
}),
180+
);
181+
182+
// Return only non-null items
183+
return results.filter((item) => item !== null);
184+
});
185+
}

0 commit comments

Comments
 (0)