]> git.lizzy.rs Git - micro.git/commitdiff
Add plugin manager
authorZachary Yedidia <zyedidia@gmail.com>
Sun, 2 Feb 2020 04:54:38 +0000 (23:54 -0500)
committerZachary Yedidia <zyedidia@gmail.com>
Sun, 2 Feb 2020 04:54:38 +0000 (23:54 -0500)
20 files changed:
cmd/micro/micro.go
go.sum
internal/action/command.go
internal/config/plugin_installer.go [new file with mode: 0644]
internal/config/plugin_installer_test.go [new file with mode: 0644]
internal/config/plugin_manager.go
internal/config/rtfiles.go
internal/config/runtime.go
internal/config/settings.go
runtime/plugins/autoclose/autoclose.lua
runtime/plugins/autoclose/info.json [deleted file]
runtime/plugins/comment/comment.lua
runtime/plugins/comment/info.json [deleted file]
runtime/plugins/ftoptions/ftoptions.lua
runtime/plugins/ftoptions/info.json [deleted file]
runtime/plugins/linter/info.json [deleted file]
runtime/plugins/linter/linter.lua
runtime/plugins/literate/info.json [deleted file]
runtime/plugins/literate/literate.lua
runtime/plugins/status/status.lua

index ba387693a36dfcd75617cb579ee9bfc9c2467fec..59cbb802fbc5b94afee02ac3f3e47f82d9008f55 100644 (file)
@@ -30,6 +30,7 @@ var (
        flagConfigDir = flag.String("config-dir", "", "Specify a custom location for the configuration directory")
        flagOptions   = flag.Bool("options", false, "Show all option help")
        flagDebug     = flag.Bool("debug", false, "Enable debug mode (prints debug info to ./log.txt)")
+       flagPlugin    = flag.String("plugin", "", "Plugin command")
        optionFlags   map[string]*string
 )
 
@@ -40,7 +41,6 @@ func InitFlags() {
                fmt.Println("    \tSpecify a custom location for the configuration directory")
                fmt.Println("[FILE]:LINE:COL")
                fmt.Println("    \tSpecify a line and column to start the cursor at when opening a buffer")
-               fmt.Println("    \tThis can also be done by opening file:LINE:COL")
                fmt.Println("-options")
                fmt.Println("    \tShow all option help")
                fmt.Println("-debug")
@@ -48,6 +48,14 @@ func InitFlags() {
                fmt.Println("-version")
                fmt.Println("    \tShow the version number and information")
 
+               fmt.Print("\nMicro's plugin's can be managed at the command line with the following commands.\n")
+               fmt.Println("-plugin install [PLUGIN]...")
+               fmt.Println("    \tInstall plugin(s)")
+               fmt.Println("-plugin remove [PLUGIN]...")
+               fmt.Println("    \tRemove plugin(s)")
+               fmt.Println("-plugin update [PLUGIN]...")
+               fmt.Println("    \tUpdate plugin(s) (if no argument is given, updates all plugins)")
+
                fmt.Print("\nMicro's options can also be set via command line arguments for quick\nadjustments. For real configuration, please use the settings.json\nfile (see 'help options').\n\n")
                fmt.Println("-option value")
                fmt.Println("    \tSet `option` to `value` for this session")
@@ -92,6 +100,87 @@ func InitFlags() {
        }
 }
 
+// DoPluginFlags parses and executes any -plugin flags
+func DoPluginFlags() {
+       if *flagPlugin != "" {
+               config.LoadAllPlugins()
+
+               args := flag.Args()
+
+               switch *flagPlugin {
+               case "install":
+                       installedVersions := config.GetInstalledVersions(false)
+                       for _, plugin := range args {
+                               pp := config.GetAllPluginPackages().Get(plugin)
+                               if pp == nil {
+                                       fmt.Println("Unknown plugin \"" + plugin + "\"")
+                               } else if err := pp.IsInstallable(); err != nil {
+                                       fmt.Println("Error installing ", plugin, ": ", err)
+                               } else {
+                                       for _, installed := range installedVersions {
+                                               if pp.Name == installed.Pack().Name {
+                                                       if pp.Versions[0].Version.Compare(installed.Version) == 1 {
+                                                               fmt.Println(pp.Name, " is already installed but out-of-date: use 'plugin update ", pp.Name, "' to update")
+                                                       } else {
+                                                               fmt.Println(pp.Name, " is already installed")
+                                                       }
+                                               }
+                                       }
+                                       pp.Install()
+                               }
+                       }
+
+               case "remove":
+                       removed := ""
+                       for _, plugin := range args {
+                               // check if the plugin exists.
+                               for _, p := range config.Plugins {
+                                       if p.Name == plugin && p.Default {
+                                               fmt.Println("Default plugins cannot be removed, but can be disabled via settings.")
+                                               continue
+                                       }
+                                       if p.Name == plugin {
+                                               config.UninstallPlugin(plugin)
+                                               removed += plugin + " "
+                                               continue
+                                       }
+                               }
+                       }
+                       if removed != "" {
+                               fmt.Println("Removed ", removed)
+                       } else {
+                               fmt.Println("No plugins removed")
+                       }
+               case "update":
+                       config.UpdatePlugins(args)
+               case "list":
+                       plugins := config.GetInstalledVersions(false)
+                       fmt.Println("The following plugins are currently installed:")
+                       for _, p := range plugins {
+                               fmt.Printf("%s (%s)\n", p.Pack().Name, p.Version)
+                       }
+               case "search":
+                       plugins := config.SearchPlugin(args)
+                       fmt.Println(len(plugins), " plugins found")
+                       for _, p := range plugins {
+                               fmt.Println("----------------")
+                               fmt.Println(p.String())
+                       }
+                       fmt.Println("----------------")
+               case "available":
+                       packages := config.GetAllPluginPackages()
+                       fmt.Println("Available Plugins:")
+                       for _, pkg := range packages {
+                               fmt.Println(pkg.Name)
+                       }
+               default:
+                       fmt.Println("Invalid plugin command")
+                       os.Exit(1)
+               }
+               os.Exit(0)
+       }
+}
+
 // LoadInput determines which files should be loaded into buffers
 // based on the input stored in flag.Args()
 func LoadInput() []*buffer.Buffer {
@@ -180,6 +269,8 @@ func main() {
                }
        }
 
+       DoPluginFlags()
+
        screen.Init()
 
        // If we have an error, we can exit cleanly and not completely
@@ -254,7 +345,7 @@ func main() {
        select {
        case event = <-events:
                action.Tabs.HandleEvent(event)
-       case <-time.After(20 * time.Millisecond):
+       case <-time.After(10 * time.Millisecond):
                // time out after 10ms
        }
 
diff --git a/go.sum b/go.sum
index cd432bdc07f6b53d64f4f660eaa984351e5a121f..170b4be862dc6f1a4267e675a5b2672e18bb9a22 100644 (file)
--- a/go.sum
+++ b/go.sum
@@ -50,10 +50,6 @@ github.com/zyedidia/poller v1.0.1 h1:Tt9S3AxAjXwWGNiC2TUdRJkQDZSzCBNVQ4xXiQ7440s
 github.com/zyedidia/poller v1.0.1/go.mod h1:vZXJOHGDcuK08GXhF6IAY0ZFd2WcgOR5DOTp84Uk5eE=
 github.com/zyedidia/pty v2.0.0+incompatible h1:Ou5vXL6tvjst+RV8sUFISbuKDnUJPhnpygApMFGweqw=
 github.com/zyedidia/pty v2.0.0+incompatible/go.mod h1:4y9l9yJZNxRa7GB/fB+mmDmGkG3CqmzLf4vUxGGotEA=
-github.com/zyedidia/tcell v1.4.0 h1:uhAz+bdB3HHlVP2hff3WURkI+pERNwgVfy27oi1Gb2A=
-github.com/zyedidia/tcell v1.4.0/go.mod h1:HhlbMSCcGX15rFDB+Q1Lk3pKEOocsCUAQC3zhZ9sadA=
-github.com/zyedidia/tcell v1.4.1 h1:zLci8cg1SLINjwSePZ1yUWnYOnZXMyr4h+zaOvhu5K8=
-github.com/zyedidia/tcell v1.4.1/go.mod h1:HhlbMSCcGX15rFDB+Q1Lk3pKEOocsCUAQC3zhZ9sadA=
 github.com/zyedidia/tcell v1.4.2 h1:JWMDs6O1saINPIR5M3kNqlWJwkfnBZeZDZszEJi3BW8=
 github.com/zyedidia/tcell v1.4.2/go.mod h1:HhlbMSCcGX15rFDB+Q1Lk3pKEOocsCUAQC3zhZ9sadA=
 github.com/zyedidia/terminal v0.0.0-20180726154117-533c623e2415 h1:752dTQ5OatJ9M5ULK2+9lor+nzyZz+LYDo3WGngg3Rc=
index 8b1d2aff1b51751c92fdb4731918733ee3ccb417..bd303a186de7260693e55bb6ae3b578f8ce6d1d8 100644 (file)
@@ -124,102 +124,7 @@ 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 {
-               InfoBar.Error("Not enough arguments, see 'help commands'")
-               return
-       }
-
-       valid := true
-       switch args[0] {
-       case "list":
-               for _, pl := range config.Plugins {
-                       var en string
-                       if pl.IsEnabled() {
-                               en = "enabled"
-                       } else {
-                               en = "disabled"
-                       }
-                       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:
-               InfoBar.Error("Not a valid plugin command")
-               return
-       }
-
-       if valid && h.Buf.Type != buffer.BTLog {
-               OpenLogBuf(h)
-       }
+       InfoBar.Error("Plugin command disabled")
 }
 
 // RetabCmd changes all spaces to tabs or all tabs to spaces
diff --git a/internal/config/plugin_installer.go b/internal/config/plugin_installer.go
new file mode 100644 (file)
index 0000000..0ca38dd
--- /dev/null
@@ -0,0 +1,630 @@
+package config
+
+import (
+       "archive/zip"
+       "bytes"
+       "fmt"
+       "io"
+       "io/ioutil"
+       "net/http"
+       "os"
+       "path/filepath"
+       "sort"
+       "strings"
+       "sync"
+
+       "github.com/blang/semver"
+       lua "github.com/yuin/gopher-lua"
+       "github.com/zyedidia/json5"
+       ulua "github.com/zyedidia/micro/internal/lua"
+       "github.com/zyedidia/micro/internal/util"
+)
+
+var (
+       allPluginPackages PluginPackages
+)
+
+// CorePluginName is a plugin dependency name for the micro core.
+const CorePluginName = "micro"
+
+// PluginChannel contains an url to a json list of PluginRepository
+type PluginChannel string
+
+// PluginChannels is a slice of PluginChannel
+type PluginChannels []PluginChannel
+
+// PluginRepository contains an url to json file containing PluginPackages
+type PluginRepository string
+
+// PluginPackage contains the meta-data of a plugin and all available versions
+type PluginPackage struct {
+       Name        string
+       Description string
+       Author      string
+       Tags        []string
+       Versions    PluginVersions
+}
+
+// PluginPackages is a list of PluginPackage instances.
+type PluginPackages []*PluginPackage
+
+// PluginVersion descripes a version of a PluginPackage. Containing a version, download url and also dependencies.
+type PluginVersion struct {
+       pack    *PluginPackage
+       Version semver.Version
+       Url     string
+       Require PluginDependencies
+}
+
+func (pv *PluginVersion) Pack() *PluginPackage {
+       return pv.pack
+}
+
+// PluginVersions is a slice of PluginVersion
+type PluginVersions []*PluginVersion
+
+// PluginDependency descripes a dependency to another plugin or micro itself.
+type PluginDependency struct {
+       Name  string
+       Range semver.Range
+}
+
+// PluginDependencies is a slice of PluginDependency
+type PluginDependencies []*PluginDependency
+
+func (pp *PluginPackage) String() string {
+       buf := new(bytes.Buffer)
+       buf.WriteString("Plugin: ")
+       buf.WriteString(pp.Name)
+       buf.WriteRune('\n')
+       if pp.Author != "" {
+               buf.WriteString("Author: ")
+               buf.WriteString(pp.Author)
+               buf.WriteRune('\n')
+       }
+       if pp.Description != "" {
+               buf.WriteRune('\n')
+               buf.WriteString(pp.Description)
+       }
+       return buf.String()
+}
+
+func fetchAllSources(count int, fetcher func(i int) PluginPackages) PluginPackages {
+       wgQuery := new(sync.WaitGroup)
+       wgQuery.Add(count)
+
+       results := make(chan PluginPackages)
+
+       wgDone := new(sync.WaitGroup)
+       wgDone.Add(1)
+       var packages PluginPackages
+       for i := 0; i < count; i++ {
+               go func(i int) {
+                       results <- fetcher(i)
+                       wgQuery.Done()
+               }(i)
+       }
+       go func() {
+               packages = make(PluginPackages, 0)
+               for res := range results {
+                       packages = append(packages, res...)
+               }
+               wgDone.Done()
+       }()
+       wgQuery.Wait()
+       close(results)
+       wgDone.Wait()
+       return packages
+}
+
+// Fetch retrieves all available PluginPackages from the given channels
+func (pc PluginChannels) Fetch() PluginPackages {
+       return fetchAllSources(len(pc), func(i int) PluginPackages {
+               return pc[i].Fetch()
+       })
+}
+
+// Fetch retrieves all available PluginPackages from the given channel
+func (pc PluginChannel) Fetch() PluginPackages {
+       resp, err := http.Get(string(pc))
+       if err != nil {
+               fmt.Println("Failed to query plugin channel:\n", err)
+               return PluginPackages{}
+       }
+       defer resp.Body.Close()
+       decoder := json5.NewDecoder(resp.Body)
+
+       var repositories []PluginRepository
+       if err := decoder.Decode(&repositories); err != nil {
+               fmt.Println("Failed to decode channel data:\n", err)
+               return PluginPackages{}
+       }
+       return fetchAllSources(len(repositories), func(i int) PluginPackages {
+               return repositories[i].Fetch()
+       })
+}
+
+// Fetch retrieves all available PluginPackages from the given repository
+func (pr PluginRepository) Fetch() PluginPackages {
+       resp, err := http.Get(string(pr))
+       if err != nil {
+               fmt.Println("Failed to query plugin repository:\n", err)
+               return PluginPackages{}
+       }
+       defer resp.Body.Close()
+       decoder := json5.NewDecoder(resp.Body)
+
+       var plugins PluginPackages
+       if err := decoder.Decode(&plugins); err != nil {
+               fmt.Println("Failed to decode repository data:\n", err)
+               return PluginPackages{}
+       }
+       if len(plugins) > 0 {
+               return PluginPackages{plugins[0]}
+       }
+       return nil
+       // return plugins
+}
+
+// UnmarshalJSON unmarshals raw json to a PluginVersion
+func (pv *PluginVersion) UnmarshalJSON(data []byte) error {
+       var values struct {
+               Version semver.Version
+               Url     string
+               Require map[string]string
+       }
+
+       if err := json5.Unmarshal(data, &values); err != nil {
+               return err
+       }
+       pv.Version = values.Version
+       pv.Url = values.Url
+       pv.Require = make(PluginDependencies, 0)
+
+       for k, v := range values.Require {
+               // don't add the dependency if it's the core and
+               // we have a unknown version number.
+               // in that case just accept that dependency (which equals to not adding it.)
+               if k != CorePluginName || !isUnknownCoreVersion() {
+                       if vRange, err := semver.ParseRange(v); err == nil {
+                               pv.Require = append(pv.Require, &PluginDependency{k, vRange})
+                       }
+               }
+       }
+       return nil
+}
+
+// UnmarshalJSON unmarshals raw json to a PluginPackage
+func (pp *PluginPackage) UnmarshalJSON(data []byte) error {
+       var values struct {
+               Name        string
+               Description string
+               Author      string
+               Tags        []string
+               Versions    PluginVersions
+       }
+       if err := json5.Unmarshal(data, &values); err != nil {
+               return err
+       }
+       pp.Name = values.Name
+       pp.Description = values.Description
+       pp.Author = values.Author
+       pp.Tags = values.Tags
+       pp.Versions = values.Versions
+       for _, v := range pp.Versions {
+               v.pack = pp
+       }
+       return nil
+}
+
+// GetAllPluginPackages gets all PluginPackages which may be available.
+func GetAllPluginPackages() PluginPackages {
+       if allPluginPackages == nil {
+               getOption := func(name string) []string {
+                       data := GetGlobalOption(name)
+                       if strs, ok := data.([]string); ok {
+                               return strs
+                       }
+                       if ifs, ok := data.([]interface{}); ok {
+                               result := make([]string, len(ifs))
+                               for i, urlIf := range ifs {
+                                       if url, ok := urlIf.(string); ok {
+                                               result[i] = url
+                                       } else {
+                                               return nil
+                                       }
+                               }
+                               return result
+                       }
+                       return nil
+               }
+
+               channels := PluginChannels{}
+               for _, url := range getOption("pluginchannels") {
+                       channels = append(channels, PluginChannel(url))
+               }
+               repos := []PluginRepository{}
+               for _, url := range getOption("pluginrepos") {
+                       repos = append(repos, PluginRepository(url))
+               }
+               allPluginPackages = fetchAllSources(len(repos)+1, func(i int) PluginPackages {
+                       if i == 0 {
+                               return channels.Fetch()
+                       }
+                       return repos[i-1].Fetch()
+               })
+       }
+       return allPluginPackages
+}
+
+func (pv PluginVersions) find(ppName string) *PluginVersion {
+       for _, v := range pv {
+               if v.pack.Name == ppName {
+                       return v
+               }
+       }
+       return nil
+}
+
+// Len returns the number of pluginversions in this slice
+func (pv PluginVersions) Len() int {
+       return len(pv)
+}
+
+// Swap two entries of the slice
+func (pv PluginVersions) Swap(i, j int) {
+       pv[i], pv[j] = pv[j], pv[i]
+}
+
+// Less returns true if the version at position i is greater then the version at position j (used for sorting)
+func (pv PluginVersions) Less(i, j int) bool {
+       return pv[i].Version.GT(pv[j].Version)
+}
+
+// Match returns true if the package matches a given search text
+func (pp PluginPackage) Match(text string) bool {
+       text = strings.ToLower(text)
+       for _, t := range pp.Tags {
+               if strings.ToLower(t) == text {
+                       return true
+               }
+       }
+       if strings.Contains(strings.ToLower(pp.Name), text) {
+               return true
+       }
+
+       if strings.Contains(strings.ToLower(pp.Description), text) {
+               return true
+       }
+
+       return false
+}
+
+// IsInstallable returns true if the package can be installed.
+func (pp PluginPackage) IsInstallable() error {
+       _, err := GetAllPluginPackages().Resolve(GetInstalledVersions(true), PluginDependencies{
+               &PluginDependency{
+                       Name:  pp.Name,
+                       Range: semver.Range(func(v semver.Version) bool { return true }),
+               }})
+       return err
+}
+
+// SearchPlugin retrieves a list of all PluginPackages which match the given search text and
+// could be or are already installed
+func SearchPlugin(texts []string) (plugins PluginPackages) {
+       plugins = make(PluginPackages, 0)
+
+pluginLoop:
+       for _, pp := range GetAllPluginPackages() {
+               for _, text := range texts {
+                       if !pp.Match(text) {
+                               continue pluginLoop
+                       }
+               }
+
+               if err := pp.IsInstallable(); err == nil {
+                       plugins = append(plugins, pp)
+               }
+       }
+       return
+}
+
+func isUnknownCoreVersion() bool {
+       _, err := semver.ParseTolerant(util.Version)
+       return err != nil
+}
+
+func newStaticPluginVersion(name, version string) *PluginVersion {
+       vers, err := semver.ParseTolerant(version)
+
+       if err != nil {
+               if vers, err = semver.ParseTolerant("0.0.0-" + version); err != nil {
+                       vers = semver.MustParse("0.0.0-unknown")
+               }
+       }
+       pl := &PluginPackage{
+               Name: name,
+       }
+       pv := &PluginVersion{
+               pack:    pl,
+               Version: vers,
+       }
+       pl.Versions = PluginVersions{pv}
+       return pv
+}
+
+// GetInstalledVersions returns a list of all currently installed plugins including an entry for
+// micro itself. This can be used to resolve dependencies.
+func GetInstalledVersions(withCore bool) PluginVersions {
+       result := PluginVersions{}
+       if withCore {
+               result = append(result, newStaticPluginVersion(CorePluginName, util.Version))
+       }
+
+       for _, p := range Plugins {
+               version := GetInstalledPluginVersion(p.Name)
+               if pv := newStaticPluginVersion(p.Name, version); pv != nil {
+                       result = append(result, pv)
+               }
+       }
+
+       return result
+}
+
+// GetInstalledPluginVersion returns the string of the exported VERSION variable of a loaded plugin
+func GetInstalledPluginVersion(name string) string {
+       plugin := ulua.L.GetGlobal(name)
+       if plugin != lua.LNil {
+               version := ulua.L.GetField(plugin, "VERSION")
+               if str, ok := version.(lua.LString); ok {
+                       return string(str)
+
+               }
+       }
+       return ""
+}
+
+// DownloadAndInstall downloads and installs the given plugin and version
+func (pv *PluginVersion) DownloadAndInstall() error {
+       fmt.Printf("Downloading %q (%s) from %q\n", pv.pack.Name, pv.Version, pv.Url)
+       resp, err := http.Get(pv.Url)
+       if err != nil {
+               return err
+       }
+       defer resp.Body.Close()
+       data, err := ioutil.ReadAll(resp.Body)
+       if err != nil {
+               return err
+       }
+       zipbuf := bytes.NewReader(data)
+       z, err := zip.NewReader(zipbuf, zipbuf.Size())
+       if err != nil {
+               return err
+       }
+       targetDir := filepath.Join(ConfigDir, "plug", pv.pack.Name)
+       dirPerm := os.FileMode(0755)
+       if err = os.MkdirAll(targetDir, dirPerm); err != nil {
+               return err
+       }
+
+       // Check if all files in zip are in the same directory.
+       // this might be the case if the plugin zip contains the whole plugin dir
+       // instead of its content.
+       var prefix string
+       allPrefixed := false
+       for i, f := range z.File {
+               parts := strings.Split(f.Name, "/")
+               if i == 0 {
+                       prefix = parts[0]
+               } else if parts[0] != prefix {
+                       allPrefixed = false
+                       break
+               } else {
+                       // switch to true since we have at least a second file
+                       allPrefixed = true
+               }
+       }
+
+       // Install files and directory's
+       for _, f := range z.File {
+               parts := strings.Split(f.Name, "/")
+               if allPrefixed {
+                       parts = parts[1:]
+               }
+
+               targetName := filepath.Join(targetDir, filepath.Join(parts...))
+               if f.FileInfo().IsDir() {
+                       if err := os.MkdirAll(targetName, dirPerm); err != nil {
+                               return err
+                       }
+               } else {
+                       basepath := filepath.Dir(targetName)
+
+                       if err := os.MkdirAll(basepath, dirPerm); err != nil {
+                               return err
+                       }
+
+                       content, err := f.Open()
+                       if err != nil {
+                               return err
+                       }
+                       defer content.Close()
+                       target, err := os.Create(targetName)
+                       if err != nil {
+                               return err
+                       }
+                       defer target.Close()
+                       if _, err = io.Copy(target, content); err != nil {
+                               return err
+                       }
+               }
+       }
+       return nil
+}
+
+func (pl PluginPackages) Get(name string) *PluginPackage {
+       for _, p := range pl {
+               if p.Name == name {
+                       return p
+               }
+       }
+       return nil
+}
+
+func (pl PluginPackages) GetAllVersions(name string) PluginVersions {
+       result := make(PluginVersions, 0)
+       p := pl.Get(name)
+       if p != nil {
+               for _, v := range p.Versions {
+                       result = append(result, v)
+               }
+       }
+       return result
+}
+
+func (req PluginDependencies) Join(other PluginDependencies) PluginDependencies {
+       m := make(map[string]*PluginDependency)
+       for _, r := range req {
+               m[r.Name] = r
+       }
+       for _, o := range other {
+               cur, ok := m[o.Name]
+               if ok {
+                       m[o.Name] = &PluginDependency{
+                               o.Name,
+                               o.Range.AND(cur.Range),
+                       }
+               } else {
+                       m[o.Name] = o
+               }
+       }
+       result := make(PluginDependencies, 0, len(m))
+       for _, v := range m {
+               result = append(result, v)
+       }
+       return result
+}
+
+// Resolve resolves dependencies between different plugins
+func (all PluginPackages) Resolve(selectedVersions PluginVersions, open PluginDependencies) (PluginVersions, error) {
+       if len(open) == 0 {
+               return selectedVersions, nil
+       }
+       currentRequirement, stillOpen := open[0], open[1:]
+       if currentRequirement != nil {
+               if selVersion := selectedVersions.find(currentRequirement.Name); selVersion != nil {
+                       if currentRequirement.Range(selVersion.Version) {
+                               return all.Resolve(selectedVersions, stillOpen)
+                       }
+                       return nil, fmt.Errorf("unable to find a matching version for \"%s\"", currentRequirement.Name)
+               }
+               availableVersions := all.GetAllVersions(currentRequirement.Name)
+               sort.Sort(availableVersions)
+
+               for _, version := range availableVersions {
+                       if currentRequirement.Range(version.Version) {
+                               resolved, err := all.Resolve(append(selectedVersions, version), stillOpen.Join(version.Require))
+
+                               if err == nil {
+                                       return resolved, nil
+                               }
+                       }
+               }
+               return nil, fmt.Errorf("unable to find a matching version for \"%s\"", currentRequirement.Name)
+       }
+       return selectedVersions, nil
+}
+
+func (pv PluginVersions) install() {
+       anyInstalled := false
+       currentlyInstalled := GetInstalledVersions(true)
+
+       for _, sel := range pv {
+               if sel.pack.Name != CorePluginName {
+                       shouldInstall := true
+                       if pv := currentlyInstalled.find(sel.pack.Name); pv != nil {
+                               if pv.Version.NE(sel.Version) {
+                                       fmt.Println("Uninstalling", sel.pack.Name)
+                                       UninstallPlugin(sel.pack.Name)
+                               } else {
+                                       shouldInstall = false
+                               }
+                       }
+
+                       if shouldInstall {
+                               if err := sel.DownloadAndInstall(); err != nil {
+                                       fmt.Println(err)
+                                       return
+                               }
+                               anyInstalled = true
+                       }
+               }
+       }
+       if anyInstalled {
+               fmt.Println("One or more plugins installed.")
+       } else {
+               fmt.Println("Nothing to install / update")
+       }
+}
+
+// UninstallPlugin deletes the plugin folder of the given plugin
+func UninstallPlugin(name string) {
+       for _, p := range Plugins {
+               if p.Name == name {
+                       p.Loaded = false
+                       if err := os.RemoveAll(filepath.Join(ConfigDir, "plug", p.DirName)); err != nil {
+                               fmt.Println(err)
+                               return
+                       }
+               }
+       }
+}
+
+// Install installs the plugin
+func (pl PluginPackage) Install() {
+       selected, err := GetAllPluginPackages().Resolve(GetInstalledVersions(true), PluginDependencies{
+               &PluginDependency{
+                       Name:  pl.Name,
+                       Range: semver.Range(func(v semver.Version) bool { return true }),
+               }})
+       if err != nil {
+               fmt.Println(err)
+               return
+       }
+       selected.install()
+}
+
+// UpdatePlugins updates the given plugins
+func UpdatePlugins(plugins []string) {
+       // if no plugins are specified, update all installed plugins.
+       if len(plugins) == 0 {
+               for _, p := range Plugins {
+                       plugins = append(plugins, p.Name)
+               }
+       }
+
+       fmt.Println("Checking for plugin updates")
+       microVersion := PluginVersions{
+               newStaticPluginVersion(CorePluginName, util.Version),
+       }
+
+       var updates = make(PluginDependencies, 0)
+       for _, name := range plugins {
+               pv := GetInstalledPluginVersion(name)
+               r, err := semver.ParseRange(">=" + pv) // Try to get newer versions.
+               if err == nil {
+                       updates = append(updates, &PluginDependency{
+                               Name:  name,
+                               Range: r,
+                       })
+               }
+       }
+
+       selected, err := GetAllPluginPackages().Resolve(microVersion, updates)
+       if err != nil {
+               fmt.Println(err)
+               return
+       }
+       selected.install()
+}
diff --git a/internal/config/plugin_installer_test.go b/internal/config/plugin_installer_test.go
new file mode 100644 (file)
index 0000000..21413fc
--- /dev/null
@@ -0,0 +1,56 @@
+package config
+
+import (
+       "testing"
+
+       "github.com/blang/semver"
+
+       "github.com/zyedidia/json5"
+)
+
+func TestDependencyResolving(t *testing.T) {
+       js := `
+[{
+  "Name": "Foo",
+  "Versions": [{ "Version": "1.0.0" }, { "Version": "1.5.0" },{ "Version": "2.0.0" }]
+}, {
+  "Name": "Bar",
+  "Versions": [{ "Version": "1.0.0", "Require": {"Foo": ">1.0.0 <2.0.0"} }]
+}, {
+  "Name": "Unresolvable",
+  "Versions": [{ "Version": "1.0.0", "Require": {"Foo": "<=1.0.0", "Bar": ">0.0.0"} }]
+       }]
+`
+       var all PluginPackages
+       err := json5.Unmarshal([]byte(js), &all)
+       if err != nil {
+               t.Error(err)
+       }
+       selected, err := all.Resolve(PluginVersions{}, PluginDependencies{
+               &PluginDependency{"Bar", semver.MustParseRange(">=1.0.0")},
+       })
+
+       check := func(name, version string) {
+               v := selected.find(name)
+               expected := semver.MustParse(version)
+               if v == nil {
+                       t.Errorf("Failed to resolve %s", name)
+               } else if expected.NE(v.Version) {
+                       t.Errorf("%s resolved in wrong version %v", name, v)
+               }
+       }
+
+       if err != nil {
+               t.Error(err)
+       } else {
+               check("Foo", "1.5.0")
+               check("Bar", "1.0.0")
+       }
+
+       selected, err = all.Resolve(PluginVersions{}, PluginDependencies{
+               &PluginDependency{"Unresolvable", semver.MustParseRange(">0.0.0")},
+       })
+       if err == nil {
+               t.Error("Unresolvable package resolved:", selected)
+       }
+}
index 19f53cdc795766b12265211527c297cb88450fd7..d64aab11de81008ac8ce043e9bc4dd0e2802115b 100644 (file)
@@ -7,12 +7,9 @@ import (
 )
 
 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")
+       ErrMissingName = errors.New("Missing or empty name field")
+       ErrMissingDesc = errors.New("Missing or empty description field")
+       ErrMissingSite = errors.New("Missing or empty website field")
 )
 
 // PluginInfo contains all the needed info about a plugin
@@ -27,19 +24,16 @@ var (
 // 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"`
+       Name string `json:"Name"`
+       Desc string `json:"Description"`
+       Site string `json:"Website"`
 }
 
 // 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
+       var info []PluginInfo
 
        dec := json.NewDecoder(bytes.NewReader(data))
        // dec.DisallowUnknownFields() // Force errors
@@ -48,19 +42,5 @@ func NewPluginInfo(data []byte) (*PluginInfo, error) {
                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
+       return &info[0], nil
 }
index a6e7fe2a0cf65c549c120aa32151ddfcfaf17f6b..4ce263e9e97dacb0916cfa2be17015c66f36ddc8 100644 (file)
@@ -191,12 +191,16 @@ func InitRuntimeFiles() {
                        for _, f := range srcs {
                                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" {
-                                       data, err := ioutil.ReadFile(filepath.Join(plugdir, d.Name(), "info.json"))
+                               } else if strings.HasSuffix(f.Name(), ".json") {
+                                       data, err := ioutil.ReadFile(filepath.Join(plugdir, d.Name(), f.Name()))
                                        if err != nil {
                                                continue
                                        }
-                                       p.Info, _ = NewPluginInfo(data)
+                                       p.Info, err = NewPluginInfo(data)
+                                       if err != nil {
+                                               log.Println(err)
+                                               continue
+                                       }
                                        p.Name = p.Info.Name
                                }
                        }
@@ -220,12 +224,16 @@ func InitRuntimeFiles() {
                                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" {
-                                               data, err := Asset(filepath.Join(plugdir, d, "info.json"))
+                                       } else if strings.HasSuffix(f, ".json") {
+                                               data, err := Asset(filepath.Join(plugdir, d, f))
+                                               if err != nil {
+                                                       continue
+                                               }
+                                               p.Info, err = NewPluginInfo(data)
                                                if err != nil {
+                                                       log.Println(err)
                                                        continue
                                                }
-                                               p.Info, _ = NewPluginInfo(data)
                                                p.Name = p.Info.Name
                                        }
                                }
index 6f1b3cb1a406b1390a7eed823181edb739542065..643f5fc13092c1f7b53b48c29cc5917cb9a080c9 100644 (file)
 // runtime/help/plugins.md
 // runtime/help/tutorial.md
 // runtime/plugins/autoclose/autoclose.lua
-// runtime/plugins/autoclose/info.json
 // runtime/plugins/comment/comment.lua
-// runtime/plugins/comment/info.json
 // runtime/plugins/ftoptions/ftoptions.lua
-// runtime/plugins/ftoptions/info.json
-// runtime/plugins/linter/info.json
 // runtime/plugins/linter/linter.lua
 // runtime/plugins/literate/README.md
-// runtime/plugins/literate/info.json
 // runtime/plugins/literate/literate.lua
 // runtime/plugins/status/status.lua
 // runtime/syntax/LICENSE
@@ -993,7 +988,7 @@ func runtimeHelpTutorialMd() (*asset, error) {
        return a, nil
 }
 
-var _runtimePluginsAutocloseAutocloseLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x55\xd1\x6a\xdb\x4a\x10\x7d\xf7\x57\x0c\xba\x0f\x96\x88\xe5\x8b\xef\xd3\x25\xa0\x42\x93\x42\x31\x98\xb6\x24\x85\xb4\x24\x81\xac\x56\xb3\xd6\x12\x79\x57\x8c\x66\xeb\x94\x90\x7f\x2f\x2b\xd9\x8e\xe4\x2a\xb2\x0d\xd1\xc3\xda\xd2\xce\xd9\x99\x39\x73\x66\xb6\xb0\x52\x14\xe0\x1c\xeb\x02\x12\xd0\xab\xd2\x12\x87\xc1\x4a\x4b\xb2\xff\xfa\x8f\x41\x34\xda\x98\xb0\xfa\xbf\x65\xe1\x5f\x77\x7b\xc2\xb1\x95\x85\xad\xf0\x9b\xd0\x54\x41\x02\xcf\xc1\x5d\x70\x17\x04\x13\x08\xc6\x63\xbf\x3e\x3c\xf8\x35\x8c\xfc\xfa\xfc\xe2\xd7\xdb\xfb\xe0\xa5\x85\xfe\x82\xeb\x42\x9b\x16\xfe\x2f\xdb\x91\x72\x46\xb2\xb6\x06\x64\x2e\xe8\x23\x87\x15\xd3\x04\x74\x34\x02\x00\x88\x63\x28\x9c\x00\x6d\x32\x7c\xd2\x66\x09\xba\x02\x6b\x10\xac\x52\xa0\xc8\xae\x60\x69\x6b\x33\x42\x76\x64\x9a\x6c\xa7\x57\xce\xe0\xee\x98\x78\x16\x8d\xd0\x64\x2d\x2f\xd6\x78\x83\x30\x2d\x27\x40\x8d\x13\x65\x09\x34\x24\x30\x9b\xc0\x3f\x7b\x19\x67\xcd\xf9\xfe\xd1\x0a\x08\x92\x64\x1b\x65\xd7\xf0\x56\xdf\x4f\xe0\xbf\x08\x38\x47\xb3\x43\xf8\xa7\x61\x42\x3a\x5a\x68\x83\x90\x40\x5a\x4e\x2f\x9c\x3a\xf7\x6f\x61\x5a\x4e\x2f\x1d\x55\x96\xa6\x3f\xa3\x51\x07\xa5\xd5\xd6\xcd\x06\x39\x81\x57\xe3\x1f\x67\xb3\xe8\xf4\x40\xfc\x93\x96\xe7\x17\x42\x3e\x56\xa5\x90\x18\x46\x7d\xdb\x8d\x8b\x2b\xbd\xcc\xb9\xcf\x80\x50\x3c\x76\xbe\xd6\xd4\xee\x45\xde\x8a\x14\x3e\xc0\x0c\x84\xc9\x20\x6c\x4a\x33\xaf\x6e\x2c\x65\x97\xb9\xa0\x70\x20\xbf\x78\x16\x45\x60\x69\x88\x82\xf8\x10\x05\xfe\x88\x7e\x0e\x7a\x73\xe8\xfb\x7f\xb8\xe0\xb3\xf7\x2c\x78\x9b\xb6\x24\xa9\xdb\xb2\x96\xf2\xa5\x75\x86\xe7\xe6\x9a\x49\x9b\xe5\x96\x8c\x9a\x1f\x63\x19\x4e\xe1\xf5\xec\x4d\x52\xe2\xd8\x7f\x87\x71\x3c\x86\x1c\x09\x7d\x9b\xb1\x85\x0c\x09\x15\x1a\x89\xf5\x66\x69\xb5\x61\x24\xbf\xf1\x7a\xe6\xc2\x4a\x58\xe7\x5a\xe6\x1e\xe2\x19\x5a\x09\xd6\x52\x14\xc5\x6f\x58\x89\x0c\xfb\x1c\xad\x73\x34\x20\xad\xf9\x85\xc4\xbe\xa5\x97\x16\x2a\x26\x27\xb9\xf6\x59\x38\xd1\x07\x9a\x33\x18\xc4\xac\x36\x49\x71\x13\x19\xf9\xd8\x32\x48\x51\x0a\x57\x35\x41\xee\xba\x1c\x9f\x4a\xf4\x47\x0a\x30\xd6\xec\x62\x6f\x1c\xf5\x08\xbf\xae\xd1\xdc\x54\x48\x1c\xc6\x9d\xf4\x26\x83\x7d\x36\xd0\x44\x0b\x54\xc7\xf7\xd0\xfe\xff\xed\xef\x66\xb0\x31\x39\xdc\x1b\x63\x25\x61\x13\xef\x66\xc2\x86\x69\xd9\x38\x3b\x5a\x80\x1d\x63\xaf\x34\x48\x86\x5a\xae\x0d\x30\xf8\xc4\x87\x11\x67\xb3\x36\x66\xed\xe7\x7f\x23\xd7\xcf\xc8\x0b\x14\x99\x36\xcb\x9b\x5c\x33\x36\xf3\x68\xab\xec\x51\xef\x4c\xee\xdc\x23\xdd\xa9\xbc\x8b\xbe\xd3\xaa\x6d\xc0\x9b\xcd\xaa\x55\x2b\x95\x61\xf8\xc0\x4c\xed\xd6\xa1\x57\x12\x8d\xc9\x77\x91\xf6\x6e\x0f\xa9\x2f\xb8\x33\x01\x4c\xa7\xb0\xae\x7a\x0f\xbe\x66\x41\xfc\x55\x2d\xde\xf4\x3c\x28\xc6\x8d\xbc\x94\x28\x2a\x3c\x4a\x93\x87\x45\xf9\x7a\xc1\x6c\x05\x79\xdc\xf5\x7a\x92\x6c\xe1\x5d\xee\x48\x7f\x31\x0d\x09\xfe\xf4\xe1\x9f\x96\xe7\x9f\xb0\x40\x6e\xd7\xe2\x20\x7d\x7f\x02\x00\x00\xff\xff\x7d\xca\x8c\x58\xaa\x09\x00\x00"
+var _runtimePluginsAutocloseAutocloseLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x55\x51\x6b\xdb\x30\x10\x7e\xcf\xaf\x38\xbc\x87\xd8\x34\xf6\xea\x3d\x8d\x82\x07\x6b\x37\x46\x20\xb4\xa3\x1d\xeb\x46\x5b\xa8\x2c\x9f\x62\x51\x47\x32\x67\x69\xe9\x28\xfd\xef\x43\x76\x92\xda\x99\xeb\x24\x50\x3f\x28\xb1\x75\x9f\xee\xee\xbb\xef\x4e\x3f\xbf\x5e\x5e\x4d\x2f\xce\x21\x01\x2f\x8e\x8e\xa3\x63\x6f\x34\x2a\x34\x67\x05\x58\x6b\x64\x01\x09\xc8\x45\xa9\xc9\xf8\xde\x42\x72\xd2\xef\xdd\x47\x2f\x58\x9b\x18\xf1\xb1\x65\xe1\x5e\x37\x7b\xcc\x1a\xcd\x0b\x5d\xe1\x77\x26\xa9\x82\x04\x9e\xbc\x5b\xef\xd6\xf3\x26\xe0\x8d\xc7\x6e\xbd\xbf\x77\xab\x1f\xb8\xf5\xe9\xd9\xad\x37\x77\xde\x73\x0b\x7d\x8e\xcb\x42\xaa\x16\xfe\x3f\xdb\x91\xb0\x8a\x1b\xa9\x15\xf0\x9c\xd1\x67\xe3\x57\x86\x26\x20\x83\x11\x00\x40\x18\x42\x61\x19\x48\x95\xe1\xa3\x54\x73\x90\x15\x68\x85\xa0\x85\x00\x41\x7a\x01\x73\x5d\x9b\x11\x1a\x4b\xaa\xc9\x36\xba\xb4\x0a\x37\xc7\x84\x71\x30\x42\x95\xb5\xbc\x68\xe5\x0c\xfc\xb4\x9c\x00\x35\x4e\x84\x26\x90\x90\x40\x3c\x81\x77\x5b\x19\x67\xcd\xf9\xee\x91\x02\x08\x92\x64\x1d\x65\xd7\xf0\x46\xde\x4d\xe0\x43\x00\x26\x47\xb5\x41\xb8\xa7\x61\x82\x5b\x9a\x49\x85\x90\x40\x5a\x46\xa7\x56\x9c\xb8\x37\x3f\x2d\xa3\x33\x4b\x95\xa6\xe8\x77\x30\xea\xa0\xa4\x58\xbb\x59\x21\x27\xf0\x62\xfc\xeb\x28\x0e\x0e\x0f\xc4\x3d\x69\x79\x72\xca\xf8\x43\x55\x32\x8e\x7e\xd0\xb7\xdd\xb8\xb8\x94\xf3\xdc\xf4\x19\x10\xb2\x87\xce\xd7\x9a\xda\xad\xc8\x5b\x91\xc2\x27\x88\x81\xa9\x0c\xfc\xa6\x34\xd3\xea\x5a\x53\x76\x96\x33\xf2\x07\xf2\x0b\xe3\x20\x00\x4d\x43\x14\x84\xbb\x28\x70\x47\xf4\x73\xd0\x9b\x43\xdf\xff\xdd\x05\x8f\xdf\xb2\xe0\x6d\xda\x92\xa4\x6e\xcb\x5a\xca\x67\xda\x2a\x33\x55\x57\x86\xa4\x9a\xaf\xc9\xa8\xf9\x51\xda\xc0\x21\xbc\x1e\xbd\x4a\x4a\x18\xba\xef\x30\x0e\xc7\x90\x23\xa1\x6b\x33\xa3\x21\x43\x42\x81\x8a\x63\xbd\x59\x6a\xa9\x0c\x92\xdb\x78\x39\x73\xa6\x39\x2c\x73\xc9\x73\x07\x71\x0c\x2d\x98\x91\x9c\x15\xc5\x5f\x58\xb0\x0c\xfb\x1c\x2d\x73\x54\xc0\xb5\xfa\x83\x64\x5c\x4b\xcf\x35\x54\x86\x2c\x37\xb5\xcf\xc2\xb2\x3e\xd0\xd4\x80\x42\xcc\x6a\x93\x14\x57\x91\x91\x8b\x2d\x83\x14\x39\xb3\x55\x13\xe4\xa6\xcb\xf1\xb1\x44\x77\x24\x03\xa5\xd5\x26\xf6\xc6\x51\x8f\xf0\xeb\x1a\x4d\x55\x85\x64\xfc\xb0\x93\xde\x64\xb0\xcf\x06\x9a\x68\x86\x62\xff\x1e\xda\xfe\xbf\xfe\x5d\x0d\x36\x43\x16\xb7\xc6\x58\x49\xd8\xc4\xbb\x9a\xb0\x7e\x5a\x36\xce\xf6\x16\x60\xc7\xd8\x29\x0d\x92\xa1\x96\x6b\x03\x14\x3e\x9a\xdd\x88\xa3\xb8\x8d\x59\xba\xf9\xdf\xc8\xf5\x1b\x9a\x19\xb2\x4c\xaa\xf9\x75\x2e\x0d\x36\xf3\x68\xad\xec\x51\xef\x4c\xee\xdc\x23\xdd\xa9\xbc\x89\xbe\xd3\xaa\x6d\xc0\xab\xcd\x2a\x45\x2b\x95\x61\xf8\xc0\x4c\xed\xd6\xa1\x57\x12\x8d\xc9\x0f\x96\xf6\x6e\x0f\xa9\xcf\xbb\x55\x1e\x44\x11\x2c\xab\xde\x83\xaf\x0c\x23\x73\x21\x66\xaf\x7a\x1e\x14\xe3\x4a\x5e\x82\x15\x15\xee\xa5\xc9\xdd\xa2\x7c\xb9\x60\xd6\x82\xdc\xef\x7a\x3d\x48\xb6\xf0\x26\x77\xa4\xbb\x98\x86\x04\x7f\xf8\xf0\x4f\xcb\x93\x2f\x58\xa0\x69\xd7\x62\x27\x7d\xff\x02\x00\x00\xff\xff\x6b\xa0\x51\x0f\xbd\x09\x00\x00"
 
 func runtimePluginsAutocloseAutocloseLuaBytes() ([]byte, error) {
        return bindataRead(
@@ -1013,27 +1008,7 @@ func runtimePluginsAutocloseAutocloseLua() (*asset, error) {
        return a, nil
 }
 
-var _runtimePluginsAutocloseInfoJson = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x8f\xc1\x4e\xc4\x40\x08\x86\xef\x7d\x0a\xd2\x73\x33\x5d\x3d\x6e\xa2\x89\xcf\x61\x3c\x50\x8a\x5b\xe2\x74\xe8\x02\xa3\x59\x8d\xef\x6e\x3a\xda\x07\xf0\xc8\xff\xf1\xe5\x87\xaf\x0e\x00\xa0\x2f\xb8\x72\x7f\x86\x1e\x6b\x28\x65\x75\xee\x87\x5f\x30\xb3\x93\xc9\x16\xa2\x65\xe7\x4f\x35\x74\xc5\x10\xc2\x9c\x6f\xb0\x65\x24\x76\xd8\x05\x29\x17\xa0\x05\x0d\x29\xd8\x1c\x5e\xd5\xe0\x5a\x35\xd8\x07\xd8\xd0\xb8\xc4\xc2\xbe\x0f\x93\x21\xbd\x71\xf8\x00\x1c\x94\x52\x3a\x7a\x3e\x78\x72\x89\x76\xc3\x12\xb1\xf9\x79\x1c\x2f\x12\x4b\x9d\x12\xe9\x3a\x7e\xde\x78\x96\x59\x70\x5c\x85\x4c\x0f\x47\x8a\x07\xe6\xfc\x2f\xe7\x9d\xcd\xff\x7e\xb9\x4b\xa7\x74\x3a\x72\xe3\x6b\x15\xdb\xfb\x9f\x5b\xd0\xc2\x66\xc2\xe3\x03\xdc\xb7\xd5\x06\x5e\xba\xef\xee\x27\x00\x00\xff\xff\x1a\x2a\xb9\x2f\x35\x01\x00\x00"
-
-func runtimePluginsAutocloseInfoJsonBytes() ([]byte, error) {
-       return bindataRead(
-               _runtimePluginsAutocloseInfoJson,
-               "runtime/plugins/autoclose/info.json",
-       )
-}
-
-func runtimePluginsAutocloseInfoJson() (*asset, error) {
-       bytes, err := runtimePluginsAutocloseInfoJsonBytes()
-       if err != nil {
-               return nil, err
-       }
-
-       info := bindataFileInfo{name: "runtime/plugins/autoclose/info.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-       a := &asset{bytes: bytes, info: info}
-       return a, nil
-}
-
-var _runtimePluginsCommentCommentLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x57\xdf\x6f\xeb\x34\x14\x7e\xef\x5f\x61\x72\xa9\x64\x6f\x4d\x76\x3b\xde\x2a\x8a\xc4\xf6\x30\x24\xca\x45\xda\x26\xe8\x54\x15\xc9\x4d\x4f\x5a\x5f\x1c\x27\xb2\x1d\xa0\x42\xf0\xb7\x23\xff\xc8\x4f\xa7\xa5\x57\x48\xf0\xc2\xa4\x2d\xc9\x97\xef\x9c\x63\x9f\xf3\x1d\x9f\x8c\x17\x29\xe5\xa8\xd2\x8c\xa3\x25\x62\x79\x59\x48\x8d\xa3\x9c\xa5\xb2\xb8\x33\x60\x44\x26\x8e\x91\x16\x22\x63\x87\x80\xe3\xe0\x86\xb5\xab\xb2\x0c\x64\xc0\x72\x70\x44\x26\x9e\x96\x69\xb4\x44\xbf\xff\x31\x99\x64\x7a\x13\xa5\xd1\x16\x2d\x51\x74\x77\x87\xa6\x2a\x72\xc8\xed\x6d\x80\x1d\x8a\x00\x2a\x4f\xfa\x58\x08\x07\xbf\x1b\xa0\x5f\x0c\xe1\xa3\xce\xb9\xc3\xbe\xfc\x2c\x8e\xd1\x54\xa1\x38\xfe\xca\xbd\xfa\x48\x7f\xa1\x81\xf3\x8f\x15\x67\x34\xf0\x0d\x92\x07\xd8\xb1\x0c\x8c\x65\xa5\x74\x00\xaa\x23\xf0\xc0\x9a\x57\x3e\x88\x5d\x53\xbb\x1e\x95\x4a\x56\x86\x3e\x64\xb5\x3b\x0d\x5d\xec\xc3\x48\xbf\xb2\xac\x6f\x3b\xc9\x2a\x91\x6a\x56\x08\x54\x88\x07\x5b\x8c\xef\x4b\x10\x78\x57\x65\x64\x82\x10\x42\x2c\x33\xa5\x4b\x5e\x40\x6b\x26\x0e\x6a\x13\xa5\x45\x9e\x83\xd0\xfa\x54\x82\x71\xb4\x44\x82\x71\xa4\x8f\x20\x2c\xdd\x9b\x64\x7a\xd3\xb7\xca\x18\x07\x67\xb2\x45\x7f\x8e\xd8\x98\x9f\x8b\x71\x2e\xba\x6c\xdc\x00\x57\xf0\x09\x3e\x7d\xae\x1a\x6b\xb1\x9f\xd4\x57\xf3\xdb\xe6\xc6\x1b\xae\x98\x00\xbc\x2b\x67\x88\x33\x01\x1f\x5c\x82\x9c\x6e\x0d\x80\x96\x68\x57\x26\x0f\x55\xb6\xb0\xbc\x80\xe3\x9d\xbc\x9e\xca\x96\x7a\x6e\x71\xa1\xd9\x33\x1c\xe0\x37\xb3\xe6\x9f\xa6\xea\x26\x42\x49\xd2\xf5\xb7\x38\xa8\x6a\x87\xa3\xe9\x4d\x34\x43\xe6\x2f\xa9\x81\xd8\x02\x71\x0b\x24\x16\x48\x5a\xe0\xd6\x02\xb7\x2d\xb0\xb5\xc0\xb6\x05\x36\x16\xd8\xb4\xc0\x54\x19\x04\x27\x37\x24\xea\xee\x4f\x81\x39\x29\xe2\x5d\x99\x3c\x56\x52\x15\xd2\x5c\x5e\x80\x83\x4d\x61\x77\x43\x95\x2c\x0b\xd5\xa7\xae\x8a\xb4\xc3\x60\x62\x6f\xf7\xaa\xb4\x64\xe2\x90\x64\x4c\xec\x71\x67\xb7\x66\x39\x53\x15\x11\x14\xa3\x79\x2d\x52\x4f\xcd\xa9\x4e\x8f\x36\xf5\xb3\x5e\xe2\x48\x5f\x6e\x95\xf0\x2f\x61\xbf\x72\x95\xfb\x3b\xfb\xc6\xd4\x97\xf8\x19\x4a\x4e\x53\xc0\xee\x00\x33\xeb\xc7\xef\x6b\x5d\xcc\x50\x07\x7d\xe7\x9c\xd5\x6f\xcc\xd1\x99\x3c\x81\x5e\x01\xdd\x33\x71\xf8\xf1\xc8\x34\xa8\xd2\x78\x32\x0c\x62\xea\x3a\x58\x1c\xe9\x36\x56\x93\xb1\xc5\x37\x54\x35\xc9\xc5\x64\xa4\x9b\x46\xcb\xb0\x99\x6f\x93\x37\xb3\x5d\xe0\xf6\xf6\x1a\x93\xfb\xd6\xe4\xfe\x4a\x93\xf9\x36\x59\xb7\x51\xd6\x57\x46\x59\xb7\x51\xd6\x17\x5a\xba\xb1\x37\x7c\x27\xa6\x64\x8d\x62\xa7\x9a\x33\xd4\xb7\x96\xfa\x16\xf6\x7b\x37\x44\xaf\xe9\x1a\x79\x8c\xf4\x9a\xed\x02\x2d\x59\xee\x2a\xf7\x6f\x2a\xe4\x7f\x7d\x7c\xba\x3e\x6e\xff\x81\x3e\xfc\xb5\x4d\xee\x33\x18\x99\x68\xc0\xa4\xff\x22\x59\x51\xa5\x7f\x60\xaa\xa2\x7c\xed\xce\x78\x6f\xf0\x04\x35\x8c\xc9\xf8\x6c\x69\x8b\x65\x06\x8c\xd2\x54\xda\x71\x33\x33\xd1\xdb\x32\x67\x85\xac\x67\x4d\x48\x41\xfb\xa2\x59\xfb\xd8\xc4\x22\x97\xa7\x9b\xe5\x51\x79\x50\xed\xe4\xbf\x4a\x4d\x5d\xe2\xb0\xcc\x8b\x27\x09\x54\x83\x7c\x3d\x52\x81\xcf\x8c\x86\xcd\xfd\x76\x44\x9f\xae\x0f\xeb\x9d\x2d\x2f\xe9\xb5\x67\x77\x69\x35\x46\x11\x4b\xf4\x3e\x0c\xe6\xf3\xe2\x43\xd5\x77\xf5\x78\x19\xea\x61\x90\xe3\x7e\xe5\x2e\x34\xc9\xa0\x96\xa3\xea\xbd\x72\xdb\x41\xa3\x9d\xdf\xf6\xfd\x7f\xb9\xed\xf9\x99\x6d\x8f\x9d\xbc\x43\xc9\x76\xba\xf3\x9c\x72\xed\xf1\xeb\xf5\x2a\x41\x57\x52\x20\xac\xfc\x01\x6d\xbe\x93\x70\x12\x93\xa9\xba\xf9\xdc\x7e\xc1\xcc\x23\x32\xec\x3d\x3f\xf5\x6d\x2b\x29\xfc\x62\x9f\x66\x2f\xe6\xa9\xe7\xb3\xa6\x55\xbb\x9a\x33\x9f\x79\x8c\x83\xc0\xce\x80\x2c\x97\xf6\xc6\x85\x70\xff\xfe\x24\xdf\xd1\x9f\xe1\xb1\xc8\x73\x2a\xf6\xb8\xfe\xc2\x33\x8b\xf1\xb7\x49\x0b\x79\x83\x0f\xc5\x63\x91\x97\x1c\x34\x90\xda\xc7\xab\x3c\x3d\x30\xb1\xff\x16\x4e\x38\xfa\x9a\xeb\xf8\xce\x38\xe0\x15\x5d\x84\x4e\x32\xca\x15\x90\xc9\x5f\x01\x00\x00\xff\xff\x04\xbe\xc6\xd7\xbb\x0d\x00\x00"
+var _runtimePluginsCommentCommentLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x57\x6d\x6f\xeb\x34\x14\xfe\xde\x5f\x61\x72\xa9\xe4\xac\x8d\xb7\x8e\x6f\x15\x45\x62\x13\x1a\x88\xb2\x2b\xad\xd3\xa5\x53\x55\x24\x37\x3d\x69\x7d\x71\x9c\xc8\x76\x80\x0a\xc1\x6f\x47\x7e\x49\xf3\xe2\xb6\xf4\x0a\x09\xbe\x30\x69\x4b\xf2\xe4\xbc\x9f\xe7\xf8\x64\x1f\xbe\x79\x59\x7c\xf7\xfe\x19\xcd\x50\x34\x21\x77\xe4\x2e\x1a\x0c\x78\x91\x52\x8e\x2a\xcd\x38\x9a\x21\x96\x97\x85\xd4\x38\xca\x59\x2a\x8b\x5b\x03\x46\xb1\x97\x48\x0b\x91\xb1\x5d\x20\xe3\xe0\xa3\xd4\xa6\xca\x32\x90\x81\x94\x83\xa3\xb8\x76\x97\x69\x34\x43\xbf\xff\x31\x18\x64\x7a\x15\xa5\xd1\xda\x04\x74\x7b\x8b\x86\x2a\x72\xc8\x68\x14\x60\xbb\x22\x80\xca\x83\xde\x17\xc2\xc1\xef\x7a\xe8\x17\x7d\x78\xaf\x73\xee\xb0\x2f\x3f\x4b\x12\x34\x54\x28\x49\xbe\x72\xaf\x3e\xd2\x5f\x68\x60\xfc\x63\xc5\x19\x0d\x6c\x83\xe4\x01\xb6\x2f\x03\x65\x59\x29\x1d\x80\x6a\x0f\x3c\xd0\xe6\x95\x77\x62\x63\x6a\xe2\x51\xa9\x64\x65\x68\x43\x56\x9b\x43\xdf\xc4\x36\xf4\xf4\x2b\xcb\xba\xba\x83\xac\x12\xa9\x66\x85\x40\x85\x78\xb0\xcd\x78\x5f\x82\xc0\x9b\x2a\x8b\x07\x08\x21\xc4\x32\xd3\x3a\xb2\x00\xad\x99\xd8\xa9\x55\x94\x16\x79\x0e\x42\xeb\x43\x09\xc6\xd0\x0c\x09\xc6\x91\xde\x83\xb0\xe2\x5e\x25\xd3\xab\xae\x56\xc6\x38\x38\x95\x35\xfa\xf3\x84\x8e\xf9\xb9\xe8\xe7\xa2\xc9\xa3\x19\xe0\x0a\x3e\xc1\xa6\xaf\xd5\x51\x5b\x6c\x07\xf5\xd5\xfc\x36\xb5\xf1\x8a\x73\x26\x00\x6f\xca\x31\xe2\x4c\xc0\xb3\x2b\x90\xe3\xad\x01\xd0\x0c\x6d\x4a\xf2\x50\x65\x53\x2b\x17\xc8\x78\x23\xaf\x87\xb2\x11\x3d\x17\x5c\xa8\xf6\x02\x3b\xf8\xcd\xc4\xfc\xd3\x50\xdd\x44\x88\x90\xb6\xbd\xe9\x4e\x55\x1b\x1c\x0d\x6f\xa2\x31\x32\x7f\xe3\x1a\x48\x2c\x90\x34\x00\xb1\x00\x69\x80\x91\x05\x46\x0d\xb0\xb6\xc0\xba\x01\x56\x16\x58\x35\xc0\x50\x19\x04\x93\x9b\x38\x6a\xe7\xa7\xc0\x9c\x14\xc9\xa6\x24\x8f\x95\x54\x85\x34\x97\x05\x70\xb0\x25\x6c\x27\x54\xc9\xb2\x50\x5d\xd1\x79\x91\xb6\x24\x98\xd8\xda\x5c\x95\x96\x4c\xec\x48\xc6\xc4\x16\xb7\xb2\x35\xe1\x0c\x55\x14\xa3\x04\x4d\x6a\x92\x7a\xd1\x9c\xea\x74\x6f\x4b\x3f\xee\x14\x2e\xee\xd2\xad\x12\xfe\x25\x6c\xe7\xae\x73\x7f\xa7\x7f\x54\xf5\x2d\x7e\x81\x92\xd3\x14\xb0\x3b\xc0\x4c\xfc\xf8\xae\xe6\xc5\x18\xb5\xd0\x77\xce\x58\xfd\xc6\x1c\x9d\xe4\x09\xf4\x1c\xe8\x96\x89\xdd\x8f\x7b\xa6\x41\x95\xc6\x92\x91\x88\x4d\x5f\x7b\xc1\xc5\xed\xc1\x3a\x56\x6c\xfa\x2d\x55\xc7\xe2\xe2\xf8\xc4\x34\x9d\x6c\xc3\x6a\xb2\x26\x6f\x26\x5d\xe0\xf6\xf6\x1a\x95\xfb\x46\xe5\xfe\x4a\x95\xc9\x9a\x2c\x1b\x2f\xcb\x2b\xbd\x2c\x1b\x2f\xcb\x0b\x23\x7d\xd4\x37\xf2\x8e\x4c\x64\x89\x12\xc7\x9a\x33\xa2\x6f\x8d\xe8\x5b\x38\xef\x6d\x17\x9d\xa1\x3b\xd2\xe3\xc4\xac\xd9\x29\xd0\x92\xe5\xae\x73\xff\x26\x43\xfe\xe7\xc7\xa7\xf3\x63\xf4\x0f\xf8\xe1\xaf\x4d\x71\x5f\xc0\xd0\x44\x03\x8e\xbb\x2f\xc8\x9c\x2a\xfd\x81\xa9\x8a\xf2\xa5\x3b\xe3\xbd\xc2\x13\xd4\x30\x8e\x4f\xef\x96\xa6\x59\x66\xc1\x28\x4d\xa5\x5d\x37\x63\xe3\xbd\x69\x73\x56\xc8\x7a\xd7\x84\x22\x68\x5b\x1c\x63\x3f\xb5\xb1\xe2\xcb\xdb\xcd\xca\x51\xb9\x53\xcd\xe6\xbf\x8a\x4d\x6d\xc1\x7e\x9b\xa7\x4f\x12\xa8\x06\xf9\xba\xa7\x02\x9f\x59\x0d\xab\xfb\xf5\x09\x7e\xba\x39\xac\x33\x9b\x5d\xe2\x6b\x47\xef\x52\x34\x86\x11\x33\x74\x17\x3a\xf3\x75\xf1\xae\xea\xbb\x7a\xbd\xf4\xf9\xd0\xab\x71\xb7\x73\x17\x86\xa4\xd7\xcb\x93\xec\xbd\x32\xed\x60\xd0\xce\xa7\x7d\xff\x5f\xa6\x3d\x39\x93\xf6\xa9\x93\xb7\x4f\xd9\xd6\x74\x9e\x63\xae\x3d\x7e\x3d\x5f\x25\xe8\x4a\x0a\x84\x95\x3f\xa0\xcd\x77\x12\x26\x49\x3c\x54\x37\x9f\xdb\x2f\x98\x49\x14\xf7\x67\xcf\x6f\x7d\x3b\x4a\x0a\x2f\xec\xd3\x78\x61\x9e\x3a\x36\x6b\xb1\x6a\x53\xcb\x4c\xc6\x1e\xe3\x20\xb0\x53\x88\x67\x33\x7b\xd3\x73\xc1\x04\xd3\xfe\x98\x70\xff\x12\x91\x1f\xe8\xcf\xf0\x58\xe4\x39\x15\x5b\x5c\x7f\xf5\x99\x00\xfd\x2d\x69\x20\xaf\xf0\x5c\x3c\x16\x79\xc9\x41\x43\xc7\xce\xab\x3c\x3c\x30\xb1\xfd\x1e\x0e\x38\xfa\x9a\xeb\xe4\xd6\x18\xe1\x15\x9d\x86\x86\x32\xca\x15\xb8\xe4\xff\x0a\x00\x00\xff\xff\xa3\x8c\x7f\x07\xea\x0d\x00\x00"
 
 func runtimePluginsCommentCommentLuaBytes() ([]byte, error) {
        return bindataRead(
@@ -1053,27 +1028,7 @@ func runtimePluginsCommentCommentLua() (*asset, error) {
        return a, nil
 }
 
-var _runtimePluginsCommentInfoJson = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x8f\x41\x4e\x03\x31\x0c\x45\xf7\x73\x8a\xaf\x59\xa3\x99\xc2\xb2\x12\xec\x38\x01\x4b\xc4\x22\x93\xb8\x53\x8b\x24\x0e\xb1\x03\x14\xc4\xdd\x51\xd3\xce\x01\xba\x7d\xdf\xcf\xdf\xfe\x1d\x00\x60\xcc\x2e\xd1\xb8\xc7\xe8\x25\x25\xca\x36\xde\x5d\x70\x20\xf5\x95\x8b\xb1\xe4\x73\xfa\xd2\x4a\x91\x6a\x38\x48\x85\x6b\x26\xc9\x19\x7b\x17\xe3\x09\x57\x8f\xf3\x8a\x25\x8a\x7f\x57\xc8\x01\x5e\x02\x4d\x78\xfe\x36\xca\xca\x4b\x24\xb8\x1c\x90\x5a\x34\x2e\x91\x10\x5d\x5e\x9b\x5b\x49\xa1\x97\xb5\x14\xa6\xad\xf7\x8b\x16\x65\xeb\x17\x1d\xcd\x8a\xee\xe7\x79\x65\x3b\xb6\x65\xf2\x92\xe6\x9f\x13\x05\x0e\xec\xe6\xc4\xbe\xca\xe6\x70\x56\x73\x31\xde\xe4\x7c\x52\xd5\xeb\x6f\xf7\xd3\x6e\xda\x6d\xbc\xd2\x47\xe3\x7a\xee\x7f\xed\xa0\xc3\x6e\xe2\xe9\x11\x0f\x7d\xb4\x07\x6f\xc3\xdf\xf0\x1f\x00\x00\xff\xff\xf1\xad\x13\x45\x43\x01\x00\x00"
-
-func runtimePluginsCommentInfoJsonBytes() ([]byte, error) {
-       return bindataRead(
-               _runtimePluginsCommentInfoJson,
-               "runtime/plugins/comment/info.json",
-       )
-}
-
-func runtimePluginsCommentInfoJson() (*asset, error) {
-       bytes, err := runtimePluginsCommentInfoJsonBytes()
-       if err != nil {
-               return nil, err
-       }
-
-       info := bindataFileInfo{name: "runtime/plugins/comment/info.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-       a := &asset{bytes: bytes, info: info}
-       return a, nil
-}
-
-var _runtimePluginsFtoptionsFtoptionsLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\xcf\xb1\x0e\x82\x40\x0c\x06\xe0\x9d\xa7\x68\x6e\x82\xc4\x49\x37\x12\x16\x07\x57\x06\x7d\x81\x3b\x6c\xe5\xe2\xd1\x5e\xb8\x32\xf0\xf6\x86\x13\x75\x82\xc4\x26\x5d\xfa\x25\xfd\xf3\xd3\xc4\x9d\x7a\x61\x10\x3e\x4f\x44\x38\xb6\x11\xb9\x74\x55\x01\x00\x10\xa4\xb3\x01\x48\xa1\x01\x57\x5f\x7c\xc0\xdb\x1c\xb1\xac\x8a\x8c\x9e\xb2\x34\x60\x1e\x62\x40\xc6\x7c\x5c\x2f\x83\x7d\x22\xf9\x80\x06\xb4\x47\xce\xb2\x8c\xab\xaf\xa8\x6d\x5c\xf2\x4a\xa3\xd6\x25\x95\x14\x6d\x87\xc9\x1c\xc0\x08\x91\x79\xc7\x62\x48\xf8\xfb\x4e\x3e\xf5\xdf\xff\xeb\xac\x14\x67\xed\x85\x77\xf1\xb8\xab\xa7\x0d\x9d\xed\x10\x36\x88\xfd\xf0\x57\x2b\xfe\x94\xe2\x7b\xb1\xec\x2b\x00\x00\xff\xff\x55\x1f\xb6\x5b\x71\x01\x00\x00"
+var _runtimePluginsFtoptionsFtoptionsLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\xcf\x31\x4b\xc5\x40\x0c\x07\xf0\xfd\x3e\x45\xc8\xd4\x07\xf2\x78\xea\x56\xe8\x22\x28\xb8\x58\xb0\xe2\x7e\x57\x13\x7b\x78\x4d\x8e\xde\x75\xe8\xb7\x97\x9e\x55\xa7\x16\x5e\x20\x4b\x7e\x90\x3f\xff\xf7\xc7\xd7\xee\xb9\x7d\x81\x06\xf0\xf6\x7c\x39\x5f\xd0\x18\x9e\xa5\xcf\x5e\x05\x54\x1e\x66\x66\x9a\xda\x48\x52\xb9\x93\x01\x00\x08\xda\xdb\x00\x9c\xa1\x01\x57\x3f\xf9\x40\x6f\x4b\xa4\xea\x64\x0a\x7a\x2e\xd2\x00\x7e\x2a\x82\x4e\xe5\xb8\x5d\x46\xfb\x45\xec\x03\x21\xe4\x81\xa4\xc8\x3a\xae\xee\x28\xb7\x71\xcd\xab\x30\x5b\x97\xb2\xa6\x68\x7b\x4a\x78\x03\xa8\xcc\xf8\x13\x4b\x21\xd1\xff\x77\xf6\x69\xf8\xfb\xbf\xcd\x46\x71\xc9\x83\xca\x21\xde\x1d\xea\xfd\x8e\x2e\x76\x0c\x3b\x24\x7e\xbc\xaa\x95\xfc\x96\x92\x0f\xb3\xee\x77\x00\x00\x00\xff\xff\xfc\x92\x06\xde\x84\x01\x00\x00"
 
 func runtimePluginsFtoptionsFtoptionsLuaBytes() ([]byte, error) {
        return bindataRead(
@@ -1093,47 +1048,7 @@ func runtimePluginsFtoptionsFtoptionsLua() (*asset, error) {
        return a, nil
 }
 
-var _runtimePluginsFtoptionsInfoJson = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x8f\x3d\x4e\xc5\x30\x10\x84\xfb\x9c\x62\xe4\x0a\x24\x94\x3c\x28\x23\xc1\x0d\xa8\x28\x11\x85\x63\x6f\xc8\x0a\xff\xe1\xdd\x07\x04\xc4\xdd\x51\x4c\x72\x80\x57\xfa\xfb\x66\xe4\xd9\x9f\x0e\x00\x4c\xb2\x91\xcc\x08\x33\x6b\x2e\xca\x39\x89\xb9\xf9\x17\x9e\xc4\x55\x6e\x6c\xf3\x4f\xa4\x82\xc9\x0a\x3b\xec\xc1\xed\x45\x1e\x39\x41\x17\xc2\xcc\x81\x74\x2d\x84\xab\x39\x57\xd0\x97\x8d\x25\x10\x1e\xed\x1b\x6d\x46\x50\xe9\xfd\xcc\x95\xa0\x76\x92\xeb\xfe\xf8\xe4\x93\x26\x61\x6d\x03\x16\xd5\x22\xe3\x30\xbc\xb2\x2e\xe7\xa9\x77\x39\x0e\xdf\x2b\x79\xf6\x6c\x87\xc8\xae\xe6\xa3\xc3\x49\xd4\x86\x70\x51\xe7\x83\xaa\xec\x87\xdc\xf6\xa7\xfe\x74\xf0\x7d\x95\x19\xf1\xdc\x40\x83\xad\x89\x87\x7b\xdc\xb5\x68\x13\x2f\xdd\x6f\xf7\x17\x00\x00\xff\xff\xcf\x0b\x0c\x9a\x32\x01\x00\x00"
-
-func runtimePluginsFtoptionsInfoJsonBytes() ([]byte, error) {
-       return bindataRead(
-               _runtimePluginsFtoptionsInfoJson,
-               "runtime/plugins/ftoptions/info.json",
-       )
-}
-
-func runtimePluginsFtoptionsInfoJson() (*asset, error) {
-       bytes, err := runtimePluginsFtoptionsInfoJsonBytes()
-       if err != nil {
-               return nil, err
-       }
-
-       info := bindataFileInfo{name: "runtime/plugins/ftoptions/info.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-       a := &asset{bytes: bytes, info: info}
-       return a, nil
-}
-
-var _runtimePluginsLinterInfoJson = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x94\x8e\x4d\x4e\xc4\x30\x0c\x85\xf7\x3d\x85\x95\x35\x4a\x06\x96\x23\x81\xc4\x39\x10\x0b\x4f\xe2\xa6\x96\xf2\x53\x1c\xa7\xa8\x20\xee\x8e\x1a\xe8\x01\x66\xfb\xbd\xf7\xf9\xf9\x7b\x02\x00\x30\x05\x33\x99\x2b\x98\xc4\x45\x49\xcc\xc3\x1f\x0d\xd4\xbc\xf0\xaa\x5c\xcb\x11\xbe\x76\xad\x19\x95\x3d\xf8\x1a\x08\x8e\x2e\x97\x08\x73\x15\x40\xd8\x50\x98\x74\x87\x3a\x43\xc2\x12\x3b\x46\x6a\xf6\x3c\xf4\x49\xb7\xc6\x3a\x16\x16\xd5\xb5\x5d\x9d\x8b\xac\x4b\xbf\x59\x5f\xb3\xfb\xda\x29\x70\x60\x74\x99\xbd\xd4\xd3\xe1\xd2\x14\x53\xba\xcb\xd9\x48\xda\xff\xb3\x8f\xf6\x62\x2f\x27\x17\xfa\xe8\x2c\xc7\xfe\xdb\x00\x03\x0e\x13\x5e\x9e\xe1\x69\x54\x47\xf0\x3e\xfd\x4c\xbf\x01\x00\x00\xff\xff\x70\xd3\x04\x06\x13\x01\x00\x00"
-
-func runtimePluginsLinterInfoJsonBytes() ([]byte, error) {
-       return bindataRead(
-               _runtimePluginsLinterInfoJson,
-               "runtime/plugins/linter/info.json",
-       )
-}
-
-func runtimePluginsLinterInfoJson() (*asset, error) {
-       bytes, err := runtimePluginsLinterInfoJsonBytes()
-       if err != nil {
-               return nil, err
-       }
-
-       info := bindataFileInfo{name: "runtime/plugins/linter/info.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-       a := &asset{bytes: bytes, info: info}
-       return a, nil
-}
-
-var _runtimePluginsLinterLinterLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x59\xdd\x8f\xdb\xb8\x11\x7f\xdf\xbf\x82\x10\x6a\x40\xce\x4a\xda\xe4\x7a\x7d\x31\x60\x14\xd7\xf4\xae\x40\x91\x8f\x02\x49\xd1\x87\x24\x57\xd0\xd4\xc8\xe6\x2d\x45\xaa\x24\x65\xaf\xbb\x48\xff\xf6\x62\xf8\x21\x53\xb2\xb4\xd9\x5e\xcf\xc0\x4a\x14\x35\x9c\xf9\xcd\x27\x87\x5a\xa1\x18\x15\xa4\xe5\x4c\x2b\xb2\x25\xbc\xed\x94\xb6\x79\xe6\x9e\xb3\xf5\x8d\x7f\xab\x7b\x69\x79\x0b\xc9\xfb\x30\x33\x50\x34\x5c\x40\x47\xed\x21\x21\xc1\xc7\xbb\x38\x3f\x10\x9a\x03\x08\x31\x15\x74\xe7\x66\x07\x9a\x5d\xdf\x34\xa0\xaf\x88\xfc\xf4\x40\xc5\x94\x6c\xf8\xfe\x8a\xca\x4f\x67\xeb\x9b\x40\x26\xb8\xb4\xa0\x0d\xd9\x92\xc7\xaf\x37\x37\x65\x49\x98\x06\x6a\xc1\x10\x1a\x5e\x11\x90\x56\x9f\x0b\xc2\xa8\x10\xa4\xd1\xaa\x25\x27\x6e\x0f\x5c\x12\x2a\x09\x97\xdc\x72\x2a\xf8\xbf\xa9\xe5\x4a\x92\xa6\x97\x0c\x07\x05\x91\xca\x22\xaf\x9a\x6b\x60\x56\x9c\x09\xb5\x91\x96\x08\x45\x6b\x82\xc6\xb9\x29\x4b\xa4\x91\xb4\x85\x8d\xbb\x12\xd5\x10\x7b\x80\x20\x17\xdf\xa1\x79\xec\xb9\x83\xcd\x30\x22\x56\x11\x76\x00\x76\x4f\x1a\xa5\xf1\xa1\x37\xe9\x02\xd6\xd6\x1b\xd2\x52\x2e\x23\xf8\x4e\x2b\x06\xc6\x10\x7b\x40\x08\x86\xc0\x03\xb0\xde\x42\x8d\xc4\x54\xef\xcd\x06\xaf\x7d\x0b\xd2\x1a\xe4\xd6\x51\xe3\xee\x17\x18\x91\x03\x2e\xc0\x1f\xca\x5b\x35\x48\xa3\x01\xbd\x10\x88\x59\xaf\x35\x48\xeb\x70\x3a\x65\x46\xf4\xf5\x22\xbd\xb7\x90\xd2\xe7\x61\x11\x68\xad\x74\xa3\x74\x4b\xed\x86\x1c\xd4\xc9\xc3\xd2\x06\x12\x50\x77\x4c\xb5\x1d\x17\x89\x7e\xaa\xb7\x5d\x6f\xa3\xd0\x55\xe3\x2d\x56\x90\x95\xd8\xe0\x1a\x20\xb2\x6f\x77\xa0\x0b\xb2\x6a\x37\x5e\xc4\xdd\x89\x6a\xc9\xe5\x9e\xb4\x60\x0c\xdd\x3b\xd9\xca\x20\xb5\xb1\xe8\x89\xf7\x1f\xd0\x6a\xdc\x44\x3b\x70\x43\x4c\xdf\x61\x28\x41\x4d\x94\x26\xbd\x4c\x1e\x65\x94\xac\x3a\x0c\x00\x2a\x10\x32\x6d\x0b\x52\x43\x43\x7b\x61\x37\x18\x5d\x65\x49\x4e\x07\x6e\x01\x25\x6c\x88\x39\xa8\x5e\xd4\x4e\xa9\xf7\x1f\xbc\xd4\x1d\x10\x4a\x76\x82\xb2\x7b\xf7\x98\xd7\x0a\x03\x09\xd3\x2b\x75\x88\x73\xfc\x01\x0c\xae\x33\xeb\x28\x38\xfc\x94\x26\xf4\x22\x85\xe4\x4a\x8a\xf3\xf3\x18\x2c\x22\x6f\xa8\x30\x40\xf2\x80\x77\x80\xe7\x16\xd6\xaa\xa5\x96\x1d\x46\xda\x0c\xa1\xba\x03\xe2\x04\x76\x1a\xd0\x48\xd4\xe5\x54\x4f\x49\x47\xad\x05\x2d\xd1\xb1\x6e\xb5\x4b\xa8\x91\x1e\xc8\x86\x32\xdb\x87\xca\x81\xdc\x0a\x54\x2d\x91\x12\x74\x71\xfa\x51\x66\xf9\x91\x5a\x20\xca\x65\x25\x3c\x50\x66\x3d\xeb\xe7\x2a\xa7\xe1\x5f\x3d\xd7\x90\x2e\x75\xfa\x09\xd5\x34\x06\x6c\x88\x21\xff\x40\x4e\x5c\x08\xe7\xab\xba\x86\x3a\xc9\x96\x18\x64\x44\x83\xed\xb5\x84\x9a\xec\xce\x93\x84\x1e\x7e\xbd\x81\xa6\x17\x84\xa7\x19\x1f\xd6\x19\xf2\xb2\xe4\xb2\x86\x07\xa8\x1d\x57\xf3\x4d\x25\x5e\xba\xd4\x8f\x50\x99\x12\x7d\x2b\x9f\x04\xcb\x94\xf8\xed\xb1\x7a\xb9\xcf\x45\x4b\x85\xd8\x51\x76\xbf\x19\x8a\xa6\xab\x6c\xd4\x81\x6d\x94\x73\x05\x56\x2a\x4c\xd0\x8b\xd4\x02\x41\x70\x1b\x85\x8f\x63\xdf\xbb\x32\x12\x63\xbe\x32\x2a\x19\x08\xa8\x2b\xf2\x11\x95\x0e\x22\xf1\x0d\xd6\x39\xf0\x81\xb4\xeb\x9b\xea\x9b\x98\x25\x17\x37\x03\xd0\x96\xde\xc3\x1b\x87\x27\xc7\xa2\x55\x24\x31\xca\xda\xba\x70\x75\xb5\x48\xeb\x58\x41\x94\x29\x2e\x59\x59\xc4\xb4\x29\x62\x7c\x15\xd1\x7b\xc5\x80\x72\x7d\x83\x80\x78\x13\x37\xa8\x4f\x28\xea\x0b\xd9\x6e\x11\x0b\x02\x97\x37\x51\xf1\x09\x05\x96\x9a\xd9\x57\xd5\x90\x99\xdb\x01\xf2\x02\x25\x6b\x6b\xb2\x45\x6d\x16\xde\xa3\x8a\x64\xeb\x34\x5d\xa0\x48\xd4\x27\xdb\xd4\x18\x0b\xf4\x0a\xf9\x29\x83\x59\xbe\x88\xff\x52\xd7\xb6\x49\x8d\x53\xda\xbb\x7e\x61\x51\xb0\x35\xd9\x46\xab\x7f\x6b\x41\xf0\x09\xd9\x46\xef\xe0\x82\x97\x4b\x86\x1a\x88\xd9\x33\x88\x63\x04\x6e\x2f\xc1\xa8\xb4\x0b\x2e\x24\x06\x59\xdf\xe0\xdf\x25\xd2\x34\xb4\xea\x98\xc6\x9a\x8f\x8a\xa9\xc3\x91\xc1\x78\x21\x36\x1b\x79\x20\x76\x6d\x4e\x0d\x47\xd9\xbb\xce\x2a\xbb\xab\xe1\x78\x87\x0f\x59\x0c\xb1\xd0\xad\x55\x7f\x79\xff\xfe\x03\x46\x58\x76\xe2\xb2\x56\x27\x93\x8d\xe3\x2c\xe1\xf1\xee\xef\x6f\xb2\x01\xb3\x1b\x24\x49\x91\xed\x19\xcb\x0a\x92\xb9\x8b\x1f\x3f\x66\x65\x63\xce\xd2\xd2\x87\x12\x2b\x36\xbe\x28\xff\x41\x85\xf0\x03\x78\xb0\x9a\xe2\x70\xd5\x64\x5f\xdd\x6d\xb3\x12\x9b\x15\xdb\x54\xb7\x1b\xb2\x6a\xb3\xf5\xa2\x84\xdb\xdb\x27\x64\x64\xa5\xb1\xf5\x96\xdd\xde\xbe\xfa\xfe\xff\x16\x58\xb7\x35\xd2\xfb\x8b\x1b\x3f\x66\x25\x53\x42\xe9\xad\x6a\x1a\xc7\x55\x95\xee\x76\xf2\x57\xee\x6e\x6c\x24\x64\x95\xaf\xc4\x6a\xfd\x84\x56\x6a\xd7\x73\xe1\x64\xec\xd5\x70\x7d\xcc\x86\xd9\x12\x9f\x83\x1b\x46\xb8\xff\x78\x61\x58\x96\x13\x9e\x18\x2d\x29\xcb\xf0\xfc\x78\xa5\xfc\x3c\xa8\x5f\xe8\x91\x3a\x35\x70\x10\xef\xc1\xde\x0e\xd4\xaa\xbe\xb2\xa4\xcf\xf7\x25\x86\xe6\x10\x10\x21\x27\xc3\x34\xef\xfc\x53\x9c\x4f\x91\xf9\x7d\x75\x25\x8a\xea\xb6\x98\x67\x27\xb8\x05\x4d\x2d\x20\x8b\xc9\x38\x78\xe9\xda\xd1\x2d\xbe\xf9\x5a\xf8\x32\x50\x10\xab\x7b\x98\x61\xdc\x53\xd7\x69\x3b\x66\x3d\x0d\xb7\x38\xf5\x98\x95\xa5\x54\x3e\x04\xe6\x22\x69\x1e\xac\xe4\x28\x7a\x7c\x7b\xcc\x06\x31\x65\x89\x15\xed\xa7\x5e\x88\xbf\x51\x7b\x30\x7e\xca\xd8\x5a\xf5\xd6\x8f\xd1\x42\x66\x13\x22\x6e\x10\x59\xad\x44\x41\x56\xac\x9a\x97\xc9\x04\x95\x7b\xa4\x57\xbb\x5f\x00\x3b\x25\xf0\x26\x79\x60\xba\x97\x5e\x7e\xa4\xf8\x6d\x93\xb4\x3b\x37\x82\xde\x83\x53\xa3\x3b\xdb\x83\x92\x7e\x34\xcc\x4e\x42\xb0\x2a\xd3\x38\x4e\x39\xb5\xe7\xee\x3c\xe6\x12\x66\x26\x1c\x96\x70\xc4\x14\x48\x51\x0c\x69\x50\x96\xfe\xf0\x50\xfa\xfd\x69\xeb\x0e\x1b\x74\x27\xc0\x9b\x5c\x03\x36\xf9\x66\x2b\xd5\x75\x98\xcf\x8a\x33\x87\xa6\x75\xd2\xfc\xa9\xd5\x0d\xfc\xcc\x73\x53\xce\x9c\x78\x63\x9d\x8f\xdc\x68\xec\xac\xcb\xcb\x05\x47\x20\x51\x4d\xf5\x89\x4b\x7c\x3d\x1f\xdb\x13\x09\x6c\x16\x5c\xc2\x4f\x70\xd9\x3f\x2c\xb3\x3b\xd3\xd6\x29\x9a\xde\x13\xfb\x7a\xc3\x3a\xb3\x53\x6d\xa2\x69\xaf\xc5\x79\x6b\x38\xee\xfe\x98\x5e\xbd\xa5\xf7\xf0\x5a\xb5\x2d\x95\x35\x66\xba\xf7\xa2\xdf\xfe\x2a\xbc\xbd\x76\xa5\x38\x10\xbf\x53\xaf\x55\xdb\x09\xb0\xb0\x9e\x6c\x87\x81\x34\xdf\x75\xbe\x3b\xf3\x1a\xec\xba\xcd\x07\x7a\x84\xb0\x4f\xea\x5e\x06\x75\x76\x5d\xf5\xa7\xbe\x99\xf2\x60\x4a\x5a\xca\xa5\xc9\x7d\x0b\x07\x02\xf0\xd4\xec\xd7\xe2\x89\xea\xbe\x20\x47\xc2\x25\xe9\x28\xd7\x9e\x68\x4d\x6a\x35\x6c\x9e\xbc\x21\x47\xdc\x5b\xc3\xba\xf1\xce\xea\xe4\xbb\x9e\xd6\x19\x78\x98\x47\x04\xe9\x3d\xd0\xf8\xee\x65\xd2\x2a\x5c\xe0\x23\xf6\xcb\xce\xdf\x60\x73\xb2\xeb\x9b\xcd\x4f\x5c\xc0\xc7\x73\x07\xa3\xbe\xc0\x9d\xd7\xdd\xfb\x0a\x4b\x4e\xda\x31\x70\x1d\xfa\xc4\x8e\xda\x43\xf5\x67\xae\x73\x7c\x08\xfe\x99\xd3\xd8\x35\x25\x23\xa5\x23\x82\xd8\x81\x21\x96\x2d\x39\x56\x57\xdd\x27\x5a\x67\xe8\xd4\xae\x4c\x73\x61\x60\xac\xe6\x72\x5f\xb9\xc7\xbc\xb1\x45\xc2\x6b\x3d\xb2\xda\x04\xc2\x81\x1a\x6c\x6d\x2e\x4e\x3c\x56\xd8\x92\xa7\x8d\xcf\x3a\x05\x83\xc7\x6e\xbf\x86\xca\x9a\x1c\x93\xce\xf3\x09\x70\xe3\xa6\x32\xfa\x2c\x70\xbc\x70\x43\xde\xbf\x9a\xe3\x44\xaf\xd0\x87\x27\x1d\x73\x70\x0c\xd5\xfb\x8b\x6b\x8e\xae\x5f\x1f\x79\x06\x7f\x38\xf9\xe9\xfe\x8b\xef\xe3\x37\x7b\xd3\xef\xf2\x6c\xb5\xc2\xad\xc5\x39\x7a\x98\xc1\x14\xab\xb9\x5e\x30\x30\x6f\x06\xc0\x57\x9a\x60\x4c\x60\x3c\x16\x2e\x56\xaa\xe4\x74\x74\xac\x46\xe7\xa3\x63\x35\x9c\x84\x8e\x15\x4b\x86\xa3\xd3\xd0\x34\x25\xc6\x19\xa0\xa4\xcb\xe6\x5d\xb7\x94\xcf\xd3\x2c\xbb\xae\x11\x1e\x6b\x3c\x6b\x2e\x1d\xe6\x10\xaa\x3f\xb1\x4d\x8f\x6b\x98\x66\xaf\x05\x50\xfd\xd6\x7f\x53\x8a\x59\x11\x92\x86\x37\x97\xbe\xff\x3f\x33\x07\xb9\x10\x78\x91\xc6\x65\xf2\x52\xa1\x98\x35\x88\x1b\xb8\x6d\xa7\xfa\xab\xda\x7d\xe8\xe8\x49\xe6\x89\x16\x59\x16\xfe\x42\x05\x55\xf2\xc7\x07\xd7\x25\x8d\xd4\x5e\xd0\x75\x5a\x0f\xfd\xe2\xdc\xef\x9d\x69\x59\x1d\x3e\xd2\x7e\x93\x65\x38\x41\x7e\x7a\xf5\xc5\xaf\xff\xf4\x5d\x1c\xfc\x3e\x0e\xbe\x8f\x83\x3f\x7c\x49\x98\xbb\xcf\x22\x58\x0e\x3a\x91\x40\xc8\x3e\xcb\xb8\x7d\x84\xef\xd2\xb0\x87\x87\xf1\xe9\x73\x14\xe6\x59\x5e\x55\xe5\x3a\xbb\x44\xba\xdb\xbc\xf2\x55\x7d\x9b\x4e\xb2\xb9\xc9\xd6\x2f\xc7\xb9\xa1\x1e\xfe\xb3\x70\xcd\x2a\x97\x84\x0f\x25\x11\xc6\x69\x57\x96\xe4\xa3\xe6\xad\x3f\xbd\x9a\x8e\xb2\xd1\x21\x14\x2b\x31\xde\x36\xbe\xbe\x65\x3f\xaf\xcc\x0b\x94\xb1\x32\x2f\x7e\x97\x8d\xea\x53\xa8\x83\x0d\x97\xb5\x93\x52\x78\x5d\x67\xa2\xe5\x52\xe6\x9d\x3b\x00\x2d\x2f\x0a\xd2\x9a\xfd\xb4\x9c\xa6\x7c\x66\x58\x1c\xa8\x61\x0a\x0f\x7f\xa3\x1d\x2a\x09\xdb\x14\xd3\xc8\xe1\xce\x86\x33\xd0\xf0\x37\x70\x1d\x97\xba\xf8\xf3\x30\x99\x12\xa3\x37\x20\x0c\x60\x2e\xe1\xc2\x99\x34\x7a\x06\xef\xb4\x38\x3b\x39\x9c\x69\x55\xbd\x51\xfb\x7c\x47\x0d\xe0\xb9\x3a\x8f\x5b\xe2\xba\x20\xc3\x9c\xab\x8b\xeb\xa9\xf2\xd7\x4b\x10\xd6\x78\xd1\x3c\xc2\x90\x2a\x5e\xcb\xf8\x19\x60\xc2\x3d\x68\x31\xbb\xfe\xc2\xa3\x35\x96\xea\xb0\xd3\x37\xa0\xab\x37\x8a\xe5\x56\xf9\x6f\x7c\x39\x53\xa2\x7c\x75\xeb\x92\xb8\x20\xc3\x2c\xfa\xbb\x7c\x75\x8b\xe9\x38\xd1\x69\xc2\x1a\x64\xbd\xcc\xf8\x57\xb0\x0d\xfa\x06\x86\xef\xe0\x14\xaa\x65\x1e\xcb\x45\x6b\xf6\x45\xd0\xa8\x70\xe2\x8b\x48\xfc\xf6\xe3\x8f\x18\x59\xd7\x7c\x61\x2e\x7a\x9e\x12\xf6\x83\x7d\xc3\xe5\x44\xe4\x48\x07\xaf\xc1\x33\x24\x4f\x42\x89\x84\x7d\xe0\x87\xba\x8e\x7a\x21\x86\xf5\x62\xfc\x2d\xef\x68\xbe\xbc\x19\xab\x0b\x62\xa0\x5b\x8f\x2a\x9b\xe9\x85\xbd\xec\xfc\xe3\x7a\x97\x67\xf9\xa7\x9f\x57\xe6\x8b\xab\x58\x3e\x0b\xf3\x81\x01\x56\x2a\xa0\xec\x80\x75\xca\x58\xbd\xd9\xfb\xec\x0f\xf5\x23\xa9\x55\x16\x1b\xf5\x8a\x4b\x03\xda\xe6\x5e\x60\xe1\x56\xae\xe7\x7a\x52\x4f\x30\x51\x60\x9c\x03\x09\x52\x03\x9d\xfb\x14\xf5\xbf\x7e\x82\x0a\xeb\x3e\x7f\xce\x46\x18\x3c\x53\xf7\x3f\xb4\xa1\xa8\xb9\x4a\xed\xeb\x5e\x96\x57\x2f\x32\x52\x55\x6e\x79\x55\x91\x6c\x9d\x57\x2f\xd6\xee\x0c\xf2\x5d\x36\xea\x0b\xdc\x3f\xa1\x90\xeb\x7f\x03\x00\x00\xff\xff\xd5\x1f\x7c\xe4\xf7\x1c\x00\x00"
+var _runtimePluginsLinterLinterLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x59\x6d\x8f\xdb\xb8\xf1\x7f\xbf\x9f\x82\x10\xfe\x06\xe4\xac\xa4\x4d\xee\x7f\x7d\x63\xc0\x28\xae\xe9\x5d\xd1\x22\x97\x14\xdd\xb4\x7d\x91\xe4\x0a\x9a\x1a\xd9\xbc\xa5\x48\x95\xa4\xec\x75\x17\xe9\x67\x2f\x86\x0f\x32\x25\x4b\xc9\xf6\x7a\x06\x56\xa2\xa8\xe1\xcc\x6f\x1e\x39\xd4\xfe\xed\xfb\xbf\xdc\xff\xf1\xdd\x5b\xb2\x25\xd9\xab\xea\x65\xf5\x32\xbb\xb9\x11\x8a\x51\x41\x5a\xce\xb4\x22\x5b\xc2\xdb\x4e\x69\x9b\x67\xee\x39\x5b\x87\xb7\xba\x97\x96\xb7\x90\xbc\x0f\x33\x03\x45\xc3\x05\x74\xd4\x1e\x12\x12\x7c\xbc\x8b\xf3\x03\xa1\x39\x80\x10\x53\x41\x77\x6e\x76\xa0\xd9\xf5\x4d\x03\xfa\x8a\xc8\x4f\x0f\x54\x4c\xc9\x86\xef\xaf\xa8\xfc\x74\xb6\x8e\x9a\x09\x2e\x2d\x68\x43\xb6\xe4\xe9\xf3\xcd\x4d\x59\x12\xa6\x81\x5a\x30\x84\x86\x57\x04\xa4\xd5\xe7\x82\x30\x2a\x04\x69\xb4\x6a\xc9\x89\xdb\x03\x97\x84\x4a\xc2\x25\xb7\x9c\x0a\xfe\x2f\x6a\xb9\x92\xa4\xe9\x25\xc3\x41\x41\xa4\xb2\xc8\xab\xe6\x1a\x98\x15\x67\x42\x6d\xa4\x25\x42\xd1\x9a\xa0\x71\x6e\xca\x12\x69\x24\x6d\x61\xe3\xae\x44\x35\xc4\x1e\x20\xc8\xc5\x77\x68\x1e\x7b\xee\x60\x33\x8c\x88\x55\x84\x1d\x80\x3d\x90\x46\x69\x7c\xe8\x4d\xba\x80\xb5\xf5\x86\xb4\x94\xcb\x08\xbe\xd3\x8a\x81\x31\xc4\x1e\x10\x82\x21\xf0\x08\xac\xb7\x50\x23\x31\xd5\x7b\xb3\xc1\x6b\xdf\x82\xb4\x06\xb9\x75\xd4\xb8\xfb\x05\x46\xe4\x80\x0b\xf0\x87\xf2\x56\x0d\xd2\x68\x40\x2f\x04\x62\xd6\x6b\x0d\xd2\x3a\x9c\x4e\x99\x11\x7d\xbd\x48\xef\x2d\xa4\xf4\x79\x58\x04\x5a\x2b\xdd\x28\xdd\x52\xbb\x21\x07\x75\xf2\xb0\xb4\x81\x04\xd4\x1d\x53\x6d\xc7\x45\xa2\x9f\xea\x6d\xd7\xdb\x28\x74\xd5\x78\x8b\x15\x64\x25\x36\xb8\x06\x88\xec\xdb\x1d\xe8\x82\xac\xda\x8d\x17\x71\x77\xa2\x5a\x72\xb9\x27\x2d\x18\x43\xf7\x4e\xb6\x32\x48\x6d\x2c\x7a\xe2\xdd\x3d\x5a\x8d\x9b\x68\x07\x6e\x88\xe9\x3b\x0c\x25\xa8\x89\xd2\xa4\x97\xc9\xa3\x8c\x92\x55\x87\x01\x40\x05\x42\xa6\x6d\x41\x6a\x68\x68\x2f\xec\x06\xa3\xab\x2c\xc9\xe9\xc0\x2d\xa0\x84\x0d\x31\x07\xd5\x8b\xda\x29\xf5\xee\xde\x4b\xdd\x01\xa1\x64\x27\x28\x7b\x70\x8f\x79\xad\x30\x90\x30\xbd\x52\x87\x38\xc7\x1f\xc0\xe0\x3a\xb3\x8e\x82\xc3\x4f\x69\x42\x2f\x52\x48\xae\xa4\x38\x3f\x8f\xc1\x22\xf2\x86\x0a\x03\x24\x0f\x78\x07\x78\x6e\x61\xad\x5a\x6a\xd9\x61\xa4\xcd\x10\xaa\x3b\x20\x4e\x60\xa7\x01\x8d\x44\x5d\x4e\xf5\x94\x74\xd4\x5a\xd0\x12\x1d\xeb\x56\xbb\x84\x1a\xe9\x81\x6c\x28\xb3\x7d\xa8\x1c\xc8\xad\x40\xd5\x12\x29\x41\x17\xa7\x1f\x65\x96\x1f\xa9\x05\xa2\x5c\x56\xc2\x23\x65\xd6\xb3\x7e\xae\x72\x1a\xfe\xd9\x73\x0d\xe9\x52\xa7\x9f\x50\x4d\x63\xc0\x86\x18\xf2\x0f\xe4\xc4\x85\x70\xbe\xaa\x6b\xa8\x93\x6c\x89\x41\x46\x34\xd8\x5e\x4b\xa8\xc9\xee\x3c\x49\xe8\xe1\xd7\x1b\x68\x7a\x41\x78\x9a\xf1\x61\x9d\x21\x2f\x4b\x2e\x6b\x78\x84\xda\x71\x35\x5f\x55\xe2\xa5\x4b\xfd\x08\x95\x29\xd1\xb7\xf2\x8b\x60\x99\x12\xbf\x3e\x56\x2f\xf7\xb9\x68\xa9\x10\x3b\xca\x1e\x36\x43\xd1\x74\x95\x8d\x3a\xb0\x8d\x72\xae\xc0\x4a\x85\x09\x7a\x91\x5a\x20\x08\x6e\xa3\xf0\x71\xec\x7b\x57\x46\x62\xcc\x57\x46\x25\x03\x01\x75\x45\xde\xa3\xd2\x41\x24\xbe\xc1\x3a\x07\x3e\x90\x76\x7d\x53\x7d\x15\xb3\xe4\xe2\x66\x00\xda\xd2\x07\x78\xe3\xf0\xe4\x58\xb4\x8a\x24\x46\x59\x5b\x17\xae\xae\x16\x69\x1d\x2b\x88\x32\xc5\x25\x2b\x8b\x98\x36\x45\x8c\xaf\x22\x7a\xaf\x18\x50\xae\x6f\x10\x10\x6f\xe2\x06\xf5\x01\x45\x7d\x22\xdb\x2d\x62\x41\xe0\xf2\x26\x2a\x3e\xa1\xc0\x52\x33\xfb\xaa\x1a\x32\x73\x3b\x40\x5e\xa0\x64\x6d\x4d\xb6\xa8\xcd\xc2\x7b\x54\x91\x6c\x9d\xa6\x0b\x14\x89\xfa\x64\x9b\x1a\x63\x81\x5e\x21\x3f\x65\x30\xcb\x17\xf1\x5f\xea\xda\x36\xa9\x71\x4a\x7b\xd7\x2f\x2c\x0a\xb6\x26\xdb\x68\xf5\xaf\x2d\x08\x3e\x21\xdb\xe8\x1d\x5c\xf0\x72\xc9\x50\x03\x31\x7b\x06\x71\x8c\xc0\xed\x25\x18\x95\x76\xc1\x85\xc4\x20\xeb\x1b\xfc\xbb\x44\x9a\x86\x56\x1d\xd3\x58\xf3\x51\x31\x75\x38\x32\x18\x2f\xc4\x66\x23\x0f\xc4\xae\xcd\xa9\xe1\x28\x7b\xd7\x59\x65\x77\x35\x1c\xef\xf0\x21\x8b\x21\x16\xba\xb5\xea\x0f\xef\xde\xdd\x63\x84\x65\x27\x2e\x6b\x75\x32\xd9\x38\xce\x12\x1e\x6f\xff\xfa\x26\x1b\x30\xbb\x41\x92\x14\xd9\x9e\xb1\xac\x20\x99\xbb\xf8\xf1\x53\x56\x36\xe6\x2c\x2d\x7d\x2c\xb1\x62\xe3\x8b\xf2\xef\x54\x08\x3f\x80\x47\xab\x29\x0e\x57\x4d\xf6\xd9\xdd\x36\x2b\xb1\x59\xb1\x4d\x75\xbb\x21\xab\x36\x5b\x2f\x4a\xb8\xbd\xfd\x82\x8c\xac\x34\xb6\xde\xb2\xdb\xdb\x57\xdf\xfe\xcf\x02\xeb\xb6\x46\x7a\x7f\x71\xe3\xa7\xac\x64\x4a\x28\xbd\x55\x4d\xe3\xb8\xaa\xd2\xdd\x4e\xfe\xca\xdd\x8d\x8d\x84\xac\xf2\x95\x58\xad\xbf\xa0\x95\xda\xf5\x5c\x38\x19\x7b\x35\x5c\x9f\xb2\x61\xb6\xc4\xe7\xe0\x86\x11\xee\xdf\x5e\x18\x96\xe5\x84\x27\x46\x4b\xca\x32\x3c\x3f\x5d\x29\x3f\x0f\xea\x67\x7a\xa4\x4e\x0d\x1c\xc4\x7b\xb0\xb7\x03\xb5\xaa\xaf\x2c\xe9\xf3\x7d\x89\xa1\x39\x04\x44\xc8\xc9\x30\xcd\x3b\xff\x14\xe7\x53\x64\x7e\x5f\x5d\x89\xa2\xba\x2d\xe6\xd9\x09\x6e\x41\x53\x0b\xc8\x62\x32\x0e\x5e\xba\x76\x74\x8b\x6f\x3e\x17\xbe\x0c\x14\xc4\xea\x1e\x66\x18\xf7\xd4\x75\xda\x8e\x59\x4f\xc3\x2d\x4e\x3d\x65\x65\x29\x95\x0f\x81\xb9\x48\x9a\x07\x2b\x39\x8a\x1e\xdf\x9e\xb2\x41\x4c\x59\x62\x45\xfb\xa1\x17\xe2\xcf\xd4\x1e\x8c\x9f\x32\xb6\x56\xbd\xf5\x63\xb4\x90\xd9\x84\x88\x1b\x44\x56\x2b\x51\x90\x15\xab\xe6\x65\x32\x41\xe5\x1e\xe9\xd5\xee\x67\xc0\x4e\x09\xbc\x49\x1e\x99\xee\xa5\x97\x1f\x29\x7e\xdd\x24\xed\xce\x8d\xa0\x0f\xe0\xd4\xe8\xce\xf6\xa0\xa4\x1f\x0d\xb3\x93\x10\xac\xca\x34\x8e\x53\x4e\xed\xb9\x3b\x8f\xb9\x84\x99\x09\x87\x25\x1c\x31\x05\x52\x14\x43\x1a\x94\xa5\x3f\x3c\x94\x7e\x7f\xda\xba\xc3\x06\xdd\x09\xf0\x26\xd7\x80\x4d\xbe\xd9\x4a\x75\x1d\xe6\xb3\xe2\xcc\xa1\x69\x9d\x34\x7f\x6a\x75\x03\x3f\xf3\xdc\x94\x33\x27\xde\x58\xe7\x23\x37\x1a\x3b\xeb\xf2\x72\xc1\x11\x48\x54\x53\x7d\xe2\x12\x5f\xcf\xc7\xf6\x44\x02\x9b\x05\x97\xf0\x13\x5c\xf6\x8f\xcb\xec\xce\xb4\x75\x8a\xa6\xf7\xc4\xbe\xde\xb0\xce\xec\x54\x9b\x68\xda\x6b\x71\xde\x1a\x8e\xbb\x3f\xa6\x57\x3f\xd2\x07\x78\xad\xda\x96\xca\x1a\x33\xdd\x7b\xd1\x6f\x7f\x15\xde\x5e\xbb\x52\x1c\x88\xdf\xaa\xd7\xaa\xed\x04\x58\x58\x4f\xb6\xc3\x40\x9a\xef\x3a\xdf\x9d\x79\x0d\x76\xdd\xe6\x9e\x1e\x21\xec\x93\xba\x97\x41\x9d\x5d\x57\xfd\xae\x6f\xa6\x3c\x98\x92\x96\x72\x69\x72\xdf\xc2\x81\x00\x3c\x35\xfb\xb5\x78\xa2\x7a\x28\xc8\x91\x70\x49\x3a\xca\xb5\x27\x5a\x93\x5a\x0d\x9b\x27\x6f\xc8\x11\xf7\xd6\xb0\x6e\xbc\xb3\x3a\xf9\xae\xa7\x75\x06\x1e\xe6\x11\x41\x7a\x0f\x34\xbe\x7b\x99\xb4\x0a\x17\xf8\x88\xfd\xb2\xf3\x37\xd8\x9c\xec\xfa\x66\xf3\x03\x17\xf0\xfe\xdc\xc1\xa8\x2f\x70\xe7\x75\xf7\xbe\xc2\x92\x93\x76\x0c\x5c\x87\x3e\xb1\xa3\xf6\x50\xfd\x9e\xeb\x1c\x1f\x82\x7f\xe6\x34\x76\x4d\xc9\x48\xe9\x88\x20\x76\x60\x88\x65\x4b\x8e\xd5\x55\xf7\x89\xd6\x19\x3a\xb5\x2b\xd3\x5c\x18\x18\xab\xb9\xdc\x57\xee\x31\x6f\x6c\x91\xf0\x5a\x8f\xac\x36\x81\x70\xa0\x06\x5b\x9b\x8b\x13\x8f\x15\xb6\xe4\x69\xe3\xb3\x4e\xc1\xe0\xb1\xdb\xaf\xa1\xb2\x26\xc7\xa4\xf3\xfc\x02\xb8\x71\x53\x19\x7d\x16\x38\x5e\xb8\x21\xef\x5f\xcc\x71\xa2\x57\xe8\xc3\x93\x8e\x39\x38\x86\xea\xfd\xc5\x35\x47\xd7\xaf\x8f\x3c\x83\x3f\x9c\xfc\xf0\xf0\xc9\xf7\xf1\x9b\xbd\xe9\x77\x79\xb6\x5a\xe1\xd6\xe2\x1c\x3d\xcc\x60\x8a\xd5\x5c\x2f\x18\x98\x37\x03\xe0\x2b\x4d\x30\x26\x30\x1e\x0b\x17\x2b\x55\x72\x3a\x3a\x56\xa3\xf3\xd1\xb1\x1a\x4e\x42\xc7\x8a\x25\xc3\xd1\x69\x68\x9a\x12\xe3\x0c\x50\xd2\x65\xf3\xae\x5b\xca\xe7\x69\x96\x5d\xd7\x08\x8f\x35\x9e\x35\x97\x0e\x73\x08\xd5\x9f\xd8\xa6\xc7\x35\x4c\xb3\xd7\x02\xa8\xfe\xd1\x7f\x53\x8a\x59\x11\x92\x86\x37\x97\xbe\xff\xdf\x33\x07\xb9\x10\x78\x91\xc6\x65\xf2\x52\xa1\x98\x35\x88\x1b\xb8\x6d\xa7\xfa\x93\xda\xdd\x77\xf4\x24\xf3\x44\x8b\x2c\x0b\x7f\xa1\x82\x2a\xf9\xfd\xa3\xeb\x92\x46\x6a\x2f\xe8\x3a\xad\x87\x7e\x71\xee\xf7\xce\xb4\xac\x0e\x1f\x69\xbf\xca\x32\x9c\x20\x3f\xbc\xfa\xe4\xd7\x7f\xf8\x26\x0e\xfe\x3f\x0e\xbe\x8d\x83\xdf\x7c\x4a\x98\xbb\xcf\x22\x58\x0e\x3a\x91\x40\xc8\x3e\xca\xb8\x7d\x84\xef\xd2\xb0\x87\xc7\xf1\xe9\x73\x14\xe6\x59\x5e\x55\xe5\x3a\xbb\x44\xba\xdb\xbc\xf2\x55\x7d\x9b\x4e\xb2\xb9\xc9\xd6\x2f\xc7\xb9\xa1\x1e\xfe\xa3\x70\xcd\x2a\x97\x84\x0f\x25\x11\xc6\x69\x57\x96\xe4\xbd\xe6\xad\x3f\xbd\x9a\x8e\xb2\xd1\x21\x14\x2b\x31\xde\x36\xbe\xbe\x65\x3f\xad\xcc\x0b\x94\xb1\x32\x2f\xfe\x2f\x1b\xd5\xa7\x50\x07\x1b\x2e\x6b\x27\xa5\xf0\xba\xce\x44\xcb\xa5\xcc\x3b\x77\x00\x5a\x5e\x14\xa4\x35\xfb\x69\x39\x4d\xf9\xcc\xb0\x38\x50\xc3\x14\x1e\xfe\x46\x3b\x54\x12\xb6\x29\xa6\x91\xc3\x9d\x0d\x67\xa0\xe1\x6f\xe0\x3a\x2e\x75\xf1\xe7\x61\x32\x25\x46\x6f\x40\x18\xc0\x5c\xc2\x85\x33\x69\xf4\x0c\xde\x69\x71\x76\x72\x38\xd3\xaa\x7a\xa3\xf6\xf9\x8e\x1a\xc0\x73\x75\x1e\xb7\xc4\x75\x41\x86\x39\x57\x17\xd7\x53\xe5\xaf\x97\x20\xac\xf1\xa2\x79\x84\x21\x55\xbc\x96\xf1\x33\xc0\x84\x7b\xd0\x62\x76\xfd\x85\x47\x6b\x2c\xd5\x61\xa7\x6f\x40\x57\x6f\x14\xcb\xad\xf2\xdf\xf8\x72\xa6\x44\xf9\xea\xd6\x25\x71\x41\x86\x59\xf4\x77\xf9\xea\x16\xd3\x71\xa2\xd3\x84\x35\xc8\x7a\x99\xf1\x2f\x60\x1b\xf4\x0d\x0c\xdf\xc2\x29\x54\xcb\x3c\x96\x8b\xd6\xec\x8b\xa0\x51\xe1\xc4\x17\x91\xf8\xc7\xf7\xdf\x63\x64\x5d\xf3\x85\xb9\xe8\xf9\x92\xb0\xef\xec\x1b\x2e\x27\x22\x47\x3a\x78\x0d\x9e\x21\x79\x12\x4a\x24\xec\x03\xdf\xd5\x75\xd4\x0b\x31\xac\x17\xe3\x6f\x79\x47\xf3\xe5\xcd\x58\x5d\x10\x03\xdd\x7a\x54\xd9\x4c\x2f\xec\x65\xe7\x1f\xd7\xbb\x3c\xcb\x3f\xfc\xb4\x32\x9f\x5c\xc5\xf2\x59\x98\x0f\x0c\xb0\x52\x01\x65\x07\xac\x53\xc6\xea\xcd\xde\x67\x7f\xa8\x1f\x49\xad\xb2\xd8\xa8\x57\x5c\x1a\xd0\x36\xf7\x02\x0b\xb7\x72\x3d\xd7\x93\x7a\x82\x89\x02\xe3\x1c\x48\x90\x1a\xe8\xdc\xa7\xa8\xff\xf6\x13\x54\x58\xf7\xf1\x63\x36\xc2\xe0\x99\xba\xff\xa1\x0d\x45\xcd\x55\x6a\x5f\xf7\xb2\xbc\x7a\x91\x91\xaa\x72\xcb\xab\x8a\x64\xeb\xbc\x7a\xb1\x76\x67\x90\x6f\xb2\x51\x5f\xe0\xfe\x09\x85\x5c\xff\x13\x00\x00\xff\xff\x45\x0e\xec\x4b\x0a\x1d\x00\x00"
 
 func runtimePluginsLinterLinterLuaBytes() ([]byte, error) {
        return bindataRead(
@@ -1173,27 +1088,7 @@ func runtimePluginsLiterateReadmeMd() (*asset, error) {
        return a, nil
 }
 
-var _runtimePluginsLiterateInfoJson = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8f\xb1\x4e\xc5\x30\x0c\x45\xf7\x7e\x85\xd5\x19\x35\x0f\xc6\x27\xc1\xcc\xf0\xfe\x00\x31\xf8\x35\x26\xb1\x94\xc4\xc1\x71\x40\x80\xf8\x77\xd4\xd0\x2e\x2c\xac\xe7\xe6\xdc\x5c\x7f\x4d\x00\x00\x73\xc1\x4c\xf3\x19\xe6\xc4\x46\x8a\x46\xf3\xcd\x2f\xf7\xd4\x56\xe5\x6a\x2c\x65\x8b\x1f\x39\xc4\xc4\x21\x1a\x97\x00\x58\x3c\x24\x2c\xa1\x63\x20\x68\xbd\x56\x51\x83\x17\x51\xb0\x48\x70\xd9\x8b\xa0\xaa\x04\xc5\x9c\x37\xc3\x44\xd2\x72\x54\xbf\xd3\xb5\xb1\x8d\x5f\xa3\x59\x6d\x67\xe7\x02\x5b\xec\xd7\x65\x95\xec\x3e\x3f\xc8\xb3\x67\x74\x97\x3f\x8b\xb8\x34\xc3\x94\xfe\xd3\x32\xaf\x2a\x87\xf3\x46\xda\xf6\x0b\x6e\x97\xd3\x72\x3a\xb8\xd2\x6b\x67\xdd\x26\x3c\x0d\x30\xe0\x30\xe1\xe1\x1e\xee\xc6\xd3\x11\x3c\x4f\xdf\xd3\x4f\x00\x00\x00\xff\xff\x5b\x8a\xe8\x27\x2a\x01\x00\x00"
-
-func runtimePluginsLiterateInfoJsonBytes() ([]byte, error) {
-       return bindataRead(
-               _runtimePluginsLiterateInfoJson,
-               "runtime/plugins/literate/info.json",
-       )
-}
-
-func runtimePluginsLiterateInfoJson() (*asset, error) {
-       bytes, err := runtimePluginsLiterateInfoJsonBytes()
-       if err != nil {
-               return nil, err
-       }
-
-       info := bindataFileInfo{name: "runtime/plugins/literate/info.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)}
-       a := &asset{bytes: bytes, info: info}
-       return a, nil
-}
-
-var _runtimePluginsLiterateLiterateLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x55\x4d\x8f\xe2\x38\x10\xbd\xf3\x2b\x4a\xde\x5d\x75\xb2\x9d\x64\xc5\x1e\x91\x22\x65\xe6\xd0\xa7\xf9\x12\x3d\x73\x02\x1a\x99\xb8\x02\x16\x8e\x1d\xd9\x95\x61\x50\xd3\xff\x7d\xe4\x38\x40\x1a\xb5\x34\xd0\xb9\xc4\x55\x7e\xf5\x5e\x95\xcb\x1f\xca\x94\x5c\x41\x69\x74\x25\xd7\x90\x83\xac\x1b\x63\x29\x62\xb5\x2c\xad\xf9\x2f\xb8\x59\x3c\x1a\x55\xad\x2e\x49\x1a\x0d\x8e\xb8\x25\xb7\x93\xb4\x89\x1c\xd9\x24\xd8\xf1\x08\x00\x2c\x52\x6b\x3d\xc0\x4a\xbd\xce\x5c\xbb\xea\x00\xe3\xa4\x77\x28\xd4\x51\x00\xc7\x79\xde\x0d\x46\xa8\xc5\x80\x19\xb5\x18\xf0\xa2\x16\x8f\x64\x87\xc4\xc1\x93\xe7\x77\x77\x60\xec\xa5\x4c\x3a\x50\xe9\x43\xe3\x3c\x0f\xa3\x0b\x1d\xd7\x28\x49\x51\xc0\x27\xe0\xb0\xe9\x44\x20\x2c\x84\xc3\x26\x81\x4a\xa2\x12\x0e\x72\x6f\x79\x2d\x36\x61\x09\x3c\xbf\x0c\x60\x0d\x27\x42\xab\x3d\x24\xe8\x56\xc6\xd6\x9c\x22\x16\xcd\x9e\xfe\x71\x8b\xfb\x98\x0d\x98\x03\x64\xb2\xf6\xb9\xf6\x81\x09\x1c\xd3\x89\xca\xb8\xd7\x9b\xfd\x15\xfe\xf7\xe3\x05\xe4\x50\xfa\x7a\x43\x7c\x5f\x7f\x98\xbd\x28\xc6\xe8\x8f\x6d\x55\xa1\xfd\xda\xa0\x8e\x56\x6d\x15\x22\x64\x05\xda\xd0\x79\x45\x57\x6d\x95\x7d\xe3\xb4\x49\x80\x65\x4a\x12\x8b\x81\x36\xa8\x3b\xe8\x59\xa0\x33\x3b\xf6\x73\x9d\xa5\x11\x48\xfb\x06\x21\x07\xd6\xea\xad\x36\x3b\xcd\xba\xe9\xca\x58\x90\xf9\x38\x59\xb5\xd5\xe4\x93\xd4\xe8\xbe\xb4\x75\x14\x83\x30\x27\xd2\x40\xa0\xa4\xf6\xc1\x47\x58\x24\xd3\x71\x7c\x82\xc8\x6a\xb8\x9d\x3c\x34\x01\x56\x78\xcd\xa5\x17\xbd\x4c\xd3\x7f\x83\x84\x42\x1f\xfb\x28\x60\xf1\xec\xff\xc5\x2b\xe8\xca\x22\xdf\x9e\x3c\xbe\xb0\x37\x0a\x74\x7b\x4d\xfc\xd7\x83\x54\x5d\x89\xa1\xb6\x57\xbe\x81\x91\x65\xc0\x2a\xa9\x3a\xfd\x09\x28\x49\x68\x39\x61\xca\xfc\xc4\x29\x2f\x0f\x9a\xeb\x3f\x13\x09\x24\x2c\x69\x72\x0d\xb4\x5b\x6f\xa9\x50\xf3\x1a\x27\x30\x67\xf3\xf9\x7c\xee\xdb\xf8\xf7\xfc\x2a\x25\xdb\x2a\x74\x57\x0b\xa5\x20\x75\xa9\x5a\xd1\x29\xd5\xdc\x6e\x85\xd9\xe9\xeb\x84\x42\xb8\x6b\xb0\x94\x5c\xf9\xf0\xa7\xa8\x70\x87\x82\x24\x29\x3c\x9c\xdb\xea\x87\x75\x8d\x9a\x7a\xab\xd7\x3b\x14\xe5\x86\xeb\xf5\xe9\xbf\xf4\xfb\xff\x9d\xc2\x51\xc1\x85\x58\x96\xce\x1d\x0a\xf3\x13\xed\xce\x4a\xc2\x60\x96\x46\x19\xeb\xca\x0d\xd6\x21\x8f\x46\x2a\xb4\x87\x02\xad\x35\x76\x19\x0e\xf1\xa1\x58\x19\xb3\xbd\x49\x5a\x60\xc5\x5b\x75\x7d\x37\xc3\xad\xc0\x2d\xf9\x64\xd3\x34\xcd\xfe\xbd\xb2\x97\x83\xdd\xdc\x87\xde\x18\xa8\x64\x2d\x29\x5d\x5b\xd3\x36\x9e\x40\x0a\xd4\x24\x2b\x89\xf6\x36\x9a\xdb\xf6\xd4\xf1\x3b\xf7\xe8\xd6\xc8\x57\x0b\x56\xf8\x03\xf0\x7c\x5b\xc2\x17\x0b\xe7\x19\x5e\xde\xc7\x10\x4a\x87\xd9\xe2\xf6\xea\x4f\x27\xeb\xed\x2b\x63\x14\x2e\x38\xff\xe4\x66\x1f\x84\x98\xb6\x9a\x64\x8d\x9e\xeb\xc1\x9a\xfa\x33\xd6\xc6\xee\xa3\x7e\x7e\xfa\xfd\xb1\x53\x4a\x80\x1d\x2f\xa2\x6c\xcf\x6b\xe5\xdf\x9d\x53\x0a\xf1\x90\x71\x8a\xca\x70\x11\x05\x9f\xbf\x8f\x7f\x34\x82\x13\x4e\x7d\x39\x51\xdc\x3d\x2b\xbf\x03\x00\x00\xff\xff\x1e\xba\xd6\x49\x0c\x08\x00\x00"
+var _runtimePluginsLiterateLiterateLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x9c\x55\xdf\x6f\xc2\x36\x10\x7e\xe7\xaf\x38\x79\x9b\x9a\xac\x49\x56\xf6\x88\x14\x29\x9b\xb4\x4a\x93\xb6\x76\xa2\xdb\x5e\x80\x22\x13\x5f\xc0\xc2\xb1\x23\xfb\x32\x86\x4a\xff\xf7\xc9\x71\x80\x14\x55\x1a\x34\x2f\xf1\x9d\xbf\xfb\xbe\x3b\x9f\x7f\xfc\xfd\xcb\xf4\xe5\xd7\xe7\x27\xc8\x81\x8d\xb3\x87\xec\x81\x8d\x46\xca\x94\x5c\x41\x69\x74\x25\xd7\x90\x83\xac\x1b\x63\x29\x62\xb5\x2c\xad\xf9\x21\xb8\x59\x3c\x1a\x55\xad\x2e\x49\x1a\x0d\x8e\xb8\x25\xb7\x93\xb4\x89\x1c\xd9\x24\xd8\xf1\x08\x00\x2c\x52\x6b\x3d\xc0\x4a\xbd\xce\x5c\xbb\xea\x00\xe3\xa4\x77\x28\xd4\x51\x00\xc7\x79\xde\x0d\x46\xa8\xc5\x80\x19\xb5\x18\xf0\xa2\x16\x2f\x64\x87\xc4\xc1\x93\xe7\x77\x77\x60\xec\xa5\x4c\x3a\x50\xe9\x43\xe3\x3c\x0f\xa3\x0b\x1d\xd7\x28\x49\x51\xc0\x27\xe0\xb0\xe9\x44\x20\x2c\x84\xc3\x26\x81\x4a\xa2\x12\x0e\x72\x6f\x79\x2d\x36\x61\x09\xbc\xbd\x0f\x60\x0d\x27\x42\xab\x3d\x24\xe8\x56\xc6\xd6\x9c\x22\x16\xcd\x5e\xbf\x73\x8b\xfb\x98\x0d\x98\x03\x64\xb2\xf6\xb9\xf6\x81\x09\x1c\xd3\x89\xca\xb8\xd7\x9b\x7d\x13\xfe\xf7\xe3\x05\xe4\x50\xfa\x7a\x43\x7c\x5f\x7f\x98\xbd\x28\xc6\xe8\x9f\xdb\xaa\x42\xfb\xdc\xa0\x8e\x56\x6d\x15\x22\x64\x05\xda\xd0\x79\x45\x57\x6d\x95\xfd\xc1\x69\x93\x00\xcb\x94\x24\x16\x03\x6d\x50\x77\xd0\xb3\x40\x67\x76\xec\xe7\x3a\x4b\x23\x90\xf6\x0d\xfa\x1d\xd3\xea\xad\x36\x3b\xcd\xba\xe9\xca\x58\x90\xf9\x38\x59\xb5\xd5\xe4\x37\xa9\xd1\x3d\xb5\x75\x14\x83\x30\x27\xd2\x40\xa0\xa4\xf6\xc1\x47\x58\x24\xd3\x71\x7c\x82\xc8\x6a\xb8\x9d\x3c\x34\x01\x56\x78\xcd\xa5\x17\xbd\x4c\xd3\x7f\x83\x84\x42\x1f\xfb\x28\x60\xf1\xec\xc7\xc5\x07\xe8\xca\x22\xdf\x9e\x3c\xbe\xb0\x4f\x0a\x74\x7b\x4d\xfc\xdf\x47\xa9\xba\x12\x43\x6d\x1f\x7c\x03\x23\xcb\x80\x55\x52\x75\xfa\x13\x50\x92\xd0\x72\xc2\x94\xf9\x89\x53\x5e\x1e\x34\xd7\xff\x4f\x24\x90\xb0\xa4\xc9\x35\xd0\x6e\xbd\xa5\x42\xcd\x6b\x9c\xc0\x9c\xcd\xe7\xf3\xb9\x6f\xe3\xb7\xf3\xab\x94\x6c\xab\xd0\x5d\x2d\x94\x82\xd4\xa5\x6a\x45\xa7\x54\x73\xbb\x15\x66\xa7\xaf\x13\x0a\xe1\xae\xc1\x52\x72\xe5\xc3\x5f\xa3\xc2\x1d\x0a\x92\xa4\xf0\x70\x6e\xab\x1f\xd6\x35\x6a\xea\xad\x5e\xef\x50\x94\x1b\xae\xd7\xa7\xff\xd2\xef\xff\x2f\x0a\x47\x05\x17\x62\x59\x3a\x77\x28\xcc\x3f\x68\x77\x56\x12\x06\xb3\x34\xca\x58\x57\x6e\xb0\x0e\x79\x34\x52\xa1\x3d\x14\x68\xad\xb1\xcb\x70\x88\x0f\xc5\xca\x98\xed\x4d\xd2\x02\x2b\xde\xaa\xeb\xbb\x19\x6e\x05\x6e\xc9\x27\x9b\xa6\x69\xf6\xfd\x95\xbd\x1c\xec\xe6\x3e\xf4\xc6\x40\x25\x6b\x49\xe9\xda\x9a\xb6\xf1\x04\x52\xa0\x26\x59\x49\xb4\xb7\xd1\xdc\xb6\xa7\x8e\xdf\xb9\x47\xb7\x46\x7e\x58\xb0\xc2\x1f\x80\xb7\xdb\x12\xbe\x58\x38\xcf\xf0\xfe\x35\x86\x50\x3a\xcc\x16\xb7\x57\x7f\x3a\x59\x9f\x5f\x19\xa3\x70\xc1\xf9\x27\x37\xfb\x49\x88\x69\xab\x49\xd6\xe8\xb9\x1e\xad\xa9\x7f\xc7\xda\xd8\x7d\xd4\xcf\x4f\xff\x7c\xe9\x94\x12\x60\xc7\x8b\x28\xdb\xf3\x5a\xf9\x77\xe7\x94\x42\x3c\x64\x9c\xa2\x32\x5c\x44\xc1\xe7\xef\xe3\xbf\x1a\xc1\x09\xa7\xbe\x9c\x28\xee\x9e\x95\xff\x02\x00\x00\xff\xff\x0d\x7e\xfd\xa0\x1f\x08\x00\x00"
 
 func runtimePluginsLiterateLiterateLuaBytes() ([]byte, error) {
        return bindataRead(
@@ -1213,7 +1108,7 @@ func runtimePluginsLiterateLiterateLua() (*asset, error) {
        return a, nil
 }
 
-var _runtimePluginsStatusStatusLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x93\xc1\x4e\xc3\x30\x0c\x86\xef\x7d\x0a\xcb\xa7\x56\xda\xc2\x89\xe3\x0e\x03\xc6\x40\x1c\x40\x6a\x5f\x20\xed\x9c\x35\x52\xeb\x54\x49\x8a\xe0\xc2\xb3\xa3\x24\x9d\x68\x99\x90\x86\x84\xc8\xa5\xb2\xfd\xcb\xfe\xfd\x35\xe9\x75\x63\x0d\x6c\x40\xf7\x83\xb1\x3e\xc7\x18\x63\x91\xd5\xa3\x52\x64\xbf\x17\xae\x52\x1a\x8b\xac\x31\xac\xf4\xf1\xac\x9e\xd2\x58\x64\x99\x1a\xb9\xf1\xda\x30\x68\xd6\x3e\x2f\x32\x00\x80\xa8\x11\x25\xf9\xd2\x4b\x3f\xba\x47\x56\xe6\x9e\x73\x74\x31\x12\xb5\x95\xdc\xb4\x78\x89\xb4\x95\xee\x32\xe1\x20\x9d\x27\x2c\x32\xe2\xc3\xcc\x52\x9a\x94\xd7\xa9\x83\x56\x50\x8b\xea\x7d\x20\xf1\xa4\xf9\x00\x1f\x1b\x48\x5b\x8a\x9b\x2a\x74\x03\xdf\x12\x47\x61\x38\x9d\x69\x64\x07\xae\xa5\xae\x3b\x5b\x3e\x66\x27\x5b\x33\xad\xb7\x9a\x8f\x6e\xa6\x9e\x32\x81\xd2\x52\x9a\x7c\xad\x80\x6c\x20\x1f\xdb\x89\xdd\x1b\x35\xb7\xa6\xef\x25\x1f\x72\x3c\x6a\x8f\x2b\x40\x4b\xaf\xeb\x41\x5a\x47\x21\x58\xaf\x65\x5d\x87\x8c\x25\x15\xe2\x87\xdd\xf6\x6e\x66\x42\xab\xd4\x6e\x03\xac\xbb\xe5\x2e\xe1\x58\xf2\xa3\xe5\x93\x49\x51\x59\xdd\x97\x83\x6c\x28\x4f\x5e\xbe\xfa\x04\x82\xa7\xef\x92\x66\xf8\x19\x3f\xb3\xbc\xfe\x47\x7e\xc1\xc9\xaf\xe9\xb9\xd6\x58\xff\x87\xe0\x82\x89\x4b\xb0\xc5\xab\x39\xe3\x96\x9e\x8e\xd8\x93\xdf\x77\xa6\x96\xdd\xf3\x10\x64\x39\x4e\x57\x78\xe9\x60\x9a\x8e\x2f\xdb\xb2\xda\x01\x66\xf3\x51\xa7\x1a\xc6\x81\x9f\x01\x00\x00\xff\xff\xcf\xbd\xdb\xff\xe1\x03\x00\x00"
+var _runtimePluginsStatusStatusLua = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xbc\x93\x41\x4b\xf4\x30\x10\x86\xef\xfd\x15\xc3\x9c\x5a\xd8\xcd\xb7\xdf\xc1\x63\x0f\xab\xd6\x75\x11\x5c\xb1\xc5\x7b\xda\x9d\x6c\x03\x6d\x52\x92\x54\xf4\xe2\x6f\x97\x34\x5d\x6d\x5d\x84\x15\xc4\x5c\xca\xcc\xbc\xcc\xbc\xf3\x34\x79\xca\x1e\xf3\xed\xee\x1e\x52\xc0\xff\x6c\xc5\x56\x18\x45\x8d\xae\x78\x03\xad\xac\x8c\x86\x14\x64\xdb\x69\xe3\x62\x1c\x62\x4c\xc6\x6a\xd9\x0b\x41\xe6\x6b\xf9\x5f\x48\x7f\xa8\x2a\xad\x84\x3c\x9c\xa8\x42\x1a\x93\x28\x12\xbd\xaa\x9c\xd4\x0a\xa4\x92\x2e\x4e\x22\x00\x08\x83\x59\x4e\x2e\x77\xdc\xf5\x76\xab\x84\xbe\x51\x31\xda\x21\x62\xa5\xe1\xaa\xaa\xf1\x1c\x69\xcd\xed\x79\xc2\x8e\x5b\x47\x98\x44\xa4\xf6\x13\x4b\x61\x52\x5c\x86\x0e\x52\x40\xc9\x8a\xd7\x8e\xd8\x9d\x54\x7b\x78\x4b\x47\x04\xec\xb2\xf0\xdd\xc0\xd5\xa4\x06\xa1\x3f\x61\x7b\x5b\x53\xd3\x9c\x2c\x3f\x64\x47\x5b\x13\xad\x33\x52\x1d\xec\x44\x3d\x66\x3c\xa5\xb9\x34\xf8\x5a\x00\x19\xcf\x7f\x68\xc7\xb2\x17\xaa\xae\x74\xdb\x72\xb5\x8f\xf1\x20\x1d\x2e\x00\x0d\x3d\x2f\x3b\x6e\x2c\xf9\x60\xb9\xe4\x65\xe9\x33\x86\x84\x8f\x6f\xb3\xf5\xf5\xc4\x84\x14\xa1\x5d\x0a\x4a\x36\xf3\x5d\xfc\x31\xe4\x7a\xa3\x8e\x26\x59\x61\x64\x9b\x77\xbc\xa2\x38\x78\xf9\xec\xe3\x09\x1e\xbf\x73\x9a\xfe\x67\x7c\xcf\xf2\xe2\x0f\xf9\x79\x27\x3f\xa6\x67\x6b\x6d\xdc\x2f\x82\xf3\x26\xce\xc1\x36\x5c\xcd\x09\xb7\xf0\x74\xd8\x86\xdc\xa6\xd1\x25\x6f\x76\x9d\x97\xc5\x38\x5e\xe1\xb9\x83\x71\x3a\x3e\xac\xf3\x22\x03\x8c\xa6\xa3\x8e\x35\x1c\x06\xbe\x07\x00\x00\xff\xff\x3d\x42\x21\x73\x06\x04\x00\x00"
 
 func runtimePluginsStatusStatusLuaBytes() ([]byte, error) {
        return bindataRead(
@@ -6577,15 +6472,10 @@ var _bindata = map[string]func() (*asset, error){
        "runtime/help/plugins.md":                 runtimeHelpPluginsMd,
        "runtime/help/tutorial.md":                runtimeHelpTutorialMd,
        "runtime/plugins/autoclose/autoclose.lua": runtimePluginsAutocloseAutocloseLua,
-       "runtime/plugins/autoclose/info.json":     runtimePluginsAutocloseInfoJson,
        "runtime/plugins/comment/comment.lua":     runtimePluginsCommentCommentLua,
-       "runtime/plugins/comment/info.json":       runtimePluginsCommentInfoJson,
        "runtime/plugins/ftoptions/ftoptions.lua": runtimePluginsFtoptionsFtoptionsLua,
-       "runtime/plugins/ftoptions/info.json":     runtimePluginsFtoptionsInfoJson,
-       "runtime/plugins/linter/info.json":        runtimePluginsLinterInfoJson,
        "runtime/plugins/linter/linter.lua":       runtimePluginsLinterLinterLua,
        "runtime/plugins/literate/README.md":      runtimePluginsLiterateReadmeMd,
-       "runtime/plugins/literate/info.json":      runtimePluginsLiterateInfoJson,
        "runtime/plugins/literate/literate.lua":   runtimePluginsLiterateLiterateLua,
        "runtime/plugins/status/status.lua":       runtimePluginsStatusStatusLua,
        "runtime/syntax/LICENSE":                  runtimeSyntaxLicense,
@@ -6933,23 +6823,18 @@ var _bintree = &bintree{nil, map[string]*bintree{
                "plugins": &bintree{nil, map[string]*bintree{
                        "autoclose": &bintree{nil, map[string]*bintree{
                                "autoclose.lua": &bintree{runtimePluginsAutocloseAutocloseLua, map[string]*bintree{}},
-                               "info.json":     &bintree{runtimePluginsAutocloseInfoJson, map[string]*bintree{}},
                        }},
                        "comment": &bintree{nil, map[string]*bintree{
                                "comment.lua": &bintree{runtimePluginsCommentCommentLua, map[string]*bintree{}},
-                               "info.json":   &bintree{runtimePluginsCommentInfoJson, map[string]*bintree{}},
                        }},
                        "ftoptions": &bintree{nil, map[string]*bintree{
                                "ftoptions.lua": &bintree{runtimePluginsFtoptionsFtoptionsLua, map[string]*bintree{}},
-                               "info.json":     &bintree{runtimePluginsFtoptionsInfoJson, map[string]*bintree{}},
                        }},
                        "linter": &bintree{nil, map[string]*bintree{
-                               "info.json":  &bintree{runtimePluginsLinterInfoJson, map[string]*bintree{}},
                                "linter.lua": &bintree{runtimePluginsLinterLinterLua, map[string]*bintree{}},
                        }},
                        "literate": &bintree{nil, map[string]*bintree{
                                "README.md":    &bintree{runtimePluginsLiterateReadmeMd, map[string]*bintree{}},
-                               "info.json":    &bintree{runtimePluginsLiterateInfoJson, map[string]*bintree{}},
                                "literate.lua": &bintree{runtimePluginsLiterateLiterateLua, map[string]*bintree{}},
                        }},
                        "status": &bintree{nil, map[string]*bintree{
index 14dbd1e30fb377d0a6bba9e3209ca69a178718c2..63fc3b58824ca5c4ec7b8723df4b023a79460197 100644 (file)
@@ -216,13 +216,15 @@ func DefaultCommonSettings() map[string]interface{} {
 // default values
 var defaultGlobalSettings = map[string]interface{}{
        // "autosave":    float64(0),
-       "colorscheme": "default",
-       "infobar":     true,
-       "keymenu":     false,
-       "mouse":       true,
-       "paste":       false,
-       "savehistory": true,
-       "sucmd":       "sudo",
+       "colorscheme":    "default",
+       "infobar":        true,
+       "keymenu":        false,
+       "mouse":          true,
+       "paste":          false,
+       "savehistory":    true,
+       "sucmd":          "sudo",
+       "pluginchannels": []string{"https://raw.githubusercontent.com/micro-editor/plugin-channel/master/channel.json"},
+       "pluginrepos":    []string{},
 }
 
 // a list of settings that should never be globally modified
index add8842d1cf9903dad7854d30d6e882ca001ffb6..dd4441813b94b277360d34c6ebdcc2b554638716 100644 (file)
@@ -1,3 +1,5 @@
+VERSION = "1.0.0"
+
 local uutil = import("micro/util")
 local utf8 = import("utf8")
 local autoclosePairs = {"\"\"", "''", "``", "()", "{}", "[]"}
diff --git a/runtime/plugins/autoclose/info.json b/runtime/plugins/autoclose/info.json
deleted file mode 100644 (file)
index 7e9fbdc..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "name": "autoclose",
-    "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"
-    ]
-}
index d4c5b7e364817c42d25bf90c9ab5691b4f5f345f..66f0393452add61a8c4fb147ed8be2b6b0879c4c 100644 (file)
@@ -1,3 +1,5 @@
+VERSION = "1.0.0"
+
 local util = import("micro/util")
 local config = import("micro/config")
 local buffer = import("micro/buffer")
@@ -102,5 +104,7 @@ function string.starts(String,Start)
     return string.sub(String,1,string.len(Start))==Start
 end
 
-config.MakeCommand("comment", "comment.comment", config.NoComplete)
-config.TryBindKey("Alt-/", "lua:comment.comment", false)
+function init()
+    config.MakeCommand("comment", "comment.comment", config.NoComplete)
+    config.TryBindKey("Alt-/", "lua:comment.comment", false)
+end
diff --git a/runtime/plugins/comment/info.json b/runtime/plugins/comment/info.json
deleted file mode 100644 (file)
index 7841e2c..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "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"
-    ]
-}
index 7c2d519d4c949a92a47b20f484cc5d3dff0d5b45..03a824d4c1ff342b4e3a194f773b79481d9bece6 100644 (file)
@@ -1,3 +1,5 @@
+VERSION = "1.0.0"
+
 function onBufferOpen(b)
     local ft = b:FileType()
 
diff --git a/runtime/plugins/ftoptions/info.json b/runtime/plugins/ftoptions/info.json
deleted file mode 100644 (file)
index 14da894..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "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"
-    ]
-}
diff --git a/runtime/plugins/linter/info.json b/runtime/plugins/linter/info.json
deleted file mode 100644 (file)
index d7986f1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "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"
-    ]
-}
index e14613e7be9837fe6cdab5d320f157eba498518e..eb82059d4fa04c663e1f3ddd4fa0c3ed9811401a 100644 (file)
@@ -1,3 +1,5 @@
+VERSION = "1.0.0"
+
 local micro = import("micro")
 local runtime = import("runtime")
 local filepath = import("path/filepath")
diff --git a/runtime/plugins/literate/info.json b/runtime/plugins/literate/info.json
deleted file mode 100644 (file)
index 6db9444..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "name": "literate",
-    "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"
-    ]
-}
index 92aec8cc3e09285ce08c0693c7c906b8edc63187..5ef9ac22b89a70cbcbd05d2d0d98df5c2be568ba 100644 (file)
@@ -1,3 +1,5 @@
+VERSION = "1.0.0"
+
 local config = import("micro/config")
 
 function startswith(str, start)
index b1092ce22696569806ed4178b1ccb9e0b6ba4bce..400a9e2d248060e3391aab39817dfd51361396fb 100644 (file)
@@ -1,6 +1,8 @@
-micro = import("micro")
-buffer = import("micro/buffer")
-config = import("micro/config")
+VERSION = "1.0.0"
+
+local micro = import("micro")
+local buffer = import("micro/buffer")
+local config = import("micro/config")
 
 function init()
     micro.SetStatusInfoFn("status.branch")