Skip to content

Commit 258f7c1

Browse files
committed
👍 Add ways to silence echo and echoerr
1 parent 74f1800 commit 258f7c1

File tree

2 files changed

+149
-19
lines changed

2 files changed

+149
-19
lines changed

denops_std/helper/README.md

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,71 @@ export async function main(denops: Denops): Promise<void> {
2525
##### Warning
2626

2727
In order to make the behavior of Vim and Neovim consistent, `timer_start()` is
28-
used internally not only in Vim but also in Neovim. Note that this means that it
29-
is not possible to control messages by prepending `silent` to them. Developers
30-
must control the display of messages by not calling this function.
28+
used internally not only in Vim but also in Neovim. Note that this means that
29+
you cannot control the message by prepending `silent` when calling it from the
30+
Vim script. If you want to control the message, use the `setSilent` function to
31+
change the silent state to `'silent'` or `'silent!'` in advance, or use the
32+
`ensureSilent` function to fix the silent state to `'silent'` or `'silent!'`
33+
during execution of any function.
34+
35+
### setSilent / getSilent
36+
37+
By setting the silent state with `setSilent`, you can control `silent` and
38+
`silent!` messages as follows.
39+
40+
```typescript
41+
import { Denops } from "../mod.ts";
42+
import { echo, echoerr, getSilent, setSilent } from "../helper/mod.ts";
43+
44+
export async function main(denops: Denops): Promise<void> {
45+
// Because silent is "silent!", `echo` and `echoerr` doesn't show messages.
46+
setSilent(denops, "silent!");
47+
await echo(denops, "Hello\nWorld!");
48+
await echoerr(denops, "This is error message");
49+
50+
// Because silent is "silent", `echo` doesn't show messages.
51+
setSilent(denops, "silent");
52+
await echo(denops, "Hello\nWorld!");
53+
await echoerr(denops, "This is error message");
54+
55+
// Because silent is "", both show messages.
56+
setSilent(denops, "");
57+
await echo(denops, "Hello\nWorld!");
58+
await echoerr(denops, "This is error message");
59+
}
60+
```
61+
62+
Use the `getSilent()` function to get the current silent state.
63+
64+
### ensureSilent
65+
66+
To control `silent` and `silent!` messages while executing a particular
67+
function, use `ensureSilent` as follows
68+
69+
```typescript
70+
import { Denops } from "../mod.ts";
71+
import { echo, echoerr, ensureSilent } from "../helper/mod.ts";
72+
73+
export async function main(denops: Denops): Promise<void> {
74+
// Because silent is "silent!", `echo` and `echoerr` doesn't show messages.
75+
await ensureSilent(denops, "silent!", async () => {
76+
await echo(denops, "Hello\nWorld!");
77+
await echoerr(denops, "This is error message");
78+
});
79+
80+
// Because silent is "silent", `echo` doesn't show messages.
81+
await ensureSilent(denops, "silent", async () => {
82+
await echo(denops, "Hello\nWorld!");
83+
await echoerr(denops, "This is error message");
84+
});
85+
86+
// Because silent is "", both shows messages.
87+
await ensureSilent(denops, "", async () => {
88+
await echo(denops, "Hello\nWorld!");
89+
await echoerr(denops, "This is error message");
90+
});
91+
}
92+
```
3193

3294
### friendlyCall
3395

denops_std/helper/echo.ts

Lines changed: 84 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { batch } from "../batch/mod.ts";
44
import { generateUniqueString } from "../util.ts";
55

66
const cacheKey = Symbol("denops_std/helper/echo");
7+
const cacheKeySilent = Symbol("denops_std/helper/echo/silent");
78
const suffix = generateUniqueString();
89

910
async function ensurePrerequisites(denops: Denops): Promise<string> {
@@ -28,6 +29,39 @@ async function ensurePrerequisites(denops: Denops): Promise<string> {
2829
return suffix;
2930
}
3031

32+
export type Silent = "" | "silent" | "silent!";
33+
34+
/**
35+
* Get global silent status
36+
*/
37+
export function getSilent(denops: Denops): Silent {
38+
return (denops.context[cacheKeySilent] ?? "") as Silent;
39+
}
40+
41+
/**
42+
* Set global silent status
43+
*/
44+
export function setSilent(denops: Denops, silent: Silent): void {
45+
denops.context[cacheKeySilent] = silent;
46+
}
47+
48+
/**
49+
* Ensure global silent status during given function
50+
*/
51+
export async function ensureSilent<T>(
52+
denops: Denops,
53+
silent: Silent,
54+
executor: () => T,
55+
): Promise<T> {
56+
const saved = denops.context[cacheKeySilent];
57+
denops.context[cacheKeySilent] = silent;
58+
try {
59+
return await executor();
60+
} finally {
61+
denops.context[cacheKeySilent] = saved;
62+
}
63+
}
64+
3165
/**
3266
* Echo message as like `echo` on Vim script.
3367
*
@@ -40,32 +74,66 @@ async function ensurePrerequisites(denops: Denops): Promise<string> {
4074
* running as 'test' mode to avoid unwilling test failures.
4175
*
4276
* WARNING:
43-
* In order to make the behavior of Vim and Neovim consistent, `timer_start()`
44-
* is used internally not only in Vim but also in Neovim. Note that this
45-
* means that it is not possible to control messages by prepending `silent`
46-
* to them. Developers must control the display of messages by not calling this
47-
* function.
77+
* In order to make the behavior of Vim and Neovim consistent,
78+
* `timer_start()` is used internally not only in Vim but also in
79+
* Neovim. Note that this means that you cannot control the message
80+
* by prepending `silent` when calling it from the Vim script.
81+
* If you want to control the message, use the `setSilent` function
82+
* to change the silent state to `'silent'` or `'silent!'` in
83+
* advance, or use the `ensureSilent` function to fix the silent state
84+
* to `'silent'` or `'silent!'` during execution of any function.
4885
*/
49-
export function echo(denops: Denops, message: string): Promise<void> {
86+
export function echo(
87+
denops: Denops,
88+
message: string,
89+
): Promise<void> {
90+
const silent = getSilent(denops);
91+
switch (silent) {
92+
case "silent":
93+
case "silent!":
94+
return Promise.resolve();
95+
}
5096
if (denops.meta.mode === "test") {
5197
return Promise.resolve();
5298
} else {
53-
return echoVim(denops, message);
99+
return echoInternal(denops, message);
54100
}
55101
}
56102

57103
/**
58104
* Echo message as an error message.
59105
*
60-
* Note that this function just use ErrorMsg highlight and is not equivalent
61-
* to `echoerr` command in Vim/Neovim.
106+
* Note that this function just use ErrorMsg highlight and is not
107+
* equivalent to `echoerr` command in Vim/Neovim.
108+
*
109+
* WARNING:
110+
* In order to make the behavior of Vim and Neovim consistent,
111+
* `timer_start()` is used internally not only in Vim but also in
112+
* Neovim. Note that this means that you cannot control the message
113+
* by prepending `silent` when calling it from the Vim script.
114+
* If you want to control the message, use the `setSilent` function
115+
* to change the silent state to `'silent!'` in advance, or use the
116+
* `ensureSilent` function to fix the silent state to `'silent!'`
117+
* during execution of any function.
62118
*/
63-
export async function echoerr(denops: Denops, message: string): Promise<void> {
64-
await batch(denops, async (denops) => {
65-
await denops.cmd("echohl ErrorMsg");
66-
await echo(denops, message);
67-
await denops.cmd("echohl None");
68-
});
119+
export async function echoerr(
120+
denops: Denops,
121+
message: string,
122+
): Promise<void> {
123+
const silent = getSilent(denops);
124+
switch (silent) {
125+
case "silent!":
126+
return Promise.resolve();
127+
}
128+
if (denops.meta.mode === "test") {
129+
return Promise.resolve();
130+
} else {
131+
await batch(denops, async (denops) => {
132+
await denops.cmd("echohl ErrorMsg");
133+
await echoInternal(denops, message);
134+
await denops.cmd("echohl None");
135+
});
136+
}
69137
}
70138

71139
/**
@@ -92,7 +160,7 @@ export async function friendlyCall(
92160
}
93161
}
94162

95-
async function echoVim(denops: Denops, message: string): Promise<void> {
163+
async function echoInternal(denops: Denops, message: string): Promise<void> {
96164
const suffix = await ensurePrerequisites(denops);
97165
await denops.call(`DenopsStdHelperEcho_${suffix}`, message);
98166
}

0 commit comments

Comments
 (0)