Full extensible linter support

This commit is contained in:
Zachary Yedidia
2019-08-03 15:19:28 -07:00
parent 4027081e0e
commit be136a4648
6 changed files with 159 additions and 82 deletions

View File

@@ -28,6 +28,8 @@ func LuaImport(pkg string) *lua.LTable {
return luaImportMicroShell()
case "micro/buffer":
return luaImportMicroBuffer()
case "micro/config":
return luaImportMicroConfig()
case "micro/util":
return luaImportMicroUtil()
default:
@@ -43,7 +45,20 @@ func luaImportMicro() *lua.LTable {
ulua.L.SetField(pkg, "InfoBar", luar.New(ulua.L, action.GetInfoBar))
ulua.L.SetField(pkg, "Log", luar.New(ulua.L, log.Println))
ulua.L.SetField(pkg, "SetStatusInfoFn", luar.New(ulua.L, display.SetStatusInfoFnLua))
// ulua.L.SetField(pkg, "TryBindKey", luar.New(ulua.L, action.TryBindKey))
return pkg
}
func luaImportMicroConfig() *lua.LTable {
pkg := ulua.L.NewTable()
ulua.L.SetField(pkg, "MakeCommand", luar.New(ulua.L, action.LuaMakeCommand))
ulua.L.SetField(pkg, "FileComplete", luar.New(ulua.L, buffer.FileComplete))
ulua.L.SetField(pkg, "HelpComplete", luar.New(ulua.L, action.HelpComplete))
ulua.L.SetField(pkg, "OptionComplete", luar.New(ulua.L, action.OptionComplete))
ulua.L.SetField(pkg, "OptionValueComplete", luar.New(ulua.L, action.OptionValueComplete))
ulua.L.SetField(pkg, "NoComplete", luar.New(ulua.L, nil))
ulua.L.SetField(pkg, "TryBindKey", luar.New(ulua.L, action.TryBindKey))
return pkg
}

View File

@@ -10,8 +10,12 @@ import (
"strings"
"unicode/utf8"
luar "layeh.com/gopher-luar"
lua "github.com/yuin/gopher-lua"
"github.com/zyedidia/micro/internal/buffer"
"github.com/zyedidia/micro/internal/config"
ulua "github.com/zyedidia/micro/internal/lua"
"github.com/zyedidia/micro/internal/screen"
"github.com/zyedidia/micro/internal/shell"
"github.com/zyedidia/micro/internal/util"
@@ -63,16 +67,29 @@ func InitCommands() {
// MakeCommand is a function to easily create new commands
// This can be called by plugins in Lua so that plugins can define their own commands
// func MakeCommand(name, function string, completions ...Completion) {
// action := commandActions[function]
// // if _, ok := commandActions[function]; !ok {
// // If the user seems to be binding a function that doesn't exist
// // We hope that it's a lua function that exists and bind it to that
// // action = LuaFunctionCommand(function)
// // }
//
// commands[name] = Command{action, completions}
// }
func LuaMakeCommand(name, function string, completer buffer.Completer) {
action := LuaFunctionCommand(function)
commands[name] = Command{action, completer}
}
// LuaFunctionCommand returns a normal function
// so that a command can be bound to a lua function
func LuaFunctionCommand(fn string) func(*BufPane, []string) {
luaFn := strings.Split(fn, ".")
plName, plFn := luaFn[0], luaFn[1]
pl := config.FindPlugin(plName)
return func(bp *BufPane, args []string) {
var luaArgs []lua.LValue
luaArgs = append(luaArgs, luar.New(ulua.L, bp))
for _, v := range args {
luaArgs = append(luaArgs, luar.New(ulua.L, v))
}
_, err := pl.Call(plFn, luaArgs...)
if err != nil {
screen.TermMessage(err)
}
}
}
// CommandEditAction returns a bindable function that opens a prompt with
// the given string and executes the command when the user presses
@@ -456,7 +473,6 @@ func (h *BufPane) SetLocalCmd(args []string) {
if err != nil {
InfoBar.Error(err)
}
}
// ShowCmd shows the value of the given option

View File

@@ -95,9 +95,7 @@ func (p *Plugin) Load() error {
return err
}
p.Loaded = true
if _, ok := GlobalSettings[p.Name]; !ok {
AddOption(p.Name, true)
}
RegisterGlobalOption(p.Name, true)
}
return nil
}

File diff suppressed because one or more lines are too long

View File

@@ -114,12 +114,35 @@ func WriteSettings(filename string) error {
return err
}
// AddOption creates a new option. This is meant to be called by plugins to add options.
func AddOption(name string, value interface{}) error {
GlobalSettings[name] = value
err := WriteSettings(ConfigDir + "/settings.json")
if err != nil {
return errors.New("Error writing settings.json file: " + err.Error())
// RegisterCommonOption creates a new option. This is meant to be called by plugins to add options.
func RegisterCommonOption(name string, defaultvalue interface{}) error {
if v, ok := GlobalSettings[name]; !ok {
defaultCommonSettings[name] = defaultvalue
GlobalSettings[name] = defaultvalue
err := WriteSettings(ConfigDir + "/settings.json")
if err != nil {
return errors.New("Error writing settings.json file: " + err.Error())
}
} else {
defaultCommonSettings[name] = v
}
return nil
}
func RegisterLocalOption(name string, defaultvalue interface{}) {
defaultLocalSettings[name] = defaultvalue
}
func RegisterGlobalOption(name string, defaultvalue interface{}) error {
if v, ok := GlobalSettings[name]; !ok {
defaultGlobalSettings[name] = defaultvalue
GlobalSettings[name] = defaultvalue
err := WriteSettings(ConfigDir + "/settings.json")
if err != nil {
return errors.New("Error writing settings.json file: " + err.Error())
}
} else {
defaultGlobalSettings[name] = v
}
return nil
}
@@ -129,42 +152,40 @@ func GetGlobalOption(name string) interface{} {
return GlobalSettings[name]
}
func DefaultCommonSettings() map[string]interface{} {
return map[string]interface{}{
"autoindent": true,
"autosave": false,
"basename": false,
"colorcolumn": float64(0),
"cursorline": true,
"encoding": "utf-8",
"eofnewline": false,
"fastdirty": true,
"fileformat": "unix",
"ignorecase": false,
"indentchar": " ",
"keepautoindent": false,
"matchbrace": false,
"matchbraceleft": false,
"rmtrailingws": false,
"ruler": true,
"savecursor": false,
"saveundo": false,
"scrollbar": false,
"scrollmargin": float64(3),
"scrollspeed": float64(2),
"smartpaste": true,
"softwrap": false,
"splitbottom": true,
"splitright": true,
"statusformatl": "$(filename) $(modified)($(line),$(col)) $(opt:filetype) $(opt:fileformat) $(opt:encoding)",
"statusformatr": "$(bind:ToggleKeyMenu): show bindings, $(bind:ToggleHelp): toggle help",
"statusline": true,
"syntax": true,
"tabmovement": false,
"tabsize": float64(4),
"tabstospaces": false,
"useprimary": true,
}
var defaultCommonSettings = map[string]interface{}{
"autoindent": true,
"autosave": false,
"basename": false,
"colorcolumn": float64(0),
"cursorline": true,
"encoding": "utf-8",
"eofnewline": false,
"fastdirty": true,
"fileformat": "unix",
"ignorecase": false,
"indentchar": " ",
"keepautoindent": false,
"matchbrace": false,
"matchbraceleft": false,
"rmtrailingws": false,
"ruler": true,
"savecursor": false,
"saveundo": false,
"scrollbar": false,
"scrollmargin": float64(3),
"scrollspeed": float64(2),
"smartpaste": true,
"softwrap": false,
"splitbottom": true,
"splitright": true,
"statusformatl": "$(filename) $(modified)($(line),$(col)) $(opt:filetype) $(opt:fileformat) $(opt:encoding)",
"statusformatr": "$(bind:ToggleKeyMenu): show bindings, $(bind:ToggleHelp): toggle help",
"statusline": true,
"syntax": true,
"tabmovement": false,
"tabsize": float64(4),
"tabstospaces": false,
"useprimary": true,
}
func GetInfoBarOffset() int {
@@ -178,41 +199,64 @@ func GetInfoBarOffset() int {
return offset
}
var defaultGlobalSettings = map[string]interface{}{
"colorscheme": "default",
"infobar": true,
"keymenu": false,
"mouse": true,
"savehistory": true,
"sucmd": "sudo",
"termtitle": false,
}
// DefaultGlobalSettings returns the default global settings for micro
// Note that colorscheme is a global only option
func DefaultGlobalSettings() map[string]interface{} {
common := DefaultCommonSettings()
common["colorscheme"] = "default"
common["infobar"] = true
common["keymenu"] = false
common["mouse"] = true
common["pluginchannels"] = []string{"https://raw.githubusercontent.com/micro-editor/plugin-channel/master/channel.json"}
common["pluginrepos"] = []string{}
common["savehistory"] = true
common["sucmd"] = "sudo"
common["termtitle"] = false
return common
globalsettings := make(map[string]interface{})
for k, v := range defaultCommonSettings {
globalsettings[k] = v
}
for k, v := range defaultGlobalSettings {
globalsettings[k] = v
}
return globalsettings
}
// LocalSettings is a list of the local only settings
var LocalSettings = []string{"filetype", "readonly"}
var defaultLocalSettings = map[string]interface{}{
"filetype": "unknown",
"readonly": false,
}
// DefaultLocalSettings returns the default local settings
// Note that filetype is a local only option
func DefaultLocalSettings() map[string]interface{} {
common := DefaultCommonSettings()
common["filetype"] = "unknown"
common["readonly"] = false
return common
localsettings := make(map[string]interface{})
for k, v := range defaultCommonSettings {
localsettings[k] = v
}
for k, v := range defaultLocalSettings {
localsettings[k] = v
}
return localsettings
}
// DefaultAllSettings returns a map of all settings and their
// default values (both local and global settings)
func DefaultAllSettings() map[string]interface{} {
global := DefaultGlobalSettings()
local := DefaultLocalSettings()
for k, v := range global {
local[k] = v
allsettings := make(map[string]interface{})
for k, v := range defaultCommonSettings {
allsettings[k] = v
}
return local
for k, v := range defaultGlobalSettings {
allsettings[k] = v
}
for k, v := range defaultLocalSettings {
allsettings[k] = v
}
return allsettings
}
func GetNativeValue(option string, realValue interface{}, value string) (interface{}, error) {

View File

@@ -2,7 +2,7 @@ local runtime = import("runtime")
local filepath = import("path/filepath")
local shell = import("micro/shell")
local buffer = import("micro/buffer")
local micro = import("micro")
local config = import("micro/config")
local linters = {}
@@ -66,6 +66,13 @@ function init()
makeLinter("switfc", "swift", "xcrun", {"swiftc", "%f"}, "%f:%l:%d+:.+: %m", {"darwin"}, true)
makeLinter("switfc", "swiftc", {"%f"}, "%f:%l:%d+:.+: %m", {"linux"}, true)
makeLinter("yaml", "yaml", "yamllint", {"--format", "parsable", "%f"}, "%f:%l:%d+:.+ %m")
config.MakeCommand("lint", "linter.lintCmd", config.NoComplete)
end
function lintCmd(bp)
bp:Save()
runLinter(bp.Buf)
end
function contains(list, element)
@@ -107,7 +114,6 @@ function runLinter(buf)
end
function onSave(bp)
micro.Log("SAVE")
runLinter(bp.Buf)
return false
end
@@ -119,8 +125,6 @@ function lint(buf, linter, cmd, args, errorformat)
end
function onExit(output, buf, linter, errorformat)
micro.Log("ONEXIT")
micro.Log(output)
local lines = split(output, "\n")
local regex = errorformat:gsub("%%f", "(..-)"):gsub("%%l", "(%d+)"):gsub("%%m", "(.+)")