Skip to content

Commit e07f88f

Browse files
authored
Merge pull request #238 from vim-denops/lambda-add
👍 Add `lambda.add()` to add a lambda function and return a Lambda object
2 parents b386002 + bf1f42c commit e07f88f

File tree

2 files changed

+178
-6
lines changed

2 files changed

+178
-6
lines changed

lambda/mod.ts

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,21 @@
1010
*
1111
* export async function main(denops: Denops): Promise<void> {
1212
* // Add lambda function
13-
* const id = lambda.register(
13+
* const lo = lambda.add(
1414
* denops,
1515
* () => {
1616
* // Do what ever you want.
1717
* },
1818
* );
1919
*
2020
* // Use id to dispatch added function from Deno
21-
* await denops.dispatch(denops.name, id);
21+
* await denops.dispatch(denops.name, lo.id);
2222
*
2323
* // Or from Vim
24-
* await denops.cmd("call denops#notify(name, id, [])", {
25-
* name: denops.name,
26-
* id,
27-
* });
24+
* await denops.cmd(`call ${lo.notify()}`);
25+
*
26+
* // Dispose the lambda object
27+
* lo.dispose();
2828
* }
2929
* ```
3030
*
@@ -142,3 +142,103 @@ export function unregister(
142142
}
143143
return false;
144144
}
145+
146+
export interface Lambda {
147+
readonly id: Identifier;
148+
149+
/**
150+
* Create a Vim script expression to notify the lambda function
151+
*
152+
* ```typescript
153+
* import type { Denops } from "https://deno.land/x/denops_std@$MODULE_VERSION/mod.ts";
154+
* import * as lambda from "https://deno.land/x/denops_std@$MODULE_VERSION/lambda/mod.ts";
155+
*
156+
* export async function main(denops: Denops): Promise<void> {
157+
* const a = lambda.add(denops, () => {
158+
* // Do what ever you want.
159+
* });
160+
* await denops.cmd(`nmap <Space> <Cmd>call ${a.notify()}<CR>`);
161+
* }
162+
* ```
163+
*/
164+
notify(...args: unknown[]): string;
165+
166+
/**
167+
* Create a Vim script expression to request the lambda function
168+
*
169+
* ```typescript
170+
* import type { Denops } from "https://deno.land/x/denops_std@$MODULE_VERSION/mod.ts";
171+
* import * as lambda from "https://deno.land/x/denops_std@$MODULE_VERSION/lambda/mod.ts";
172+
*
173+
* export async function main(denops: Denops): Promise<void> {
174+
* const a = lambda.add(denops, () => {
175+
* // Do what ever you want.
176+
* });
177+
* await denops.cmd(`nmap <Space> <Cmd>call ${a.request()}<CR>`);
178+
* }
179+
* ```
180+
*/
181+
request(...args: unknown[]): string;
182+
183+
/**
184+
* Dispose the lambda function
185+
*
186+
* ```typescript
187+
* import type { Denops } from "https://deno.land/x/denops_std@$MODULE_VERSION/mod.ts";
188+
* import * as lambda from "https://deno.land/x/denops_std@$MODULE_VERSION/lambda/mod.ts";
189+
*
190+
* export async function main(denops: Denops): Promise<void> {
191+
* const a = lambda.add(denops, () => {
192+
* // Do what ever you want.
193+
* });
194+
* // Dispose the lambda function manually
195+
* a.dispose();
196+
* }
197+
* ```
198+
*/
199+
dispose(): void;
200+
201+
[Symbol.dispose](): void;
202+
}
203+
204+
/**
205+
* Add a lambda function to a denops API and return the lambda object
206+
*
207+
* ```typescript
208+
* import type { Denops } from "https://deno.land/x/denops_std@$MODULE_VERSION/mod.ts";
209+
* import * as lambda from "https://deno.land/x/denops_std@$MODULE_VERSION/lambda/mod.ts";
210+
*
211+
* export async function main(denops: Denops): Promise<void> {
212+
* // Add lambda function
213+
* const lo = lambda.add(
214+
* denops,
215+
* () => {
216+
* // Do what ever you want.
217+
* },
218+
* );
219+
*
220+
* // Call the lambda function from Vim script
221+
* await denops.eval(lo.request());
222+
*
223+
* // Dispose the lambda object
224+
* lo.dispose();
225+
* }
226+
* ```
227+
*/
228+
export function add(denops: Denops, fn: Fn): Lambda {
229+
const id = register(denops, fn);
230+
const name = denops.name;
231+
return {
232+
id,
233+
notify: (...args: unknown[]) => {
234+
args = args.map((v) => JSON.stringify(v));
235+
return `denops#notify('${name}', '${id}', [${args}])`;
236+
},
237+
request: (...args: unknown[]) => {
238+
args = args.map((v) => JSON.stringify(v));
239+
return `denops#request('${name}', '${id}', [${args}])`;
240+
},
241+
dispose: () => unregister(denops, id),
242+
[Symbol.dispose]: () => unregister(denops, id),
243+
};
244+
}

lambda/mod_test.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,77 @@ test({
6161
);
6262
},
6363
});
64+
65+
await t.step({
66+
name: "add() registers a lambda function and returns a Lambda object",
67+
fn: async () => {
68+
let counter = 0;
69+
using lo = lambda.add(
70+
denops,
71+
() => {
72+
counter++;
73+
return counter;
74+
},
75+
);
76+
assertEquals(
77+
lo.request(),
78+
`denops#request('${denops.name}', '${lo.id}', [])`,
79+
);
80+
assertEquals(
81+
lo.notify(),
82+
`denops#notify('${denops.name}', '${lo.id}', [])`,
83+
);
84+
assertEquals(await denops.eval(lo.request()), 1);
85+
await denops.eval(lo.notify());
86+
assertEquals(counter, 2);
87+
},
88+
});
89+
90+
await t.step({
91+
name:
92+
"add() registers a lambda function with arguments and returns a Lambda object",
93+
fn: async () => {
94+
using lo = lambda.add(
95+
denops,
96+
(a: unknown, b: unknown, c: unknown) => {
97+
return [a, b, c];
98+
},
99+
);
100+
assertEquals(
101+
lo.request(1, "2", [3]),
102+
`denops#request('${denops.name}', '${lo.id}', [1,"2",[3]])`,
103+
);
104+
assertEquals(
105+
lo.notify(1, "2", [3]),
106+
`denops#notify('${denops.name}', '${lo.id}', [1,"2",[3]])`,
107+
);
108+
assertEquals(await denops.eval(lo.request(1, "2", [3])), [1, "2", [3]]);
109+
},
110+
});
111+
112+
await t.step({
113+
name: "add() return a disposable object",
114+
fn: async () => {
115+
// Unregister all methods
116+
denops.dispatcher = {};
117+
{
118+
let counter = 0;
119+
using lo = lambda.add(
120+
denops,
121+
() => {
122+
counter++;
123+
return counter;
124+
},
125+
);
126+
assertEquals(await denops.eval(lo.request()), 1);
127+
await denops.eval(lo.notify());
128+
assertEquals(counter, 2);
129+
// Still available
130+
assertEquals(Object.keys(denops.dispatcher), [lo.id]);
131+
}
132+
// Unregistered automatically
133+
assertEquals(Object.keys(denops.dispatcher), []);
134+
},
135+
});
64136
},
65137
});

0 commit comments

Comments
 (0)