Skip to content

Fix escaping issue for shell commands #401

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

arntanguy
Copy link

I am using overseer.nvim in conjunction with cmake-tools.nvim.
In cmake-tools I defined a task as

{       
  cmake_command = "source /home/ubuntu/setup.sh && cmake", -- I am doing cross compilation and need specific $PATH and such
  cmake_generate_options = { "-DCMAKE_EXPORT_COMPILE_COMMANDS=1", "-GNinja", " -DCMAKE_C_COMPILER_LAUNCHER=ccache", "-DCMAKE_CXX_COMPILER_LAUNCHER=ccache" }
}

from which cmake-tasks constructs an overseer task, so far so good. However, the following command gets escaped by overseer, and ends up being sent to the shell (bash) as

'source /home/ubuntu/setup.sh && cmake' -B /home/arnaud/devel/fotowall/build/Debug -S . -D CMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -GNinja

which obviously does not work: the command is escaped out between single quotes '...'.

FAILURE: 'source /home/ubuntu/setup.sh && cmake' -B /home/arnaud/devel/fotowall/build/Debug -S . -D CMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -GNinja
out: zsh:1: no such file or directory: source /home/ubuntu/setup.sh && cmake

A simple way to simulate this failure is to run bash -c "'echo test1' && echo test2" in a terminal, which gives bash: line 1: echo test1: command not found

The patch in this PR removes escaping of the command, and leaves it for the arguments. This works in this case, but I am unsure if it might break other use cases.

@github-actions github-actions bot requested a review from stevearc February 3, 2025 18:47
@stevearc
Copy link
Owner

This is a tricky edge case that is not well documented, so apologies for that. As you have discovered, when you pass in a string for the command it is run in the shell, but that still gets escaped. However, what you may not have noticed is that the escaping only happens if you also pass in args.

if opts.args then
local cmd = opts.cmd
if type(cmd) == "string" then
local full_cmd = vim.list_extend({ cmd }, opts.args or {})
opts.cmd = shell.escape_cmd(full_cmd)
else
cmd = vim.deepcopy(cmd)
opts.cmd = vim.list_extend(cmd, opts.args)
end
end

Is it possible for you to pass all of those arguments in with the command string? If so, that should solve your issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants