17 NumTypes = 4 // How many filetypes are there
22 // RuntimeFile allows the program to read runtime data like colorschemes or syntax files
23 type RuntimeFile interface {
24 // Name returns a name of the file without paths or extensions
26 // Data returns the content of the file.
27 Data() ([]byte, error)
30 // allFiles contains all available files, mapped by filetype
31 var allFiles [NumTypes][]RuntimeFile
33 // some file on filesystem
39 // some file on filesystem but with a different name
40 type namedFile struct {
45 // a file with the data stored in memory
46 type memoryFile struct {
51 func (mf memoryFile) Name() string {
54 func (mf memoryFile) Data() ([]byte, error) {
58 func (rf realFile) Name() string {
59 fn := filepath.Base(string(rf))
60 return fn[:len(fn)-len(filepath.Ext(fn))]
63 func (rf realFile) Data() ([]byte, error) {
64 return ioutil.ReadFile(string(rf))
67 func (af assetFile) Name() string {
68 fn := path.Base(string(af))
69 return fn[:len(fn)-len(path.Ext(fn))]
72 func (af assetFile) Data() ([]byte, error) {
73 return Asset(string(af))
76 func (nf namedFile) Name() string {
80 // AddRuntimeFile registers a file for the given filetype
81 func AddRuntimeFile(fileType RTFiletype, file RuntimeFile) {
82 allFiles[fileType] = append(allFiles[fileType], file)
85 // AddRuntimeFilesFromDirectory registers each file from the given directory for
86 // the filetype which matches the file-pattern
87 func AddRuntimeFilesFromDirectory(fileType RTFiletype, directory, pattern string) {
88 files, _ := ioutil.ReadDir(directory)
89 for _, f := range files {
90 if ok, _ := filepath.Match(pattern, f.Name()); !f.IsDir() && ok {
91 fullPath := filepath.Join(directory, f.Name())
92 AddRuntimeFile(fileType, realFile(fullPath))
97 // AddRuntimeFilesFromAssets registers each file from the given asset-directory for
98 // the filetype which matches the file-pattern
99 func AddRuntimeFilesFromAssets(fileType RTFiletype, directory, pattern string) {
100 files, err := AssetDir(directory)
104 for _, f := range files {
105 if ok, _ := path.Match(pattern, f); ok {
106 AddRuntimeFile(fileType, assetFile(path.Join(directory, f)))
111 // FindRuntimeFile finds a runtime file of the given filetype and name
112 // will return nil if no file was found
113 func FindRuntimeFile(fileType RTFiletype, name string) RuntimeFile {
114 for _, f := range ListRuntimeFiles(fileType) {
115 if f.Name() == name {
122 // ListRuntimeFiles lists all known runtime files for the given filetype
123 func ListRuntimeFiles(fileType RTFiletype) []RuntimeFile {
124 return allFiles[fileType]
127 // InitRuntimeFiles initializes all assets file and the config directory
128 func InitRuntimeFiles() {
129 add := func(fileType RTFiletype, dir, pattern string) {
130 AddRuntimeFilesFromDirectory(fileType, filepath.Join(ConfigDir, dir), pattern)
131 AddRuntimeFilesFromAssets(fileType, path.Join("runtime", dir), pattern)
134 add(RTColorscheme, "colorschemes", "*.micro")
135 add(RTSyntax, "syntax", "*.yaml")
136 add(RTHelp, "help", "*.md")
138 // Search ConfigDir for plugin-scripts
139 plugdir := filepath.Join(ConfigDir, "plugins")
140 files, _ := ioutil.ReadDir(plugdir)
141 log.Println("reading", plugdir)
142 for _, d := range files {
144 srcs, _ := ioutil.ReadDir(filepath.Join(plugdir, d.Name()))
147 for _, f := range srcs {
148 if strings.HasSuffix(f.Name(), ".lua") {
149 p.Srcs = append(p.Srcs, realFile(filepath.Join(plugdir, d.Name(), f.Name())))
150 } else if f.Name() == "info.json" {
151 p.Info = realFile(filepath.Join(plugdir, d.Name(), "info.json"))
154 Plugins = append(Plugins, p)
158 plugdir = filepath.Join("runtime", "plugins")
159 if files, err := AssetDir(plugdir); err == nil {
160 for _, d := range files {
161 if srcs, err := AssetDir(filepath.Join(plugdir, d)); err == nil {
164 for _, f := range srcs {
165 if strings.HasSuffix(f, ".lua") {
166 p.Srcs = append(p.Srcs, assetFile(filepath.Join(plugdir, d, f)))
167 } else if f == "info.json" {
168 p.Info = assetFile(filepath.Join(plugdir, d, "info.json"))
171 Plugins = append(Plugins, p)
177 // PluginReadRuntimeFile allows plugin scripts to read the content of a runtime file
178 func PluginReadRuntimeFile(fileType RTFiletype, name string) string {
179 if file := FindRuntimeFile(fileType, name); file != nil {
180 if data, err := file.Data(); err == nil {
187 // PluginListRuntimeFiles allows plugins to lists all runtime files of the given type
188 func PluginListRuntimeFiles(fileType RTFiletype) []string {
189 files := ListRuntimeFiles(fileType)
190 result := make([]string, len(files))
191 for i, f := range files {
197 // PluginAddRuntimeFile adds a file to the runtime files for a plugin
198 func PluginAddRuntimeFile(plugin string, filetype RTFiletype, filePath string) {
199 fullpath := filepath.Join(ConfigDir, "plugins", plugin, filePath)
200 if _, err := os.Stat(fullpath); err == nil {
201 AddRuntimeFile(filetype, realFile(fullpath))
203 fullpath = path.Join("runtime", "plugins", plugin, filePath)
204 AddRuntimeFile(filetype, assetFile(fullpath))
208 // PluginAddRuntimeFilesFromDirectory adds files from a directory to the runtime files for a plugin
209 func PluginAddRuntimeFilesFromDirectory(plugin string, filetype RTFiletype, directory, pattern string) {
210 fullpath := filepath.Join(ConfigDir, "plugins", plugin, directory)
211 if _, err := os.Stat(fullpath); err == nil {
212 AddRuntimeFilesFromDirectory(filetype, fullpath, pattern)
214 fullpath = path.Join("runtime", "plugins", plugin, directory)
215 AddRuntimeFilesFromAssets(filetype, fullpath, pattern)
219 // PluginAddRuntimeFileFromMemory adds a file to the runtime files for a plugin from a given string
220 func PluginAddRuntimeFileFromMemory(plugin string, filetype RTFiletype, filename, data string) {
221 AddRuntimeFile(filetype, memoryFile{filename, []byte(data)})