Skip to content

Commit 104f063

Browse files
authored
Merge #332 console.log() patching
2 parents ab7e260 + 865abe8 commit 104f063

22 files changed

+320
-316
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ on:
1010

1111
env:
1212
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
13+
# Purpose of this (currently) is to exercise related codepaths.
14+
NVIM_NODE_LOG_FILE: 'node-client.test.log'
1315

1416
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
1517
jobs:

README.md

Lines changed: 70 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,19 @@ See below for a quickstart example that you can copy and run immediately.
2121

2222
The `neovim` package provides these functions:
2323

24-
- `findNvim`: Tries to find a usable `nvim` binary on the current system.
25-
- `attach`: The primary interface. Takes a process, socket, or pair of write/read streams and returns a `NeovimClient` connected to an `nvim` process.
24+
- `attach()`: The primary interface. Takes a process, socket, or pair of write/read streams and returns a `NeovimClient` connected to an `nvim` process.
25+
- `findNvim()`: Tries to find a usable `nvim` binary on the current system.
26+
27+
### Logging
28+
29+
- At load-time, the `neovim` module replaces ("monkey patches") `console` with its `logger`
30+
interface, so `console.log` will call `logger.info` instead of writing to stdout (which would
31+
break the stdio RPC channel).
32+
- To skip this patching of `console.log`, pass a custom `logger` to `attach()`.
33+
- Best practice in any case is to use the `logger` available from the `NeovimClient` returned by
34+
`attach()`, instead of `console` logging functions.
35+
- Set the `$NVIM_NODE_LOG_FILE` env var to (also) write logs to a file.
36+
- Set the `$ALLOW_CONSOLE` env var to (also) write logs to stdout.
2637

2738
### Quickstart: connect to Nvim
2839

@@ -34,53 +45,54 @@ Following is a complete, working example.
3445
```
3546
2. Paste the script below into a `demo.mjs` file and run it!
3647
```
37-
node demo.mjs
48+
ALLOW_CONSOLE=1 node demo.mjs
3849
```
39-
40-
```js
41-
import * as child_process from 'node:child_process'
42-
import * as assert from 'node:assert'
43-
import { attach, findNvim } from 'neovim'
44-
45-
// Find `nvim` on the system and open a channel to it.
46-
(async function() {
47-
const found = findNvim({ orderBy: 'desc', minVersion: '0.9.0' })
48-
console.log(found);
49-
const nvim_proc = child_process.spawn(found.matches[0].path, ['--clean', '--embed'], {});
50-
51-
const nvim = attach({ proc: nvim_proc });
52-
nvim.command('vsp | vsp | vsp');
53-
54-
const windows = await nvim.windows;
55-
assert.deepStrictEqual(windows.length, 4);
56-
assert.ok(windows[0] instanceof nvim.Window);
57-
58-
nvim.window = windows[2];
59-
const win = await nvim.window;
60-
assert.ok(win.id !== windows[0].id);
61-
assert.deepStrictEqual(win.id, windows[2].id);
62-
63-
const buf = await nvim.buffer;
64-
assert.ok(buf instanceof nvim.Buffer);
65-
const lines = await buf.lines;
66-
assert.deepStrictEqual(lines, []);
67-
68-
await buf.replace(['line1', 'line2'], 0);
69-
const newLines = await buf.lines;
70-
assert.deepStrictEqual(newLines, ['line1', 'line2']);
71-
72-
// console.log('%O', nvim_proc);
73-
if (nvim_proc.disconnect) {
74-
nvim_proc.disconnect();
75-
}
76-
nvim.quit();
77-
while (nvim_proc.exitCode === null) {
78-
await new Promise(resolve => setTimeout(resolve, 100))
79-
console.log('waiting for Nvim (pid %d) to exit', nvim_proc.pid);
80-
}
81-
console.log('Nvim exit code: %d', nvim_proc.exitCode);
82-
})();
83-
```
50+
- `$ALLOW_CONSOLE` env var must be set, because logs are normally not printed to stdout.
51+
- Script:
52+
```js
53+
import * as child_process from 'node:child_process'
54+
import * as assert from 'node:assert'
55+
import { attach, findNvim } from 'neovim'
56+
57+
// Find `nvim` on the system and open a channel to it.
58+
(async function() {
59+
const found = findNvim({ orderBy: 'desc', minVersion: '0.9.0' })
60+
console.log(found);
61+
const nvim_proc = child_process.spawn(found.matches[0].path, ['--clean', '--embed'], {});
62+
63+
const nvim = attach({ proc: nvim_proc });
64+
nvim.command('vsp | vsp | vsp');
65+
66+
const windows = await nvim.windows;
67+
assert.deepStrictEqual(windows.length, 4);
68+
assert.ok(windows[0] instanceof nvim.Window);
69+
70+
nvim.window = windows[2];
71+
const win = await nvim.window;
72+
assert.ok(win.id !== windows[0].id);
73+
assert.deepStrictEqual(win.id, windows[2].id);
74+
75+
const buf = await nvim.buffer;
76+
assert.ok(buf instanceof nvim.Buffer);
77+
const lines = await buf.lines;
78+
assert.deepStrictEqual(lines, []);
79+
80+
await buf.replace(['line1', 'line2'], 0);
81+
const newLines = await buf.lines;
82+
assert.deepStrictEqual(newLines, ['line1', 'line2']);
83+
84+
// console.log('%O', nvim_proc);
85+
if (nvim_proc.disconnect) {
86+
nvim_proc.disconnect();
87+
}
88+
nvim.quit();
89+
while (nvim_proc.exitCode === null) {
90+
await new Promise(resolve => setTimeout(resolve, 100))
91+
console.log('waiting for Nvim (pid %d) to exit', nvim_proc.pid);
92+
}
93+
console.log('Nvim exit code: %d', nvim_proc.exitCode);
94+
})();
95+
```
8496

8597
### Create a remote plugin
8698

@@ -94,8 +106,6 @@ The plugin must export a function which takes a `NvimPlugin` object as its only
94106
**Avoid heavy initialisation or async functions at this stage,** because Nvim may only be collecting information about your plugin without wishing to actually use it.
95107
Instead, wait for one of your autocmds, commands or functions to be called before starting any processing.
96108
97-
The host replaces `console` with a `winston` interface, so `console.log` will call `winston.info`.
98-
99109
### Remote plugin examples
100110
101111
See [`examples/`](https://github.com/neovim/node-client/tree/master/examples) for remote plugin examples.
@@ -169,7 +179,7 @@ For debugging and configuring logging, you can set the following environment var
169179
170180
- `NVIM_NODE_HOST_DEBUG`: Spawns the node process that calls `neovim-client-host` with `--inspect-brk` so you can have a debugger.
171181
Pair that with this [Node Inspector Manager Chrome plugin](https://chrome.google.com/webstore/detail/nodejs-v8-inspector-manag/gnhhdgbaldcilmgcpfddgdbkhjohddkj?hl=en)
172-
- Logging: Logging is done using `winston` through the `logger` module. Plugins have `console` replaced with this interface.
182+
- Logging: Logging is done using `winston` through the `logger` module. This package replaces `console` with this interface.
173183
- `NVIM_NODE_LOG_LEVEL`: Sets the logging level for winston. Default is `debug`.
174184
Available levels: `{ error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5 }`
175185
- `NVIM_NODE_LOG_FILE`: Sets the log file path.
@@ -190,6 +200,14 @@ For debugging and configuring logging, you can set the following environment var
190200
191201
See the tests and [`scripts`](https://github.com/neovim/node-client/tree/master/packages/neovim/scripts) for more examples.
192202
203+
## Develop
204+
205+
After cloning the repo, run `npm install` to install dev dependencies. The main `neovim` library is in `packages/neovim`.
206+
207+
### Run tests
208+
209+
npm run build && NVIM_NODE_LOG_FILE=log npm run test
210+
193211
## Maintain
194212
195213
### Release
@@ -232,11 +250,7 @@ git commit -m 'publish docs'
232250
git push origin HEAD:gh-pages
233251
```
234252
235-
## Contributing
236-
237-
After cloning the repo, run `npm install` to install dev dependencies. The main `neovim` library is in `packages/neovim`.
238-
239-
### Contributors
253+
## Contributors
240254
241255
* [@billyvg](https://github.com/billyvg) for rewrite
242256
* [@mhartington](https://github.com/mhartington) for TypeScript rewrite

package-lock.json

Lines changed: 1 addition & 58 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/integration-tests/CHANGELOG.md

Lines changed: 0 additions & 16 deletions
This file was deleted.

packages/integration-tests/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TODO: why is this a separate project? move this to packages/neovim

packages/integration-tests/__tests__/integration.test.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import * as fs from 'fs';
44
import * as path from 'path';
55
import * as http from 'http';
66

7-
import { attach } from 'neovim';
7+
import { NeovimClient, attach, findNvim } from 'neovim';
88

99
describe('Node host', () => {
1010
const testdir = process.cwd();
11-
let proc;
11+
let proc: cp.ChildProcessWithoutNullStreams;
1212
let args;
13-
let nvim;
13+
let nvim: NeovimClient;
1414

1515
beforeAll(async () => {
1616
const plugdir = path.resolve(__dirname);
@@ -36,10 +36,18 @@ describe('Node host', () => {
3636
let g:node_host_prog = '${path.resolve(plugdir, '../../neovim/bin/cli')}'
3737
`
3838
);
39-
cp.spawnSync('nvim', args);
39+
40+
const minVersion = '0.9.5'
41+
const nvimInfo = findNvim({ minVersion: minVersion });
42+
const nvimPath = nvimInfo.matches[0]?.path;
43+
if (!nvimPath) {
44+
throw new Error(`nvim ${minVersion} not found`)
45+
}
46+
47+
cp.spawnSync(nvimPath, args);
4048

4149
proc = cp.spawn(
42-
'nvim',
50+
nvimPath,
4351
['-u', nvimrc, '-i', 'NONE', '--headless', '--embed', '-n'],
4452
{}
4553
);
@@ -65,6 +73,14 @@ describe('Node host', () => {
6573
// done();
6674
// });
6775

76+
it('console.log is monkey-patched to logger.info #329', async () => {
77+
const spy = jest.spyOn(nvim.logger, 'info');
78+
console.log('log message');
79+
expect(spy).toHaveBeenCalledWith('log message');
80+
// Still alive?
81+
expect(await nvim.eval('1+1')).toEqual(2);
82+
});
83+
6884
it('can run a command from plugin', async () => {
6985
await nvim.command('JSHostTestCmd');
7086
const line = await nvim.line;

packages/neovim/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,12 @@
5959
"@babel/preset-typescript": "^7.23.3",
6060
"@types/jest": "^29.5.12",
6161
"@types/node": "16.9.x",
62-
"@types/which": "^3.0.3",
6362
"babel-jest": "^29.7.0",
6463
"jest": "^29.7.0",
6564
"jest-haste-map": "^29.7.0",
6665
"jest-resolve": "^29.6.1",
6766
"typedoc": "^0.25.7",
68-
"typescript": "^5.3.3",
69-
"which": "^4.0.0"
67+
"typescript": "^5.3.3"
7068
},
7169
"scripts": {
7270
"doc": "typedoc --out doc --exclude '**/*.test.ts' src",
@@ -88,6 +86,9 @@
8886
"json",
8987
"node"
9088
],
89+
"setupFilesAfterEnv": [
90+
"<rootDir>/src/testSetup.ts"
91+
],
9192
"testEnvironment": "node",
9293
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.ts$",
9394
"coverageDirectory": "./coverage/",

0 commit comments

Comments
 (0)