]> git.lizzy.rs Git - micro.git/blob - runtime/plugins/linter/linter.lua
6cf07de73446771c56d9c36b9051624953d95799
[micro.git] / runtime / plugins / linter / linter.lua
1 if GetOption("linter") == nil then
2     AddOption("linter", true)
3 end
4
5 MakeCommand("lint", "linter.runLinter", 0)
6
7 function runLinter()
8     CurView():Save(false)
9     local ft = CurView().Buf.FileType
10     local file = CurView().Buf.Path
11     local devnull = "/dev/null"
12     if OS == "windows" then
13         devnull = "NUL"
14     end
15     if ft == "go" then
16         lint("gobuild", "go build -o " .. devnull, "%f:%l: %m")
17         lint("golint", "golint " .. CurView().Buf.Path, "%f:%l:%d+: %m")
18     elseif ft == "lua" then
19         lint("luacheck", "luacheck --no-color " .. file, "%f:%l:%d+: %m")
20     elseif ft == "python" then
21         lint("pyflakes", "pyflakes " .. file, "%f:%l: %m")
22     elseif ft == "c" then
23         lint("gcc", "gcc -fsyntax-only -Wall -Wextra " .. file, "%f:%l:%d+:.+: %m")
24     elseif ft == "d" then
25         lint("dmd", "dmd -color=off -o- -w -wi -c " .. file, "%f%(%l%):.+: %m")
26     elseif ft == "java" then
27         lint("javac", "javac " .. file, "%f:%l: error: %m")
28     elseif ft == "javascript" then
29         lint("jshint", "jshint " .. file, "%f: line %l,.+, %m")
30     end
31 end
32
33 function onSave()
34     if GetOption("linter") then
35         runLinter()
36     else
37         CurView():ClearAllGutterMessages()
38     end
39 end
40
41 function lint(linter, cmd, errorformat)
42     CurView():ClearGutterMessages(linter)
43
44     JobStart(cmd, "", "", "linter.onExit", linter, errorformat)
45 end
46
47 function onExit(output, linter, errorformat)
48     local lines = split(output, "\n")
49
50     local regex = errorformat:gsub("%%f", "(.+)"):gsub("%%l", "(%d+)"):gsub("%%m", "(.+)")
51     for _,line in ipairs(lines) do
52         -- Trim whitespace
53         line = line:match("^%s*(.+)%s*$")
54         if string.find(line, regex) then
55             local file, line, msg = string.match(line, regex)
56             if basename(CurView().Buf.Path) == basename(file) then
57                 CurView():GutterMessage(linter, tonumber(line), msg, 2)
58             end
59         end
60     end
61 end
62
63 function split(str, sep)
64     local result = {}
65     local regex = ("([^%s]+)"):format(sep)
66     for each in str:gmatch(regex) do
67         table.insert(result, each)
68     end
69     return result
70 end
71
72 function basename(file)
73     local name = string.gsub(file, "(.*/)(.*)", "%2")
74     return name
75 end