init.lua (3155B)
1 -- See LICENSE for copyright details 2 local lint = {} 3 4 lint.linters = {} 5 lint.linters["bash"] = {"shellcheck -"} 6 lint.linters["json"] = {"jq"} 7 lint.linters["lua"] = {"luacheck --no-color -"} 8 lint.linters["man"] = {"mandoc -T lint"} 9 lint.linters["meson"] = {"muon check -"} 10 lint.linters["python"] = {"black --quiet --check -", "isort --check -"} 11 lint.linters["rust"] = {"rustfmt --check", "clippy-driver -"} 12 13 lint.fixers = {} 14 lint.fixers["c"] = {"clang-format -fallback-style=none"} 15 lint.fixers["cpp"] = {"clang-format -fallback-style=none"} 16 lint.fixers["json"] = {"jq"} 17 lint.fixers["meson"] = {"muon fmt -"} 18 lint.fixers["python"] = {"black -", "isort -"} 19 lint.fixers["rust"] = {"rustfmt"} 20 21 lint.log = {} 22 lint.log.INFO = 1 23 lint.log.ERROR = 2 24 lint.log.OUTPUT = 3 25 26 lint.logger = function(str, level) 27 if level == lint.log.INFO then 28 vis:info(str) 29 else 30 vis:message(str) 31 end 32 end 33 34 local run_on_file = function(cmd, file, range, modify) 35 if range == nil or range.finish - range.start <= 1 then 36 range = {start = 0, finish = file.size} 37 end 38 local ret, ostr, estr = vis:pipe(file, range, cmd) 39 if ostr ~= nil or estr ~= nil then 40 if (modify and ostr) then 41 local pos = vis.win.selection.pos 42 file:delete(range.start, range.finish) 43 file:insert(range.start, ostr) 44 vis.win.selection.pos = pos 45 else 46 if ostr then lint.logger(ostr, lint.log.OUTPUT) end 47 end 48 if estr then lint.logger(estr, lint.log.ERROR) end 49 vis:redraw() 50 end 51 return ret 52 end 53 54 local run_actions_on_file = function(actions, file, range, modify) 55 local cmds = actions[vis.win.syntax] 56 if cmds == nil or #cmds == 0 then 57 lint.logger("vis-lint: action not defined for vis.win.syntax = " 58 .. (vis.win.syntax or "undefined"), lint.log.INFO) 59 return 60 end 61 -- print this to separate different outputs in the message buffer 62 local prefix = "--- " 63 lint.logger(prefix .. "vis-lint: (" .. os.date() .. ")") 64 local all_succeeded = true 65 local failure_count = 0 66 for _, cmd in ipairs(cmds) do 67 lint.logger(prefix .. "piping " 68 .. (file.name or "buffer") 69 .. (range and "<" .. range.start .. "," .. range.finish .. ">" or "") 70 .. " to `" .. cmd .. "`") 71 local ret = run_on_file(cmd, file, range, modify) 72 if ret ~= 0 then 73 all_succeeded = false 74 failure_count = failure_count + 1 75 -- exit early if modify was specified 76 if modify then 77 lint.logger("Command failed with exit code: " .. ret, lint.log.ERROR) 78 return false 79 end 80 end 81 end 82 lint.logger(prefix .. #cmds .. " commands done, " .. failure_count .. " reported a problem") 83 return all_succeeded 84 end 85 86 lint.lint = function(file, range) 87 return run_actions_on_file(lint.linters, file, range) 88 end 89 90 lint.fix = function(file, range) 91 return run_actions_on_file(lint.fixers, file, range, true) 92 end 93 94 vis:command_register("lint", function(argv, force, win, selection, range) 95 return lint.lint(win.file, range) 96 end, "Lint the current file and display output in the message window") 97 98 vis:command_register("fix", function(argv, force, win, selection, range) 99 return lint.fix(win.file, range) 100 end, "Pipe the current file through defined fixers. Modifies the buffer.") 101 102 return lint