Recommended development flow with Vim and terminal

Hi there!

I’m a lazy butt so used ReasonML/ReScript for a few years without any bells and whistles (other than syntax highlight) using nvim + terminal. Now NeoVim 0.5 is out and it provides LSP support out of the box, so I recently set up the newest plugin and LSP. Works like a charm! I’m feeling myself over all those VSCode valetry again :grin: (just a joke). Kudos to @ryyppy!

But one anoying thing I cannot mange is the conflict between the language server inside NVim and the compiler in the terminal. The typical way I develop is running a continuous parallel process in the terminal like:

.PHONY: dev
dev:
	yarn concurrently \
	  --names "rescript,next----" \
	  --kill-others \
	  "$(BSB_FORCE_COLOR) -clean -make-world -w" \
	  "$(NEXT) dev --port 7700"

…and once I run it, it either fails to acquire .bsb.lock or it starts and LSP in NVim dies. So, obviously, they both want the exclusive rights for the compiler, and one who loses the race will suffer.

So, dear vimmers out there, what is the way you develop? Is there any way to have a running LSP and the watching terminal at the same time?

The langauge server doesn’t start build process if you already ran it in terminal so my workflow is like this.
I start a terminal to run rescript build prcess, a terminal running next js’s dev server and another terminal running nvim and i’m quite happy with this.

Doesn’t work for me, unfortunately.

After LSP client dies when running the compiler with -w in a terminal (see status line). I can no longer see auto-completions after C-x-o and other LSP goodness.

Can you paste the logs related to language server?
the log file lives here in linux

~/.cache/nvim/lsp.log

I see a repeating pattern there:

[ START ] 2021-08-13T23:14:55+0300 ] LSP logging initiated
[ ERROR ] 2021-08-14T01:24:26+0300 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ]	"rpc"	"node"	"stderr"	"node:internal/fs/utils:343\n    throw err;\n    ^\n\nError: ENOENT: no such file or directory, open '/home/nkrkv/devel/amperka-hq/amperka-cut/packages/cut-app/lib/bs/.compiler.log'\n    at Object.openSync (node:fs:582:3)\n    at Object.readFileSync (node:fs:450:35)\n    at /home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:53:36\n    at Map.forEach (<anonymous>)\n    at sendUpdatedDiagnostics (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:52:19)\n    at FSWatcher.<anonymous> (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:115:5)\n    at FSWatcher.emit (node:events:394:28)\n    at /home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/node_modules/chokidar/index.js:576:16\n    at Map.forEach (<anonymous>)\n    at Timeout._onTimeout (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/node_modules/chokidar/index.js:574:30) {\n  errno: -2,\n  syscall: 'open',\n  code: 'ENOENT',\n  path: '/home/nkrkv/devel/amperka-hq/amperka-cut/packages/cut-app/lib/bs/.compiler.log'\n}\n"
[ ERROR ] 2021-08-14T01:25:41+0300 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ]	"rpc"	"node"	"stderr"	"node:internal/fs/utils:343\n    throw err;\n    ^\n\nError: ENOENT: no such file or directory, open '/home/nkrkv/devel/amperka-hq/amperka-cut/packages/cut-app/lib/bs/.compiler.log'\n    at Object.openSync (node:fs:582:3)\n    at Object.readFileSync (node:fs:450:35)\n    at /home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:53:36\n    at Map.forEach (<anonymous>)\n    at sendUpdatedDiagnostics (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:52:19)\n    at FSWatcher.<anonymous> (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:115:5)\n    at FSWatcher.emit (node:events:394:28)\n    at /home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/node_modules/chokidar/index.js:576:16\n    at Map.forEach (<anonymous>)\n    at Timeout._onTimeout (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/node_modules/chokidar/index.js:574:30) {\n  errno: -2,\n  syscall: 'open',\n  code: 'ENOENT',\n  path: '/home/nkrkv/devel/amperka-hq/amperka-cut/packages/cut-app/lib/bs/.compiler.log'\n}\n"
[ ERROR ] 2021-08-14T11:25:17+0300 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ]	"rpc"	"node"	"stderr"	"node:fs:582\n  handleErrorFromBinding(ctx);\n  ^\n\nError: ENOENT: no such file or directory, open '/home/nkrkv/devel/amperka-hq/amperka-cut/packages/cut-app/lib/bs/.compiler.log'\n    at Object.openSync (node:fs:582:3)\n    at Object.readFileSync (node:fs:450:35)\n    at /home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:53:36\n    at Map.forEach (<anonymous>)\n    at sendUpdatedDiagnostics (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:52:19)\n    at FSWatcher.<anonymous> (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:115:5)\n    at FSWatcher.emit (node:events:394:28)\n    at FSWatcher.emitWithAll (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/node_modules/chokidar/index.js:535:32)\n    at FSWatcher._emit (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/node_modules/chokidar/index.js:626:8)\n    at FSWatcher._remove (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/node_modules/chokidar/index.js:889:50) {\n  errno: -2,\n  syscall: 'open',\n  code: 'ENOENT',\n  path: '/home/nkrkv/devel/amperka-hq/amperka-cut/packages/cut-app/lib/bs/.compiler.log'\n}\n"

The errors happen exactly at the moments when I run the compiler in a terminal while LSP client is being running within NVim.

Here’s one of these errors better formatted:

[ ERROR ] 2021-08-14T11:25:17+0300 ] /usr/share/nvim/runtime/lua/vim/lsp/rpc.lua:462 ]	"rpc"	"node"	"stderr"	"node:fs:582
  handleErrorFromBinding(ctx);
  ^

Error: ENOENT: no such file or directory, open '/home/nkrkv/devel/amperka-hq/amperka-cut/packages/cut-app/lib/bs/.compiler.log'
    at Object.openSync (node:fs:582:3)
    at Object.readFileSync (node:fs:450:35)
    at /home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:53:36
    at Map.forEach (<anonymous>)
    at sendUpdatedDiagnostics (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:52:19)
    at FSWatcher.<anonymous> (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/out/server.js:115:5)
    at FSWatcher.emit (node:events:394:28)
    at FSWatcher.emitWithAll (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/node_modules/chokidar/index.js:535:32)
    at FSWatcher._emit (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/node_modules/chokidar/index.js:626:8)
    at FSWatcher._remove (/home/nkrkv/.local/share/nvim/plugged/vim-rescript/server/node_modules/chokidar/index.js:889:50) {
  errno: -2,
  syscall: 'open',
  code: 'ENOENT',
  path: '/home/nkrkv/devel/amperka-hq/amperka-cut/packages/cut-app/lib/bs/.compiler.log'
}
"

This is strange, please open an issue in rescript-vscode.
would be good if you check it’s happening on vscode too or not.

I’ve tried to make a minimal reproducible example (a fresh trivial project, latest rescript, etc), and got some observations. Things happening depend on the order.

Scenario #1

  1. Start compiler in the terminal (rescript build -w)
  2. Run NVim

Everything just works like it should in the minimal project and my complex project. Now I understand that my programming sessions always followed another scenario.

Scenario #2

  1. Run NVim and open a .res file
  2. NVim asks “Start a build for this project to get the freshest data?”, I agree
  3. I write some code and now its time to check the result, I start the compiler in terminal
  4. The terminal compiler fails to start telling:
Error: could not acquire lockfile /home/nkrkv/devel/playground/rescript-lsp-test/.bsb.lock
Could be another process running in the background 
Either kill that process or delete the staled lock
Try run command:  `kill  161577  || rm -f .bsb.lock`

5a (simple project). Start the compiler again. In the simple project, the error about .bsb.lock happens again and again. So I cannot start the compiler at all until I exec :LspStop in NVim. Then I can start the terminal compiler, exec :LspStart, and since this moment everything goes fine.

5b (complex project). Start the compiler again. It starts successfully stealing .bsb.lock and LSP client dies inside NVim at the same moment. Trying to edit .res file again in NVim asks “Start a build for this project to get the freshest data?” again and if I confirm, the client dies immediately, and things happen as I described previously.

My project differs in that it uses a slightly older ReScript version ("bs-platform": "^9.0.2"), it is a monorepo using Yarn workspaces, and I use Makefiles to run tasks. I cannot quickly test what component is in charge for the difference in behavior to make a sane bug report right now, but if someone struggles the same way…

Rule of thumb

Start the compiler in a terminal first and only after that start your NVim.

This sequence guarantees LSP will just work in any case.