TransWikia.com

Why does system(cmd) append ^@ to its output?

Vi and Vim Asked on February 15, 2021

I want to set node’s executable path for neovim. So I have added this line in init.vim.

let g:coc_node_path = system('which node')

But when I open nvim I get this error.

[coc.nvim] "/home/akash/.nvm/versions/node/v15.5.0/bin/node^@" is not executable, checkout https://nodejs.org/en/download

But if I edit the path manually,

let g:coc_node_path = '/home/akash/.nvm/versions/node/v15.5.0/bin/node'

then it works fine. So why does system('which node') append ^@ to its output?

2 Answers

What a coincidence. I encountered this exact same thing a few hours before you posted this. I just figured it was a line-ending issue and solved it by wrapping the system() call in a call to trim().

Since you mentioned it I since verified that the cause is the presence of a newline in the output of system().

So you can solve this with a trim() call that directly addresses the problem like so...

trim(system(...), "n")

If you are using an older version of Vim which doesn't have trim() you can use something like this instead...

let foo = system(...)
let foo = strcharpart(foo, 0, strchars(foo)-1))

Or this...

let foo = substitute(system(...), "n$", "", "")

Update: I should point out that this isn't a bug or anything. When running a command from the shell you'll get a newline at the end and that's expected. system() does the right thing and passes everything back to the caller. It just so happens that there's a fairly common use case, assigning the result to a variable, where we don't want that newline.

(Note: One thing that might not be expected is that Vim normalizes line-endings on non-unix systems so, for example, Windows CRLF becomes LF. It makes sense but one needs to be aware of it.)

Correct answer by B Layer on February 15, 2021

What you're seeing is the newline at the end of the command, as @BLayer's answer states.

A better approach for this specific case of finding a binary would be to use the Vimscript function exepath() here instead of shelling out to the which command:

let g:coc_node_path = exepath('node')

This is more efficient (since it doesn't need to spawn an external process) and ends up avoiding the issue with the newline altogether.

Answered by filbranden on February 15, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP