From 1f8ba3a7db3b9e185d309c16f666d966ead59298 Mon Sep 17 00:00:00 2001 From: Erich L Foster Date: Tue, 21 May 2024 20:34:23 +0200 Subject: [PATCH 1/5] Open NVIM immediately and eliminate extra script --- bin/connect_to_devcontainer.sh | 31 ++++++++----------- bin/open_shell_in_devcontainer.sh | 34 --------------------- lua/devcontainer-cli/config/init.lua | 7 ++++- lua/devcontainer-cli/devcontainer_cli.lua | 32 +++++-------------- lua/devcontainer-cli/devcontainer_utils.lua | 30 ++++++++++++++++++ 5 files changed, 57 insertions(+), 77 deletions(-) delete mode 100755 bin/open_shell_in_devcontainer.sh diff --git a/bin/connect_to_devcontainer.sh b/bin/connect_to_devcontainer.sh index ee8cc48..cd8d837 100755 --- a/bin/connect_to_devcontainer.sh +++ b/bin/connect_to_devcontainer.sh @@ -7,36 +7,31 @@ set -e # TODO: Give the possibility of using multiple terminals, not only gnome-terminal # TODO: Give the possibility of opening a new tmux page instead of opening a new container -# Get the folder of the current file -function get_script_dir { - # SOURCE: https://stackoverflow.com/a/246128/10491337 - local SOURCE="${BASH_SOURCE[0]}" - local DIR="" - while [ -h "${SOURCE}" ]; do - DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)" - SOURCE="$(readlink "${SOURCE}")" - [[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}" - done - cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd -} +if [ -n "$TMUX" ]; then + tmux_open="tmux split-window -h -t \"$TMUX_PANE\" " +else + tmux_open="" +fi -SCRIPT_DIR=$(get_script_dir) # Execute the command for opening the devcontainer in the following terminal: if [ -x "$(command -v alacritty)" ]; then # ALACRITTY TERMINAL EMULATOR REPOSTORY_NAME=$(basename "$(pwd)") - TERMINAL_TITLE="Devcontainer [${REPOSTORY_NAME}] - You are inside a Docker Container now...!" - alacritty --working-directory . --title "${TERMINAL_TITLE}" -e "${SCRIPT_DIR}"/open_shell_in_devcontainer.sh & + TERMINAL_TITLE="Devcontainer [${REPOSTORY_NAME}]" + command="alacritty --working-directory . --title "${TERMINAL_TITLE}" -e ${tmux_open}$@ &" elif [ -x "$(command -v gnome-terminal)" ]; then # GNOME TERMINAL - gnome-terminal -- bash -c "${SCRIPT_DIR}"/open_shell_in_devcontainer.sh + command="gnome-terminal -- ${tmux_open}$@" elif [ "$(uname)" == "Darwin" ] && [ -x "$(command -v iTerm)" ]; then # MAC ITERM2 TERMINAL EMULATOR - open -a iTerm.app "${SCRIPT_DIR}"/open_shell_in_devcontainer.sh + command="open -a iTerm.app ${tmux_open}$@" elif [ "$(uname)" == "Darwin" ] && [ -x "$(command -v Terminal)" ]; then # MAC TERMINAL - open -a Terminal.app "${SCRIPT_DIR}"/open_shell_in_devcontainer.sh + command="open -a Terminal.app ${tmux_open}$@" else # TERMINAL NO DEFINED echo "ERROR: No compatible emulators found!" + exit 1 fi + +eval "${command}" diff --git a/bin/open_shell_in_devcontainer.sh b/bin/open_shell_in_devcontainer.sh deleted file mode 100755 index 99304ea..0000000 --- a/bin/open_shell_in_devcontainer.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -# This executable file has been isolated from ./bin/connect_to_devcontainer.sh so it -# can be executed in MAC Terminals (Termina.app/iTerm.app) - -tmux-split-cmd() (tmux split-window -h -t "$TMUX_PANE" "bash --rcfile <(echo '. ~/.bashrc;$*')") -tmux-new-cmd() (tmux new-window -n Devcontainer "bash --rcfile <(echo '. ~/.bashrc;$*')") - -set -e - -WORKSPACE="$(pwd)" -SHELL="zsh" - -workspace_folder=$(devcontainer read-configuration --include-merged-configuration --log-format json --workspace-folder . 2>/dev/null | jq .workspace.workspaceFolder | sed 's/"//g') -docker_id=$(docker ps -q -a --filter label=devcontainer.local_folder="${WORKSPACE}" --filter label=devcontainer.config_file="${WORKSPACE}"/.devcontainer/devcontainer.json) - -open_shell_in_devcontainer_command="docker exec -it ${docker_id} bash -c \"cd ${workspace_folder} && ${SHELL}\"" - -# Check if we are inside a tmux session -# If so, create a new pane and execute the open_shell_in_devcontainer_command -# If not, just execute the open_shell_in_devcontainer_command - -if [ -n "$TMUX" ]; then - # Replace by tmux-split-cmd if you want to split the current pane horizontally - tmux-new-cmd "${open_shell_in_devcontainer_command}" -else - eval "${open_shell_in_devcontainer_command}" -fi -# docker exec -it "${docker_id}" ${SHELL} - -# TODO: It would be great to use th devcontainer exec command as long as we know how to fix the visualization issue inside the docker container! -# If you want to give a try, just comment the docker exec -it ... above and uncommend the line below. Then execute the :DevcontainerConnect and open vim. -# There you will see visualzation issues which do not occur when connectint to docker via docker exec - -# devcontainer exec --workspace-folder ${WORKSPACE} ${SHELL} diff --git a/lua/devcontainer-cli/config/init.lua b/lua/devcontainer-cli/config/init.lua index f9381fe..269121b 100644 --- a/lua/devcontainer-cli/config/init.lua +++ b/lua/devcontainer-cli/config/init.lua @@ -35,7 +35,7 @@ local default_config = { 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) - dotfiles_repository = "devcontainer", + dotfiles_branch = "main", -- directory for the setup environment dotfiles_targetPath = "~/dotfiles", -- command that's executed for installed the dependencies from the @@ -43,9 +43,14 @@ local default_config = { dotfiles_installCommand = "install.sh", -- The number of columns to wrap text at terminal_columns = 80, + -- The particular binary to use for connecting to in the devcontainer + -- Most likely this should remain nvim + nvim_binary = "nvim", -- 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', + -- The name of the socket file to use + port = "7777", } local options diff --git a/lua/devcontainer-cli/devcontainer_cli.lua b/lua/devcontainer-cli/devcontainer_cli.lua index bf0ecd9..ea3343f 100644 --- a/lua/devcontainer-cli/devcontainer_cli.lua +++ b/lua/devcontainer-cli/devcontainer_cli.lua @@ -1,15 +1,15 @@ -- Copyright (c) 2024 Erich L Foster --- +-- -- Permission is hereby granted, free of charge, to any person obtaining a copy of -- this software and associated documentation files (the "Software"), to deal in -- the Software without restriction, including without limitation the rights to -- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -- of the Software, and to permit persons to whom the Software is furnished to do -- so, subject to the following conditions: --- +-- -- The above copyright notice and this permission notice shall be included in all -- copies or substantial portions of the Software. --- +-- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -17,30 +17,10 @@ -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- SOFTWARE. - -local config = require("devcontainer-cli.config") local utils = require("devcontainer-cli.devcontainer_utils") local M = {} -local function define_autocommands() - local au_id = vim.api.nvim_create_augroup("devcontainer.docker.terminal", {}) - vim.api.nvim_create_autocmd("UILeave", { - group = au_id, - callback = function() - -- It connects with the Devcontainer just after quiting neovim. - -- TODO: checks that the devcontainer is not already connected - -- TODO: checks that there is a devcontainer running - vim.schedule( - function() - local command = config.nvim_plugin_folder .. "/bin/connect_to_devcontainer.sh" - vim.fn.jobstart(command, { detach = true }) - end - ) - end, - }) -end - -- executes a given command in the devcontainer of the current project directory ---@param opts (table) options for executing the command function M.exec(opts) @@ -82,7 +62,11 @@ 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() - define_autocommands() + if not utils.create_connect_cmd() then + vim.notify("Failed to create autocommand", vim.log.levels.ERROR) + return + end + vim.cmd("wqa") end diff --git a/lua/devcontainer-cli/devcontainer_utils.lua b/lua/devcontainer-cli/devcontainer_utils.lua index 15c74c0..daa133b 100644 --- a/lua/devcontainer-cli/devcontainer_utils.lua +++ b/lua/devcontainer-cli/devcontainer_utils.lua @@ -333,4 +333,34 @@ function M.toggle() _terminal:toggle() end +-- create the necessary functions needed to connect to nvim in a devcontainer +function M.create_connect_cmd() + local au_id = vim.api.nvim_create_augroup("devcontainer-cli.connect", {}) + local dev_command = _devcontainer_command("exec") + if dev_command == nil then + return false + end + dev_command = dev_command .. " " .. config.nvim_binary + + vim.api.nvim_create_autocmd( + "UILeave", + { + group = au_id, + callback = + function() + local connect_command = {config.nvim_plugin_folder .. "/bin/connect_to_devcontainer.sh"} + table.insert(connect_command, dev_command) + local command = table.concat(connect_command, " ") + vim.schedule( + function() + vim.fn.jobstart(command, { detach = true }) + end + ) + end + } + ) + + return true +end + return M From aa0efb68b5cc0023fed1ab60433bac879b7cfec5 Mon Sep 17 00:00:00 2001 From: Erich L Foster Date: Thu, 23 May 2024 16:40:29 +0200 Subject: [PATCH 2/5] Remove connect script in favor of lua --- bin/connect_to_devcontainer.sh | 37 --------------------- lua/devcontainer-cli/devcontainer_utils.lua | 16 ++++++++- 2 files changed, 15 insertions(+), 38 deletions(-) delete mode 100755 bin/connect_to_devcontainer.sh diff --git a/bin/connect_to_devcontainer.sh b/bin/connect_to_devcontainer.sh deleted file mode 100755 index cd8d837..0000000 --- a/bin/connect_to_devcontainer.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/bash - -set -e -# The following code creates a new terminal (using gnome-terminal) and it -# connects to the container using the devcontainer built in command. -# TODO: Add a check to see if the container is running. -# TODO: Give the possibility of using multiple terminals, not only gnome-terminal -# TODO: Give the possibility of opening a new tmux page instead of opening a new container - -if [ -n "$TMUX" ]; then - tmux_open="tmux split-window -h -t \"$TMUX_PANE\" " -else - tmux_open="" -fi - -# Execute the command for opening the devcontainer in the following terminal: -if [ -x "$(command -v alacritty)" ]; then - # ALACRITTY TERMINAL EMULATOR - REPOSTORY_NAME=$(basename "$(pwd)") - TERMINAL_TITLE="Devcontainer [${REPOSTORY_NAME}]" - command="alacritty --working-directory . --title "${TERMINAL_TITLE}" -e ${tmux_open}$@ &" -elif [ -x "$(command -v gnome-terminal)" ]; then - # GNOME TERMINAL - command="gnome-terminal -- ${tmux_open}$@" -elif [ "$(uname)" == "Darwin" ] && [ -x "$(command -v iTerm)" ]; then - # MAC ITERM2 TERMINAL EMULATOR - command="open -a iTerm.app ${tmux_open}$@" -elif [ "$(uname)" == "Darwin" ] && [ -x "$(command -v Terminal)" ]; then - # MAC TERMINAL - command="open -a Terminal.app ${tmux_open}$@" -else - # TERMINAL NO DEFINED - echo "ERROR: No compatible emulators found!" - exit 1 -fi - -eval "${command}" diff --git a/lua/devcontainer-cli/devcontainer_utils.lua b/lua/devcontainer-cli/devcontainer_utils.lua index daa133b..c2b7c2c 100644 --- a/lua/devcontainer-cli/devcontainer_utils.lua +++ b/lua/devcontainer-cli/devcontainer_utils.lua @@ -348,7 +348,21 @@ function M.create_connect_cmd() group = au_id, callback = function() - local connect_command = {config.nvim_plugin_folder .. "/bin/connect_to_devcontainer.sh"} + local connect_command = {} + if vim.env.TMUX ~= "" then + connect_command = {"tmux split-window -h -t \"$TMUX_PANE\""} + elseif vim.fn.executable("allacrity") == 1 then + connect_command = {"alacritty --working-directory . --title \"Devcontainer\" -e"} + elseif vim.fn.executable("gnome-terminal") == 1 then + connect_command = {"gnome-terminal --"} + elseif vim.fn.executable("iTerm.app") == 1 then + connect_command = {"iTerm.app"} + elseif vim.fn.executable("Terminal.app") == 1 then + connect_command = {"Terminal.app"} + else + vim.notify("No supported terminal emulator found.", vim.log.levels.ERROR) + end + table.insert(connect_command, dev_command) local command = table.concat(connect_command, " ") vim.schedule( From f79eb9bb532538c5da39612324664ca94435ba75 Mon Sep 17 00:00:00 2001 From: Erich L Foster Date: Fri, 24 May 2024 09:20:04 +0200 Subject: [PATCH 3/5] Refactor terminal --- lua/devcontainer-cli/devcontainer_cli.lua | 3 +- lua/devcontainer-cli/devcontainer_utils.lua | 182 ++++---------------- lua/devcontainer-cli/terminal.lua | 135 +++++++++++++++ 3 files changed, 169 insertions(+), 151 deletions(-) create mode 100644 lua/devcontainer-cli/terminal.lua diff --git a/lua/devcontainer-cli/devcontainer_cli.lua b/lua/devcontainer-cli/devcontainer_cli.lua index ea3343f..fddbee4 100644 --- a/lua/devcontainer-cli/devcontainer_cli.lua +++ b/lua/devcontainer-cli/devcontainer_cli.lua @@ -18,6 +18,7 @@ -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- SOFTWARE. local utils = require("devcontainer-cli.devcontainer_utils") +local terminal = require("devcontainer-cli.terminal") local M = {} @@ -51,7 +52,7 @@ end -- toggle the current devcontainer window function M.toggle() - utils.toggle() + terminal.toggle() end -- bring up the devcontainer in the current project directory diff --git a/lua/devcontainer-cli/devcontainer_utils.lua b/lua/devcontainer-cli/devcontainer_utils.lua index c2b7c2c..0b4f664 100644 --- a/lua/devcontainer-cli/devcontainer_utils.lua +++ b/lua/devcontainer-cli/devcontainer_utils.lua @@ -1,15 +1,15 @@ -- Copyright (c) 2024 Erich L Foster --- +-- -- Permission is hereby granted, free of charge, to any person obtaining a copy of -- this software and associated documentation files (the "Software"), to deal in -- the Software without restriction, including without limitation the rights to -- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -- of the Software, and to permit persons to whom the Software is furnished to do -- so, subject to the following conditions: --- +-- -- The above copyright notice and this permission notice shall be included in all -- copies or substantial portions of the Software. --- +-- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -20,25 +20,10 @@ local config = require("devcontainer-cli.config") local folder_utils = require("devcontainer-cli.folder_utils") -local Terminal = require('toggleterm.terminal').Terminal -local mode = require('toggleterm.terminal').mode +local terminal = require("devcontainer-cli.terminal") local M = {} --- valid window directions -local directions = { - "float", - "horizontal", - "tab", - "vertical", -} - --- window management variables -local _terminal = nil --- --- number of columns for displaying text -local terminal_columns = config.terminal_columns - -- wrap the given text at max_width ---@param text (string) the text to wrap ---@return (string) the text wrapped @@ -47,7 +32,7 @@ local function _wrap_text(text) for line in text:gmatch("[^\n]+") do local current_line = "" for word in line:gmatch("%S+") do - if #current_line + #word <= terminal_columns then + if #current_line + #word <= terminal.columns then current_line = current_line .. word .. " " else table.insert(wrapped_lines, current_line) @@ -59,49 +44,6 @@ local function _wrap_text(text) return table.concat(wrapped_lines, "\n") end --- window the created window detaches set things back to -1 -local _on_detach = function() - _terminal = nil -end - --- on_fail callback ----@param exit_code (number) 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 - ) - - vim.cmd("silent! :checktime") -end - -local _on_success = function() - vim.notify("Devcontainer process succeeded!", vim.log.levels.INFO) -end - --- on_exit callback function to delete the open buffer when devcontainer exits --- in a neovim terminal ----@param code (number) the exit code -local _on_exit = function(code) - if code == 0 then - _on_success() - return - end - - _on_fail(code) -end - --- check if the value is in the given table -local function tableContains(tbl, value) - for _, item in ipairs(tbl) do - if item == value then - return true - end - end - - return false -end - ---@class ParsedArgs ---@field direction string? ---@field cmd string? @@ -200,57 +142,6 @@ local function _get_devcontainer_up_cmd() return command end --- create a new window and execute the given command ----@param cmd (string) the command to execute in the devcontainer terminal ----@param direction (string|nil) the placement of the window to be created (float, horizontal, vertical) ----@param size (number|nil) the size of the window to be created -local function _spawn_and_execute(cmd, direction, size) - direction = vim.F.if_nil(direction, "float") - if tableContains(directions, direction) == false then - vim.notify("Invalid direction: " .. direction, vim.log.levels.ERROR) - return - end - - -- create the terminal - _terminal = Terminal:new { - cmd = cmd, - hidden = false, - display_name = "devcontainer-cli", - direction = vim.F.if_nil(direction, "float"), - dir = folder_utils.get_root(config.toplevel), - size = size, - close_on_exit = false, - on_open = function(term) - -- ensure that we are not in insert mode - vim.cmd("stopinsert") - vim.api.nvim_buf_set_keymap( - term.bufnr, - 'n', - '', - 'lua vim.api.nvim_buf_delete(' .. term.bufnr .. ', { force = true } )close', - { noremap = true, silent = true } - ) - vim.api.nvim_buf_set_keymap( - term.bufnr, - 'n', - 'q', - 'lua vim.api.nvim_buf_delete(' .. term.bufnr .. ', { force = true } )close', - { noremap = true, silent = true } - ) - vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 't', 'close', { noremap = true, silent = true }) - end, - auto_scroll = true, - on_exit = function(_, _, code, _) - _on_exit(code) - _on_detach() - end, -- callback for when process closes - } - -- start in insert mode - _terminal:set_mode(mode.NORMAL) - -- now execute the command - _terminal:open() -end - -- issues command to bringup devcontainer function M.bringup() local command = _get_devcontainer_up_cmd() @@ -272,14 +163,14 @@ function M.bringup() "\nUser cancelled bringing up devcontainer" ) else - _spawn_and_execute(command) + terminal.spawn(command) end end ) return end - _spawn_and_execute(command) + terminal.spawn(command) end -- execute the given cmd within the given devcontainer_parent @@ -294,7 +185,7 @@ function M._exec_cmd(cmd, direction, size) command = command .. " " .. config.shell .. " -c '" .. cmd .. "'" vim.notify(command) - _spawn_and_execute(command, direction, size) + terminal.spawn(command, direction, size) end -- execute a given cmd within the given devcontainer_parent @@ -303,7 +194,7 @@ end -- (left, right, bottom, float) ---@param size (number|nil) size of the window to create function M.exec(cmd, direction, size) - if _terminal ~= nil then + if terminal.is_open() then vim.notify("There is already a devcontainer process running.", vim.log.levels.WARN) return end @@ -324,15 +215,6 @@ function M.exec(cmd, direction, size) end end --- toggle the current terminal -function M.toggle() - if _terminal == nil then - vim.notify("No devcontainer window to toggle.", vim.log.levels.WARN) - return - end - _terminal:toggle() -end - -- create the necessary functions needed to connect to nvim in a devcontainer function M.create_connect_cmd() local au_id = vim.api.nvim_create_augroup("devcontainer-cli.connect", {}) @@ -347,30 +229,30 @@ function M.create_connect_cmd() { group = au_id, callback = - function() - local connect_command = {} - if vim.env.TMUX ~= "" then - connect_command = {"tmux split-window -h -t \"$TMUX_PANE\""} - elseif vim.fn.executable("allacrity") == 1 then - connect_command = {"alacritty --working-directory . --title \"Devcontainer\" -e"} - elseif vim.fn.executable("gnome-terminal") == 1 then - connect_command = {"gnome-terminal --"} - elseif vim.fn.executable("iTerm.app") == 1 then - connect_command = {"iTerm.app"} - elseif vim.fn.executable("Terminal.app") == 1 then - connect_command = {"Terminal.app"} - else - vim.notify("No supported terminal emulator found.", vim.log.levels.ERROR) - end - - table.insert(connect_command, dev_command) - local command = table.concat(connect_command, " ") - vim.schedule( - function() - vim.fn.jobstart(command, { detach = true }) + function() + local connect_command = {} + if vim.env.TMUX ~= "" then + connect_command = { "tmux split-window -h -t \"$TMUX_PANE\"" } + elseif vim.fn.executable("allacrity") == 1 then + connect_command = { "alacritty --working-directory . --title \"Devcontainer\" -e" } + elseif vim.fn.executable("gnome-terminal") == 1 then + connect_command = { "gnome-terminal --" } + elseif vim.fn.executable("iTerm.app") == 1 then + connect_command = { "iTerm.app" } + elseif vim.fn.executable("Terminal.app") == 1 then + connect_command = { "Terminal.app" } + else + vim.notify("No supported terminal emulator found.", vim.log.levels.ERROR) end - ) - end + + table.insert(connect_command, dev_command) + local command = table.concat(connect_command, " ") + vim.schedule( + function() + vim.fn.jobstart(command, { detach = true }) + end + ) + end } ) diff --git a/lua/devcontainer-cli/terminal.lua b/lua/devcontainer-cli/terminal.lua new file mode 100644 index 0000000..2f638ce --- /dev/null +++ b/lua/devcontainer-cli/terminal.lua @@ -0,0 +1,135 @@ +local config = require("devcontainer-cli.config") +local folder_utils = require("devcontainer-cli.folder_utils") + +local Terminal = require('toggleterm.terminal').Terminal +local mode = require('toggleterm.terminal').mode + +local M = {} + +-- valid window directions +M.directions = { + "float", + "horizontal", + "tab", + "vertical", +} + +-- window management variables +local _terminal = nil + +-- when the created window detaches set things back to -1 +local _on_detach = function() + _terminal = nil +end + +-- on_fail callback +---@param exit_code (number) 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 + ) + + vim.cmd("silent! :checktime") +end + +local _on_success = function() + vim.notify("Devcontainer process succeeded!", vim.log.levels.INFO) +end + +-- on_exit callback function to delete the open buffer when devcontainer exits +-- in a neovim terminal +---@param code (number) the exit code +local _on_exit = function(code) + if code == 0 then + _on_success() + return + end + + _on_fail(code) +end + +local _on_open = function(term) + -- ensure that we are not in insert mode + vim.cmd("stopinsert") + vim.api.nvim_buf_set_keymap( + term.bufnr, + 'n', + '', + 'lua vim.api.nvim_buf_delete(' .. term.bufnr .. ', { force = true } )close', + { noremap = true, silent = true } + ) + vim.api.nvim_buf_set_keymap( + term.bufnr, + 'n', + 'q', + 'lua vim.api.nvim_buf_delete(' .. term.bufnr .. ', { force = true } )close', + { noremap = true, silent = true } + ) + vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 't', 'close', { noremap = true, silent = true }) +end + +-- check if the value is in the given table +local function tableContains(tbl, value) + for _, item in ipairs(tbl) do + if item == value then + return true + end + end + + return false +end + +-- number of columns for displaying text +M.columns = config.terminal_columns + +-- create a new window and execute the given command +---@param cmd (string) the command to execute in the devcontainer terminal +---@param direction (string|nil) the placement of the window to be created (float, horizontal, vertical) +---@param size (number|nil) the size of the window to be created +function M.spawn(cmd, direction, size) + direction = vim.F.if_nil(direction, "float") + if tableContains(M.directions, direction) == false then + vim.notify("Invalid direction: " .. direction, vim.log.levels.ERROR) + return + end + + -- create the terminal + _terminal = Terminal:new { + cmd = cmd, + hidden = false, + display_name = "devcontainer-cli", + direction = vim.F.if_nil(direction, "float"), + dir = folder_utils.get_root(config.toplevel), + size = size, + close_on_exit = false, + on_open = _on_open, + auto_scroll = true, + on_exit = function(_, _, code, _) + _on_exit(code) + _on_detach() + end, -- callback for when process closes + } + -- start in insert mode + _terminal:set_mode(mode.NORMAL) + -- now execute the command + _terminal:open() +end + +-- check if there is already a terminal window open +---@return true if a terminal window is already open +function M.is_open() + return _terminal ~= nil +end + +-- toggle the current terminal +function M.toggle() + if _terminal == nil then + vim.notify("No devcontainer window to toggle.", vim.log.levels.WARN) + return + end + + _terminal:toggle() +end + +return M From 0af61d78b2c2cea7cc3dd3697d730e0ce7e6fb74 Mon Sep 17 00:00:00 2001 From: Erich L Foster Date: Fri, 24 May 2024 09:24:10 +0200 Subject: [PATCH 4/5] Move config/init.lua to config.lua --- lua/devcontainer-cli/{config/init.lua => config.lua} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lua/devcontainer-cli/{config/init.lua => config.lua} (100%) diff --git a/lua/devcontainer-cli/config/init.lua b/lua/devcontainer-cli/config.lua similarity index 100% rename from lua/devcontainer-cli/config/init.lua rename to lua/devcontainer-cli/config.lua From 2f18cf3dc8ccebf3940a548230014db43ed104dd Mon Sep 17 00:00:00 2001 From: Erich L Foster Date: Fri, 24 May 2024 09:27:43 +0200 Subject: [PATCH 5/5] Update formatting --- lua/devcontainer-cli/devcontainer_utils.lua | 8 ++++---- lua/devcontainer-cli/init.lua | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lua/devcontainer-cli/devcontainer_utils.lua b/lua/devcontainer-cli/devcontainer_utils.lua index 0b4f664..916f9c1 100644 --- a/lua/devcontainer-cli/devcontainer_utils.lua +++ b/lua/devcontainer-cli/devcontainer_utils.lua @@ -18,11 +18,11 @@ -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- SOFTWARE. -local config = require("devcontainer-cli.config") -local folder_utils = require("devcontainer-cli.folder_utils") -local terminal = require("devcontainer-cli.terminal") +local config = require("devcontainer-cli.config") +local folder_utils = require("devcontainer-cli.folder_utils") +local terminal = require("devcontainer-cli.terminal") -local M = {} +local M = {} -- wrap the given text at max_width ---@param text (string) the text to wrap diff --git a/lua/devcontainer-cli/init.lua b/lua/devcontainer-cli/init.lua index a5c802b..99a256f 100644 --- a/lua/devcontainer-cli/init.lua +++ b/lua/devcontainer-cli/init.lua @@ -1,15 +1,15 @@ -- Copyright (c) 2024 Erich L Foster --- +-- -- Permission is hereby granted, free of charge, to any person obtaining a copy of -- this software and associated documentation files (the "Software"), to deal in -- the Software without restriction, including without limitation the rights to -- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -- of the Software, and to permit persons to whom the Software is furnished to do -- so, subject to the following conditions: --- +-- -- The above copyright notice and this permission notice shall be included in all -- copies or substantial portions of the Software. --- +-- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE