Skip to content

fix #147 white-space bug in by shellescape-ing all variable substitutions#148

Merged
CRAG666 merged 1 commit intoCRAG666:mainfrom
aditya-an1l:main
Mar 10, 2026
Merged

fix #147 white-space bug in by shellescape-ing all variable substitutions#148
CRAG666 merged 1 commit intoCRAG666:mainfrom
aditya-an1l:main

Conversation

@aditya-an1l
Copy link
Contributor

Aims to fix the issue #147

The root cause of the issue lies in the lua/code_runner/utils.lua file, where, the replaceVars function substitutes $fileName, $file, $dir, and $fileNameWithoutExt variables directly into the shell command string without quoting:

-- Current code (broken for paths with spaces)
local file_info = {
  nameWithoutExt = vim.fn.fnamemodify(path, ":t:r"),
  name = vim.fn.fnamemodify(path, ":t"),
  dir = vim.fn.fnamemodify(path, ":p:h")
}

When any of these values contains a space, the shell tokenises the resulting command incorrectly. The same issue affects the fallback path-append at the bottom of replaceVars when no $var substitution is matched.

Major changes made

All file path values substituted into shell commands in replaceVars are now wrapped with vim.fn.shellescape(). This ensures paths containing spaces (or other shell-special characters) are treated as single arguments by the shell.

The issue was resolved by shellescape-ing variables, since functions like vim.fn.shellescape() is Neovim's built-in shell quoting function. It wraps the value in single quotes and escapes any single quotes within the value.

File: lua/code_runner/code_runner.luaM.run_code function

1. Shellescape the bufname passed to runMode

-- BEFORE
utils:runMode(cmd_to_execute, vim.fn.expand("%:t:r"))

-- AFTER
local filename = vim.fn.shellescape(vim.fn.expand("%:t:r"))
utils:runMode(cmd_to_execute, filename)

This is where the path first enters the execution pipeline. vim.fn.expand("%:t:r") returns the raw filename stem (e.g. my file) with no quoting. The shell then splits it into separate tokens. Wrapping it with vim.fn.shellescape() before it is passed to runMode ensures it is treated as a single argument.

File: lua/code_runner/utils.luareplaceVars function

2. Quote file_info values

-- BEFORE
local file_info = {
  nameWithoutExt = vim.fn.fnamemodify(path, ":t:r"),
  name = vim.fn.fnamemodify(path, ":t"),
  dir = vim.fn.fnamemodify(path, ":p:h")
}

-- AFTER
local file_info = {
  nameWithoutExt = vim.fn.shellescape(vim.fn.fnamemodify(path, ":t:r")),
  name = vim.fn.shellescape(vim.fn.fnamemodify(path, ":t")),
  dir = vim.fn.shellescape(vim.fn.fnamemodify(path, ":p:h"))
}

3. Quote $file substitution (raw path variable)

-- BEFORE
elseif var == "file" then
  return path

-- AFTER
elseif var == "file" then
  return vim.fn.shellescape(path)

4. Quote fallback path append

-- BEFORE
if command == no_sub_command then
  command = command .. " " .. path
end

-- AFTER
if command == no_sub_command then
  command = command .. " " .. vim.fn.shellescape(path)
end

All in all, this fix covers all touch points across both files: the runMode call in code_runner.lua, and all four substitution points in replaceVars : $fileNameWithoutExt, $fileName, $file, $dir.

@CRAG666 CRAG666 merged commit 90a986f into CRAG666:main Mar 10, 2026
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