Skip to content

Commit 6d5517b

Browse files
committed
feat: support multiple matchers
1 parent feb03c0 commit 6d5517b

File tree

5 files changed

+75
-6
lines changed

5 files changed

+75
-6
lines changed

denops/fall/event.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export type Event =
2121
| { type: "move-cursor-at"; cursor: number | "$" }
2222
| { type: "select-item"; cursor?: number | "$"; method?: SelectMethod }
2323
| { type: "select-all-items"; method?: SelectMethod }
24+
| { type: "switch-matcher"; amount: number; cycle?: boolean }
25+
| { type: "switch-matcher-at"; index: number | "$" }
2426
| { type: "action-invoke"; name: string }
2527
| { type: "list-component-execute"; command: string }
2628
| { type: "preview-component-execute"; command: string }

denops/fall/main/event.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ const isEventComplement = is.UnionOf([
4141
type: is.LiteralOf("select-all-items"),
4242
method: as.Optional(is.LiteralOneOf(["on", "off", "toggle"] as const)),
4343
}),
44+
// Switch
45+
is.ObjectOf({
46+
type: is.LiteralOf("switch-matcher"),
47+
amount: is.Number,
48+
cycle: as.Optional(is.Boolean),
49+
}),
50+
is.ObjectOf({
51+
type: is.LiteralOf("switch-matcher-at"),
52+
index: is.UnionOf([is.Number, is.LiteralOf("$")]),
53+
}),
4454
// Action
4555
is.ObjectOf({
4656
type: is.LiteralOf("action-invoke"),

denops/fall/picker.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,7 @@ export class Picker<T extends Detail> implements AsyncDisposable {
101101
new CollectProcessor(params.source),
102102
);
103103
this.#matchProcessor = this.#stack.use(
104-
// TODO: Support multiple matchers
105-
new MatchProcessor(params.matchers[0]),
104+
new MatchProcessor(params.matchers),
106105
);
107106
this.#visualizeProcessor = this.#stack.use(
108107
// TODO: Support multiple sorters/renderers
@@ -359,6 +358,33 @@ export class Picker<T extends Detail> implements AsyncDisposable {
359358
this.#selectAll(event.method);
360359
this.#listComponent.selection = this.#selection;
361360
break;
361+
case "switch-matcher": {
362+
let index = this.#matchProcessor.matcherIndex + event.amount;
363+
if (event.cycle) {
364+
if (index < 0) {
365+
index = this.#matchProcessor.matcherCount - 1;
366+
} else if (index >= this.#matchProcessor.matcherCount) {
367+
index = 0;
368+
}
369+
}
370+
this.#matchProcessor.matcherIndex = index;
371+
this.#matchProcessor.start(denops, {
372+
items: this.#collectProcessor.items,
373+
query: this.#inputComponent.cmdline,
374+
}, {
375+
restart: true,
376+
});
377+
break;
378+
}
379+
case "switch-matcher-at":
380+
this.#matchProcessor.matcherIndex = event.index;
381+
this.#matchProcessor.start(denops, {
382+
items: this.#collectProcessor.items,
383+
query: this.#inputComponent.cmdline,
384+
}, {
385+
restart: true,
386+
});
387+
break;
362388
case "action-invoke":
363389
accept(event.name);
364390
break;

denops/fall/processor/match.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export type MatchProcessorOptions = {
1919
};
2020

2121
export class MatchProcessor<T extends Detail> {
22-
#filter: Matcher<T>;
22+
#matchers: Matcher<T>[];
2323
#interval: number;
2424
#threshold: number;
2525
#chunkSize: number;
@@ -28,21 +28,43 @@ export class MatchProcessor<T extends Detail> {
2828
#reserved?: () => void;
2929
#paused?: PromiseWithResolvers<void>;
3030
#items: IdItem<T>[] = [];
31+
#matcherIndex = 0;
3132

3233
constructor(
33-
filter: Matcher<T>,
34+
filters: Matcher<T>[],
3435
options: MatchProcessorOptions = {},
3536
) {
36-
this.#filter = filter;
37+
this.#matchers = filters;
3738
this.#interval = options.interval ?? INTERVAL;
3839
this.#threshold = options.threshold ?? THRESHOLD;
3940
this.#chunkSize = options.chunkSize ?? CHUNK_SIZE;
4041
}
4142

43+
get #matcher(): Matcher<T> {
44+
return this.#matchers[this.#matcherIndex];
45+
}
46+
4247
get items(): IdItem<T>[] {
4348
return this.#items;
4449
}
4550

51+
get matcherCount(): number {
52+
return this.#matchers.length;
53+
}
54+
55+
get matcherIndex(): number {
56+
return this.#matcherIndex;
57+
}
58+
59+
set matcherIndex(index: number | "$") {
60+
if (index === "$" || index >= this.#matchers.length) {
61+
index = this.#matchers.length - 1;
62+
} else if (index < 0) {
63+
index = 0;
64+
}
65+
this.#matcherIndex = index;
66+
}
67+
4668
start(
4769
denops: Denops,
4870
{ items, query }: MatchParams<T>,
@@ -64,7 +86,7 @@ export class MatchProcessor<T extends Detail> {
6486
const iter = take(
6587
query === ""
6688
? toAsyncIterable(items)
67-
: this.#filter.match(denops, { items, query }, { signal }),
89+
: this.#matcher.match(denops, { items, query }, { signal }),
6890
this.#threshold,
6991
);
7092
// Gradually update items when `items` is empty to improve latency

plugin/fall/mapping.vim

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,16 @@ cnoremap <silent> <Plug>(fall-right) <Cmd>call fall#internal#dispatch(#{type: 'l
1515
cnoremap <silent> <Plug>(fall-left:scroll) <Cmd>call fall#internal#dispatch(#{type: 'list-component-execute', command: 'silent! normal! zH'})<CR>
1616
cnoremap <silent> <Plug>(fall-right:scroll) <Cmd>call fall#internal#dispatch(#{type: 'list-component-execute', command: 'silent! normal! zL'})<CR>
1717
18+
" Select
1819
cnoremap <silent> <Plug>(fall-select) <Cmd>call fall#internal#dispatch(#{type: 'select-item'})<CR>
1920
cnoremap <silent> <Plug>(fall-select-all) <Cmd>call fall#internal#dispatch(#{type: 'select-all-items'})<CR>
2021
22+
" Switch
23+
cnoremap <silent> <Plug>(fall-switch-matcher-first) <Cmd>call fall#internal#dispatch(#{type: 'switch-matcher-at', index: 0})<CR>
24+
cnoremap <silent> <Plug>(fall-switch-matcher-last) <Cmd>call fall#internal#dispatch(#{type: 'switch-matcher-at', index: '$'})<CR>
25+
cnoremap <silent> <Plug>(fall-switch-matcher-prev) <Cmd>call fall#internal#dispatch(#{type: 'switch-matcher', amount: -1, cycle: v:true})<CR>
26+
cnoremap <silent> <Plug>(fall-switch-matcher-next) <Cmd>call fall#internal#dispatch(#{type: 'switch-matcher', amount: 1, cycle: v:true})<CR>
27+
2128
" Preview
2229
cnoremap <silent> <Plug>(fall-preview-first) <Cmd>call fall#internal#dispatch(#{type: 'preview-component-execute', command: 'silent! normal! gg'})<CR>
2330
cnoremap <silent> <Plug>(fall-preview-last) <Cmd>call fall#internal#dispatch(#{type: 'preview-component-execute', command: 'silent! normal! G'})<CR>
@@ -63,6 +70,8 @@ if !get(g:, 'fall_disable_default_mapping')
6370
cnoremap <nowait> <S-Right> <Plug>(fall-preview-right:scroll)
6471
" Action
6572
cnoremap <nowait> <Tab> <Plug>(fall-action-select)
73+
" Switch
74+
cnoremap <nowait> <F2> <Plug>(fall-switch-matcher-next)
6675
endfunction
6776

6877
augroup fall_mapping_plugin

0 commit comments

Comments
 (0)