From 9eeb14956cd12959cddcc00ce91a03defa8a308e Mon Sep 17 00:00:00 2001 From: Florian Sundermann Date: Thu, 15 Sep 2016 16:42:45 +0200 Subject: [PATCH] allow plugins to list / read runtime files also renamed most of the new functions to be more specific about what kind of files this is for. --- cmd/micro/autocomplete.go | 2 +- cmd/micro/colorscheme.go | 4 +- cmd/micro/command.go | 2 +- cmd/micro/extfiles.go | 115 ------------------------------ cmd/micro/highlighter.go | 2 +- cmd/micro/micro.go | 6 +- cmd/micro/plugin.go | 2 +- cmd/micro/rtfiles.go | 144 ++++++++++++++++++++++++++++++++++++++ cmd/micro/view.go | 2 +- 9 files changed, 156 insertions(+), 123 deletions(-) delete mode 100644 cmd/micro/extfiles.go create mode 100644 cmd/micro/rtfiles.go diff --git a/cmd/micro/autocomplete.go b/cmd/micro/autocomplete.go index 5a1c9825..4946b797 100644 --- a/cmd/micro/autocomplete.go +++ b/cmd/micro/autocomplete.go @@ -84,7 +84,7 @@ func CommandComplete(input string) (string, []string) { func HelpComplete(input string) (string, []string) { var suggestions []string - for _, file := range ListExtensionFiles(FILE_Help) { + for _, file := range ListRuntimeFiles(FILE_Help) { topic := file.Name() if strings.HasPrefix(topic, input) { suggestions = append(suggestions, topic) diff --git a/cmd/micro/colorscheme.go b/cmd/micro/colorscheme.go index 18898249..2332e434 100644 --- a/cmd/micro/colorscheme.go +++ b/cmd/micro/colorscheme.go @@ -17,7 +17,7 @@ var colorscheme Colorscheme // ColorschemeExists checks if a given colorscheme exists func ColorschemeExists(colorschemeName string) bool { - return FindExtensionFile(FILE_ColorScheme, colorschemeName) != nil + return FindRuntimeFile(FILE_ColorScheme, colorschemeName) != nil } // InitColorscheme picks and initializes the colorscheme when micro starts @@ -39,7 +39,7 @@ func LoadDefaultColorscheme() { // LoadColorscheme loads the given colorscheme from a directory func LoadColorscheme(colorschemeName string) { - file := FindExtensionFile(FILE_ColorScheme, colorschemeName) + file := FindRuntimeFile(FILE_ColorScheme, colorschemeName) if file == nil { TermMessage(colorschemeName, "is not a valid colorscheme") } else { diff --git a/cmd/micro/command.go b/cmd/micro/command.go index 10be7dab..b687a6d7 100644 --- a/cmd/micro/command.go +++ b/cmd/micro/command.go @@ -94,7 +94,7 @@ func Help(args []string) { CurView().openHelp("help") } else { helpPage := args[0] - if FindExtensionFile(FILE_Help, helpPage) != nil { + if FindRuntimeFile(FILE_Help, helpPage) != nil { CurView().openHelp(helpPage) } else { messenger.Error("Sorry, no help for ", helpPage) diff --git a/cmd/micro/extfiles.go b/cmd/micro/extfiles.go deleted file mode 100644 index 549b54ca..00000000 --- a/cmd/micro/extfiles.go +++ /dev/null @@ -1,115 +0,0 @@ -package main - -import ( - "io/ioutil" - "path" - "path/filepath" -) - -const ( - FILE_ColorScheme = "colorscheme" - FILE_Syntax = "syntax" - FILE_Help = "help" -) - -// ExtensionFile allows the program to read runtime data like colorschemes or syntax files -type ExtensionFile interface { - // Name returns a name of the file without paths or extensions - Name() string - // Data returns the content of the file. - Data() ([]byte, error) -} - -// allFiles contains all available files, mapped by filetype -var allFiles map[string][]ExtensionFile - -// some file on filesystem -type realFile string - -// some asset file -type assetFile string - -// some file on filesystem but with a different name -type namedFile struct { - realFile - name string -} - -func (rf realFile) Name() string { - fn := filepath.Base(string(rf)) - return fn[:len(fn)-len(filepath.Ext(fn))] -} - -func (rf realFile) Data() ([]byte, error) { - return ioutil.ReadFile(string(rf)) -} - -func (af assetFile) Name() string { - fn := path.Base(string(af)) - return fn[:len(fn)-len(path.Ext(fn))] -} - -func (af assetFile) Data() ([]byte, error) { - return Asset(string(af)) -} - -func (nf namedFile) Name() string { - return nf.name -} - -func AddFile(fileType string, file ExtensionFile) { - if allFiles == nil { - allFiles = make(map[string][]ExtensionFile) - } - allFiles[fileType] = append(allFiles[fileType], file) -} - -func AddFilesFromDirectory(fileType, directory, pattern string) { - files, _ := ioutil.ReadDir(directory) - for _, f := range files { - if ok, _ := filepath.Match(pattern, f.Name()); !f.IsDir() && ok { - fullPath := filepath.Join(directory, f.Name()) - AddFile(fileType, realFile(fullPath)) - } - } -} - -func AddFilesFromAssets(fileType, directory, pattern string) { - files, err := AssetDir(directory) - if err != nil { - return - } - for _, f := range files { - if ok, _ := path.Match(pattern, f); ok { - AddFile(fileType, assetFile(path.Join(directory, f))) - } - } -} - -func FindExtensionFile(fileType, name string) ExtensionFile { - for _, f := range ListExtensionFiles(fileType) { - if f.Name() == name { - return f - } - } - return nil -} - -func ListExtensionFiles(fileType string) []ExtensionFile { - if files, ok := allFiles[fileType]; ok { - return files - } else { - return []ExtensionFile{} - } -} - -func InitExtensionFiles() { - add := func(fileType, dir, pattern string) { - AddFilesFromDirectory(fileType, filepath.Join(configDir, dir), pattern) - AddFilesFromAssets(fileType, path.Join("runtime", dir), pattern) - } - - add(FILE_ColorScheme, "colorschemes", "*.micro") - add(FILE_Syntax, "syntax", "*.micro") - add(FILE_Help, "help", "*.md") -} diff --git a/cmd/micro/highlighter.go b/cmd/micro/highlighter.go index 72ea26e9..c66385fb 100644 --- a/cmd/micro/highlighter.go +++ b/cmd/micro/highlighter.go @@ -32,7 +32,7 @@ var syntaxFiles map[[2]*regexp.Regexp]FileTypeRules func LoadSyntaxFiles() { InitColorscheme() syntaxFiles = make(map[[2]*regexp.Regexp]FileTypeRules) - for _, f := range ListExtensionFiles(FILE_Syntax) { + for _, f := range ListRuntimeFiles(FILE_Syntax) { data, err := f.Data() if err != nil { TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error()) diff --git a/cmd/micro/micro.go b/cmd/micro/micro.go index 331d1a7f..66e0e836 100644 --- a/cmd/micro/micro.go +++ b/cmd/micro/micro.go @@ -234,7 +234,7 @@ func main() { InitConfigDir() // Build a list of available Extensions (Syntax, Colorscheme etc.) - InitExtensionFiles() + InitRuntimeFiles() // Load the user's settings InitGlobalSettings() @@ -316,6 +316,10 @@ func main() { L.SetGlobal("JobSend", luar.New(L, JobSend)) L.SetGlobal("JobStop", luar.New(L, JobStop)) + // Extension Files + L.SetGlobal("ReadRuntimeFile", luar.New(L, PluginReadRuntimeFile)) + L.SetGlobal("ListRuntimeFiles", luar.New(L, PluginListRuntimeFiles)) + LoadPlugins() jobs = make(chan JobFunction, 100) diff --git a/cmd/micro/plugin.go b/cmd/micro/plugin.go index 073774d0..6594e276 100644 --- a/cmd/micro/plugin.go +++ b/cmd/micro/plugin.go @@ -138,7 +138,7 @@ func LoadPlugins() { } loadedPlugins = append(loadedPlugins, pluginName) } else if f.Name() == "help.md" { - AddFile(FILE_Help, namedFile{realFile(fullPath), pluginName}) + AddRuntimeFile(FILE_Help, namedFile{realFile(fullPath), pluginName}) } } } diff --git a/cmd/micro/rtfiles.go b/cmd/micro/rtfiles.go new file mode 100644 index 00000000..5466b548 --- /dev/null +++ b/cmd/micro/rtfiles.go @@ -0,0 +1,144 @@ +package main + +import ( + "io/ioutil" + "path" + "path/filepath" +) + +const ( + FILE_ColorScheme = "colorscheme" + FILE_Syntax = "syntax" + FILE_Help = "help" +) + +// RuntimeFile allows the program to read runtime data like colorschemes or syntax files +type RuntimeFile interface { + // Name returns a name of the file without paths or extensions + Name() string + // Data returns the content of the file. + Data() ([]byte, error) +} + +// allFiles contains all available files, mapped by filetype +var allFiles map[string][]RuntimeFile + +// some file on filesystem +type realFile string + +// some asset file +type assetFile string + +// some file on filesystem but with a different name +type namedFile struct { + realFile + name string +} + +func (rf realFile) Name() string { + fn := filepath.Base(string(rf)) + return fn[:len(fn)-len(filepath.Ext(fn))] +} + +func (rf realFile) Data() ([]byte, error) { + return ioutil.ReadFile(string(rf)) +} + +func (af assetFile) Name() string { + fn := path.Base(string(af)) + return fn[:len(fn)-len(path.Ext(fn))] +} + +func (af assetFile) Data() ([]byte, error) { + return Asset(string(af)) +} + +func (nf namedFile) Name() string { + return nf.name +} + +// AddRuntimeFile registers a file for the given filetype +func AddRuntimeFile(fileType string, file RuntimeFile) { + if allFiles == nil { + allFiles = make(map[string][]RuntimeFile) + } + allFiles[fileType] = append(allFiles[fileType], file) +} + +// AddRuntimeFilesFromDirectory registers each file from the given directory for +// the filetype which matches the file-pattern +func AddRuntimeFilesFromDirectory(fileType, directory, pattern string) { + files, _ := ioutil.ReadDir(directory) + for _, f := range files { + if ok, _ := filepath.Match(pattern, f.Name()); !f.IsDir() && ok { + fullPath := filepath.Join(directory, f.Name()) + AddRuntimeFile(fileType, realFile(fullPath)) + } + } +} + +// AddRuntimeFilesFromDirectory registers each file from the given asset-directory for +// the filetype which matches the file-pattern +func AddRuntimeFilesFromAssets(fileType, directory, pattern string) { + files, err := AssetDir(directory) + if err != nil { + return + } + for _, f := range files { + if ok, _ := path.Match(pattern, f); ok { + AddRuntimeFile(fileType, assetFile(path.Join(directory, f))) + } + } +} + +// FindRuntimeFile finds a runtime file of the given filetype and name +// will return nil if no file was found +func FindRuntimeFile(fileType, name string) RuntimeFile { + for _, f := range ListRuntimeFiles(fileType) { + if f.Name() == name { + return f + } + } + return nil +} + +// Lists all known runtime files for the given filetype +func ListRuntimeFiles(fileType string) []RuntimeFile { + if files, ok := allFiles[fileType]; ok { + return files + } else { + return []RuntimeFile{} + } +} + +// Initializes all assets file and the config directory +func InitRuntimeFiles() { + add := func(fileType, dir, pattern string) { + AddRuntimeFilesFromDirectory(fileType, filepath.Join(configDir, dir), pattern) + AddRuntimeFilesFromAssets(fileType, path.Join("runtime", dir), pattern) + } + + add(FILE_ColorScheme, "colorschemes", "*.micro") + add(FILE_Syntax, "syntax", "*.micro") + add(FILE_Help, "help", "*.md") +} + +// Allows plugin scripts to read the content of a runtime file +func PluginReadRuntimeFile(fileType, name string) string { + if file := FindRuntimeFile(fileType, name); file != nil { + if data, err := file.Data(); err == nil { + return string(data) + } + } + return "" +} + +// Allows plugins to lists all runtime files of the given type +func PluginListRuntimeFiles(fileType string) []string { + files := ListRuntimeFiles(fileType) + result := make([]string, len(files)) + for i, f := range files { + result[i] = f.Name() + } + return result +} diff --git a/cmd/micro/view.go b/cmd/micro/view.go index 2117b9c1..3aaa7ef8 100644 --- a/cmd/micro/view.go +++ b/cmd/micro/view.go @@ -529,7 +529,7 @@ func (v *View) ClearAllGutterMessages() { // Opens the given help page in a new horizontal split func (v *View) openHelp(helpPage string) { - if data, err := FindExtensionFile(FILE_Help, helpPage).Data(); err != nil { + if data, err := FindRuntimeFile(FILE_Help, helpPage).Data(); err != nil { TermMessage("Unable to load help text", helpPage, "\n", err) } else { helpBuffer := NewBuffer(data, helpPage+".md")