dart-lang / dart-lang/dart-vim-plugin

job_start is incompatible with neovim

Open
#153 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
Vim Script
Stars
653
Forks
51
PR merge metrics
No merged PRs in 30d

Description

Unfortunately vim and neovim have different job APIs. In vim it's `job_start`, and in neovim it's `jobstart`. Since 5d8f54c when this plugin moved to `job_start`, this plugin stopped working for neovim.

Here's an initial attempt to resolve it:

```
if has('nvim')
let l:options = {
\ 'on_stdout': { id, data, event -> extend(l:stdout_data, data) },
\ 'on_stderr': { id, data, event -> extend(l:stderr_data, data) },
\ 'on_exit': { id, code, event ->
\ s:formatResult(l:stdout_data, l:stderr_data, l:buffer_content)} }
let l:job = jobstart(l:cmd, l:options)
call chansend(l:job, join(l:buffer_content, "\n") . "\n")
call chanclose(l:job, 'stdin')
else
let l:job = job_start(l:cmd, l:options)
call ch_sendraw(job_getchannel(l:job), join(l:buffer_content, "\n"))
call ch_close_in(job_getchannel(l:job))
endif
```

However, it ends up writing the buffer BEFORE the formatted code is applied to the buffer. With a bit of hackery, I got it to work with:

```
function! s:FormatOnSave()
" Dart code formatting on save
if get(g:, 'dart_format_on_save', 0)
if has('nvim')
if get(b:, 'dart_formatting_for_save', 0)
return
endif
let b:dart_formatting_for_save = 1
endif
call dart#fmt()
endif
endfunction
```

and

```
function! s:onNvimFormatExit(stdout_data, stderr_data, buffer_content) abort
call s:formatResult(a:stdout_data, a:stderr_data, a:buffer_content)
if get(b:, 'dart_formatting_for_save', 0)
let b:dart_formatting_for_save = 0
noautocmd write
endif
endfunction

function! dart#fmt(...) abort
...
if has('nvim')
let l:options = {
\ 'on_stdout': { id, data, event -> extend(l:stdout_data, data) },
\ 'on_stderr': { id, data, event -> extend(l:stderr_data, data) },
\ 'on_exit': { id, code, event ->
\ s:onNvimFormatExit(l:stdout_data, l:stderr_data, l:buffer_content)} }
let l:job = jobstart(l:cmd, l:options)
call chansend(l:job, join(l:buffer_content, "\n") . "\n")
call chanclose(l:job, 'stdin')
else
let l:job = job_start(l:cmd, l:options)
call ch_sendraw(job_getchannel(l:job), join(l:buffer_content, "\n"))
call ch_close_in(job_getchannel(l:job))
endif
endfunction
```

I acknowledge it's messy but I don't have the time to work on it further, so feel free to adapt the code. I declare my contributions as public domain.

Contributor guide

Open the contributing guide

Research direction

Start at dart#fmt and s:FormatOnSave, then compare the proposed jobstart/chansend/chanclose path with the job_start/job_getchannel path. Done means Dart formatting on save works in both Vim and Neovim, with the formatted buffer written only after formatting completes.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, vim
Domain
developer-experience, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.