]> git.lizzy.rs Git - micro.git/blob - internal/config/rtfiles.go
Improve gutter messages
[micro.git] / internal / config / rtfiles.go
1 package config
2
3 import (
4         "io/ioutil"
5         "os"
6         "path"
7         "path/filepath"
8         "strings"
9 )
10
11 const (
12         RTColorscheme = 0
13         RTSyntax      = 1
14         RTHelp        = 2
15         RTPlugin      = 3
16         NumTypes      = 4 // How many filetypes are there
17 )
18
19 type RTFiletype byte
20
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
24         Name() string
25         // Data returns the content of the file.
26         Data() ([]byte, error)
27 }
28
29 // allFiles contains all available files, mapped by filetype
30 var allFiles [NumTypes][]RuntimeFile
31
32 // some file on filesystem
33 type realFile string
34
35 // some asset file
36 type assetFile string
37
38 // some file on filesystem but with a different name
39 type namedFile struct {
40         realFile
41         name string
42 }
43
44 // a file with the data stored in memory
45 type memoryFile struct {
46         name string
47         data []byte
48 }
49
50 func (mf memoryFile) Name() string {
51         return mf.name
52 }
53 func (mf memoryFile) Data() ([]byte, error) {
54         return mf.data, nil
55 }
56
57 func (rf realFile) Name() string {
58         fn := filepath.Base(string(rf))
59         return fn[:len(fn)-len(filepath.Ext(fn))]
60 }
61
62 func (rf realFile) Data() ([]byte, error) {
63         return ioutil.ReadFile(string(rf))
64 }
65
66 func (af assetFile) Name() string {
67         fn := path.Base(string(af))
68         return fn[:len(fn)-len(path.Ext(fn))]
69 }
70
71 func (af assetFile) Data() ([]byte, error) {
72         return Asset(string(af))
73 }
74
75 func (nf namedFile) Name() string {
76         return nf.name
77 }
78
79 // AddRuntimeFile registers a file for the given filetype
80 func AddRuntimeFile(fileType RTFiletype, file RuntimeFile) {
81         allFiles[fileType] = append(allFiles[fileType], file)
82 }
83
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))
92                 }
93         }
94 }
95
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)
100         if err != nil {
101                 return
102         }
103         for _, f := range files {
104                 if ok, _ := path.Match(pattern, f); ok {
105                         AddRuntimeFile(fileType, assetFile(path.Join(directory, f)))
106                 }
107         }
108 }
109
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 {
115                         return f
116                 }
117         }
118         return nil
119 }
120
121 // ListRuntimeFiles lists all known runtime files for the given filetype
122 func ListRuntimeFiles(fileType RTFiletype) []RuntimeFile {
123         return allFiles[fileType]
124 }
125
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)
131         }
132
133         add(RTColorscheme, "colorschemes", "*.micro")
134         add(RTSyntax, "syntax", "*.yaml")
135         add(RTHelp, "help", "*.md")
136
137         // Search ConfigDir for plugin-scripts
138         plugdir := filepath.Join(ConfigDir, "plugins")
139         files, _ := ioutil.ReadDir(plugdir)
140         for _, d := range files {
141                 if d.IsDir() {
142                         srcs, _ := ioutil.ReadDir(filepath.Join(plugdir, d.Name()))
143                         p := new(Plugin)
144                         p.Name = 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"))
150                                 }
151                         }
152                         Plugins = append(Plugins, p)
153                 }
154         }
155
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 {
160                                 p := new(Plugin)
161                                 p.Name = d
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"))
167                                         }
168                                 }
169                                 Plugins = append(Plugins, p)
170                         }
171                 }
172         }
173 }
174
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 {
179                         return string(data)
180                 }
181         }
182         return ""
183 }
184
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 {
190                 result[i] = f.Name()
191         }
192         return result
193 }
194
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))
200         } else {
201                 fullpath = path.Join("runtime", "plugins", plugin, filePath)
202                 AddRuntimeFile(filetype, assetFile(fullpath))
203         }
204 }
205
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)
211         } else {
212                 fullpath = path.Join("runtime", "plugins", plugin, directory)
213                 AddRuntimeFilesFromAssets(filetype, fullpath, pattern)
214         }
215 }
216
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)})
220 }