20 NumTypes = 5 // How many filetypes are there
25 // RuntimeFile allows the program to read runtime data like colorschemes or syntax files
26 type RuntimeFile interface {
27 // Name returns a name of the file without paths or extensions
29 // Data returns the content of the file.
30 Data() ([]byte, error)
33 // allFiles contains all available files, mapped by filetype
34 var allFiles [NumTypes][]RuntimeFile
35 var realFiles [NumTypes][]RuntimeFile
37 // some file on filesystem
43 // some file on filesystem but with a different name
44 type namedFile struct {
49 // a file with the data stored in memory
50 type memoryFile struct {
55 func (mf memoryFile) Name() string {
58 func (mf memoryFile) Data() ([]byte, error) {
62 func (rf realFile) Name() string {
63 fn := filepath.Base(string(rf))
64 return fn[:len(fn)-len(filepath.Ext(fn))]
67 func (rf realFile) Data() ([]byte, error) {
68 return ioutil.ReadFile(string(rf))
71 func (af assetFile) Name() string {
72 fn := path.Base(string(af))
73 return fn[:len(fn)-len(path.Ext(fn))]
76 func (af assetFile) Data() ([]byte, error) {
77 return Asset(string(af))
80 func (nf namedFile) Name() string {
84 // AddRuntimeFile registers a file for the given filetype
85 func AddRuntimeFile(fileType RTFiletype, file RuntimeFile) {
86 allFiles[fileType] = append(allFiles[fileType], file)
89 // AddRealRuntimeFile registers a file for the given filetype
90 func AddRealRuntimeFile(fileType RTFiletype, file RuntimeFile) {
91 allFiles[fileType] = append(allFiles[fileType], file)
92 realFiles[fileType] = append(realFiles[fileType], file)
95 // AddRuntimeFilesFromDirectory registers each file from the given directory for
96 // the filetype which matches the file-pattern
97 func AddRuntimeFilesFromDirectory(fileType RTFiletype, directory, pattern string) {
98 files, _ := ioutil.ReadDir(directory)
99 for _, f := range files {
100 if ok, _ := filepath.Match(pattern, f.Name()); !f.IsDir() && ok {
101 fullPath := filepath.Join(directory, f.Name())
102 AddRealRuntimeFile(fileType, realFile(fullPath))
107 // AddRuntimeFilesFromAssets registers each file from the given asset-directory for
108 // the filetype which matches the file-pattern
109 func AddRuntimeFilesFromAssets(fileType RTFiletype, directory, pattern string) {
110 files, err := AssetDir(directory)
114 for _, f := range files {
115 if ok, _ := path.Match(pattern, f); ok {
116 AddRuntimeFile(fileType, assetFile(path.Join(directory, f)))
121 // FindRuntimeFile finds a runtime file of the given filetype and name
122 // will return nil if no file was found
123 func FindRuntimeFile(fileType RTFiletype, name string) RuntimeFile {
124 for _, f := range ListRuntimeFiles(fileType) {
125 if f.Name() == name {
132 // ListRuntimeFiles lists all known runtime files for the given filetype
133 func ListRuntimeFiles(fileType RTFiletype) []RuntimeFile {
134 return allFiles[fileType]
137 // ListRealRuntimeFiles lists all real runtime files (on disk) for a filetype
138 // these runtime files will be ones defined by the user and loaded from the config directory
139 func ListRealRuntimeFiles(fileType RTFiletype) []RuntimeFile {
140 return realFiles[fileType]
143 // InitRuntimeFiles initializes all assets file and the config directory
144 func InitRuntimeFiles() {
145 add := func(fileType RTFiletype, dir, pattern string) {
146 AddRuntimeFilesFromDirectory(fileType, filepath.Join(ConfigDir, dir), pattern)
147 AddRuntimeFilesFromAssets(fileType, path.Join("runtime", dir), pattern)
150 add(RTColorscheme, "colorschemes", "*.micro")
151 add(RTSyntax, "syntax", "*.yaml")
152 add(RTSyntaxHeader, "syntax", "*.hdr")
153 add(RTHelp, "help", "*.md")
155 initlua := filepath.Join(ConfigDir, "init.lua")
156 if _, err := os.Stat(initlua); !os.IsNotExist(err) {
159 p.DirName = "initlua"
160 p.Srcs = append(p.Srcs, realFile(initlua))
161 Plugins = append(Plugins, p)
164 // Search ConfigDir for plugin-scripts
165 plugdir := filepath.Join(ConfigDir, "plug")
166 files, _ := ioutil.ReadDir(plugdir)
168 isID := regexp.MustCompile(`^[_A-Za-z0-9]+$`).MatchString
170 for _, d := range files {
172 srcs, _ := ioutil.ReadDir(filepath.Join(plugdir, d.Name()))
176 for _, f := range srcs {
177 if strings.HasSuffix(f.Name(), ".lua") {
178 p.Srcs = append(p.Srcs, realFile(filepath.Join(plugdir, d.Name(), f.Name())))
179 } else if f.Name() == "info.json" {
180 data, err := ioutil.ReadFile(filepath.Join(plugdir, d.Name(), "info.json"))
184 p.Info, _ = NewPluginInfo(data)
190 log.Println("Invalid plugin name", p.Name)
193 Plugins = append(Plugins, p)
197 plugdir = filepath.Join("runtime", "plugins")
198 if files, err := AssetDir(plugdir); err == nil {
199 for _, d := range files {
200 if srcs, err := AssetDir(filepath.Join(plugdir, d)); err == nil {
205 for _, f := range srcs {
206 if strings.HasSuffix(f, ".lua") {
207 p.Srcs = append(p.Srcs, assetFile(filepath.Join(plugdir, d, f)))
208 } else if f == "info.json" {
209 data, err := Asset(filepath.Join(plugdir, d, "info.json"))
213 p.Info, _ = NewPluginInfo(data)
218 log.Println("Invalid plugin name", p.Name)
221 Plugins = append(Plugins, p)
227 // PluginReadRuntimeFile allows plugin scripts to read the content of a runtime file
228 func PluginReadRuntimeFile(fileType RTFiletype, name string) string {
229 if file := FindRuntimeFile(fileType, name); file != nil {
230 if data, err := file.Data(); err == nil {
237 // PluginListRuntimeFiles allows plugins to lists all runtime files of the given type
238 func PluginListRuntimeFiles(fileType RTFiletype) []string {
239 files := ListRuntimeFiles(fileType)
240 result := make([]string, len(files))
241 for i, f := range files {
247 // PluginAddRuntimeFile adds a file to the runtime files for a plugin
248 func PluginAddRuntimeFile(plugin string, filetype RTFiletype, filePath string) error {
249 pl := FindPlugin(plugin)
251 return errors.New("Plugin " + plugin + " does not exist")
254 fullpath := filepath.Join(ConfigDir, "plug", pldir, filePath)
255 if _, err := os.Stat(fullpath); err == nil {
256 AddRealRuntimeFile(filetype, realFile(fullpath))
258 fullpath = path.Join("runtime", "plugins", pldir, filePath)
259 AddRuntimeFile(filetype, assetFile(fullpath))
264 // PluginAddRuntimeFilesFromDirectory adds files from a directory to the runtime files for a plugin
265 func PluginAddRuntimeFilesFromDirectory(plugin string, filetype RTFiletype, directory, pattern string) error {
266 pl := FindPlugin(plugin)
268 return errors.New("Plugin " + plugin + " does not exist")
271 fullpath := filepath.Join(ConfigDir, "plug", pldir, directory)
272 if _, err := os.Stat(fullpath); err == nil {
273 AddRuntimeFilesFromDirectory(filetype, fullpath, pattern)
275 fullpath = path.Join("runtime", "plugins", pldir, directory)
276 AddRuntimeFilesFromAssets(filetype, fullpath, pattern)
281 // PluginAddRuntimeFileFromMemory adds a file to the runtime files for a plugin from a given string
282 func PluginAddRuntimeFileFromMemory(filetype RTFiletype, filename, data string) {
283 AddRealRuntimeFile(filetype, memoryFile{filename, []byte(data)})