23 NumTypes = 5 // How many filetypes are there
28 // RuntimeFile allows the program to read runtime data like colorschemes or syntax files
29 type RuntimeFile interface {
30 // Name returns a name of the file without paths or extensions
32 // Data returns the content of the file.
33 Data() ([]byte, error)
36 // allFiles contains all available files, mapped by filetype
37 var allFiles [][]RuntimeFile
38 var realFiles [][]RuntimeFile
41 allFiles = make([][]RuntimeFile, NumTypes)
42 realFiles = make([][]RuntimeFile, NumTypes)
45 func NewRTFiletype() int {
47 allFiles = append(allFiles, []RuntimeFile{})
48 realFiles = append(realFiles, []RuntimeFile{})
52 // some file on filesystem
58 // some file on filesystem but with a different name
59 type namedFile struct {
64 // a file with the data stored in memory
65 type memoryFile struct {
70 func (mf memoryFile) Name() string {
73 func (mf memoryFile) Data() ([]byte, error) {
77 func (rf realFile) Name() string {
78 fn := filepath.Base(string(rf))
79 return fn[:len(fn)-len(filepath.Ext(fn))]
82 func (rf realFile) Data() ([]byte, error) {
83 return ioutil.ReadFile(string(rf))
86 func (af assetFile) Name() string {
87 fn := path.Base(string(af))
88 return fn[:len(fn)-len(path.Ext(fn))]
91 func (af assetFile) Data() ([]byte, error) {
92 return Asset(string(af))
95 func (nf namedFile) Name() string {
99 // AddRuntimeFile registers a file for the given filetype
100 func AddRuntimeFile(fileType RTFiletype, file RuntimeFile) {
101 allFiles[fileType] = append(allFiles[fileType], file)
104 // AddRealRuntimeFile registers a file for the given filetype
105 func AddRealRuntimeFile(fileType RTFiletype, file RuntimeFile) {
106 allFiles[fileType] = append(allFiles[fileType], file)
107 realFiles[fileType] = append(realFiles[fileType], file)
110 // AddRuntimeFilesFromDirectory registers each file from the given directory for
111 // the filetype which matches the file-pattern
112 func AddRuntimeFilesFromDirectory(fileType RTFiletype, directory, pattern string) {
113 files, _ := ioutil.ReadDir(directory)
114 for _, f := range files {
115 if ok, _ := filepath.Match(pattern, f.Name()); !f.IsDir() && ok {
116 fullPath := filepath.Join(directory, f.Name())
117 AddRealRuntimeFile(fileType, realFile(fullPath))
122 // AddRuntimeFilesFromAssets registers each file from the given asset-directory for
123 // the filetype which matches the file-pattern
124 func AddRuntimeFilesFromAssets(fileType RTFiletype, directory, pattern string) {
125 files, err := AssetDir(directory)
129 for _, f := range files {
130 if ok, _ := path.Match(pattern, f); ok {
131 AddRuntimeFile(fileType, assetFile(path.Join(directory, f)))
136 // FindRuntimeFile finds a runtime file of the given filetype and name
137 // will return nil if no file was found
138 func FindRuntimeFile(fileType RTFiletype, name string) RuntimeFile {
139 for _, f := range ListRuntimeFiles(fileType) {
140 if f.Name() == name {
147 // ListRuntimeFiles lists all known runtime files for the given filetype
148 func ListRuntimeFiles(fileType RTFiletype) []RuntimeFile {
149 return allFiles[fileType]
152 // ListRealRuntimeFiles lists all real runtime files (on disk) for a filetype
153 // these runtime files will be ones defined by the user and loaded from the config directory
154 func ListRealRuntimeFiles(fileType RTFiletype) []RuntimeFile {
155 return realFiles[fileType]
158 // InitRuntimeFiles initializes all assets file and the config directory
159 func InitRuntimeFiles() {
160 add := func(fileType RTFiletype, dir, pattern string) {
161 AddRuntimeFilesFromDirectory(fileType, filepath.Join(ConfigDir, dir), pattern)
162 AddRuntimeFilesFromAssets(fileType, path.Join("runtime", dir), pattern)
165 add(RTColorscheme, "colorschemes", "*.micro")
166 add(RTSyntax, "syntax", "*.yaml")
167 add(RTSyntaxHeader, "syntax", "*.hdr")
168 add(RTHelp, "help", "*.md")
170 initlua := filepath.Join(ConfigDir, "init.lua")
171 if _, err := os.Stat(initlua); !os.IsNotExist(err) {
174 p.DirName = "initlua"
175 p.Srcs = append(p.Srcs, realFile(initlua))
176 Plugins = append(Plugins, p)
179 // Search ConfigDir for plugin-scripts
180 plugdir := filepath.Join(ConfigDir, "plug")
181 files, _ := ioutil.ReadDir(plugdir)
183 isID := regexp.MustCompile(`^[_A-Za-z0-9]+$`).MatchString
185 for _, d := range files {
187 srcs, _ := ioutil.ReadDir(filepath.Join(plugdir, d.Name()))
191 for _, f := range srcs {
192 if strings.HasSuffix(f.Name(), ".lua") {
193 p.Srcs = append(p.Srcs, realFile(filepath.Join(plugdir, d.Name(), f.Name())))
194 } else if strings.HasSuffix(f.Name(), ".json") {
195 data, err := ioutil.ReadFile(filepath.Join(plugdir, d.Name(), f.Name()))
199 p.Info, err = NewPluginInfo(data)
208 if !isID(p.Name) || len(p.Srcs) <= 0 {
209 log.Println(p.Name, "is not a plugin")
212 Plugins = append(Plugins, p)
216 plugdir = filepath.Join("runtime", "plugins")
217 if files, err := AssetDir(plugdir); err == nil {
218 for _, d := range files {
219 if srcs, err := AssetDir(filepath.Join(plugdir, d)); err == nil {
224 for _, f := range srcs {
225 if strings.HasSuffix(f, ".lua") {
226 p.Srcs = append(p.Srcs, assetFile(filepath.Join(plugdir, d, f)))
227 } else if strings.HasSuffix(f, ".json") {
228 data, err := Asset(filepath.Join(plugdir, d, f))
232 p.Info, err = NewPluginInfo(data)
240 if !isID(p.Name) || len(p.Srcs) <= 0 {
241 log.Println(p.Name, "is not a plugin")
244 Plugins = append(Plugins, p)
250 // PluginReadRuntimeFile allows plugin scripts to read the content of a runtime file
251 func PluginReadRuntimeFile(fileType RTFiletype, name string) string {
252 if file := FindRuntimeFile(fileType, name); file != nil {
253 if data, err := file.Data(); err == nil {
260 // PluginListRuntimeFiles allows plugins to lists all runtime files of the given type
261 func PluginListRuntimeFiles(fileType RTFiletype) []string {
262 files := ListRuntimeFiles(fileType)
263 result := make([]string, len(files))
264 for i, f := range files {
270 // PluginAddRuntimeFile adds a file to the runtime files for a plugin
271 func PluginAddRuntimeFile(plugin string, filetype RTFiletype, filePath string) error {
272 pl := FindPlugin(plugin)
274 return errors.New("Plugin " + plugin + " does not exist")
277 fullpath := filepath.Join(ConfigDir, "plug", pldir, filePath)
278 if _, err := os.Stat(fullpath); err == nil {
279 AddRealRuntimeFile(filetype, realFile(fullpath))
281 fullpath = path.Join("runtime", "plugins", pldir, filePath)
282 AddRuntimeFile(filetype, assetFile(fullpath))
287 // PluginAddRuntimeFilesFromDirectory adds files from a directory to the runtime files for a plugin
288 func PluginAddRuntimeFilesFromDirectory(plugin string, filetype RTFiletype, directory, pattern string) error {
289 pl := FindPlugin(plugin)
291 return errors.New("Plugin " + plugin + " does not exist")
294 fullpath := filepath.Join(ConfigDir, "plug", pldir, directory)
295 if _, err := os.Stat(fullpath); err == nil {
296 AddRuntimeFilesFromDirectory(filetype, fullpath, pattern)
298 fullpath = path.Join("runtime", "plugins", pldir, directory)
299 AddRuntimeFilesFromAssets(filetype, fullpath, pattern)
304 // PluginAddRuntimeFileFromMemory adds a file to the runtime files for a plugin from a given string
305 func PluginAddRuntimeFileFromMemory(filetype RTFiletype, filename, data string) {
306 AddRealRuntimeFile(filetype, memoryFile{filename, []byte(data)})