Skip to content

Commit 33835a2

Browse files
committed
Add PickerContext to restore internal state of picker
1 parent 6f469e7 commit 33835a2

1 file changed

Lines changed: 55 additions & 11 deletions

File tree

denops/fall/picker.ts

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export type PickerParams<T extends Detail> = {
5757
renderers?: readonly Renderer<T>[];
5858
previewers?: readonly Previewer<T>[];
5959
zindex?: number;
60+
context?: PickerContext<T>;
6061
};
6162

6263
export type PickerResult<T extends Detail> = {
@@ -71,6 +72,19 @@ export type PickerOptions = {
7172
schedulerInterval?: number;
7273
};
7374

75+
export type PickerContext<T extends Detail> = {
76+
readonly query: string;
77+
readonly selection: Set<unknown>;
78+
readonly collectedItems: readonly IdItem<T>[];
79+
readonly filteredItems: readonly IdItem<T>[];
80+
readonly cursor: number;
81+
readonly offset: number;
82+
readonly matcherIndex: number;
83+
readonly sorterIndex: number;
84+
readonly rendererIndex: number;
85+
readonly previewerIndex?: number;
86+
};
87+
7488
export class Picker<T extends Detail> implements AsyncDisposable {
7589
static readonly ZINDEX_ALLOCATION = 4;
7690
readonly #stack = new AsyncDisposableStack();
@@ -92,15 +106,17 @@ export class Picker<T extends Detail> implements AsyncDisposable {
92106
readonly #sorterIcon: string;
93107
readonly #rendererIcon: string;
94108
readonly #previewerIcon: string;
95-
#selection: Set<unknown> = new Set();
109+
#selection: Set<unknown>;
96110

97111
constructor(params: PickerParams<T>, options: PickerOptions = {}) {
98112
this.#schedulerInterval = options.schedulerInterval ?? SCHEDULER_INTERVAL;
99-
this.#name = params.name;
100-
this.#coordinator = params.coordinator;
113+
114+
const { name, theme, coordinator, zindex = 50, context } = params;
115+
this.#name = name;
116+
this.#coordinator = coordinator;
117+
this.#selection = context?.selection ?? new Set();
101118

102119
// Components
103-
const { theme, zindex = 50 } = params;
104120
this.#matcherIcon = theme.matcherIcon ?? MATCHER_ICON;
105121
this.#sorterIcon = theme.sorterIcon ?? SORTER_ICON;
106122
this.#rendererIcon = theme.rendererIcon ?? RENDERER_ICON;
@@ -109,6 +125,7 @@ export class Picker<T extends Detail> implements AsyncDisposable {
109125
const style = this.#coordinator.style(theme);
110126
this.#inputComponent = this.#stack.use(
111127
new InputComponent({
128+
cmdline: context?.query ?? "",
112129
spinner: theme.spinner,
113130
headSymbol: theme.headSymbol,
114131
failSymbol: theme.failSymbol,
@@ -141,27 +158,54 @@ export class Picker<T extends Detail> implements AsyncDisposable {
141158

142159
// Processor
143160
this.#collectProcessor = this.#stack.use(
144-
new CollectProcessor(params.source),
161+
new CollectProcessor(params.source, {
162+
initialItems: context?.collectedItems,
163+
}),
145164
);
146165
this.#matchProcessor = this.#stack.use(
147166
new MatchProcessor(params.matchers, {
167+
initialItems: context?.filteredItems,
168+
initialQuery: context?.query,
169+
initialIndex: context?.matcherIndex,
148170
// Use incremental mode for Curator matcher
149171
incremental: isIncrementalMatcher(params.matchers[0]),
150172
}),
151173
);
152174
this.#sortProcessor = this.#stack.use(
153-
new SortProcessor(params.sorters ?? []),
175+
new SortProcessor(params.sorters ?? [], {
176+
// initialItems: this.#matchProcessor.items,
177+
initialIndex: context?.sorterIndex,
178+
}),
154179
);
155180
this.#renderProcessor = this.#stack.use(
156-
new RenderProcessor(
157-
params.renderers ?? [],
158-
),
181+
new RenderProcessor(params.renderers ?? [], {
182+
// initialItems: session?.renderedItems,
183+
initialIndex: context?.rendererIndex,
184+
initialCursor: context?.cursor,
185+
initialOffset: context?.offset,
186+
}),
159187
);
160188
this.#previewProcessor = this.#stack.use(
161-
new PreviewProcessor(params.previewers ?? []),
189+
new PreviewProcessor(params.previewers ?? [], {
190+
initialIndex: context?.previewerIndex,
191+
}),
162192
);
163193
}
164194

195+
get context(): PickerContext<T> {
196+
return {
197+
query: this.#inputComponent.cmdline,
198+
selection: this.#selection,
199+
collectedItems: this.#collectProcessor.items,
200+
filteredItems: this.#matchProcessor.items,
201+
cursor: this.#renderProcessor.cursor,
202+
offset: this.#renderProcessor.offset,
203+
matcherIndex: this.#matchProcessor.matcherIndex,
204+
sorterIndex: this.#sortProcessor.sorterIndex,
205+
rendererIndex: this.#renderProcessor.rendererIndex,
206+
};
207+
}
208+
165209
#getHelpDimension(screen: Size): Dimension {
166210
const width = Math.floor(screen.width * this.#helpWidthRatio);
167211
const height = Math.floor(screen.height * this.#helpHeightRatio);
@@ -290,7 +334,7 @@ export class Picker<T extends Detail> implements AsyncDisposable {
290334

291335
async start(
292336
denops: Denops,
293-
{ args }: { args: string[] },
337+
{ args }: { args: readonly string[] },
294338
{ signal }: { signal?: AbortSignal } = {},
295339
): Promise<PickerResult<T> | undefined> {
296340
await using stack = new AsyncDisposableStack();

0 commit comments

Comments
 (0)