From 796638d095d6c459607c25b26e7d3588db66ac3b Mon Sep 17 00:00:00 2001 From: Florian Sundermann Date: Thu, 15 Sep 2016 15:50:26 +0200 Subject: [PATCH 1/2] simplified file handling for runtime files --- cmd/micro/autocomplete.go | 3 +- cmd/micro/colorscheme.go | 78 +++++++++----------- cmd/micro/command.go | 2 +- cmd/micro/extfiles.go | 115 +++++++++++++++++++++++++++++ cmd/micro/help.go | 38 ---------- cmd/micro/highlighter.go | 148 ++------------------------------------ cmd/micro/micro.go | 3 + cmd/micro/plugin.go | 2 +- cmd/micro/view.go | 2 +- 9 files changed, 161 insertions(+), 230 deletions(-) create mode 100644 cmd/micro/extfiles.go delete mode 100644 cmd/micro/help.go diff --git a/cmd/micro/autocomplete.go b/cmd/micro/autocomplete.go index 5620f3df..5a1c9825 100644 --- a/cmd/micro/autocomplete.go +++ b/cmd/micro/autocomplete.go @@ -84,7 +84,8 @@ func CommandComplete(input string) (string, []string) { func HelpComplete(input string) (string, []string) { var suggestions []string - for topic, _ := range helpPages { + for _, file := range ListExtensionFiles(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 b54bbae3..18898249 100644 --- a/cmd/micro/colorscheme.go +++ b/cmd/micro/colorscheme.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "io/ioutil" "regexp" "strconv" "strings" @@ -16,66 +15,53 @@ type Colorscheme map[string]tcell.Style // The current colorscheme var colorscheme Colorscheme -var preInstalledColors = []string{"default", "simple", "solarized", "solarized-tc", "atom-dark-tc", "monokai", "gruvbox", "zenburn", "bubblegum"} - // ColorschemeExists checks if a given colorscheme exists func ColorschemeExists(colorschemeName string) bool { - files, _ := ioutil.ReadDir(configDir + "/colorschemes") - for _, f := range files { - if f.Name() == colorschemeName+".micro" { - return true - } - } - - for _, name := range preInstalledColors { - if name == colorschemeName { - return true - } - } - - return false + return FindExtensionFile(FILE_ColorScheme, colorschemeName) != nil } // InitColorscheme picks and initializes the colorscheme when micro starts func InitColorscheme() { + colorscheme = make(Colorscheme) + if screen != nil { + screen.SetStyle(tcell.StyleDefault. + Foreground(tcell.ColorDefault). + Background(tcell.ColorDefault)) + } + LoadDefaultColorscheme() } // LoadDefaultColorscheme loads the default colorscheme from $(configDir)/colorschemes func LoadDefaultColorscheme() { - LoadColorscheme(globalSettings["colorscheme"].(string), configDir+"/colorschemes") + LoadColorscheme(globalSettings["colorscheme"].(string)) } // LoadColorscheme loads the given colorscheme from a directory -func LoadColorscheme(colorschemeName, dir string) { - files, _ := ioutil.ReadDir(dir) - found := false - for _, f := range files { - if f.Name() == colorschemeName+".micro" { - text, err := ioutil.ReadFile(dir + "/" + f.Name()) - if err != nil { - fmt.Println("Error loading colorscheme:", err) - continue - } - colorscheme = ParseColorscheme(string(text)) - found = true - } - } - - for _, name := range preInstalledColors { - if name == colorschemeName { - data, err := Asset("runtime/colorschemes/" + name + ".micro") - if err != nil { - TermMessage("Unable to load pre-installed colorscheme " + name) - continue - } - colorscheme = ParseColorscheme(string(data)) - found = true - } - } - - if !found { +func LoadColorscheme(colorschemeName string) { + file := FindExtensionFile(FILE_ColorScheme, colorschemeName) + if file == nil { TermMessage(colorschemeName, "is not a valid colorscheme") + } else { + if data, err := file.Data(); err != nil { + fmt.Println("Error loading colorscheme:", err) + } else { + colorscheme = ParseColorscheme(string(data)) + + // Default style + defStyle = tcell.StyleDefault. + Foreground(tcell.ColorDefault). + Background(tcell.ColorDefault) + + // There may be another default style defined in the colorscheme + // In that case we should use that one + if style, ok := colorscheme["default"]; ok { + defStyle = style + } + if screen != nil { + screen.SetStyle(defStyle) + } + } } } diff --git a/cmd/micro/command.go b/cmd/micro/command.go index f5b7a15c..10be7dab 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 _, ok := helpPages[helpPage]; ok { + if FindExtensionFile(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 new file mode 100644 index 00000000..549b54ca --- /dev/null +++ b/cmd/micro/extfiles.go @@ -0,0 +1,115 @@ +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/help.go b/cmd/micro/help.go deleted file mode 100644 index caaad5b5..00000000 --- a/cmd/micro/help.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import ( - "io/ioutil" -) - -type HelpPage interface { - HelpFile() ([]byte, error) -} - -var helpPages map[string]HelpPage = map[string]HelpPage{ - "help": assetHelpPage("help"), - "keybindings": assetHelpPage("keybindings"), - "plugins": assetHelpPage("plugins"), - "colors": assetHelpPage("colors"), - "options": assetHelpPage("options"), - "commands": assetHelpPage("commands"), - "tutorial": assetHelpPage("tutorial"), -} - -type assetHelpPage string - -func (file assetHelpPage) HelpFile() ([]byte, error) { - return Asset("runtime/help/" + string(file) + ".md") -} - -type fileHelpPage string - -func (file fileHelpPage) HelpFile() ([]byte, error) { - return ioutil.ReadFile(string(file)) -} - -func AddPluginHelp(name, file string) { - if _, exists := helpPages[name]; exists { - return - } - helpPages[name] = fileHelpPage(file) -} diff --git a/cmd/micro/highlighter.go b/cmd/micro/highlighter.go index 661a7e8a..72ea26e9 100644 --- a/cmd/micro/highlighter.go +++ b/cmd/micro/highlighter.go @@ -1,8 +1,6 @@ package main import ( - "io/ioutil" - "path/filepath" "regexp" "strings" @@ -30,150 +28,16 @@ type SyntaxRule struct { var syntaxFiles map[[2]*regexp.Regexp]FileTypeRules -// These syntax files are pre installed and embedded in the resulting binary by go-bindata -var preInstalledSynFiles = []string{ - "Dockerfile", - "apacheconf", - "arduino", - "asciidoc", - "asm", - "awk", - "c", - "caddyfile", - "cmake", - "coffeescript", - "colortest", - "conf", - "conky", - "csharp", - "css", - "cython", - "d", - "dart", - "dot", - "erb", - "fish", - "fortran", - "gdscript", - "gentoo-ebuild", - "gentoo-etc-portage", - "git-commit", - "git-config", - "git-rebase-todo", - "glsl", - "go", - "golo", - "groff", - "haml", - "haskell", - "html", - "ini", - "inputrc", - "java", - "javascript", - "json", - "keymap", - "kickstart", - "ledger", - "lilypond", - "lisp", - "lua", - "makefile", - "man", - "markdown", - "mpdconf", - "micro", - "nanorc", - "nginx", - "ocaml", - "pascal", - "patch", - "peg", - "perl", - "perl6", - "php", - "pkg-config", - "po", - "pov", - "privoxy-action", - "privoxy-config", - "privoxy-filter", - "puppet", - "python", - "r", - "reST", - "rpmspec", - "ruby", - "rust", - "scala", - "sed", - "sh", - "sls", - "sql", - "swift", - "systemd", - "tcl", - "tex", - "vala", - "vi", - "xml", - "xresources", - "yaml", - "yum", - "zsh", -} - // LoadSyntaxFiles loads the syntax files from the default directory (configDir) func LoadSyntaxFiles() { - // Load the user's custom syntax files, if there are any - LoadSyntaxFilesFromDir(configDir + "/syntax") - - // Load the pre-installed syntax files from inside the binary - for _, filetype := range preInstalledSynFiles { - data, err := Asset("runtime/syntax/" + filetype + ".micro") - if err != nil { - TermMessage("Unable to load pre-installed syntax file " + filetype) - continue - } - - LoadSyntaxFile(string(data), filetype+".micro") - } -} - -// LoadSyntaxFilesFromDir loads the syntax files from a specified directory -// To load the syntax files, we must fill the `syntaxFiles` map -// This involves finding the regex for syntax and if it exists, the regex -// for the header. Then we must get the text for the file and the filetype. -func LoadSyntaxFilesFromDir(dir string) { - colorscheme = make(Colorscheme) InitColorscheme() - - // Default style - defStyle = tcell.StyleDefault. - Foreground(tcell.ColorDefault). - Background(tcell.ColorDefault) - - // There may be another default style defined in the colorscheme - // In that case we should use that one - if style, ok := colorscheme["default"]; ok { - defStyle = style - } - if screen != nil { - screen.SetStyle(defStyle) - } - syntaxFiles = make(map[[2]*regexp.Regexp]FileTypeRules) - files, _ := ioutil.ReadDir(dir) - for _, f := range files { - if filepath.Ext(f.Name()) == ".micro" { - filename := dir + "/" + f.Name() - text, err := ioutil.ReadFile(filename) - - if err != nil { - TermMessage("Error loading syntax file " + filename + ": " + err.Error()) - return - } - LoadSyntaxFile(string(text), filename) + for _, f := range ListExtensionFiles(FILE_Syntax) { + data, err := f.Data() + if err != nil { + TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error()) + } else { + LoadSyntaxFile(string(data), f.Name()) } } } diff --git a/cmd/micro/micro.go b/cmd/micro/micro.go index 53e3e7b2..331d1a7f 100644 --- a/cmd/micro/micro.go +++ b/cmd/micro/micro.go @@ -233,6 +233,9 @@ func main() { // Find the user's configuration directory (probably $XDG_CONFIG_HOME/micro) InitConfigDir() + // Build a list of available Extensions (Syntax, Colorscheme etc.) + InitExtensionFiles() + // Load the user's settings InitGlobalSettings() diff --git a/cmd/micro/plugin.go b/cmd/micro/plugin.go index 0c84ae62..073774d0 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" { - AddPluginHelp(pluginName, fullPath) + AddFile(FILE_Help, namedFile{realFile(fullPath), pluginName}) } } } diff --git a/cmd/micro/view.go b/cmd/micro/view.go index dff2b11b..2117b9c1 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 := helpPages[helpPage].HelpFile(); err != nil { + if data, err := FindExtensionFile(FILE_Help, helpPage).Data(); err != nil { TermMessage("Unable to load help text", helpPage, "\n", err) } else { helpBuffer := NewBuffer(data, helpPage+".md") From 9eeb14956cd12959cddcc00ce91a03defa8a308e Mon Sep 17 00:00:00 2001 From: Florian Sundermann Date: Thu, 15 Sep 2016 16:42:45 +0200 Subject: [PATCH 2/2] 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")