-- Runs ./build.sh from vis's cwd (project root), logs the output for the -- error picker (pickers.errors), and returns to vis on Enter/Esc. local M = {} -- last build's output; pickers.errors() reads it M.log = '/tmp/vis-build.log' -- single-quote a string for the shell local function q(s) return "'" .. s:gsub("'", "'\\''") .. "'" end -- write a raw escape sequence straight to the terminal local function tty(s) local t = io.open('/dev/tty', 'w') if t then t:write(s) t:close() end end local function exists(path) local f = io.open(path, 'r') if f then f:close() end return f ~= nil end -- args: flags passed through to build.sh, e.g. { 'run' } function M.run(args) if not exists('build.sh') then vis:info('No build.sh in current directory') return end -- save so the build sees your latest changes local file = vis.win and vis.win.file if file and file.modified and file.path then vis:command('w') end local parts = {} for _, a in ipairs(args or {}) do parts[#parts + 1] = q(a) end local argstr = table.concat(parts, ' ') local script = table.concat({ 'saved=$(stty -g); stty sane', -- script runs the build on a pty (colors stay on) and logs it to M.log 'script -qefc ' .. q('bash ./build.sh ' .. argstr) .. ' ' .. q(M.log), 'st=$?', [[printf '\n[exit %s] enter/esc: back to vis ' "$st"]], [[while IFS= read -rsn1 k; do [ -z "$k" ] || [ "$k" = $'\e' ] && break; done]], 'stty "$saved"', }, '\n') -- leave the alt screen and clear it, so each run starts fresh and the -- output lands in normal scrollback; run; come back to vis tty('\27[?1049l\27[H\27[2J') os.execute('bash -c ' .. q(script) .. ' /dev/tty 2>&1') tty('\27[?1049h') vis:redraw() end -- --------------------------------------------------------------------------- -- events -- --------------------------------------------------------------------------- -- re-index tags in the background after saving an .odin file -- (build.sh -t re-scans src and merges it with the cached stdlib tags) vis.events.subscribe(vis.events.FILE_SAVE_POST, function(file, path) -- luacheck: no unused args if path and path:match('%.odin$') and exists('build.sh') then os.execute('bash ./build.sh -t /dev/null 2>&1 &') end end) return M