]> git.lizzy.rs Git - micro.git/blobdiff - internal/config/rtfiles.go
better top
[micro.git] / internal / config / rtfiles.go
index d31b412333c830d9f337d0ed6739425e2589c3f2..09e9176883cbabc712d3ce3f5dca33cf18aaa4ff 100644 (file)
@@ -1,22 +1,29 @@
 package config
 
 import (
+       "errors"
        "io/ioutil"
+       "log"
        "os"
        "path"
        "path/filepath"
+       "regexp"
        "strings"
 )
 
 const (
-       RTColorscheme = 0
-       RTSyntax      = 1
-       RTHelp        = 2
-       RTPlugin      = 3
-       NumTypes      = 4 // How many filetypes are there
+       RTColorscheme  = 0
+       RTSyntax       = 1
+       RTHelp         = 2
+       RTPlugin       = 3
+       RTSyntaxHeader = 4
 )
 
-type RTFiletype byte
+var (
+       NumTypes = 5 // How many filetypes are there
+)
+
+type RTFiletype int
 
 // RuntimeFile allows the program to read runtime data like colorschemes or syntax files
 type RuntimeFile interface {
@@ -27,7 +34,21 @@ type RuntimeFile interface {
 }
 
 // allFiles contains all available files, mapped by filetype
-var allFiles [NumTypes][]RuntimeFile
+var allFiles [][]RuntimeFile
+var realFiles [][]RuntimeFile
+
+func init() {
+       allFiles = make([][]RuntimeFile, NumTypes)
+       realFiles = make([][]RuntimeFile, NumTypes)
+}
+
+// NewRTFiletype creates a new RTFiletype
+func NewRTFiletype() int {
+       NumTypes++
+       allFiles = append(allFiles, []RuntimeFile{})
+       realFiles = append(realFiles, []RuntimeFile{})
+       return NumTypes - 1
+}
 
 // some file on filesystem
 type realFile string
@@ -81,6 +102,12 @@ func AddRuntimeFile(fileType RTFiletype, file RuntimeFile) {
        allFiles[fileType] = append(allFiles[fileType], file)
 }
 
+// AddRealRuntimeFile registers a file for the given filetype
+func AddRealRuntimeFile(fileType RTFiletype, file RuntimeFile) {
+       allFiles[fileType] = append(allFiles[fileType], file)
+       realFiles[fileType] = append(realFiles[fileType], file)
+}
+
 // AddRuntimeFilesFromDirectory registers each file from the given directory for
 // the filetype which matches the file-pattern
 func AddRuntimeFilesFromDirectory(fileType RTFiletype, directory, pattern string) {
@@ -88,7 +115,7 @@ func AddRuntimeFilesFromDirectory(fileType RTFiletype, directory, pattern string
        for _, f := range files {
                if ok, _ := filepath.Match(pattern, f.Name()); !f.IsDir() && ok {
                        fullPath := filepath.Join(directory, f.Name())
-                       AddRuntimeFile(fileType, realFile(fullPath))
+                       AddRealRuntimeFile(fileType, realFile(fullPath))
                }
        }
 }
@@ -123,6 +150,12 @@ func ListRuntimeFiles(fileType RTFiletype) []RuntimeFile {
        return allFiles[fileType]
 }
 
+// ListRealRuntimeFiles lists all real runtime files (on disk) for a filetype
+// these runtime files will be ones defined by the user and loaded from the config directory
+func ListRealRuntimeFiles(fileType RTFiletype) []RuntimeFile {
+       return realFiles[fileType]
+}
+
 // InitRuntimeFiles initializes all assets file and the config directory
 func InitRuntimeFiles() {
        add := func(fileType RTFiletype, dir, pattern string) {
@@ -132,23 +165,51 @@ func InitRuntimeFiles() {
 
        add(RTColorscheme, "colorschemes", "*.micro")
        add(RTSyntax, "syntax", "*.yaml")
+       add(RTSyntaxHeader, "syntax", "*.hdr")
        add(RTHelp, "help", "*.md")
 
+       initlua := filepath.Join(ConfigDir, "init.lua")
+       if _, err := os.Stat(initlua); !os.IsNotExist(err) {
+               p := new(Plugin)
+               p.Name = "initlua"
+               p.DirName = "initlua"
+               p.Srcs = append(p.Srcs, realFile(initlua))
+               Plugins = append(Plugins, p)
+       }
+
        // Search ConfigDir for plugin-scripts
-       plugdir := filepath.Join(ConfigDir, "plugins")
+       plugdir := filepath.Join(ConfigDir, "plug")
        files, _ := ioutil.ReadDir(plugdir)
+
+       isID := regexp.MustCompile(`^[_A-Za-z0-9]+$`).MatchString
+
        for _, d := range files {
                if d.IsDir() {
                        srcs, _ := ioutil.ReadDir(filepath.Join(plugdir, d.Name()))
                        p := new(Plugin)
                        p.Name = d.Name()
+                       p.DirName = d.Name()
                        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" {
-                                       p.Info = realFile(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, err = NewPluginInfo(data)
+                                       if err != nil {
+                                               log.Println(err)
+                                               continue
+                                       }
+                                       p.Name = p.Info.Name
                                }
                        }
+
+                       if !isID(p.Name) || len(p.Srcs) <= 0 {
+                               log.Println(p.Name, "is not a plugin")
+                               continue
+                       }
                        Plugins = append(Plugins, p)
                }
        }
@@ -159,13 +220,28 @@ func InitRuntimeFiles() {
                        if srcs, err := AssetDir(filepath.Join(plugdir, d)); err == nil {
                                p := new(Plugin)
                                p.Name = d
+                               p.DirName = d
+                               p.Default = true
                                for _, f := range srcs {
                                        if strings.HasSuffix(f, ".lua") {
                                                p.Srcs = append(p.Srcs, assetFile(filepath.Join(plugdir, d, f)))
-                                       } else if f == "info.json" {
-                                               p.Info = assetFile(filepath.Join(plugdir, d, "info.json"))
+                                       } 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.Name = p.Info.Name
                                        }
                                }
+                               if !isID(p.Name) || len(p.Srcs) <= 0 {
+                                       log.Println(p.Name, "is not a plugin")
+                                       continue
+                               }
                                Plugins = append(Plugins, p)
                        }
                }
@@ -193,28 +269,40 @@ func PluginListRuntimeFiles(fileType RTFiletype) []string {
 }
 
 // PluginAddRuntimeFile adds a file to the runtime files for a plugin
-func PluginAddRuntimeFile(plugin string, filetype RTFiletype, filePath string) {
-       fullpath := filepath.Join(ConfigDir, "plugins", plugin, filePath)
+func PluginAddRuntimeFile(plugin string, filetype RTFiletype, filePath string) error {
+       pl := FindPlugin(plugin)
+       if pl == nil {
+               return errors.New("Plugin " + plugin + " does not exist")
+       }
+       pldir := pl.DirName
+       fullpath := filepath.Join(ConfigDir, "plug", pldir, filePath)
        if _, err := os.Stat(fullpath); err == nil {
-               AddRuntimeFile(filetype, realFile(fullpath))
+               AddRealRuntimeFile(filetype, realFile(fullpath))
        } else {
-               fullpath = path.Join("runtime", "plugins", plugin, filePath)
+               fullpath = path.Join("runtime", "plugins", pldir, filePath)
                AddRuntimeFile(filetype, assetFile(fullpath))
        }
+       return nil
 }
 
 // PluginAddRuntimeFilesFromDirectory adds files from a directory to the runtime files for a plugin
-func PluginAddRuntimeFilesFromDirectory(plugin string, filetype RTFiletype, directory, pattern string) {
-       fullpath := filepath.Join(ConfigDir, "plugins", plugin, directory)
+func PluginAddRuntimeFilesFromDirectory(plugin string, filetype RTFiletype, directory, pattern string) error {
+       pl := FindPlugin(plugin)
+       if pl == nil {
+               return errors.New("Plugin " + plugin + " does not exist")
+       }
+       pldir := pl.DirName
+       fullpath := filepath.Join(ConfigDir, "plug", pldir, directory)
        if _, err := os.Stat(fullpath); err == nil {
                AddRuntimeFilesFromDirectory(filetype, fullpath, pattern)
        } else {
-               fullpath = path.Join("runtime", "plugins", plugin, directory)
+               fullpath = path.Join("runtime", "plugins", pldir, directory)
                AddRuntimeFilesFromAssets(filetype, fullpath, pattern)
        }
+       return nil
 }
 
 // PluginAddRuntimeFileFromMemory adds a file to the runtime files for a plugin from a given string
-func PluginAddRuntimeFileFromMemory(plugin string, filetype RTFiletype, filename, data string) {
-       AddRuntimeFile(filetype, memoryFile{filename, []byte(data)})
+func PluginAddRuntimeFileFromMemory(filetype RTFiletype, filename, data string) {
+       AddRealRuntimeFile(filetype, memoryFile{filename, []byte(data)})
 }