-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathpackage.go
233 lines (196 loc) · 5.75 KB
/
package.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
// Copyright 2016 The lime Authors.
// Use of this source code is governed by a 2-clause
// BSD-style license that can be found in the LICENSE file.
package sublime
import (
"io/ioutil"
"os"
"path/filepath"
"github.com/limetext/backend"
"github.com/limetext/backend/keys"
"github.com/limetext/backend/log"
"github.com/limetext/backend/packages"
_ "github.com/limetext/sublime/api"
"github.com/limetext/text"
)
// Represents a sublime package
// TODO: iss#71
type pkg struct {
dir string
name string
text.HasSettings
keys.HasKeyBindings
platformSettings *text.HasSettings
defaultSettings *text.HasSettings
defaultKB *keys.HasKeyBindings
plugins map[string]*plugin
syntaxes map[string]*syntax
colorSchemes map[string]*colorScheme
}
func newPKG(dir string) packages.Package {
p := &pkg{
dir: dir,
name: pkgName(dir),
platformSettings: new(text.HasSettings),
defaultSettings: new(text.HasSettings),
defaultKB: new(keys.HasKeyBindings),
plugins: make(map[string]*plugin),
syntaxes: make(map[string]*syntax),
colorSchemes: make(map[string]*colorScheme),
}
ed := backend.GetEditor()
// Initializing settings hierarchy
// editor <- default <- platform <- user(package)
p.Settings().SetParent(p.platformSettings)
p.platformSettings.Settings().SetParent(p.defaultSettings)
p.defaultSettings.Settings().SetParent(ed)
// Initializing keybidings hierarchy
// default <- platform(package) <- editor.default
edDefault := ed.KeyBindings().Parent().KeyBindings().Parent().KeyBindings().Parent()
tmp := edDefault.KeyBindings().Parent()
edDefault.KeyBindings().SetParent(p)
p.KeyBindings().SetParent(p.defaultKB)
if tmp != nil {
p.defaultKB.KeyBindings().SetParent(tmp)
}
backend.OnUserPathAdd.Add(p.loadUserSettings)
return p
}
func (p *pkg) Load() {
log.Debug("Loading package %s", p.Name())
p.loadKeyBindings()
p.loadSettings()
p.loadUserSettings(backend.GetEditor().UserPath())
// When we failed on importing sublime_plugin module we continue
// loading packages but not package plugins
if module != nil {
p.loadPlugins()
}
// load files that could be anywhere in the package dir like syntax,
// colour scheme and preferences
filepath.Walk(p.Path(), p.scan)
}
func (p *pkg) UnLoad() {}
func (p *pkg) Path() string {
return p.dir
}
func (p *pkg) Name() string {
return p.name
}
// TODO: how we should watch the package and the files containing?
func (p *pkg) FileCreated(name string) {}
func (p *pkg) loadPlugins() {
log.Fine("Loading %s plugins", p.Name())
fis, err := ioutil.ReadDir(p.Path())
if err != nil {
log.Warn("Error on reading directory %s, %s", p.Path(), err)
return
}
for _, fi := range fis {
if isPlugin(fi.Name()) {
p.loadPlugin(filepath.Join(p.Path(), fi.Name()))
}
}
}
func (p *pkg) loadPlugin(path string) {
pl := newPlugin(path)
pl.Load()
p.plugins[path] = pl.(*plugin)
}
func (p *pkg) loadColorScheme(path string) {
log.Fine("Loading %s package color scheme %s", p.Name(), path)
cs, err := newColorScheme(path)
if err != nil {
log.Warn("Error loading %s color scheme %s: %s", p.Name(), path, err)
return
}
p.colorSchemes[path] = cs
backend.GetEditor().AddColorScheme(path, cs)
}
func (p *pkg) loadSyntax(path string) {
log.Fine("Loading %s package syntax %s", p.Name(), path)
syn, err := newSyntax(path)
if err != nil {
log.Warn("Error loading %s syntax: %s", p.Name(), err)
return
}
p.syntaxes[path] = syn
backend.GetEditor().AddSyntax(path, syn)
}
func (p *pkg) loadKeyBindings() {
log.Fine("Loading %s keybindings", p.Name())
ed := backend.GetEditor()
pt := filepath.Join(p.Path(), "Default.sublime-keymap")
log.Finest("Loading %s", pt)
packages.LoadJSON(pt, p.defaultKB.KeyBindings())
pt = filepath.Join(p.Path(), "Default ("+ed.Plat()+").sublime-keymap")
log.Finest("Loading %s", pt)
packages.LoadJSON(pt, p.KeyBindings())
}
func (p *pkg) loadSettings() {
log.Fine("Loading %s settings", p.Name())
ed := backend.GetEditor()
pt := filepath.Join(p.Path(), "Preferences.sublime-settings")
log.Finest("Loading %s", pt)
packages.LoadJSON(pt, p.defaultSettings.Settings())
pt = filepath.Join(p.Path(), "Preferences ("+ed.Plat()+").sublime-settings")
log.Finest("Loading %s", pt)
packages.LoadJSON(pt, p.platformSettings.Settings())
}
func (p *pkg) loadUserSettings(dir string) {
log.Fine("Loading %s user settings", p.Name())
pt := filepath.Join(dir, p.Name()+".sublime-settings")
log.Finest("Loading %s", pt)
packages.LoadJSON(pt, p.Settings())
}
func (p *pkg) scan(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
if isColorScheme(path) {
p.loadColorScheme(path)
}
if isSyntax(path) {
p.loadSyntax(path)
}
return nil
}
func pkgName(dir string) string {
return filepath.Base(dir)
}
// Any directory in sublime is a package
func isPKG(dir string) bool {
fi, err := os.Stat(dir)
if err != nil || !fi.IsDir() {
return false
}
name := pkgName(dir)
ed := backend.GetEditor()
if ignoreds, ok := ed.Settings().Get("ignored_packages").([]interface{}); ok {
for _, ignored := range ignoreds {
if ignored == name {
return false
}
}
}
return true
}
var packageRecord = &packages.Record{isPKG, newPKG}
func onInit() {
// Assuming there is a sublime_plugin.py file in the current directory
// for that we should add current directory to python paths
// Every package that imports sublime package should have a copy of
// sublime_plugin.py file in the "." directory
pyAddPath(".")
packages.Register(packageRecord)
var err error
if module, err = pyImport("sublime_plugin"); err != nil {
log.Error("Error importing sublime_plugin: %s", err)
return
}
backend.OnPackagesPathAdd.Add(pyAddPath)
packages.Register(pluginRecord)
}
func init() {
backend.OnInit.Add(onInit)
}