Transforming program arguments to JSON
Nobody has claimed this yet.
- Dominant language
- Vim Script
- Stars
- 3.2k
- Forks
- 411
- Avg merge
- 1h 30m
- Merged PRs (30d)
- 5
Description
Hello. I have used vim-test for a long time now and it has made testing in vim a real joy, thank you for this plugin.
I have recently started trying to get a debugger into my testing workflow when running tests with neovim, and found vimspector. It works surprisingly well, and I thought I would try to get something working so I can use it with the convenience of vim-test.
vimspector uses the vscode-node debug adapter for javascript/typescript tests. In practice, this means I need to configure how the test is invoked by modifying a file in the working directory, .vimspector.json, that looks similar to vscode's launch.json, i.e. something like this:
{
"configurations": {
"run": {
"adapter": "vscode-node",
"configuration": {
"request": "launch",
"protocol": "auto",
"stopOnEntry": true,
"console": "integratedTerminal",
"program": "${workspaceRoot}/node_modules/.bin/jest",
"args": ["--", "./src/test.js"],
"cwd": "${workspaceRoot}"
}
}
}
}
In short I need to convert the test command to program and args values.
I tried my hand at integrating a vim-test custom strategy:
function VimTestVimspectorStrategy(cmd)
if !(filereadable(".vimspector.json"))
echo "No '.vimspector.json' found, starting with vscode-node sample"
system('cp ~/.vimspector.json.sample ./.vimspector.json')
endif
let l:vimspector_config = json_decode(join(readfile('.vimspector.json')))
" Assign program
let l:program = split(a:cmd, ' ')[0]
let l:vimspector_config['configurations']['run']['configuration']['program'] =
\ '${workspaceFolder}/' . l:program
" Assign program_args
" Remove the program from the string
let l:program_args = join(split(a:cmd, " ")[1:], " ")
" split by spaces unless within quotes. No good way to do this with vimscript
" TODO: is this escaping enough?
let l:split_cmd = 'printf "%s" "' . escape(l:program_args, '"') . '" | xargs -n 1 printf "%s\n"'
let l:print_output = system(l:split_cmd)
let l:program_args = split(l:print_output, "\n")
" Re-quote strings with spaces in them
call map(l:program_args, { _, arg -> match(arg, ' ') >= 0 ? "'" . arg . "'" : arg })
let l:vimspector_config['configurations']['run']['configuration']['args'] = l:program_args
call writefile(split(json_encode(l:vimspector_config), "\n"), glob('.vimspector.json'), 'b')
" Start the debugger
call vimspector#Continue()
endfunction
let g:test#custom_strategies = {
\ ...
\ 'vimspector': function('VimTestVimspectorStrategy'),
\ }
nnoremap <space>dn :TestNearest -strategy=vimspector<CR>
nnoremap <space>df :TestFile -strategy=vimspector<CR>
nnoremap <space>ds :TestSuite -strategy=vimspector<CR>
A bit scrappy, but it works! Since I needed the program arguments to be a JSON array, splitting the single a:cmd into this array was very difficult since it can include search patterns wrapped in quotes, for example:
echo a:cmd
" node_modules/.bin/jest --no-coverage -t '^this is a test name$' -- src/example/vimspector.test.ts
into
{
"configurations": {
"run": {
"configuration": {
...
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": [
"--no-coverage",
"-t",
"'^this is a test name$'",
"--",
"src/example/vimspector.test.ts"
],
...
}
}
}
What I'm wondering is, is there any better approach for this? Is there some API where I could receive the program arguments as a list before they are joined together into 1 string? For example if the custom_strategies dictionary could use a special token in the key to indicate that the parameters are passed as a list instead of a joined string. For example:
let g:test#custom_strategies = {
\ 'vimspector*': function('VimTestVimspectorStrategy'),
\ }
(fzf does something similar, by allowing users to specify a sink or sink* key to fzf#run() function to change how the callback function is invoked).
However I suppose this wouldn't work with the :TestNearest --strategy=vimspector syntax? Not quite sure, just throwing it out there.
Any guidance is highly appreciated, thanks for your time.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The issue names custom_strategies and the :TestNearest, :TestFile, and :TestSuite entry points; start by tracing how these commands invoke a strategy and turn command arguments into a:cmd. Compare that path with the requested list-preserving callback behavior. Done means a strategy can receive program arguments as a JSON-ready list while preserving existing --strategy=vimspector usage and the quoted-argument examples.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- vim
- Domain
- testing, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100