build.lua (4134B)
1 local gf = require('goto-ref') 2 local util = require('util') 3 4 vis.events.subscribe(vis.events.FILE_SAVE_PRE, function(file) 5 local M = require('plugins/vis-lint') 6 M.logger = function(str, level) 7 if level == M.log.ERROR then 8 vis:message(str) 9 end 10 end 11 M.fixers["bibtex"] = { "bibtidy" } 12 M.fixers["c"] = { "clang-format -fallback-style=none" } 13 M.fixers["cpp"] = { "clang-format -fallback-style=none" } 14 M.fixers["json"] = { "jq --tab" } 15 return M.fix(file) 16 end) 17 18 local logger = function(clear, ostr, estr) 19 if ostr == nil and estr == nil then return end 20 if clear then util.message_clear(vis) end 21 if ostr then vis:message(ostr) end 22 if estr then vis:message(estr) end 23 vis:message(string.rep("=", vis.win.viewport.width / 2)) 24 end 25 26 local file_exists = function(file) 27 local f = io.open(file, "r") 28 if f ~= nil then io.close(f) return true else return false end 29 end 30 31 local default_error_search = function(error_string) 32 gf.setup_iterators_from_text(error_string, function(str) 33 return str:find(" error:") or 34 str:find(": note:") or 35 str:find(": warning:") 36 37 end) 38 end 39 40 local function build_files(win) 41 local build_tex = function (f) 42 local cmd = "lualatex -halt-on-error -shell-escape " 43 44 -- build in draft mode to update references 45 local err, ostr = vis:pipe(cmd .. "-draftmode " .. f.name) 46 if err ~= 0 then logger(true, ostr) return false end 47 48 local fp = util.splitext(f.name) 49 -- update refrences 50 vis:command("!biber " .. fp .. " >/dev/null") 51 -- update glossary 52 -- vis:command("!makeglossaries " .. fp .. " >/dev/null") 53 54 -- build actual pdf 55 err = vis:pipe(cmd .. f.name) 56 if err ~= 0 then return false end 57 58 -- reload pdf (zathura does this automatically) 59 -- vis:command('!pkill -HUP mupdf') 60 61 return true 62 end 63 64 local run_python = function (f) 65 local _, ostr, estr = vis:pipe('python ' .. f.name) 66 logger(true, ostr, estr) 67 if estr then return false end 68 return true 69 end 70 71 local run_sh = function (f) 72 local _, ostr, estr = vis:pipe("$PWD/" .. f.name) 73 logger(true, ostr, estr) 74 default_error_search(estr) 75 return true 76 end 77 78 local build_c = function (f) 79 local cmd 80 if cmd == nil and file_exists('./build') then cmd = '$PWD/build --debug' end 81 if cmd == nil and file_exists('./build.sh') then cmd = '$PWD/build.sh' end 82 if cmd == nil and file_exists('Makefile') then cmd = 'make' end 83 if not cmd then return false, 'failed to determine method to build' end 84 85 local _, _, estr = vis:pipe(cmd) 86 logger(true, nil, estr) 87 default_error_search(estr) 88 return true 89 end 90 91 local lang = { 92 bash = run_sh, 93 c = build_c, 94 cpp = build_c, 95 latex = build_tex, 96 python = run_python, 97 rc = run_sh, 98 } 99 100 local builder = lang[win.syntax] 101 if builder == nil then 102 builder = function () 103 vis:info(win.syntax .. ': filetype not supported') 104 return false 105 end 106 end 107 108 win:map(vis.modes.NORMAL, " c", function () 109 vis:command('X/.*/w') 110 local s = "built: " .. win.file.name 111 local ret, info = builder(win.file) 112 if info then s = s .. " | info: " .. info end 113 114 -- check for FIXMEs/TODOs 115 local _, out = vis:pipe('ag --depth=0 --count "(FIXME|TODO)"') 116 if out then 117 local file_count_table = gf.generate_line_indices(out) 118 local count = 0 119 for i = 1, #file_count_table do 120 local file, occurences = table.unpack(file_count_table[i]) 121 count = count + tonumber(occurences) 122 end 123 if count ~= 0 then s = s .. " | FIXME/TODOs: " .. tostring(count) end 124 end 125 126 if ret == true then vis:info(s) end 127 return ret 128 end, "build file in current window") 129 end 130 131 local cached_command 132 vis:command_register("build", function(argv) 133 if #argv == 0 and cached_command == nil then vis:info("build cmd [arg ...]") return false end 134 if #argv ~= 0 then cached_command = table.concat(argv, " ") end 135 136 vis:command('X/.*/w') 137 vis:info("running: " .. cached_command) 138 vis:redraw() 139 local code, ostr, estr = vis:pipe(cached_command) 140 if code ~= 0 then 141 logger(true, ostr, estr) 142 default_error_search(estr) 143 end 144 end, "run command and try to collect errors") 145 146 vis.events.subscribe(vis.events.WIN_OPEN, build_files)