Swapped vim for vis + yazi

This commit is contained in:
2026-10-06 05:40:37 +02:00
parent ac8adf9554
commit 4264a4c05c
8 changed files with 612 additions and 7 deletions
+129
View File
@@ -0,0 +1,129 @@
-- ~/.config/vis/build.lua
-- Runs the nearest build.sh, shows the output, and can jump to the first
-- Odin error. Loaded from visrc.lua.
local M = {}
-- args: list of flags passed through to build.sh, e.g. { 'run' }
function M.run(args)
-- find the nearest build.sh, searching upward from vis's working dir
local p = io.popen('pwd')
local dir = p and p:read('*l')
if p then p:close() end
while dir and dir ~= '' do
local f = io.open(dir .. '/build.sh', 'r')
if f then
f:close()
break
end
dir = dir:match('^(.*)/[^/]*$')
end
if not dir or dir == '' then
vis:info('No build.sh found in this directory or any parent')
return
end
-- save the current buffer so the build sees your latest changes
local win = vis.win
if win and win.file and win.file.modified and win.file.path then
vis:command('w')
end
-- shell-quote each flag and the directory
local quoted = {}
for _, a in ipairs(args) do
table.insert(quoted, "'" .. a:gsub("'", "'\\''") .. "'")
end
local argstr = table.concat(quoted, ' ')
local qdir = "'" .. dir:gsub("'", "'\\''") .. "'"
local display = ('./build.sh ' .. table.concat(args, ' ')):gsub('%s+$', '')
local qdisplay = "'" .. display:gsub("'", "'\\''") .. "'"
local out_file = os.tmpname()
local status_file = os.tmpname()
local answer_file = os.tmpname()
local script = table.concat({
'saved=$(stty -g)',
'stty sane',
'cd ' .. qdir .. ' || exit 1',
'printf "\\n\\033[1m$ %s\\033[0m (in %s)\\n\\n" ' .. qdisplay .. ' ' .. qdir,
'{ if [ -x ./build.sh ]; then ./build.sh ' .. argstr
.. '; else bash ./build.sh ' .. argstr .. '; fi; echo $? > \''
.. status_file .. "'; } 2>&1 | tee '" .. out_file .. "'",
"st=$(cat '" .. status_file .. "')",
'if [ "$st" = 0 ]; then',
' printf "\\n\\033[32m[build ok]\\033[0m enter: back to vis "',
'else',
' printf "\\n\\033[31m[build failed: exit %s]\\033[0m '
.. 'enter: back to vis | e + enter: jump to first error " "$st"',
'fi',
'read -r ans',
"printf '%s' \"$ans\" > '" .. answer_file .. "'",
'stty "$saved"',
}, '\n')
-- leave the alternate screen so the build output lands in your normal
-- terminal scrollback, run it, then come back to vis
local tty = io.open('/dev/tty', 'w')
if tty then tty:write('\27[?1049l') tty:close() end
os.execute('{\n' .. script .. '\n} </dev/tty >/dev/tty 2>&1')
tty = io.open('/dev/tty', 'w')
if tty then tty:write('\27[?1049h') tty:close() end
vis:redraw()
-- read back exit status and the key you answered with
local f = io.open(status_file, 'r')
local status = f and f:read('*l')
if f then f:close() end
f = io.open(answer_file, 'r')
local answer = f and f:read('*l')
if f then f:close() end
-- first Odin error: `file.odin(12:5)` (default) or `file.odin:12:5` (unix)
local path, line, col
f = io.open(out_file, 'r')
if f then
for l in f:lines() do
path, line, col = l:match('^%s*(.-%.odin)%((%d+):(%d+)%)')
if not path then
path, line, col = l:match('^%s*(.-%.odin):(%d+):(%d+)')
end
if path then break end
end
f:close()
end
if path and path:sub(1, 1) ~= '/' then path = dir .. '/' .. path end
os.remove(out_file)
os.remove(status_file)
os.remove(answer_file)
if status == '0' then
vis:info('build ok: ' .. display)
return
end
if not path then
vis:info('build failed: exit ' .. (status or '?'))
return
end
if answer ~= 'e' then
vis:info(string.format('build failed: first error at %s:%s', path, line))
return
end
-- jump to the error: open the file unless it's already the current one
local current = vis.win and vis.win.file and vis.win.file.path
if current ~= path then
if vis.win.file.modified then
vis:info('Buffer has unsaved changes — :w first (or use :e! manually)')
return
end
vis:command(string.format("e '%s'", path))
end
vis.win.selection:to(tonumber(line), tonumber(col))
end
return M