akinsho / toggleterm.nvim

A neovim lua plugin to help easily manage multiple terminal windows
GNU General Public License v3.0
4.21k stars 170 forks source link

Is it possible to include double quotes in the `cmd` argument? #508

Open reidprichard opened 10 months ago

reidprichard commented 10 months ago

I run Windows, and due to organizational constraints I'm forced to have spaces in my directories. I frequently want to execute the open Python file with TermExec cmd="python %". As you can imagine, this causes issues if % expands to a path with a space, as you get e.g.:

python C:/this/is the/file/path.py Can't open file 'C:/this/is': no such file or directory.

I've tried every which way to escape quotes, mixing single and double quotes, escaping spaces with backslashes/backticks, etc., but I'm getting nowhere. Using the dir argument to TermExec works if the terminal is not open yet, but it will not change the working directory if there's an open terminal already.

Thoughts?

Ajaymamtora commented 4 months ago

Got it working using this code:

        open_in_terminal = function(state)
          local node = state.tree:get_node()
          local path = node:get_id()
          path = path:gsub(" ", "\\ ")
          local the_cmd = string.format([[1TermExec cmd="cd %s"]], path)
          vim.cmd(the_cmd)
          print("Opening terminal in " .. tostring(path))
        end,
mooreye commented 3 months ago

I'm looking for a solution to a broader problem, namely I want to execute the currently opened file in terminal: :TermExec cmd='./%' but this fails if filename contains any shell special characters, not just spaces but also things like ' " $ etc. Is there a way to pass a shell-escaped filename to cmd=?

reidprichard commented 3 months ago

Can't you just surround the filename in quotes?

mooreye commented 3 months ago

Can't you just surround the filename in quotes?

No, that won't work for cases when " is part of the filename, and will also try to expand variables if filename contains something like $foo.

The best way to escape would be to wrap the whole name in ', and change every ' to '\''. The shellescape() function can do it, but I know nothing about Lua myself.

reidprichard commented 3 months ago

Oh, duh. Here's my code to run the current file as a Python script. I don't specially handle anything but spaces, but hopefully this is a useful starting point. I wasn't aware of the shellescape() function, but I think you could just switch it out for my gsub call.

local function run_python()
  vim.cmd.write()
  print("Running...")
  local script_path = vim.fn.expand("%:p"):gsub(" ", "\\ ")
  local command = "python \"" .. script_path .. "\""
  toggleterm.exec(command)
end

Note that this (being Lua) would need to be in your nvim config and assigned a keymap.