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