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.
This commit is contained in:
Florian Sundermann
2016-09-15 16:42:45 +02:00
parent 796638d095
commit 9eeb14956c
9 changed files with 156 additions and 123 deletions

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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")
}

View File

@@ -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())

View File

@@ -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)

View File

@@ -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})
}
}
}

144
cmd/micro/rtfiles.go Normal file
View File

@@ -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
}

View File

@@ -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")