13 rt "github.com/zyedidia/micro/v2/runtime"
25 NumTypes = 5 // How many filetypes are there
30 // RuntimeFile allows the program to read runtime data like colorschemes or syntax files
31 type RuntimeFile interface {
32 // Name returns a name of the file without paths or extensions
34 // Data returns the content of the file.
35 Data() ([]byte, error)
38 // allFiles contains all available files, mapped by filetype
39 var allFiles [][]RuntimeFile
40 var realFiles [][]RuntimeFile
43 allFiles = make([][]RuntimeFile, NumTypes)
44 realFiles = make([][]RuntimeFile, NumTypes)
47 // NewRTFiletype creates a new RTFiletype
48 func NewRTFiletype() int {
50 allFiles = append(allFiles, []RuntimeFile{})
51 realFiles = append(realFiles, []RuntimeFile{})
55 // some file on filesystem
61 // some file on filesystem but with a different name
62 type namedFile struct {
67 // a file with the data stored in memory
68 type memoryFile struct {
73 func (mf memoryFile) Name() string {
76 func (mf memoryFile) Data() ([]byte, error) {
80 func (rf realFile) Name() string {
81 fn := filepath.Base(string(rf))
82 return fn[:len(fn)-len(filepath.Ext(fn))]
85 func (rf realFile) Data() ([]byte, error) {
86 return ioutil.ReadFile(string(rf))
89 func (af assetFile) Name() string {
90 fn := path.Base(string(af))
91 return fn[:len(fn)-len(path.Ext(fn))]
94 func (af assetFile) Data() ([]byte, error) {
95 return rt.Asset(string(af))
98 func (nf namedFile) Name() string {
102 // AddRuntimeFile registers a file for the given filetype
103 func AddRuntimeFile(fileType RTFiletype, file RuntimeFile) {
104 allFiles[fileType] = append(allFiles[fileType], file)
107 // AddRealRuntimeFile registers a file for the given filetype
108 func AddRealRuntimeFile(fileType RTFiletype, file RuntimeFile) {
109 allFiles[fileType] = append(allFiles[fileType], file)
110 realFiles[fileType] = append(realFiles[fileType], file)
113 // AddRuntimeFilesFromDirectory registers each file from the given directory for
114 // the filetype which matches the file-pattern
115 func AddRuntimeFilesFromDirectory(fileType RTFiletype, directory, pattern string) {
116 files, _ := ioutil.ReadDir(directory)
117 for _, f := range files {
118 if ok, _ := filepath.Match(pattern, f.Name()); !f.IsDir() && ok {
119 fullPath := filepath.Join(directory, f.Name())
120 AddRealRuntimeFile(fileType, realFile(fullPath))
125 // AddRuntimeFilesFromAssets registers each file from the given asset-directory for
126 // the filetype which matches the file-pattern
127 func AddRuntimeFilesFromAssets(fileType RTFiletype, directory, pattern string) {
128 files, err := rt.AssetDir(directory)
132 for _, f := range files {
133 if ok, _ := path.Match(pattern, f); ok {
134 AddRuntimeFile(fileType, assetFile(path.Join(directory, f)))
139 // FindRuntimeFile finds a runtime file of the given filetype and name
140 // will return nil if no file was found
141 func FindRuntimeFile(fileType RTFiletype, name string) RuntimeFile {
142 for _, f := range ListRuntimeFiles(fileType) {
143 if f.Name() == name {
150 // ListRuntimeFiles lists all known runtime files for the given filetype
151 func ListRuntimeFiles(fileType RTFiletype) []RuntimeFile {
152 return allFiles[fileType]
155 // ListRealRuntimeFiles lists all real runtime files (on disk) for a filetype
156 // these runtime files will be ones defined by the user and loaded from the config directory
157 func ListRealRuntimeFiles(fileType RTFiletype) []RuntimeFile {
158 return realFiles[fileType]
161 // InitRuntimeFiles initializes all assets file and the config directory
162 func InitRuntimeFiles() {
163 add := func(fileType RTFiletype, dir, pattern string) {
164 AddRuntimeFilesFromDirectory(fileType, filepath.Join(ConfigDir, dir), pattern)
165 AddRuntimeFilesFromAssets(fileType, path.Join("runtime", dir), pattern)
168 add(RTColorscheme, "colorschemes", "*.micro")
169 add(RTSyntax, "syntax", "*.yaml")
170 add(RTSyntaxHeader, "syntax", "*.hdr")
171 add(RTHelp, "help", "*.md")
173 initlua := filepath.Join(ConfigDir, "init.lua")
174 if _, err := os.Stat(initlua); !os.IsNotExist(err) {
177 p.DirName = "initlua"
178 p.Srcs = append(p.Srcs, realFile(initlua))
179 Plugins = append(Plugins, p)
182 // Search ConfigDir for plugin-scripts
183 plugdir := filepath.Join(ConfigDir, "plug")
184 files, _ := ioutil.ReadDir(plugdir)
186 isID := regexp.MustCompile(`^[_A-Za-z0-9]+$`).MatchString
188 for _, d := range files {
190 srcs, _ := ioutil.ReadDir(filepath.Join(plugdir, d.Name()))
194 for _, f := range srcs {
195 if strings.HasSuffix(f.Name(), ".lua") {
196 p.Srcs = append(p.Srcs, realFile(filepath.Join(plugdir, d.Name(), f.Name())))
197 } else if strings.HasSuffix(f.Name(), ".json") {
198 data, err := ioutil.ReadFile(filepath.Join(plugdir, d.Name(), f.Name()))
202 p.Info, err = NewPluginInfo(data)
210 if !isID(p.Name) || len(p.Srcs) <= 0 {
211 log.Println(p.Name, "is not a plugin")
214 Plugins = append(Plugins, p)
218 plugdir = filepath.Join("runtime", "plugins")
219 if files, err := rt.AssetDir(plugdir); err == nil {
220 for _, d := range files {
221 if srcs, err := rt.AssetDir(filepath.Join(plugdir, d)); err == nil {
226 for _, f := range srcs {
227 if strings.HasSuffix(f, ".lua") {
228 p.Srcs = append(p.Srcs, assetFile(filepath.Join(plugdir, d, f)))
229 } else if strings.HasSuffix(f, ".json") {
230 data, err := rt.Asset(filepath.Join(plugdir, d, f))
234 p.Info, err = NewPluginInfo(data)
241 if !isID(p.Name) || len(p.Srcs) <= 0 {
242 log.Println(p.Name, "is not a plugin")
245 Plugins = append(Plugins, p)
251 // PluginReadRuntimeFile allows plugin scripts to read the content of a runtime file
252 func PluginReadRuntimeFile(fileType RTFiletype, name string) string {
253 if file := FindRuntimeFile(fileType, name); file != nil {
254 if data, err := file.Data(); err == nil {
261 // PluginListRuntimeFiles allows plugins to lists all runtime files of the given type
262 func PluginListRuntimeFiles(fileType RTFiletype) []string {
263 files := ListRuntimeFiles(fileType)
264 result := make([]string, len(files))
265 for i, f := range files {
271 // PluginAddRuntimeFile adds a file to the runtime files for a plugin
272 func PluginAddRuntimeFile(plugin string, filetype RTFiletype, filePath string) error {
273 pl := FindPlugin(plugin)
275 return errors.New("Plugin " + plugin + " does not exist")
278 fullpath := filepath.Join(ConfigDir, "plug", pldir, filePath)
279 if _, err := os.Stat(fullpath); err == nil {
280 AddRealRuntimeFile(filetype, realFile(fullpath))
282 fullpath = path.Join("runtime", "plugins", pldir, filePath)
283 AddRuntimeFile(filetype, assetFile(fullpath))
288 // PluginAddRuntimeFilesFromDirectory adds files from a directory to the runtime files for a plugin
289 func PluginAddRuntimeFilesFromDirectory(plugin string, filetype RTFiletype, directory, pattern string) error {
290 pl := FindPlugin(plugin)
292 return errors.New("Plugin " + plugin + " does not exist")
295 fullpath := filepath.Join(ConfigDir, "plug", pldir, directory)
296 if _, err := os.Stat(fullpath); err == nil {
297 AddRuntimeFilesFromDirectory(filetype, fullpath, pattern)
299 fullpath = path.Join("runtime", "plugins", pldir, directory)
300 AddRuntimeFilesFromAssets(filetype, fullpath, pattern)
305 // PluginAddRuntimeFileFromMemory adds a file to the runtime files for a plugin from a given string
306 func PluginAddRuntimeFileFromMemory(filetype RTFiletype, filename, data string) {
307 AddRealRuntimeFile(filetype, memoryFile{filename, []byte(data)})