16 NumTypes = 4 // How many filetypes are there
21 // RuntimeFile allows the program to read runtime data like colorschemes or syntax files
22 type RuntimeFile interface {
23 // Name returns a name of the file without paths or extensions
25 // Data returns the content of the file.
26 Data() ([]byte, error)
29 // allFiles contains all available files, mapped by filetype
30 var allFiles [NumTypes][]RuntimeFile
32 // some file on filesystem
38 // some file on filesystem but with a different name
39 type namedFile struct {
44 // a file with the data stored in memory
45 type memoryFile struct {
50 func (mf memoryFile) Name() string {
53 func (mf memoryFile) Data() ([]byte, error) {
57 func (rf realFile) Name() string {
58 fn := filepath.Base(string(rf))
59 return fn[:len(fn)-len(filepath.Ext(fn))]
62 func (rf realFile) Data() ([]byte, error) {
63 return ioutil.ReadFile(string(rf))
66 func (af assetFile) Name() string {
67 fn := path.Base(string(af))
68 return fn[:len(fn)-len(path.Ext(fn))]
71 func (af assetFile) Data() ([]byte, error) {
72 return Asset(string(af))
75 func (nf namedFile) Name() string {
79 // AddRuntimeFile registers a file for the given filetype
80 func AddRuntimeFile(fileType RTFiletype, file RuntimeFile) {
81 allFiles[fileType] = append(allFiles[fileType], file)
84 // AddRuntimeFilesFromDirectory registers each file from the given directory for
85 // the filetype which matches the file-pattern
86 func AddRuntimeFilesFromDirectory(fileType RTFiletype, directory, pattern string) {
87 files, _ := ioutil.ReadDir(directory)
88 for _, f := range files {
89 if ok, _ := filepath.Match(pattern, f.Name()); !f.IsDir() && ok {
90 fullPath := filepath.Join(directory, f.Name())
91 AddRuntimeFile(fileType, realFile(fullPath))
96 // AddRuntimeFilesFromAssets registers each file from the given asset-directory for
97 // the filetype which matches the file-pattern
98 func AddRuntimeFilesFromAssets(fileType RTFiletype, directory, pattern string) {
99 files, err := AssetDir(directory)
103 for _, f := range files {
104 if ok, _ := path.Match(pattern, f); ok {
105 AddRuntimeFile(fileType, assetFile(path.Join(directory, f)))
110 // FindRuntimeFile finds a runtime file of the given filetype and name
111 // will return nil if no file was found
112 func FindRuntimeFile(fileType RTFiletype, name string) RuntimeFile {
113 for _, f := range ListRuntimeFiles(fileType) {
114 if f.Name() == name {
121 // ListRuntimeFiles lists all known runtime files for the given filetype
122 func ListRuntimeFiles(fileType RTFiletype) []RuntimeFile {
123 return allFiles[fileType]
126 // InitRuntimeFiles initializes all assets file and the config directory
127 func InitRuntimeFiles() {
128 add := func(fileType RTFiletype, dir, pattern string) {
129 AddRuntimeFilesFromDirectory(fileType, filepath.Join(ConfigDir, dir), pattern)
130 AddRuntimeFilesFromAssets(fileType, path.Join("runtime", dir), pattern)
133 add(RTColorscheme, "colorschemes", "*.micro")
134 add(RTSyntax, "syntax", "*.yaml")
135 add(RTHelp, "help", "*.md")
137 // Search ConfigDir for plugin-scripts
138 plugdir := filepath.Join(ConfigDir, "plugins")
139 files, _ := ioutil.ReadDir(plugdir)
140 for _, d := range files {
142 srcs, _ := ioutil.ReadDir(filepath.Join(plugdir, d.Name()))
145 for _, f := range srcs {
146 if strings.HasSuffix(f.Name(), ".lua") {
147 p.Srcs = append(p.Srcs, realFile(filepath.Join(plugdir, d.Name(), f.Name())))
148 } else if f.Name() == "info.json" {
149 p.Info = realFile(filepath.Join(plugdir, d.Name(), "info.json"))
152 Plugins = append(Plugins, p)
156 plugdir = filepath.Join("runtime", "plugins")
157 if files, err := AssetDir(plugdir); err == nil {
158 for _, d := range files {
159 if srcs, err := AssetDir(filepath.Join(plugdir, d)); err == nil {
162 for _, f := range srcs {
163 if strings.HasSuffix(f, ".lua") {
164 p.Srcs = append(p.Srcs, assetFile(filepath.Join(plugdir, d, f)))
165 } else if f == "info.json" {
166 p.Info = assetFile(filepath.Join(plugdir, d, "info.json"))
169 Plugins = append(Plugins, p)
175 // PluginReadRuntimeFile allows plugin scripts to read the content of a runtime file
176 func PluginReadRuntimeFile(fileType RTFiletype, name string) string {
177 if file := FindRuntimeFile(fileType, name); file != nil {
178 if data, err := file.Data(); err == nil {
185 // PluginListRuntimeFiles allows plugins to lists all runtime files of the given type
186 func PluginListRuntimeFiles(fileType RTFiletype) []string {
187 files := ListRuntimeFiles(fileType)
188 result := make([]string, len(files))
189 for i, f := range files {
195 // PluginAddRuntimeFile adds a file to the runtime files for a plugin
196 func PluginAddRuntimeFile(plugin string, filetype RTFiletype, filePath string) {
197 fullpath := filepath.Join(ConfigDir, "plugins", plugin, filePath)
198 if _, err := os.Stat(fullpath); err == nil {
199 AddRuntimeFile(filetype, realFile(fullpath))
201 fullpath = path.Join("runtime", "plugins", plugin, filePath)
202 AddRuntimeFile(filetype, assetFile(fullpath))
206 // PluginAddRuntimeFilesFromDirectory adds files from a directory to the runtime files for a plugin
207 func PluginAddRuntimeFilesFromDirectory(plugin string, filetype RTFiletype, directory, pattern string) {
208 fullpath := filepath.Join(ConfigDir, "plugins", plugin, directory)
209 if _, err := os.Stat(fullpath); err == nil {
210 AddRuntimeFilesFromDirectory(filetype, fullpath, pattern)
212 fullpath = path.Join("runtime", "plugins", plugin, directory)
213 AddRuntimeFilesFromAssets(filetype, fullpath, pattern)
217 // PluginAddRuntimeFileFromMemory adds a file to the runtime files for a plugin from a given string
218 func PluginAddRuntimeFileFromMemory(plugin string, filetype RTFiletype, filename, data string) {
219 AddRuntimeFile(filetype, memoryFile{filename, []byte(data)})