Compare commits
No commits in common. '4ccf9f84c2a66818bdcd866568ad08bb8ea45b8f' and 'f61518bd8d656341a5f989dd7082fa57143ded1b' have entirely different histories.
4ccf9f84c2
...
f61518bd8d
18 changed files with 204 additions and 582 deletions
@ -0,0 +1,145 @@ |
|||||||
|
-- Terminal helpers layered on top of the native LazyVim/Snacks terminal. |
||||||
|
-- |
||||||
|
-- Native behaviour is kept intact and untouched: |
||||||
|
-- <C-/> / <C-_> toggle a bottom terminal at the project root (supports a |
||||||
|
-- count, e.g. 2<C-/> opens a *separate* terminal #2) |
||||||
|
-- <leader>fT terminal in the current working directory |
||||||
|
-- |
||||||
|
-- This module adds (actual key bindings are declared in lua/plugins/terminal.lua): |
||||||
|
-- open_float() open/focus a *dedicated* floating terminal (close it with <C-/>) |
||||||
|
-- picker() list every live terminal so any contextual terminal can be |
||||||
|
-- focused or restored even after its window was closed/hidden. |
||||||
|
local M = {} |
||||||
|
|
||||||
|
-- The floating terminal. Tracked as an upvalue so the same key always re-focuses |
||||||
|
-- the *same* float regardless of which directory the editor is in. |
||||||
|
---@type snacks.win? |
||||||
|
local float |
||||||
|
|
||||||
|
--- Open or focus the floating terminal, or hide it if already focused. |
||||||
|
-- NOTE: currently unused; the binding calls open_float() instead so shell |
||||||
|
-- tab-completion keeps working while the terminal is open. Kept around for a |
||||||
|
-- future explicit open/close toggle. |
||||||
|
function M.toggle_float() |
||||||
|
-- Reuse the existing instance: hide if visible, re-show if hidden. |
||||||
|
if float and float:buf_valid() then |
||||||
|
if float:win_valid() then |
||||||
|
float:hide() |
||||||
|
else |
||||||
|
float:show() |
||||||
|
vim.cmd("startinsert") |
||||||
|
end |
||||||
|
return |
||||||
|
end |
||||||
|
|
||||||
|
-- First open: a high fixed count guarantees this terminal never collides with |
||||||
|
-- the count-keyed bottom terminals (1, 2, 3 ...), so it is always the *same* |
||||||
|
-- float for <C-Tab> no matter the context. |
||||||
|
float = Snacks.terminal(nil, { |
||||||
|
count = 99, |
||||||
|
win = { position = "float", border = "rounded" }, |
||||||
|
}) |
||||||
|
|
||||||
|
-- Close it with a single keystroke from inside the shell: hides the |
||||||
|
-- window (buffer-local, so it only affects this floating terminal and never |
||||||
|
-- the bottom split, where shell tab-completion must keep working). |
||||||
|
if float and float.buf then |
||||||
|
vim.keymap.set("t", "<leader>tt", function() |
||||||
|
if float and float:win_valid() then |
||||||
|
float:hide() |
||||||
|
end |
||||||
|
end, { buffer = float.buf, silent = true, desc = "Hide floating terminal" }) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
--- Open or focus the floating terminal. This never hides the window, so |
||||||
|
--- once the float is open the key falls through to the shell and stays available |
||||||
|
--- for tab-completion. Close the floating terminal with <C-/> while it is |
||||||
|
--- visible (handled by Snacks' native terminal keymap). |
||||||
|
function M.open_float() |
||||||
|
if float and float:buf_valid() then |
||||||
|
if not float:win_valid() then |
||||||
|
float:show() |
||||||
|
end |
||||||
|
if float:win_valid() then |
||||||
|
vim.api.nvim_set_current_win(float.win) |
||||||
|
end |
||||||
|
vim.cmd("startinsert") |
||||||
|
return |
||||||
|
end |
||||||
|
|
||||||
|
-- First open: a high fixed count guarantees this terminal never collides with |
||||||
|
-- the count-keyed bottom terminals (1, 2, 3 ...), so it is always the *same* |
||||||
|
-- float for <C-Tab> no matter the context. |
||||||
|
float = Snacks.terminal(nil, { |
||||||
|
count = 99, |
||||||
|
win = { position = "float", border = "rounded" }, |
||||||
|
}) |
||||||
|
end |
||||||
|
|
||||||
|
--- List every live Snacks terminal in a picker. Restore/focus one with <CR>, |
||||||
|
--- kill one with <d>. |
||||||
|
function M.picker() |
||||||
|
local terms = Snacks.terminal.list() |
||||||
|
if #terms == 0 then |
||||||
|
Snacks.notify.info("No open terminals") |
||||||
|
return |
||||||
|
end |
||||||
|
|
||||||
|
local items = {} ---@type snacks.picker.finder.Item[] |
||||||
|
for _, term in ipairs(terms) do |
||||||
|
local meta = vim.b[term.buf] and vim.b[term.buf].snacks_terminal or {} |
||||||
|
items[#items + 1] = { |
||||||
|
term = term, |
||||||
|
buf = term.buf, |
||||||
|
id = meta.id, |
||||||
|
cwd = meta.cwd or "?", |
||||||
|
cmd = meta.cmd or vim.o.shell, |
||||||
|
visible = term:win_valid(), |
||||||
|
text = ("#%s %s %s"):format(meta.id or "?", meta.cwd or "?", meta.cmd or vim.o.shell), |
||||||
|
} |
||||||
|
end |
||||||
|
|
||||||
|
Snacks.picker({ |
||||||
|
title = "Terminals", |
||||||
|
items = items, |
||||||
|
format = function(item) |
||||||
|
local ret = {} ---@type snacks.picker.Highlight[] |
||||||
|
ret[#ret + 1] = { |
||||||
|
item.visible and "● " or "○ ", |
||||||
|
item.visible and "SnacksPickerSpecial" or "SnacksPickerComment", |
||||||
|
} |
||||||
|
ret[#ret + 1] = { ("#%-2s"):format(item.id or "?"), "Number" } |
||||||
|
ret[#ret + 1] = { " " .. vim.fn.fnamemodify(item.cwd, ":~"), "SnacksPickerPath" } |
||||||
|
ret[#ret + 1] = { " " .. vim.fn.fnamemodify(item.cmd, ":t"), "SnacksPickerComment" } |
||||||
|
return ret |
||||||
|
end, |
||||||
|
confirm = function(picker, item) |
||||||
|
picker:close() |
||||||
|
local term = item.term |
||||||
|
if not term:buf_valid() then |
||||||
|
Snacks.notify.warn("Terminal no longer exists") |
||||||
|
return |
||||||
|
end |
||||||
|
if term:win_valid() then |
||||||
|
vim.api.nvim_set_current_win(term.win) |
||||||
|
else |
||||||
|
term:show() |
||||||
|
vim.cmd("startinsert") |
||||||
|
end |
||||||
|
end, |
||||||
|
win = { input = { keys = { ["d"] = "term_delete" } } }, |
||||||
|
actions = { |
||||||
|
term_delete = function(picker, item) |
||||||
|
local term = item.term |
||||||
|
picker:close() |
||||||
|
if term and term:buf_valid() then |
||||||
|
term:close() |
||||||
|
pcall(vim.api.nvim_buf_delete, term.buf, { force = true }) |
||||||
|
end |
||||||
|
end, |
||||||
|
}, |
||||||
|
}) |
||||||
|
end |
||||||
|
|
||||||
|
return M |
||||||
@ -1,11 +0,0 @@ |
|||||||
return { |
|
||||||
{ |
|
||||||
"chodak166/clangd-container.nvim", |
|
||||||
-- dir = vim.fn.expand("~/src/git/clangd-container.nvim"), |
|
||||||
dependencies = { "p00f/clangd_extensions.nvim" }, |
|
||||||
opts = {}, |
|
||||||
keys = { |
|
||||||
{ "<leader>cC", "<cmd>ClangdContainer<cr>", desc = "Clangd Container" }, |
|
||||||
}, |
|
||||||
}, |
|
||||||
} |
|
||||||
@ -1,13 +0,0 @@ |
|||||||
return { |
|
||||||
{ |
|
||||||
"https://codeberg.org/esensar/nvim-dev-container", |
|
||||||
dependencies = "nvim-treesitter/nvim-treesitter", |
|
||||||
config = function() |
|
||||||
require("devcontainer").setup({ |
|
||||||
-- Your options go here |
|
||||||
-- e.g., auto_start = true, icons = { ... } |
|
||||||
container_runtime = docker, |
|
||||||
}) |
|
||||||
end, |
|
||||||
}, |
|
||||||
} |
|
||||||
@ -1,11 +1,23 @@ |
|||||||
-- Terminal UX layered on Snacks (replaces toggleterm). |
-- Terminal UX layered on Snacks (replaces toggleterm). |
||||||
-- All keymaps (<leader>tt, <leader>ft, <C-/> with 99-count float) are |
-- Helpers live in lua/config/terminal.lua; keys are declared here so lazy.nvim |
||||||
-- registered by the plugin's setup(). |
-- registers the which-key labels with the rest of the snacks spec. |
||||||
return { |
return { |
||||||
"chodak166/snacks-terminal-ctl.nvim", |
"folke/snacks.nvim", |
||||||
-- dir = "~/src/git/snacks-terminal-ctl.nvim", |
keys = { |
||||||
name = "snacks-terminal-ctl.nvim", |
{ |
||||||
dependencies = { "folke/snacks.nvim" }, |
"<leader>tt", |
||||||
event = "VeryLazy", |
function() |
||||||
opts = {}, |
require("config.terminal").open_float() |
||||||
|
end, |
||||||
|
desc = "Terminal (float)", |
||||||
|
mode = "n", |
||||||
|
}, |
||||||
|
{ |
||||||
|
"<leader>ft", |
||||||
|
function() |
||||||
|
require("config.terminal").picker() |
||||||
|
end, |
||||||
|
desc = "Terminals (list/restore)", |
||||||
|
}, |
||||||
|
}, |
||||||
} |
} |
||||||
|
|||||||
@ -1,135 +0,0 @@ |
|||||||
local M = {} |
|
||||||
|
|
||||||
local function get_yanked_info() |
|
||||||
return ya.sync(function() |
|
||||||
local cwd = cx.active.current.cwd |
|
||||||
local cut = cx.yanked.is_cut |
|
||||||
|
|
||||||
local yanked = {} |
|
||||||
for _, f in pairs(cx.yanked) do |
|
||||||
yanked[#yanked + 1] = { url = f.url, name = tostring(f.url:name()) } |
|
||||||
end |
|
||||||
|
|
||||||
return cwd, cut, yanked |
|
||||||
end) |
|
||||||
end |
|
||||||
|
|
||||||
local function rename_default(name) |
|
||||||
local suffix = os.date("-%y%m%d") |
|
||||||
local stem = name:match("^(.+)%..-$") or name |
|
||||||
local ext = name:match("%.(.+)$") or "" |
|
||||||
if ext ~= "" then |
|
||||||
return stem .. suffix .. "." .. ext |
|
||||||
else |
|
||||||
return name .. suffix |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
function M:entry(_, job) |
|
||||||
local cwd, cut, yanked = get_yanked_info() |
|
||||||
if #yanked == 0 then |
|
||||||
return |
|
||||||
end |
|
||||||
|
|
||||||
local follow = job.args.follow or false |
|
||||||
local resolved = {} |
|
||||||
|
|
||||||
-- Partition: check each yanked item for conflicts |
|
||||||
local conflicts = {} |
|
||||||
for _, item in ipairs(yanked) do |
|
||||||
local dest = cwd:join(item.name) |
|
||||||
local cha = fs.cha(dest) |
|
||||||
if cha ~= nil then |
|
||||||
conflicts[#conflicts + 1] = { url = item.url, dest = dest, name = item.name } |
|
||||||
else |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(dest), |
|
||||||
overwrite = false, |
|
||||||
} |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
-- Process conflicts |
|
||||||
local sync_all = false |
|
||||||
for _, item in ipairs(conflicts) do |
|
||||||
if sync_all then |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(item.dest), |
|
||||||
overwrite = true, |
|
||||||
} |
|
||||||
else |
|
||||||
local choice = ya.pick({ |
|
||||||
title = "Paste conflict: " .. item.name, |
|
||||||
items = { |
|
||||||
"Sync (merge/overwrite)", |
|
||||||
"Sync all remaining", |
|
||||||
"Rename", |
|
||||||
"Skip", |
|
||||||
"Cancel", |
|
||||||
}, |
|
||||||
}) |
|
||||||
|
|
||||||
-- ya.pick returns 0-based index or nil |
|
||||||
if choice == nil or choice == 4 then |
|
||||||
-- Cancel: paste what we have so far, then abort |
|
||||||
if #resolved > 0 then |
|
||||||
ya.emit("paste_resolved", { |
|
||||||
cut = cut, |
|
||||||
follow = follow, |
|
||||||
items = resolved, |
|
||||||
}) |
|
||||||
end |
|
||||||
return |
|
||||||
|
|
||||||
elseif choice == 0 then |
|
||||||
-- Sync current |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(item.dest), |
|
||||||
overwrite = true, |
|
||||||
} |
|
||||||
|
|
||||||
elseif choice == 1 then |
|
||||||
-- Sync all remaining |
|
||||||
sync_all = true |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(item.dest), |
|
||||||
overwrite = true, |
|
||||||
} |
|
||||||
|
|
||||||
elseif choice == 2 then |
|
||||||
-- Rename |
|
||||||
local default = rename_default(item.name) |
|
||||||
local value, event = ya.input({ |
|
||||||
title = "New name", |
|
||||||
value = default, |
|
||||||
}) |
|
||||||
if event == 1 then |
|
||||||
local new_dest = cwd:join(value) |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(new_dest), |
|
||||||
overwrite = false, |
|
||||||
} |
|
||||||
end |
|
||||||
|
|
||||||
elseif choice == 3 then |
|
||||||
-- Skip: do nothing |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
-- Dispatch all resolved items |
|
||||||
if #resolved > 0 then |
|
||||||
ya.emit("paste_resolved", { |
|
||||||
cut = cut, |
|
||||||
follow = follow, |
|
||||||
items = resolved, |
|
||||||
}) |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
return M |
|
||||||
@ -1,21 +0,0 @@ |
|||||||
MIT License |
|
||||||
|
|
||||||
Copyright (c) 2026 chodak166 |
|
||||||
|
|
||||||
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 |
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
||||||
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. |
|
||||||
@ -1,220 +0,0 @@ |
|||||||
local M = {} |
|
||||||
|
|
||||||
local get_yanked_info = ya.sync(function() |
|
||||||
local cwd = cx.active.current.cwd |
|
||||||
local cut = cx.yanked.is_cut |
|
||||||
|
|
||||||
local yanked = {} |
|
||||||
for _, url in ipairs(cx.yanked:urls()) do |
|
||||||
yanked[#yanked + 1] = { url = url, name = tostring(url.name) } |
|
||||||
end |
|
||||||
|
|
||||||
return { cwd = cwd, cut = cut, yanked = yanked } |
|
||||||
end) |
|
||||||
|
|
||||||
local function rename_default(name, attempt) |
|
||||||
if attempt and attempt > 1 then |
|
||||||
local suffix = string.format("-%d", attempt) |
|
||||||
local stem = name:match("^(.+)%..-$") or name |
|
||||||
local ext = name:match("%.(.+)$") or "" |
|
||||||
if ext ~= "" then |
|
||||||
return stem .. suffix .. "." .. ext |
|
||||||
else |
|
||||||
return name .. suffix |
|
||||||
end |
|
||||||
end |
|
||||||
local suffix = os.date("-%y%m%d") |
|
||||||
local stem = name:match("^(.+)%..-$") or name |
|
||||||
local ext = name:match("%.(.+)$") or "" |
|
||||||
if ext ~= "" then |
|
||||||
return stem .. suffix .. "." .. ext |
|
||||||
else |
|
||||||
return name .. suffix |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
--Choices: |
|
||||||
-- 0: Merge — merge directory contents, overwrite individual files |
|
||||||
-- 1: Merge all — same, applied to all remaining conflicts |
|
||||||
-- 2: Replace — replace destination entirely (delete then copy) |
|
||||||
-- 3: Rename — prompt for a new name |
|
||||||
-- 4: Skip — skip this item |
|
||||||
-- 5: Cancel(nil) — abort |
|
||||||
local function pick_conflict(name) |
|
||||||
return ya.pick({ |
|
||||||
title = "Paste conflict: " .. name, |
|
||||||
items = { |
|
||||||
"Merge", |
|
||||||
"Merge all remaining", |
|
||||||
"Replace", |
|
||||||
"Rename", |
|
||||||
"Skip", |
|
||||||
"Cancel", |
|
||||||
}, |
|
||||||
}) |
|
||||||
end |
|
||||||
|
|
||||||
function M:entry(job) |
|
||||||
local info = get_yanked_info() |
|
||||||
local cwd, cut, yanked = info.cwd, info.cut, info.yanked |
|
||||||
|
|
||||||
if #yanked == 0 then |
|
||||||
return |
|
||||||
end |
|
||||||
|
|
||||||
local follow = job.args.follow or false |
|
||||||
local resolved = {} |
|
||||||
|
|
||||||
-- Partition: check each yanked item for conflicts |
|
||||||
local conflicts = {} |
|
||||||
for _, item in ipairs(yanked) do |
|
||||||
local dest = cwd:join(item.name) |
|
||||||
local cha = fs.cha(dest) |
|
||||||
if cha ~= nil then |
|
||||||
conflicts[#conflicts + 1] = { url = item.url, dest = dest, name = item.name } |
|
||||||
else |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(dest), |
|
||||||
overwrite = false, |
|
||||||
replace = false, |
|
||||||
} |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
-- Dispatch helper |
|
||||||
local function dispatch(items) |
|
||||||
if #items > 0 then |
|
||||||
ya.emit("paste_resolved", { |
|
||||||
cut = cut, |
|
||||||
follow = follow, |
|
||||||
items = items, |
|
||||||
}) |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
-- Process conflicts |
|
||||||
local merge_all = false |
|
||||||
for _, item in ipairs(conflicts) do |
|
||||||
if merge_all then |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(item.dest), |
|
||||||
overwrite = true, |
|
||||||
replace = false, |
|
||||||
} |
|
||||||
else |
|
||||||
local choice = pick_conflict(item.name) |
|
||||||
|
|
||||||
if choice == nil or choice == 5 then |
|
||||||
-- Cancel: paste what we have so far, then abort |
|
||||||
dispatch(resolved) |
|
||||||
return |
|
||||||
|
|
||||||
elseif choice == 0 then |
|
||||||
-- Merge current |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(item.dest), |
|
||||||
overwrite = true, |
|
||||||
replace = false, |
|
||||||
} |
|
||||||
|
|
||||||
elseif choice == 1 then |
|
||||||
-- Merge all remaining |
|
||||||
merge_all = true |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(item.dest), |
|
||||||
overwrite = true, |
|
||||||
replace = false, |
|
||||||
} |
|
||||||
|
|
||||||
elseif choice == 2 then |
|
||||||
-- Replace |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(item.dest), |
|
||||||
overwrite = true, |
|
||||||
replace = true, |
|
||||||
} |
|
||||||
|
|
||||||
elseif choice == 3 then |
|
||||||
-- Rename: loop until a non-conflicting name is chosen or cancelled |
|
||||||
local attempt = 0 |
|
||||||
while true do |
|
||||||
attempt = attempt + 1 |
|
||||||
local default = rename_default(item.name, attempt) |
|
||||||
local value, event = ya.input({ |
|
||||||
title = "New name", |
|
||||||
value = default, |
|
||||||
pos = { "center", w = 60 }, |
|
||||||
}) |
|
||||||
if event ~= 1 then |
|
||||||
-- User cancelled the input — skip this item |
|
||||||
break |
|
||||||
end |
|
||||||
|
|
||||||
local new_dest = cwd:join(value) |
|
||||||
if fs.cha(new_dest) == nil then |
|
||||||
-- No conflict — add and continue |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(new_dest), |
|
||||||
overwrite = false, |
|
||||||
replace = false, |
|
||||||
} |
|
||||||
break |
|
||||||
else |
|
||||||
-- New name also conflicts — show the conflict dialog again |
|
||||||
local sub_choice = pick_conflict(value) |
|
||||||
if sub_choice == nil or sub_choice == 5 then |
|
||||||
-- Cancel everything |
|
||||||
dispatch(resolved) |
|
||||||
return |
|
||||||
elseif sub_choice == 0 then |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(new_dest), |
|
||||||
overwrite = true, |
|
||||||
replace = false, |
|
||||||
} |
|
||||||
break |
|
||||||
elseif sub_choice == 1 then |
|
||||||
merge_all = true |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(new_dest), |
|
||||||
overwrite = true, |
|
||||||
replace = false, |
|
||||||
} |
|
||||||
break |
|
||||||
elseif sub_choice == 2 then |
|
||||||
resolved[#resolved + 1] = { |
|
||||||
from = tostring(item.url), |
|
||||||
to = tostring(new_dest), |
|
||||||
overwrite = true, |
|
||||||
replace = true, |
|
||||||
} |
|
||||||
break |
|
||||||
elseif sub_choice == 3 then |
|
||||||
-- Rename again — increment attempt for different default |
|
||||||
-- (loop continues) |
|
||||||
elseif sub_choice == 4 then |
|
||||||
-- Skip |
|
||||||
break |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
elseif choice == 4 then |
|
||||||
-- Skip: do nothing |
|
||||||
end |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
-- Dispatch all resolved items |
|
||||||
dispatch(resolved) |
|
||||||
end |
|
||||||
|
|
||||||
return M |
|
||||||
Loading…
Reference in new issue