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