First I want to say I love Micro. It's got just the right blend of functionality and simplicity that works for much of what I do. I typically stay away from bloated IDE's, and my normal go-to is Sublime but sometimes even that is a bit more than I want. I like the minimal linting provided by Micro but jshint is a little dated. A lot of people are moving to ESLint for JavaScript.
Micro's built-in linter doesn't support ESLint by default. This was also the subject of https://github.com/zyedidia/micro/issues/1089.
I'm generalizing this issue to adding support for any linter.
I am willing to do that myself and make a PR, but I'm a little confused as to how to go about it. From what I can tell, I should make my own plugin first and make sure it works. > help linter tells me
The linter plugin also allows users to extend the supported filetypes. From inside another micro plugin, the function
linter.makeLintercan be called to register a new filetype. Here is the spec for themakeLinterfunction:
linter.makeLinter(name, filetype, cmd, args, errorformat, os, whitelist, domatch, loffset, coffset, callback)
Then, it gives an example.
Below is an example for including a linter for any filetype using the
misspelllinter which checks for misspelled words in a file.
local config = import("micro/config")
config.RegisterCommonOption("misspell", true)
function init()
-- uses the default linter plugin
-- matches any filetype
linter.makeLinter("misspell", "", "misspell", {"%f"}, "%f:%l:%c: %m", {}, false, true, 0, 0, hasMisspell)
end
function hasMisspell(buf)
return buf.Settings["misspell"]
end
So let me get this straight. config.Registerregisters a new plugin called misspell and has it default to being enabled. hasMisspell is a check for whether it is enabled in Micro's settings. linter.makeLinter is the line that defines the linter in Micro. Once I get that working, I can submit a PR with the makeLinter call included in https://github.com/zyedidia/micro/blob/04f281bf1d79d2f8178e99ff0f2443b411e4dc1d/runtime/plugins/linter/linter.lua#L68-L86
Version: 2.0.6
Commit hash: 60846f5
Compiled on June 24, 2020
ok here's what I've got:
ESLint on an example file splash-page.js with eslint -f compact splash-page.js outputs
/home/efrem/Dropbox/Coding/Projects/Heatflask/frontend/src/js/splash-page.js: line 13, col 7, Error - 'ga' is assigned a value but never used. (no-unused-vars)
/home/efrem/Dropbox/Coding/Projects/Heatflask/frontend/src/js/splash-page.js: line 20, col 1, Error - Mixed spaces and tabs. (no-mixed-spaces-and-tabs)
so for eslint.lua I have
local config = import("micro/config")
config.RegisterCommonOption("eslint", true)
function init()
-- linter.makeLinter("eslint", "javascript", "eslint", {"-f","compact","%f"}, "%f: line %l,.+, %m", {}, false, true, 0, 0, hasESLint)
linter.makeLinter("eslint", "javascript", "eslint", {"-f","compact","%f"}, ".+: line %l,.+, %m", {})
end
function hasESLint(buf)
return buf.Settings["eslint"]
end
When starting micro I get the error
eslint:4: invalid number of function arguments (3 expected, got 2)
stack traceback:
[G]: in function 'RegisterCommonOption'
eslint:4: in main chunk
[G]: ?
According to plugins.md,
RegisterCommonOption(pl string, name string, defaultvalue interface{}): registers a new option with for the given plugin. The name of the option will be pl.name, and will have the given default value. Since this registers a common option, the option will be modifiable on a per-buffer basis, while also having a global value (in the GlobalSettings map).
I'm confused by this.
Also I tried removing the RegisterCommonOption call and removing the hasESLint callback but then no linting happens.
Thanks in advance for any suggestions!
Ah sorry about that it appears the documentation example for the linter is slightly outdated. Now plugins all automatically have an option associated with them (to enable or disable individual plugins) so there is no need to register a "misspell" option to enable/disable the plugin functionality. FYI the third argument is the default value for that option, i.e. true, or false, or 1, etc... The interface{} type means in Go-speak that the argument may be any type.
For your case, you can just get rid of all the option stuff, and make sure you use the %f directive in your regex so that the filename is parsed from the error message. The following plugin worked for me (I put this code in ~/.config/micro/init.lua, but it could also be a separate plugin in ~/.config/micro/plug/eslint/ for example):
function init()
linter.makeLinter("eslint", "javascript", "eslint", {"-f","compact","%f"}, "%f: line %l, col %c, %m")
end
I also added %c since you may as well match the column number as well because eslint includes it.
Since you say that eslint is the new standard for javascript, I have gone ahead and added it to the default linter plugin.
Thanks @zyedidia! One more thing: I tried updating with > plugin update linter and got
Checking for plugin updates
unable to find a matching version for "linter"
In fact I cannot update at all. If I do a general > plugin update I get
Checking for plugin updates
unable to find a matching version for "filemanager"
I guess because filemanager is the first plugin it tries and then quits there. For now I'll just put what you did in ~/.config/micro/init.lua.
The linter plugin is a default plugin, meaning it is bundled directly inside the micro binary. This means that it can't be updated like a normal plugin. The way to update it would be to download a new version of micro (i.e. the nightly build). Of course you can also just put the code from above in init.lua.