]> git.lizzy.rs Git - micro.git/blob - cmd/micro/rtfiles.go
1b8c01f33c78b678dabe2df6d0666e75ea8137ca
[micro.git] / cmd / micro / rtfiles.go
1 package main
2
3 import (
4         "io/ioutil"
5         "os"
6         "path"
7         "path/filepath"
8 )
9
10 const (
11         RTColorscheme = "colorscheme"
12         RTSyntax      = "syntax"
13         RTHelp        = "help"
14         RTPlugin      = "plugin"
15 )
16
17 // RuntimeFile allows the program to read runtime data like colorschemes or syntax files
18 type RuntimeFile interface {
19         // Name returns a name of the file without paths or extensions
20         Name() string
21         // Data returns the content of the file.
22         Data() ([]byte, error)
23 }
24
25 // allFiles contains all available files, mapped by filetype
26 var allFiles map[string][]RuntimeFile
27
28 // some file on filesystem
29 type realFile string
30
31 // some asset file
32 type assetFile string
33
34 // some file on filesystem but with a different name
35 type namedFile struct {
36         realFile
37         name string
38 }
39
40 func (rf realFile) Name() string {
41         fn := filepath.Base(string(rf))
42         return fn[:len(fn)-len(filepath.Ext(fn))]
43 }
44
45 func (rf realFile) Data() ([]byte, error) {
46         return ioutil.ReadFile(string(rf))
47 }
48
49 func (af assetFile) Name() string {
50         fn := path.Base(string(af))
51         return fn[:len(fn)-len(path.Ext(fn))]
52 }
53
54 func (af assetFile) Data() ([]byte, error) {
55         return Asset(string(af))
56 }
57
58 func (nf namedFile) Name() string {
59         return nf.name
60 }
61
62 // AddRuntimeFile registers a file for the given filetype
63 func AddRuntimeFile(fileType string, file RuntimeFile) {
64         if allFiles == nil {
65                 allFiles = make(map[string][]RuntimeFile)
66         }
67         allFiles[fileType] = append(allFiles[fileType], file)
68 }
69
70 // AddRuntimeFilesFromDirectory registers each file from the given directory for
71 // the filetype which matches the file-pattern
72 func AddRuntimeFilesFromDirectory(fileType, directory, pattern string) {
73         files, _ := ioutil.ReadDir(directory)
74         for _, f := range files {
75                 if ok, _ := filepath.Match(pattern, f.Name()); !f.IsDir() && ok {
76                         fullPath := filepath.Join(directory, f.Name())
77                         AddRuntimeFile(fileType, realFile(fullPath))
78                 }
79         }
80 }
81
82 // AddRuntimeFilesFromAssets registers each file from the given asset-directory for
83 // the filetype which matches the file-pattern
84 func AddRuntimeFilesFromAssets(fileType, directory, pattern string) {
85         files, err := AssetDir(directory)
86         if err != nil {
87                 return
88         }
89         for _, f := range files {
90                 if ok, _ := path.Match(pattern, f); ok {
91                         AddRuntimeFile(fileType, assetFile(path.Join(directory, f)))
92                 }
93         }
94 }
95
96 // FindRuntimeFile finds a runtime file of the given filetype and name
97 // will return nil if no file was found
98 func FindRuntimeFile(fileType, name string) RuntimeFile {
99         for _, f := range ListRuntimeFiles(fileType) {
100                 if f.Name() == name {
101                         return f
102                 }
103         }
104         return nil
105 }
106
107 // ListRuntimeFiles lists all known runtime files for the given filetype
108 func ListRuntimeFiles(fileType string) []RuntimeFile {
109         if files, ok := allFiles[fileType]; ok {
110                 return files
111         }
112         return []RuntimeFile{}
113 }
114
115 // InitRuntimeFiles initializes all assets file and the config directory
116 func InitRuntimeFiles() {
117         add := func(fileType, dir, pattern string) {
118                 AddRuntimeFilesFromDirectory(fileType, filepath.Join(configDir, dir), pattern)
119                 AddRuntimeFilesFromAssets(fileType, path.Join("runtime", dir), pattern)
120         }
121
122         add(RTColorscheme, "colorschemes", "*.micro")
123         add(RTSyntax, "syntax", "*.micro")
124         add(RTHelp, "help", "*.md")
125
126         // Search configDir for plugin-scripts
127         files, _ := ioutil.ReadDir(filepath.Join(configDir, "plugins"))
128         for _, f := range files {
129                 realpath, _ := filepath.EvalSymlinks(filepath.Join(configDir, "plugins", f.Name()))
130                 realpathStat, _ := os.Stat(realpath)
131                 if realpathStat.IsDir() {
132                         scriptPath := filepath.Join(configDir, "plugins", f.Name(), f.Name()+".lua")
133                         if _, err := os.Stat(scriptPath); err == nil {
134                                 AddRuntimeFile(RTPlugin, realFile(scriptPath))
135                         }
136                 }
137         }
138
139         if files, err := AssetDir("runtime/plugins"); err == nil {
140                 for _, f := range files {
141                         scriptPath := path.Join("runtime/plugins", f, f+".lua")
142                         if _, err := AssetInfo(scriptPath); err == nil {
143                                 AddRuntimeFile(RTPlugin, assetFile(scriptPath))
144                         }
145                 }
146         }
147 }
148
149 // PluginReadRuntimeFile allows plugin scripts to read the content of a runtime file
150 func PluginReadRuntimeFile(fileType, name string) string {
151         if file := FindRuntimeFile(fileType, name); file != nil {
152                 if data, err := file.Data(); err == nil {
153                         return string(data)
154                 }
155         }
156         return ""
157 }
158
159 // PluginListRuntimeFiles allows plugins to lists all runtime files of the given type
160 func PluginListRuntimeFiles(fileType string) []string {
161         files := ListRuntimeFiles(fileType)
162         result := make([]string, len(files))
163         for i, f := range files {
164                 result[i] = f.Name()
165         }
166         return result
167 }
168
169 // PluginAddRuntimeFile adds a file to the runtime files for a plugin
170 func PluginAddRuntimeFile(plugin, filetype, filePath string) {
171         fullpath := filepath.Join(configDir, "plugins", plugin, filePath)
172         if _, err := os.Stat(fullpath); err == nil {
173                 AddRuntimeFile(filetype, realFile(fullpath))
174         } else {
175                 fullpath = path.Join("runtime", "plugins", plugin, filePath)
176                 AddRuntimeFile(filetype, assetFile(fullpath))
177         }
178 }
179
180 // PluginAddRuntimeFilesFromDirectory adds files from a directory to the runtime files for a plugin
181 func PluginAddRuntimeFilesFromDirectory(plugin, filetype, directory, pattern string) {
182         fullpath := filepath.Join(configDir, "plugins", plugin, directory)
183         if _, err := os.Stat(fullpath); err == nil {
184                 AddRuntimeFilesFromDirectory(filetype, fullpath, pattern)
185         } else {
186                 fullpath = path.Join("runtime", "plugins", plugin, directory)
187                 AddRuntimeFilesFromAssets(filetype, fullpath, pattern)
188         }
189 }