Skip to content

Commit ff50838

Browse files
committed
👍 Support denops.redraw() in batch
The `denops.redraw()` was introduced from denops v3.2.0
1 parent 1a1a49a commit ff50838

File tree

5 files changed

+133
-0
lines changed

5 files changed

+133
-0
lines changed

denops_std/batch/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ export async function main(denops: Denops): Promise<void> {
9494
}
9595
```
9696

97+
Note that `denops.redraw()` is executed only once after the batch is actually
98+
executed, no matter how many times it is called in the `batch()`. If the `force`
99+
option is specified even once, the last call will be the one with the force
100+
option specified.
101+
97102
### gather
98103

99104
Use `gather()` to call multiple denops functions sequentially without overhead
@@ -138,3 +143,6 @@ export async function main(denops: Denops): Promise<void> {
138143
The `denops` instance passed to the `gather` block is NOT available outside of
139144
the block. An error is thrown when `denops.call()`, `denops.cmd()`, or
140145
`denops.eval()` is called.
146+
147+
Note that `denops.redraw()` cannot be called within `gather()`. If it is called,
148+
an error is raised.

denops_std/batch/batch.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ import type {
55
Meta,
66
} from "https://deno.land/x/denops_core@v3.2.0/mod.ts";
77

8+
type Redraw = undefined | boolean;
9+
810
class BatchHelper implements Denops {
911
#denops: Denops;
1012
#calls: [string, ...unknown[]][];
13+
#redraw: Redraw;
1114
#closed: boolean;
1215

1316
constructor(denops: Denops) {
@@ -20,6 +23,10 @@ class BatchHelper implements Denops {
2023
return helper.#calls;
2124
}
2225

26+
static getRedraw(helper: BatchHelper): Redraw {
27+
return helper.#redraw;
28+
}
29+
2330
static close(helper: BatchHelper): void {
2431
helper.#closed = true;
2532
}
@@ -44,6 +51,12 @@ class BatchHelper implements Denops {
4451
this.#denops.dispatcher = dispatcher;
4552
}
4653

54+
redraw(force?: boolean): Promise<void> {
55+
// Prefer 'force' if the method is called multiple times
56+
this.#redraw = !!this.#redraw || !!force;
57+
return Promise.resolve();
58+
}
59+
4760
call(fn: string, ...args: unknown[]): Promise<unknown> {
4861
if (this.#closed) {
4962
return this.#denops.call(fn, ...args);
@@ -96,6 +109,10 @@ export async function batch(
96109
}
97110
const calls = BatchHelper.getCalls(helper);
98111
await denops.batch(...calls);
112+
const redraw = BatchHelper.getRedraw(helper);
113+
if (redraw != null) {
114+
await denops.redraw(redraw);
115+
}
99116
}
100117

101118
export type { BatchHelper };

denops_std/batch/batch_test.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import { assertEquals } from "https://deno.land/std@0.159.0/testing/asserts.ts";
2+
import {
3+
assertSpyCall,
4+
assertSpyCalls,
5+
spy,
6+
} from "https://deno.land/std@0.159.0/testing/mock.ts";
27
import { test } from "https://deno.land/x/denops_core@v3.2.0/test/mod.ts";
38
import { batch, BatchHelper } from "./batch.ts";
49

@@ -161,3 +166,87 @@ test({
161166
]);
162167
},
163168
});
169+
test({
170+
mode: "any",
171+
name:
172+
"batch() invokes 'redraw()' only once after the batch is actually executed.",
173+
fn: async (denops) => {
174+
await denops.cmd("let g:denops_batch_test = []");
175+
await denops.cmd(
176+
"command! -nargs=1 DenopsBatchTest let g:denops_batch_test += [<f-args>]",
177+
);
178+
const redrawSpy = spy(denops, "redraw");
179+
try {
180+
await batch(denops, async (denops) => {
181+
assertEquals(
182+
await denops.call("execute", "DenopsBatchTest 1"),
183+
undefined,
184+
);
185+
await denops.redraw();
186+
assertEquals(
187+
await denops.call("execute", "DenopsBatchTest 2"),
188+
undefined,
189+
);
190+
await denops.redraw();
191+
assertEquals(
192+
await denops.call("execute", "DenopsBatchTest 3"),
193+
undefined,
194+
);
195+
await denops.redraw();
196+
});
197+
} finally {
198+
redrawSpy.restore();
199+
}
200+
assertEquals(await denops.eval("g:denops_batch_test") as string[], [
201+
"1",
202+
"2",
203+
"3",
204+
]);
205+
assertSpyCalls(redrawSpy, 1);
206+
assertSpyCall(redrawSpy, 0, {
207+
args: [false],
208+
});
209+
},
210+
});
211+
test({
212+
mode: "any",
213+
name:
214+
"batch() invokes 'redraw(true)' only once after the batch is actually executed.",
215+
fn: async (denops) => {
216+
await denops.cmd("let g:denops_batch_test = []");
217+
await denops.cmd(
218+
"command! -nargs=1 DenopsBatchTest let g:denops_batch_test += [<f-args>]",
219+
);
220+
const redrawSpy = spy(denops, "redraw");
221+
try {
222+
await batch(denops, async (denops) => {
223+
assertEquals(
224+
await denops.call("execute", "DenopsBatchTest 1"),
225+
undefined,
226+
);
227+
await denops.redraw();
228+
assertEquals(
229+
await denops.call("execute", "DenopsBatchTest 2"),
230+
undefined,
231+
);
232+
await denops.redraw(true);
233+
assertEquals(
234+
await denops.call("execute", "DenopsBatchTest 3"),
235+
undefined,
236+
);
237+
await denops.redraw();
238+
});
239+
} finally {
240+
redrawSpy.restore();
241+
}
242+
assertEquals(await denops.eval("g:denops_batch_test") as string[], [
243+
"1",
244+
"2",
245+
"3",
246+
]);
247+
assertSpyCalls(redrawSpy, 1);
248+
assertSpyCall(redrawSpy, 0, {
249+
args: [true],
250+
});
251+
},
252+
});

denops_std/batch/gather.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class GatherHelper implements Denops {
4444
this.#denops.dispatcher = dispatcher;
4545
}
4646

47+
redraw(_force?: boolean): Promise<void> {
48+
throw new Error("The 'redraw' method is not available on GatherHelper.");
49+
}
50+
4751
call(fn: string, ...args: unknown[]): Promise<unknown> {
4852
if (this.#closed) {
4953
throw new Error(

denops_std/batch/gather_test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,18 @@ test({
9393
);
9494
},
9595
});
96+
test({
97+
mode: "any",
98+
name: "gather() throws an error when 'denops.redraw()' is called.",
99+
fn: async (denops) => {
100+
await assertRejects(
101+
async () => {
102+
await gather(denops, async (denops) => {
103+
await denops.redraw();
104+
});
105+
},
106+
"method is not available",
107+
);
108+
},
109+
prelude: ["let g:denops#enable_workaround_vim_before_8_2_3081 = 1"],
110+
});

0 commit comments

Comments
 (0)