From 016f1168aa5e5eca0b5a96ff9093151678b784de Mon Sep 17 00:00:00 2001 From: Erich L Foster Date: Wed, 24 Apr 2024 12:44:29 +0200 Subject: [PATCH 1/3] Add shell to DevcontainerExec --- README.md | 1 + lua/devcontainer_cli/config/init.lua | 14 ++++++++++---- lua/devcontainer_cli/devcontainer_utils.lua | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6bc96ae..0158460 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ make assumptions about how you work. dotfiles_branch = "main", -- branch to clone from dotfiles_repository` dotfiles_targetPath = "~/dotfiles", -- location to install dotfiles dotfiles_intallCommand = "install.sh", -- script to run after dotfiles are cloned + shell = "bash", -- shell to use when executing commands }, keys = { -- stylua: ignore diff --git a/lua/devcontainer_cli/config/init.lua b/lua/devcontainer_cli/config/init.lua index 1d12663..dedc76c 100644 --- a/lua/devcontainer_cli/config/init.lua +++ b/lua/devcontainer_cli/config/init.lua @@ -8,18 +8,24 @@ local default_config = { -- Folder where the nvim-devcontainer-cli is installed nvim_plugin_folder = file_path:gsub("init.lua", "") .. "../../../", -- Remove existing container each time DevcontainerUp is executed - -- If set to True [default_value] it can take extra time as you force to start from scratch + -- If set to True [default_value] it can take extra time as you force to + -- start from scratch remove_existing_container = true, - -- dependencies that have to be installed in the devcontainer (remoteUser = root) + -- dotfiles to be downloaded dotfiles_repository = "git@github.com:erichlf/dotfiles", - -- branch to checkout for repositories (this is a feature not supported by devcontainers in general, but we do) + -- branch to checkout for repositories (this is a feature not supported by + -- devcontainers in general, but we do) dotfiles_repository = "devcontainer", -- directory for the setup environment dotfiles_targetPath = "~/dotfiles", - -- command that's executed for installed the dependencies from the setup_environment_repo + -- command that's executed for installed the dependencies from the + -- setup_environment_repo dotfiles_installCommand = "install.sh", -- The number of columns to wrap text at terminal_columns = 80, + -- The shell to use for executing command. Available sh, bash, zsh or any + -- other that uses '-c' to signify a command is to follow + shell = 'bash', } local options diff --git a/lua/devcontainer_cli/devcontainer_utils.lua b/lua/devcontainer_cli/devcontainer_utils.lua index 3371b15..996d8bc 100644 --- a/lua/devcontainer_cli/devcontainer_utils.lua +++ b/lua/devcontainer_cli/devcontainer_utils.lua @@ -173,7 +173,7 @@ function M.exec_cmd(cmd, cwd) return end - command = command .. " " .. cmd + command = command .. " " .. config.shell .. " -c '" .. cmd .. "'" spawn_and_execute(command) end From ba9c5cc58b0409ef716d85f5d23c4d9c3fbfa499 Mon Sep 17 00:00:00 2001 From: Erich L Foster Date: Wed, 24 Apr 2024 13:29:34 +0200 Subject: [PATCH 2/3] Update docstrings --- lua/devcontainer_cli/devcontainer_cli.lua | 6 ++-- lua/devcontainer_cli/devcontainer_utils.lua | 32 ++++++++++----------- lua/devcontainer_cli/folder_utils.lua | 14 ++++----- lua/devcontainer_cli/init.lua | 2 +- lua/devcontainer_cli/windows_utils.lua | 12 ++++---- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/lua/devcontainer_cli/devcontainer_cli.lua b/lua/devcontainer_cli/devcontainer_cli.lua index a262781..b404d59 100644 --- a/lua/devcontainer_cli/devcontainer_cli.lua +++ b/lua/devcontainer_cli/devcontainer_cli.lua @@ -20,7 +20,7 @@ local function define_autocommands() end -- executes a given command in the devcontainer of the current project directory --- @param opts options for executing the command +---@param opts options for executing the command function M.exec(opts) cwd = vim.loop.cwd() @@ -37,9 +37,9 @@ function M.up() devcontainer_utils.bringup(vim.loop.cwd()) end +-- Thanks to the autocommand executed after leaving the UI, after closing the +-- neovim window the devcontainer will be automatically open in a new terminal function M.connect() - -- Thanks to the autocommand executed after leaving the UI, after closing the - -- neovim window the devcontainer will be automatically open in a new terminal define_autocommands() vim.cmd("wqa") end diff --git a/lua/devcontainer_cli/devcontainer_utils.lua b/lua/devcontainer_cli/devcontainer_utils.lua index 996d8bc..d66d302 100644 --- a/lua/devcontainer_cli/devcontainer_utils.lua +++ b/lua/devcontainer_cli/devcontainer_utils.lua @@ -17,7 +17,7 @@ local on_detach = function() end -- on_fail callback --- @param exit_code the exit code from the failed job +---@param exit_code the exit code from the failed job local on_fail = function(exit_code) vim.notify( "Devcontainer process has failed! exit_code: " .. exit_code, @@ -33,9 +33,9 @@ end -- on_exit callback function to delete the open buffer when devcontainer exits -- in a neovim terminal --- @param job_id the id of the running job --- @param code the exit code --- @param event thrown by job +---@param job_id the id of the running job +---@param code the exit code +---@param event thrown by job local on_exit = function(job_id, code, event) if code == 0 then on_success() @@ -46,7 +46,7 @@ local on_exit = function(job_id, code, event) end --- execute command --- @param cmd the command to execute in the devcontainer terminal +---@param cmd the command to execute in the devcontainer terminal local function exec_command(cmd) vim.fn.termopen( cmd, @@ -66,7 +66,7 @@ local function exec_command(cmd) end -- create a new window and execute the given command --- @param cmd the command to execute in the devcontainer terminal +---@param cmd the command to execute in the devcontainer terminal function spawn_and_execute(cmd) prev_win = vim.api.nvim_get_current_win() win, buffer = windows_utils.open_floating_window() @@ -74,11 +74,11 @@ function spawn_and_execute(cmd) end -- build the initial part of a devcontainer command --- @param action the action for the devcontainer to perform +---@param action the action for the devcontainer to perform -- (see man devcontainer) --- @param cwd the current working directory. Used as a starting place to find +---@param cwd the current working directory. Used as a starting place to find -- .devcontainer directory --- @return nil if no devcontainer_parent could be found otherwise +---@return nil if no devcontainer_parent could be found otherwise -- the basic devcontainer command for the given type local function devcontainer_command(action, cwd) devcontainer_root = folder_utils.get_root(cwd) @@ -94,9 +94,9 @@ local function devcontainer_command(action, cwd) end -- helper function to generate devcontainer bringup command --- @param cwd the current working directory. Used as a starting place to find +---@param cwd the current working directory. Used as a starting place to find -- .devcontainer directory --- @return nil if no devcontainer_parent could be found otherwise the +---@return nil if no devcontainer_parent could be found otherwise the -- devcontainer bringup command local function get_devcontainer_up_cmd(cwd) local command = devcontainer_command("up", cwd) @@ -132,7 +132,7 @@ local function get_devcontainer_up_cmd(cwd) end -- issues command to bringup devcontainer --- @param cwd the current working directory. Used as a starting place to find +---@param cwd the current working directory. Used as a starting place to find -- .devcontainer directory function M.bringup(cwd) local command = get_devcontainer_up_cmd(cwd) @@ -164,8 +164,8 @@ function M.bringup(cwd) end -- execute the given cmd within the given devcontainer_parent --- @param cmd the command to issue in the devcontainer terminal --- @param cwd the current working directory. Used as a starting place to find +---@param cmd the command to issue in the devcontainer terminal +---@param cwd the current working directory. Used as a starting place to find -- .devcontainer directory function M.exec_cmd(cmd, cwd) command = devcontainer_command("exec", cwd) @@ -178,9 +178,9 @@ function M.exec_cmd(cmd, cwd) end -- execute a given cmd within the given devcontainer_parent --- @param cwd the current working directory. Used as a starting place to find +---@param cwd the current working directory. Used as a starting place to find -- .devcontainer directory --- @param devcontainer_parent the location guess for .devcontainer directory +---@param devcontainer_parent the location guess for .devcontainer directory function M.exec(cwd) vim.ui.input( {prompt="Enter command:"}, diff --git a/lua/devcontainer_cli/folder_utils.lua b/lua/devcontainer_cli/folder_utils.lua index fab6eee..a6cc58d 100644 --- a/lua/devcontainer_cli/folder_utils.lua +++ b/lua/devcontainer_cli/folder_utils.lua @@ -6,8 +6,8 @@ local function directory_exists(target_folder) end -- get the devcontainer path for the given directory --- @param directory the directory containing .devcontainer --- @return directory if a devcontainer exists within it or nil otherwise +---@param directory the directory containing .devcontainer +---@return directory if a devcontainer exists within it or nil otherwise local function get_devcontainer_parent(directory) local devcontainer_directory = directory .. '/.devcontainer' @@ -19,10 +19,10 @@ local function get_devcontainer_parent(directory) end -- get the root directory the devcontainer given a directory --- @param directory to begin search in --- @param toplevel flag indicating if the directory closes to root should be +---@param directory to begin search in +---@param toplevel flag indicating if the directory closes to root should be -- returned --- @return the devcontainer directory closest to the root directory +---@return the devcontainer directory closest to the root directory -- or the first if toplevel is true, and nil if no directory was found local function get_root_directory(directory, toplevel) local parent_directory = vim.fn.fnamemodify(directory, ':h') @@ -49,9 +49,9 @@ end -- find the .devcontainer directory closes to the root upward from the current -- directory --- @param toplevel flag indicating if the directory closes to root should be +---@param toplevel flag indicating if the directory closes to root should be -- returned --- @return the devcontainer directory closest to the root directory +---@return the devcontainer directory closest to the root directory -- or the first if toplevel is true, and nil if no directory was found function M.get_root(toplevel) local current_directory = vim.fn.getcwd() diff --git a/lua/devcontainer_cli/init.lua b/lua/devcontainer_cli/init.lua index d0a2171..b23704a 100644 --- a/lua/devcontainer_cli/init.lua +++ b/lua/devcontainer_cli/init.lua @@ -5,7 +5,7 @@ local config = require("devcontainer_cli.config") local configured = false -- setup the devcontainer-cli plugin --- @param opts the options to set (see config/init.lua) +---@param opts the options to set (see config/init.lua) function M.setup(opts) config.setup(opts) diff --git a/lua/devcontainer_cli/windows_utils.lua b/lua/devcontainer_cli/windows_utils.lua index 3689dfc..1117de4 100644 --- a/lua/devcontainer_cli/windows_utils.lua +++ b/lua/devcontainer_cli/windows_utils.lua @@ -6,8 +6,8 @@ local M = {} local terminal_columns = config.terminal_columns -- wrap the given text at max_width --- @param text the text to wrap --- @return the text wrapped +---@param text the text to wrap +---@return the text wrapped function M.wrap_text(text) local wrapped_lines = {} for line in text:gmatch("[^\n]+") do @@ -26,8 +26,8 @@ function M.wrap_text(text) end -- create a floating window --- @param on_detach call back for when the window is detached --- @return the window and buffer numbers +---@param on_detach call back for when the window is detached +---@return the window and buffer numbers function M.open_floating_window(on_detach) local buf = vim.api.nvim_create_buf(false, true) vim.api.nvim_buf_set_option(buf, 'bufhidden', 'wipe') @@ -64,8 +64,8 @@ function M.open_floating_window(on_detach) end -- send text to the given buffer --- @param text the text to send --- @param buffer the buffer to send text to +---@param text the text to send +---@param buffer the buffer to send text to function M.send_text(text, buffer) local text = vim.split(wrap_text(text), "\n") From 717dce66d9b1e5edc3340866e1bc54e978db8e3d Mon Sep 17 00:00:00 2001 From: Erich L Foster Date: Thu, 25 Apr 2024 12:04:34 +0200 Subject: [PATCH 3/3] Fix docstrings and formatting, and follow lsp suggestions --- lua/devcontainer_cli/devcontainer_cli.lua | 8 +- lua/devcontainer_cli/devcontainer_utils.lua | 90 +++++++++------------ lua/devcontainer_cli/folder_utils.lua | 20 ++--- lua/devcontainer_cli/init.lua | 10 +-- lua/devcontainer_cli/windows_utils.lua | 26 +++--- 5 files changed, 70 insertions(+), 84 deletions(-) diff --git a/lua/devcontainer_cli/devcontainer_cli.lua b/lua/devcontainer_cli/devcontainer_cli.lua index b404d59..4f672ad 100644 --- a/lua/devcontainer_cli/devcontainer_cli.lua +++ b/lua/devcontainer_cli/devcontainer_cli.lua @@ -20,15 +20,13 @@ local function define_autocommands() end -- executes a given command in the devcontainer of the current project directory ----@param opts options for executing the command +---@param opts (table) options for executing the command function M.exec(opts) - cwd = vim.loop.cwd() - vim.validate({ args = { opts.args, "string" } }) if opts.args == nil or opts.args == "" then - devcontainer_utils.exec(cwd) + devcontainer_utils.exec() else - devcontainer_utils.exec_cmd(opts.args, cwd) + devcontainer_utils.exec_cmd(opts.args) end end diff --git a/lua/devcontainer_cli/devcontainer_utils.lua b/lua/devcontainer_cli/devcontainer_utils.lua index d66d302..8c8f363 100644 --- a/lua/devcontainer_cli/devcontainer_utils.lua +++ b/lua/devcontainer_cli/devcontainer_utils.lua @@ -17,26 +17,24 @@ local on_detach = function() end -- on_fail callback ----@param exit_code the exit code from the failed job +---@param exit_code (integer) the exit code from the failed job local on_fail = function(exit_code) vim.notify( - "Devcontainer process has failed! exit_code: " .. exit_code, - vim.log.levels.ERROR + "Devcontainer process has failed! exit_code: " .. exit_code, + vim.log.levels.ERROR ) vim.cmd("silent! :checktime") end local on_success = function() - vim.notify("Devcontainer process succeeded!", vim.log.levels.INFO) + vim.notify("Devcontainer process succeeded!", vim.log.levels.INFO) end --- on_exit callback function to delete the open buffer when devcontainer exits +-- on_exit callback function to delete the open buffer when devcontainer exits -- in a neovim terminal ----@param job_id the id of the running job ----@param code the exit code ----@param event thrown by job -local on_exit = function(job_id, code, event) +---@param code (integer) the exit code +local on_exit = function(_, code, _) if code == 0 then on_success() return @@ -46,19 +44,19 @@ local on_exit = function(job_id, code, event) end --- execute command ----@param cmd the command to execute in the devcontainer terminal +---@param cmd (string) the command to execute in the devcontainer terminal local function exec_command(cmd) vim.fn.termopen( - cmd, - { + cmd, + { on_exit = on_exit, - on_stdout = function(_, data, _) - vim .api.nvim_win_call( + on_stdout = function(_, _, _) + vim.api.nvim_win_call( win, function() vim.cmd("normal! G") end - ) + ) end, } ) @@ -66,22 +64,20 @@ local function exec_command(cmd) end -- create a new window and execute the given command ----@param cmd the command to execute in the devcontainer terminal -function spawn_and_execute(cmd) +---@param cmd (string) the command to execute in the devcontainer terminal +local function spawn_and_execute(cmd) prev_win = vim.api.nvim_get_current_win() - win, buffer = windows_utils.open_floating_window() + win, buffer = windows_utils.open_floating_window(on_detach) exec_command(cmd) end -- build the initial part of a devcontainer command ----@param action the action for the devcontainer to perform --- (see man devcontainer) ----@param cwd the current working directory. Used as a starting place to find --- .devcontainer directory ----@return nil if no devcontainer_parent could be found otherwise +---@param action (string) the action for the devcontainer to perform +-- (see man devcontainer) +---@return (string|nil) nil if no devcontainer_parent could be found otherwise -- the basic devcontainer command for the given type -local function devcontainer_command(action, cwd) - devcontainer_root = folder_utils.get_root(cwd) +local function devcontainer_command(action) + local devcontainer_root = folder_utils.get_root(config.toplevel) if devcontainer_root == nil then vim.notify("Unable to find devcontainer directory...", vim.log.levels.ERROR) return nil @@ -94,26 +90,24 @@ local function devcontainer_command(action, cwd) end -- helper function to generate devcontainer bringup command ----@param cwd the current working directory. Used as a starting place to find --- .devcontainer directory ----@return nil if no devcontainer_parent could be found otherwise the +---@return (string|nil) nil if no devcontainer_parent could be found otherwise the -- devcontainer bringup command -local function get_devcontainer_up_cmd(cwd) - local command = devcontainer_command("up", cwd) +local function get_devcontainer_up_cmd() + local command = devcontainer_command("up") if command == nil then return command end - + if config.remove_existing_container then command = command .. " --remove-existing-container" end - command = command .. " --update-remote-user-uid-default off" + command = command .. " --update-remote-user-uid-default off" if config.dotfiles_repository == "" or config.dotfiles_repository == nil then return command end - command = command .. " --dotfiles-repository '" .. config.dotfiles_repository + command = command .. " --dotfiles-repository '" .. config.dotfiles_repository -- only include the branch if it exists if config.dotfiles_branch ~= "" and config.dotfiles_branch ~= nil then command = command .. " -b " .. config.dotfiles_branch @@ -132,19 +126,18 @@ local function get_devcontainer_up_cmd(cwd) end -- issues command to bringup devcontainer ----@param cwd the current working directory. Used as a starting place to find --- .devcontainer directory -function M.bringup(cwd) - local command = get_devcontainer_up_cmd(cwd) +function M.bringup() + local command = get_devcontainer_up_cmd() if command == nil then - return + return end if config.interactive then vim.ui.input( - {prompt=windows_utils.wrap_text( - "Spawning devcontainer with command: " .. command + { + prompt = windows_utils.wrap_text( + "Spawning devcontainer with command: " .. command ) .. "\n\n" .. "Press q to cancel or any other key to continue\n" }, function(input) @@ -164,11 +157,9 @@ function M.bringup(cwd) end -- execute the given cmd within the given devcontainer_parent ----@param cmd the command to issue in the devcontainer terminal ----@param cwd the current working directory. Used as a starting place to find --- .devcontainer directory -function M.exec_cmd(cmd, cwd) - command = devcontainer_command("exec", cwd) +---@param cmd (string) the command to issue in the devcontainer terminal +function M.exec_cmd(cmd) + local command = devcontainer_command("exec") if command == nil then return end @@ -178,15 +169,12 @@ function M.exec_cmd(cmd, cwd) end -- execute a given cmd within the given devcontainer_parent ----@param cwd the current working directory. Used as a starting place to find --- .devcontainer directory ----@param devcontainer_parent the location guess for .devcontainer directory -function M.exec(cwd) +function M.exec() vim.ui.input( - {prompt="Enter command:"}, + { prompt = "Enter command:" }, function(input) if input ~= nil then - M.exec_cmd(input, devcontainer_parent) + M.exec_cmd(input) end end ) diff --git a/lua/devcontainer_cli/folder_utils.lua b/lua/devcontainer_cli/folder_utils.lua index a6cc58d..b86c6a6 100644 --- a/lua/devcontainer_cli/folder_utils.lua +++ b/lua/devcontainer_cli/folder_utils.lua @@ -6,8 +6,8 @@ local function directory_exists(target_folder) end -- get the devcontainer path for the given directory ----@param directory the directory containing .devcontainer ----@return directory if a devcontainer exists within it or nil otherwise +---@param directory (string) the directory containing .devcontainer +---@return (string|nil) directory if a devcontainer exists within it or nil otherwise local function get_devcontainer_parent(directory) local devcontainer_directory = directory .. '/.devcontainer' @@ -15,19 +15,19 @@ local function get_devcontainer_parent(directory) return directory end - return nil + return nil end -- get the root directory the devcontainer given a directory ----@param directory to begin search in ----@param toplevel flag indicating if the directory closes to root should be +---@param directory (string) to begin search in +---@param toplevel (boolean) flag indicating if the directory closes to root should be -- returned ----@return the devcontainer directory closest to the root directory +---@return (string|nil) the devcontainer directory closest to the root directory -- or the first if toplevel is true, and nil if no directory was found local function get_root_directory(directory, toplevel) local parent_directory = vim.fn.fnamemodify(directory, ':h') - local devcontainer_parent = get_devcontainer_parent(directory) - + local devcontainer_parent = get_devcontainer_parent(directory) + -- Base case: If we've reached the root directory if parent_directory == directory then return devcontainer_parent @@ -49,9 +49,9 @@ end -- find the .devcontainer directory closes to the root upward from the current -- directory ----@param toplevel flag indicating if the directory closes to root should be +---@param toplevel (boolean) flag indicating if the directory closes to root should be -- returned ----@return the devcontainer directory closest to the root directory +---@return (string|nil) the devcontainer directory closest to the root directory -- or the first if toplevel is true, and nil if no directory was found function M.get_root(toplevel) local current_directory = vim.fn.getcwd() diff --git a/lua/devcontainer_cli/init.lua b/lua/devcontainer_cli/init.lua index b23704a..86c6b3d 100644 --- a/lua/devcontainer_cli/init.lua +++ b/lua/devcontainer_cli/init.lua @@ -5,7 +5,7 @@ local config = require("devcontainer_cli.config") local configured = false -- setup the devcontainer-cli plugin ----@param opts the options to set (see config/init.lua) +---@param opts (table) the options to set (see config/init.lua) function M.setup(opts) config.setup(opts) @@ -18,7 +18,7 @@ function M.setup(opts) -- Docker vim.api.nvim_create_user_command( - "DevcontainerUp", + "DevcontainerUp", devcontainer_cli.up, { nargs = 0, @@ -27,8 +27,8 @@ function M.setup(opts) ) vim.api.nvim_create_user_command( - "DevcontainerExec", - devcontainer_cli.exec, + "DevcontainerExec", + devcontainer_cli.exec, { nargs = "?", desc = "Execute command in devcontainer.", @@ -36,7 +36,7 @@ function M.setup(opts) ) vim.api.nvim_create_user_command( - "DevcontainerConnect", + "DevcontainerConnect", devcontainer_cli.connect, { nargs = 0, diff --git a/lua/devcontainer_cli/windows_utils.lua b/lua/devcontainer_cli/windows_utils.lua index 1117de4..d94a925 100644 --- a/lua/devcontainer_cli/windows_utils.lua +++ b/lua/devcontainer_cli/windows_utils.lua @@ -3,11 +3,11 @@ local config = require("devcontainer_cli.config") local M = {} -- number of columns for displaying text -local terminal_columns = config.terminal_columns +local terminal_columns = config.terminal_columns -- wrap the given text at max_width ----@param text the text to wrap ----@return the text wrapped +---@param text (string) the text to wrap +---@return (string) the text wrapped function M.wrap_text(text) local wrapped_lines = {} for line in text:gmatch("[^\n]+") do @@ -26,13 +26,13 @@ function M.wrap_text(text) end -- create a floating window ----@param on_detach call back for when the window is detached ----@return the window and buffer numbers -function M.open_floating_window(on_detach) +---@param on_detach (function) call back for when the window is detached +---@return integer, integer the window and buffer numbers +function M.open_floating_window(on_detach) local buf = vim.api.nvim_create_buf(false, true) vim.api.nvim_buf_set_option(buf, 'bufhidden', 'wipe') vim.api.nvim_buf_set_option(buf, 'filetype', 'devcontainer-cli') - vim.api.nvim_buf_set_keymap(buf, 'n', 'q', 'close', {}) + vim.api.nvim_buf_set_keymap(buf, 'n', 'q', 'close', {}) vim.api.nvim_buf_set_keymap(buf, 'n', '', 'close', {}) local width = math.ceil( @@ -52,25 +52,25 @@ function M.open_floating_window(on_detach) style = "minimal", border = "rounded", title = "devcontainer-cli", - title_pos = center, + title_pos = "center", -- noautocommand = false, }) -- Attach autocommand for when the buffer is detached (closed) vim.api.nvim_buf_attach(buf, false, { - on_detach = on_detach + on_detach = on_detach }) return win, buf end -- send text to the given buffer ----@param text the text to send ----@param buffer the buffer to send text to +---@param text (string) the text to send +---@param buffer (integer) the buffer to send text to function M.send_text(text, buffer) - local text = vim.split(wrap_text(text), "\n") + local text_tbl = vim.split(M.wrap_text(text), "\n") -- Set the content of the buffer - vim.api.nvim_buf_set_lines(buffer, 0, -1, false, text) + vim.api.nvim_buf_set_lines(buffer, 0, -1, false, text_tbl) end return M