mirror of
https://github.com/zyedidia/micro
synced 2024-09-30 05:06:02 +00:00
Add plugin info.json support
This commit is contained in:
parent
26c545267d
commit
adaddba696
|
@ -1,6 +1,7 @@
|
|||
package action
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
@ -52,7 +53,7 @@ func InitCommands() {
|
|||
"help": Command{(*BufPane).HelpCmd, HelpComplete},
|
||||
"eval": Command{(*BufPane).EvalCmd, nil},
|
||||
"log": Command{(*BufPane).ToggleLogCmd, nil},
|
||||
"plugin": Command{(*BufPane).PluginCmd, nil},
|
||||
"plugin": Command{(*BufPane).PluginCmd, PluginComplete},
|
||||
"reload": Command{(*BufPane).ReloadCmd, nil},
|
||||
"reopen": Command{(*BufPane).ReopenCmd, nil},
|
||||
"cd": Command{(*BufPane).CdCmd, buffer.FileComplete},
|
||||
|
@ -115,6 +116,8 @@ func CommandAction(cmd string) BufKeyAction {
|
|||
}
|
||||
}
|
||||
|
||||
var PluginCmds = []string{"list", "info", "version"}
|
||||
|
||||
// PluginCmd installs, removes, updates, lists, or searches for given plugins
|
||||
func (h *BufPane) PluginCmd(args []string) {
|
||||
if len(args) <= 0 {
|
||||
|
@ -132,10 +135,82 @@ func (h *BufPane) PluginCmd(args []string) {
|
|||
} else {
|
||||
en = "disabled"
|
||||
}
|
||||
WriteLog(fmt.Sprintf("%s: %s\n", pl.Name, en))
|
||||
WriteLog(fmt.Sprintf("%s: %s", pl.Name, en))
|
||||
if pl.Default {
|
||||
WriteLog(" (default)\n")
|
||||
} else {
|
||||
WriteLog("\n")
|
||||
}
|
||||
}
|
||||
WriteLog("Default plugins come pre-installed with micro.")
|
||||
case "version":
|
||||
if len(args) <= 1 {
|
||||
InfoBar.Error("No plugin provided to give info for")
|
||||
return
|
||||
}
|
||||
found := false
|
||||
for _, pl := range config.Plugins {
|
||||
if pl.Name == args[1] {
|
||||
found = true
|
||||
if pl.Info == nil {
|
||||
InfoBar.Message("Sorry no version for", pl.Name)
|
||||
return
|
||||
}
|
||||
|
||||
WriteLog("Version: " + pl.Info.Vstr + "\n")
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
InfoBar.Message(args[1], "is not installed")
|
||||
}
|
||||
case "info":
|
||||
if len(args) <= 1 {
|
||||
InfoBar.Error("No plugin provided to give info for")
|
||||
return
|
||||
}
|
||||
found := false
|
||||
for _, pl := range config.Plugins {
|
||||
if pl.Name == args[1] {
|
||||
found = true
|
||||
if pl.Info == nil {
|
||||
InfoBar.Message("Sorry no info for ", pl.Name)
|
||||
return
|
||||
}
|
||||
|
||||
var buffer bytes.Buffer
|
||||
buffer.WriteString("Name: ")
|
||||
buffer.WriteString(pl.Info.Name)
|
||||
buffer.WriteString("\n")
|
||||
buffer.WriteString("Description: ")
|
||||
buffer.WriteString(pl.Info.Desc)
|
||||
buffer.WriteString("\n")
|
||||
buffer.WriteString("Website: ")
|
||||
buffer.WriteString(pl.Info.Site)
|
||||
buffer.WriteString("\n")
|
||||
buffer.WriteString("Installation link: ")
|
||||
buffer.WriteString(pl.Info.Install)
|
||||
buffer.WriteString("\n")
|
||||
buffer.WriteString("Version: ")
|
||||
buffer.WriteString(pl.Info.Vstr)
|
||||
buffer.WriteString("\n")
|
||||
buffer.WriteString("Requirements:")
|
||||
buffer.WriteString("\n")
|
||||
for _, r := range pl.Info.Require {
|
||||
buffer.WriteString(" - ")
|
||||
buffer.WriteString(r)
|
||||
buffer.WriteString("\n")
|
||||
}
|
||||
|
||||
WriteLog(buffer.String())
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
InfoBar.Message(args[1], "is not installed")
|
||||
return
|
||||
}
|
||||
default:
|
||||
valid = false
|
||||
InfoBar.Error("Not a valid plugin command")
|
||||
return
|
||||
}
|
||||
|
||||
if valid && h.Buf.Type != buffer.BTLog {
|
||||
|
|
|
@ -197,6 +197,62 @@ func OptionValueComplete(b *buffer.Buffer) ([]string, []string) {
|
|||
return completions, suggestions
|
||||
}
|
||||
|
||||
// OptionComplete autocompletes options
|
||||
func PluginCmdComplete(b *buffer.Buffer) ([]string, []string) {
|
||||
c := b.GetActiveCursor()
|
||||
input, argstart := buffer.GetArg(b)
|
||||
|
||||
var suggestions []string
|
||||
for _, cmd := range PluginCmds {
|
||||
if strings.HasPrefix(cmd, input) {
|
||||
suggestions = append(suggestions, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(suggestions)
|
||||
completions := make([]string, len(suggestions))
|
||||
for i := range suggestions {
|
||||
completions[i] = util.SliceEndStr(suggestions[i], c.X-argstart)
|
||||
}
|
||||
return completions, suggestions
|
||||
}
|
||||
|
||||
// PluginComplete completes values for the plugin command
|
||||
func PluginComplete(b *buffer.Buffer) ([]string, []string) {
|
||||
c := b.GetActiveCursor()
|
||||
l := b.LineBytes(c.Y)
|
||||
l = util.SliceStart(l, c.X)
|
||||
input, argstart := buffer.GetArg(b)
|
||||
|
||||
completeValue := false
|
||||
args := bytes.Split(l, []byte{' '})
|
||||
if len(args) >= 2 {
|
||||
for _, cmd := range PluginCmds {
|
||||
if cmd == string(args[len(args)-2]) {
|
||||
completeValue = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !completeValue {
|
||||
return PluginCmdComplete(b)
|
||||
}
|
||||
|
||||
var suggestions []string
|
||||
for _, pl := range config.Plugins {
|
||||
if strings.HasPrefix(pl.Name, input) {
|
||||
suggestions = append(suggestions, pl.Name)
|
||||
}
|
||||
}
|
||||
sort.Strings(suggestions)
|
||||
|
||||
completions := make([]string, len(suggestions))
|
||||
for i := range suggestions {
|
||||
completions[i] = util.SliceEndStr(suggestions[i], c.X-argstart)
|
||||
}
|
||||
return completions, suggestions
|
||||
}
|
||||
|
||||
// // MakeCompletion registers a function from a plugin for autocomplete commands
|
||||
// func MakeCompletion(function string) Completion {
|
||||
// pluginCompletions = append(pluginCompletions, LuaFunctionComplete(function))
|
||||
|
|
|
@ -65,10 +65,11 @@ func RunPluginFnBool(fn string, args ...lua.LValue) (bool, error) {
|
|||
}
|
||||
|
||||
type Plugin struct {
|
||||
Name string // name of plugin
|
||||
Info RuntimeFile // json file containing info
|
||||
Srcs []RuntimeFile // lua files
|
||||
Loaded bool
|
||||
Name string // name of plugin
|
||||
Info *PluginInfo // json file containing info
|
||||
Srcs []RuntimeFile // lua files
|
||||
Loaded bool
|
||||
Default bool // pre-installed plugin
|
||||
}
|
||||
|
||||
func (p *Plugin) IsEnabled() bool {
|
||||
|
|
66
internal/config/plugin_manager.go
Normal file
66
internal/config/plugin_manager.go
Normal file
|
@ -0,0 +1,66 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrMissingName = errors.New("Missing or empty name field")
|
||||
ErrMissingDesc = errors.New("Missing or empty description field")
|
||||
ErrMissingSite = errors.New("Missing or empty website field")
|
||||
ErrMissingInstall = errors.New("Missing or empty install field")
|
||||
ErrMissingVstr = errors.New("Missing or empty versions field")
|
||||
ErrMissingRequire = errors.New("Missing or empty require field")
|
||||
)
|
||||
|
||||
// PluginInfo contains all the needed info about a plugin
|
||||
// The info is just strings and are not used beyond that (except
|
||||
// the Site and Install fields should be valid URLs). This means
|
||||
// that the requirements for example can be formatted however the
|
||||
// plugin maker decides, the fields will only be parsed by humans
|
||||
// Name: name of plugin
|
||||
// Desc: description of plugin
|
||||
// Site: home website of plugin
|
||||
// Install: install link for plugin (can be link to repo or zip file)
|
||||
// Vstr: version
|
||||
// Require: list of dependencies and requirements
|
||||
type PluginInfo struct {
|
||||
Name string `json:"name"`
|
||||
Desc string `json:"description"`
|
||||
Site string `json:"website"`
|
||||
Install string `json:"install"`
|
||||
Vstr string `json:"version"`
|
||||
Require []string `json:"require"`
|
||||
}
|
||||
|
||||
// NewPluginInfo parses a JSON input into a valid PluginInfo struct
|
||||
// Returns an error if there are any missing fields or any invalid fields
|
||||
// There are no optional fields in a plugin info json file
|
||||
func NewPluginInfo(data []byte) (*PluginInfo, error) {
|
||||
var info PluginInfo
|
||||
|
||||
dec := json.NewDecoder(bytes.NewReader(data))
|
||||
// dec.DisallowUnknownFields() // Force errors
|
||||
|
||||
if err := dec.Decode(&info); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if len(info.Name) == 0 {
|
||||
// return nil, ErrMissingName
|
||||
// } else if len(info.Desc) == 0 {
|
||||
// return nil, ErrMissingDesc
|
||||
// } else if len(info.Site) == 0 {
|
||||
// return nil, ErrMissingSite
|
||||
// } else if len(info.Install) == 0 {
|
||||
// return nil, ErrMissingInstall
|
||||
// } else if len(info.Vstr) == 0 {
|
||||
// return nil, ErrMissingVstr
|
||||
// } else if len(info.Require) == 0 {
|
||||
// return nil, ErrMissingRequire
|
||||
// }
|
||||
|
||||
return &info, nil
|
||||
}
|
|
@ -154,7 +154,11 @@ func InitRuntimeFiles() {
|
|||
if strings.HasSuffix(f.Name(), ".lua") {
|
||||
p.Srcs = append(p.Srcs, realFile(filepath.Join(plugdir, d.Name(), f.Name())))
|
||||
} else if f.Name() == "info.json" {
|
||||
p.Info = realFile(filepath.Join(plugdir, d.Name(), "info.json"))
|
||||
data, err := ioutil.ReadFile(filepath.Join(plugdir, d.Name(), "info.json"))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
p.Info, _ = NewPluginInfo(data)
|
||||
}
|
||||
}
|
||||
Plugins = append(Plugins, p)
|
||||
|
@ -167,11 +171,16 @@ func InitRuntimeFiles() {
|
|||
if srcs, err := AssetDir(filepath.Join(plugdir, d)); err == nil {
|
||||
p := new(Plugin)
|
||||
p.Name = d
|
||||
p.Default = true
|
||||
for _, f := range srcs {
|
||||
if strings.HasSuffix(f, ".lua") {
|
||||
p.Srcs = append(p.Srcs, assetFile(filepath.Join(plugdir, d, f)))
|
||||
} else if f == "info.json" {
|
||||
p.Info = assetFile(filepath.Join(plugdir, d, "info.json"))
|
||||
data, err := Asset(filepath.Join(plugdir, d, "info.json"))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
p.Info, _ = NewPluginInfo(data)
|
||||
}
|
||||
}
|
||||
Plugins = append(Plugins, p)
|
||||
|
|
File diff suppressed because one or more lines are too long
10
runtime/plugins/autoclose/info.json
Normal file
10
runtime/plugins/autoclose/info.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "linter",
|
||||
"description": "Automatically places closing characters for quotes, parentheses, brackets, etc...",
|
||||
"website": "https://github.com/zyedidia/micro",
|
||||
"install": "https://github.com/zyedidia/micro",
|
||||
"version": "1.0.0",
|
||||
"require": [
|
||||
"micro >= 2.0.0"
|
||||
]
|
||||
}
|
10
runtime/plugins/comment/info.json
Normal file
10
runtime/plugins/comment/info.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "comment",
|
||||
"description": "Support for automatically commenting blocks of code. Extensible and multiple languages supported.",
|
||||
"website": "https://github.com/zyedidia/micro",
|
||||
"install": "https://github.com/zyedidia/micro",
|
||||
"version": "1.0.0",
|
||||
"require": [
|
||||
"micro >= 2.0.0"
|
||||
]
|
||||
}
|
10
runtime/plugins/ftoptions/info.json
Normal file
10
runtime/plugins/ftoptions/info.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "ftoptions",
|
||||
"description": "Sets basic options based on the filetype (for example Makefiles require tabs).",
|
||||
"website": "https://github.com/zyedidia/micro",
|
||||
"install": "https://github.com/zyedidia/micro",
|
||||
"version": "1.0.0",
|
||||
"require": [
|
||||
"micro >= 2.0.0"
|
||||
]
|
||||
}
|
10
runtime/plugins/linter/info.json
Normal file
10
runtime/plugins/linter/info.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "linter",
|
||||
"description": "Automatic code linting for a variety of languages.",
|
||||
"website": "https://github.com/zyedidia/micro",
|
||||
"install": "https://github.com/zyedidia/micro",
|
||||
"version": "1.0.0",
|
||||
"require": [
|
||||
"micro >= 2.0.0"
|
||||
]
|
||||
}
|
10
runtime/plugins/literate/info.json
Normal file
10
runtime/plugins/literate/info.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "linter",
|
||||
"description": "Highlighting and language support for the Literate programming tool.",
|
||||
"website": "https://github.com/zyedidia/Literate",
|
||||
"install": "https://github.com/zyedidia/micro",
|
||||
"version": "1.0.0",
|
||||
"require": [
|
||||
"micro >= 2.0.0"
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue