sublime_dsl 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +136 -0
- data/Rakefile +248 -0
- data/SYNTAX.md +927 -0
- data/bin/subdsl +4 -0
- data/lib/sublime_dsl/cli/export.rb +134 -0
- data/lib/sublime_dsl/cli/import.rb +143 -0
- data/lib/sublime_dsl/cli.rb +125 -0
- data/lib/sublime_dsl/core_ext/enumerable.rb +24 -0
- data/lib/sublime_dsl/core_ext/string.rb +129 -0
- data/lib/sublime_dsl/core_ext.rb +4 -0
- data/lib/sublime_dsl/sublime_text/command.rb +157 -0
- data/lib/sublime_dsl/sublime_text/command_set.rb +112 -0
- data/lib/sublime_dsl/sublime_text/keyboard.rb +659 -0
- data/lib/sublime_dsl/sublime_text/keymap/dsl_reader.rb +194 -0
- data/lib/sublime_dsl/sublime_text/keymap.rb +385 -0
- data/lib/sublime_dsl/sublime_text/macro.rb +91 -0
- data/lib/sublime_dsl/sublime_text/menu.rb +237 -0
- data/lib/sublime_dsl/sublime_text/mouse.rb +149 -0
- data/lib/sublime_dsl/sublime_text/mousemap.rb +185 -0
- data/lib/sublime_dsl/sublime_text/package/dsl_reader.rb +91 -0
- data/lib/sublime_dsl/sublime_text/package/exporter.rb +138 -0
- data/lib/sublime_dsl/sublime_text/package/importer.rb +127 -0
- data/lib/sublime_dsl/sublime_text/package/reader.rb +102 -0
- data/lib/sublime_dsl/sublime_text/package/writer.rb +112 -0
- data/lib/sublime_dsl/sublime_text/package.rb +96 -0
- data/lib/sublime_dsl/sublime_text/setting_set.rb +123 -0
- data/lib/sublime_dsl/sublime_text.rb +48 -0
- data/lib/sublime_dsl/textmate/custom_base_name.rb +45 -0
- data/lib/sublime_dsl/textmate/grammar/dsl_reader.rb +383 -0
- data/lib/sublime_dsl/textmate/grammar/dsl_writer.rb +178 -0
- data/lib/sublime_dsl/textmate/grammar/plist_reader.rb +163 -0
- data/lib/sublime_dsl/textmate/grammar/plist_writer.rb +153 -0
- data/lib/sublime_dsl/textmate/grammar.rb +252 -0
- data/lib/sublime_dsl/textmate/plist.rb +141 -0
- data/lib/sublime_dsl/textmate/preference.rb +301 -0
- data/lib/sublime_dsl/textmate/snippet.rb +437 -0
- data/lib/sublime_dsl/textmate/theme/dsl_reader.rb +87 -0
- data/lib/sublime_dsl/textmate/theme/item.rb +74 -0
- data/lib/sublime_dsl/textmate/theme/plist_writer.rb +53 -0
- data/lib/sublime_dsl/textmate/theme.rb +364 -0
- data/lib/sublime_dsl/textmate.rb +9 -0
- data/lib/sublime_dsl/tools/blank_slate.rb +49 -0
- data/lib/sublime_dsl/tools/console.rb +74 -0
- data/lib/sublime_dsl/tools/helpers.rb +152 -0
- data/lib/sublime_dsl/tools/regexp_wannabe.rb +154 -0
- data/lib/sublime_dsl/tools/stable_inspect.rb +20 -0
- data/lib/sublime_dsl/tools/value_equality.rb +37 -0
- data/lib/sublime_dsl/tools/xml.rb +66 -0
- data/lib/sublime_dsl/tools.rb +66 -0
- data/lib/sublime_dsl.rb +23 -0
- metadata +145 -0
@@ -0,0 +1,237 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SublimeDSL
|
4
|
+
module SublimeText
|
5
|
+
|
6
|
+
class Menu
|
7
|
+
|
8
|
+
def self.import(file)
|
9
|
+
name = File.basename(file, File.extname(file))
|
10
|
+
set = new(name)
|
11
|
+
list = JSON[File.read(file, encoding: 'utf-8')]
|
12
|
+
set.items.concat list.map { |h| Item.from_json(h) }
|
13
|
+
|
14
|
+
set
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :name, :items
|
18
|
+
|
19
|
+
def initialize(name)
|
20
|
+
@name = name
|
21
|
+
@items = []
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_dsl
|
25
|
+
dsl = "menu #{name.to_source} do\n\n"
|
26
|
+
items.each { |i| dsl << "#{i.to_dsl}\n" }
|
27
|
+
dsl << "\nend"
|
28
|
+
end
|
29
|
+
|
30
|
+
def write(dir)
|
31
|
+
file = "#{dir}/#{name}.menu.rb"
|
32
|
+
File.open(file, 'wb:utf-8') do |f|
|
33
|
+
f.puts '# encoding: utf-8'
|
34
|
+
f.puts "\n#{to_dsl}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def export(dir)
|
39
|
+
file = "#{dir}/#{name}.sublime-menu"
|
40
|
+
File.open(file, 'wb:utf-8') { |f| f.write to_json }
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_json
|
44
|
+
"[\n" <<
|
45
|
+
items.map { |i| i.to_json(' ') }.join(",\n") <<
|
46
|
+
"\n]"
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
class Item
|
51
|
+
|
52
|
+
def self.from_json(json_hash)
|
53
|
+
h = json_hash.dup
|
54
|
+
item = Item.new.tap do |i|
|
55
|
+
i.caption = h.delete('caption')
|
56
|
+
i.mnemonic = h.delete('mnemonic')
|
57
|
+
cmd = h.delete('command')
|
58
|
+
args = h.delete('args')
|
59
|
+
i.command = Command.new(cmd, args) if cmd
|
60
|
+
i.id = h.delete('id')
|
61
|
+
i.checkbox = h.delete('checkbox')
|
62
|
+
i.platform = h.delete('platform')
|
63
|
+
end
|
64
|
+
children = h.delete('children') || []
|
65
|
+
children.each do |c|
|
66
|
+
item.items << Item.from_json(c)
|
67
|
+
end
|
68
|
+
h.empty? or warn "unkown keys ignored: #{h.inspect}"
|
69
|
+
|
70
|
+
item
|
71
|
+
end
|
72
|
+
|
73
|
+
attr_accessor :command, :caption, :mnemonic, :id, :checkbox, :platform
|
74
|
+
attr_reader :items
|
75
|
+
|
76
|
+
def initialize()
|
77
|
+
@command = nil
|
78
|
+
@caption = nil
|
79
|
+
@mnemonic = nil
|
80
|
+
@id = nil
|
81
|
+
@checkbox = nil
|
82
|
+
@platform = nil
|
83
|
+
@items = []
|
84
|
+
end
|
85
|
+
|
86
|
+
def to_dsl(indent = ' ')
|
87
|
+
args = ''
|
88
|
+
options = []
|
89
|
+
|
90
|
+
if caption
|
91
|
+
cap = caption.gsub('&', '&&')
|
92
|
+
if mnemonic
|
93
|
+
if cap =~ /^(.*?)(#{mnemonic})(.*)$/i
|
94
|
+
args << "#{$1}&#{$2}#{$3}".to_source
|
95
|
+
else
|
96
|
+
args << cap.to_source
|
97
|
+
options << "mnemonic: #{mnemonic.to_source}"
|
98
|
+
end
|
99
|
+
else
|
100
|
+
args << cap.to_source
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if command
|
105
|
+
args << ', ' unless args.empty?
|
106
|
+
args << command.to_dsl
|
107
|
+
options << "mnemonic: #{mnemonic.to_source}" if caption.nil? && mnemonic
|
108
|
+
end
|
109
|
+
|
110
|
+
options << "id: #{id.to_source}" if id
|
111
|
+
options << "checkbox: true" if checkbox
|
112
|
+
options << "platform: #{platform.to_source}" if platform
|
113
|
+
|
114
|
+
dsl = "#{indent}item #{args}"
|
115
|
+
unless options.empty?
|
116
|
+
dsl << ', ' unless args.empty?
|
117
|
+
dsl << options.join(', ')
|
118
|
+
end
|
119
|
+
|
120
|
+
unless items.empty?
|
121
|
+
i = indent + ' '
|
122
|
+
dsl << " do\n"
|
123
|
+
items.each do |c|
|
124
|
+
dsl << c.to_dsl(i) << "\n"
|
125
|
+
end
|
126
|
+
dsl << "#{indent}end"
|
127
|
+
end
|
128
|
+
|
129
|
+
dsl
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_h(include_items = true)
|
133
|
+
h = {}
|
134
|
+
h['caption'] = caption if caption
|
135
|
+
h['mnemonic'] = mnemonic if mnemonic
|
136
|
+
h.merge! command.to_h if command
|
137
|
+
h['id'] = id if id
|
138
|
+
h['checkbox'] = checkbox if checkbox
|
139
|
+
h['platform'] = platform if platform
|
140
|
+
h['children'] = items.map(&:to_h) if include_items && !items.empty?
|
141
|
+
h
|
142
|
+
end
|
143
|
+
|
144
|
+
def to_json(indent)
|
145
|
+
return indent + JSON.generate(to_h) if items.empty?
|
146
|
+
json = indent + JSON.pretty_generate(to_h(false))
|
147
|
+
json = json[0..-3] # remove trailing "\n}"
|
148
|
+
json.gsub!("\n", "\n#{indent}")
|
149
|
+
json << %(,\n#{indent} "children": [\n)
|
150
|
+
ind = indent + ' '
|
151
|
+
json << items.map { |i| i.to_json(ind) }.join(",\n")
|
152
|
+
json << "\n#{indent} ]\n#{indent}}"
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
class DSLReader < Tools::BlankSlate
|
159
|
+
|
160
|
+
def initialize(file = nil)
|
161
|
+
@menus = []
|
162
|
+
@item_stack = []
|
163
|
+
instance_eval File.read(file, encoding: 'utf-8'), file if file
|
164
|
+
end
|
165
|
+
|
166
|
+
def _menus
|
167
|
+
@menus
|
168
|
+
end
|
169
|
+
|
170
|
+
def menu(name, &block)
|
171
|
+
@item_stack.empty? or raise Error, "menu blocks cannot be nested"
|
172
|
+
@item_stack.push Menu.new(name)
|
173
|
+
instance_eval(&block)
|
174
|
+
@menus << @item_stack.pop
|
175
|
+
end
|
176
|
+
|
177
|
+
def item(*args, &block)
|
178
|
+
@item_stack.empty? and raise Error, "'item' is invalid outside of a menu block"
|
179
|
+
item = new_item(args)
|
180
|
+
@item_stack.last.items << item
|
181
|
+
return unless block
|
182
|
+
@item_stack.push item
|
183
|
+
instance_eval(&block)
|
184
|
+
@item_stack.pop
|
185
|
+
end
|
186
|
+
|
187
|
+
def method_missing(sym, *args, &block)
|
188
|
+
@item_stack.empty? and raise Error, "'#{sym}' is invalid outside of a menu block"
|
189
|
+
Command.from_method_missing(sym, args)
|
190
|
+
end
|
191
|
+
|
192
|
+
def new_item(args)
|
193
|
+
args.empty? and raise Error, "no argument for 'item'"
|
194
|
+
item = Item.new
|
195
|
+
|
196
|
+
# get the caption if any
|
197
|
+
if args.first.is_a?(String)
|
198
|
+
caption = args.shift
|
199
|
+
caption =~ /&([^& ])/ and item.mnemonic = $1.upcase
|
200
|
+
item.caption = caption.gsub(/&(.)/, '\1')
|
201
|
+
return item if args.empty?
|
202
|
+
end
|
203
|
+
|
204
|
+
# get the command if any
|
205
|
+
cmd = args.first
|
206
|
+
if cmd.is_a?(Command)
|
207
|
+
cmd.error and raise Error, "item '#{caption}': #{cmd.error}"
|
208
|
+
item.command = cmd
|
209
|
+
args.shift
|
210
|
+
return item if args.empty?
|
211
|
+
end
|
212
|
+
|
213
|
+
# options
|
214
|
+
options = args.first
|
215
|
+
args.length == 1 && options.is_a?(Hash) or
|
216
|
+
raise Error, "invalid arguments for 'item': #{args.inspect}"
|
217
|
+
|
218
|
+
item.id = options.delete(:id)
|
219
|
+
item.checkbox = options.delete(:checkbox)
|
220
|
+
item.platform = options.delete(:platform)
|
221
|
+
mnemonic = options.delete(:mnemonic)
|
222
|
+
if mnemonic
|
223
|
+
item.mnemonic && mnemonic != item.mnemonic and
|
224
|
+
warn "item '#{caption}': mnemonic #{item.mnemonic} overwritten by #{mnemonic}"
|
225
|
+
item.mnemonic = mnemonic
|
226
|
+
end
|
227
|
+
|
228
|
+
item
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SublimeDSL
|
4
|
+
module SublimeText
|
5
|
+
|
6
|
+
class Mouse
|
7
|
+
|
8
|
+
def self.sublime
|
9
|
+
@sublime ||= create_sublime_mouse
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create_sublime_mouse
|
13
|
+
mouse = new('Sublime Text')
|
14
|
+
(1..9).each { |i| mouse.add_button "button#{i}" }
|
15
|
+
mouse.add_button "scroll_up"
|
16
|
+
mouse.add_button "scroll_down"
|
17
|
+
%w(shift ctrl alt super).each { |m| mouse.add_modifier m }
|
18
|
+
mouse.modifiers.concat mouse.buttons
|
19
|
+
mouse
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :name, :buttons, :modifiers
|
23
|
+
|
24
|
+
def initialize(name)
|
25
|
+
@name = name
|
26
|
+
@buttons = []
|
27
|
+
@modifiers = []
|
28
|
+
@clicks = []
|
29
|
+
end
|
30
|
+
|
31
|
+
alias to_s name
|
32
|
+
|
33
|
+
def clone(name)
|
34
|
+
clone = Mouse.new(name)
|
35
|
+
buttons.each { |b| clone.add_button b.st_name, b.name }
|
36
|
+
(modifiers - buttons).each { |m| clone.add_modifier m.st_name, m.name }
|
37
|
+
clone.modifiers.concat clone.buttons
|
38
|
+
clone
|
39
|
+
end
|
40
|
+
|
41
|
+
def button(name)
|
42
|
+
buttons.find { |b| b.name == name }
|
43
|
+
end
|
44
|
+
|
45
|
+
def modifier(name)
|
46
|
+
modifiers.find { |b| b.name == name }
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_button(st_name, name = nil)
|
50
|
+
@buttons << Button.new(st_name, name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_modifier(st_name, name = nil)
|
54
|
+
@modifiers << Button.new(st_name, name)
|
55
|
+
end
|
56
|
+
|
57
|
+
def clicks_hash
|
58
|
+
@clicks_hash ||= {}
|
59
|
+
end
|
60
|
+
|
61
|
+
def modifiers_index_hash
|
62
|
+
@modifiers_index_hash ||= begin
|
63
|
+
h = {}
|
64
|
+
modifiers.each_with_index { |b,i| h[b.name] = i }
|
65
|
+
h
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def ensure_click(spec)
|
70
|
+
*modifier_names, button_name = spec.split('+')
|
71
|
+
|
72
|
+
button = button(button_name) or
|
73
|
+
raise Error, "invalid button #{button_name.inspect}"
|
74
|
+
|
75
|
+
# check & reorder the modifiers
|
76
|
+
unless modifier_names.empty?
|
77
|
+
sorted = []
|
78
|
+
modifier_names.each do |name|
|
79
|
+
i = modifiers_index_hash[name]
|
80
|
+
i or raise Error, "invalid modifier #{name.inspect}"
|
81
|
+
sorted[i] = name
|
82
|
+
end
|
83
|
+
modifier_names = sorted.compact
|
84
|
+
end
|
85
|
+
|
86
|
+
# if there is a registered click for this spec, return it
|
87
|
+
std_spec = [*modifier_names, button_name].join('+')
|
88
|
+
click = clicks_hash[std_spec]
|
89
|
+
return click if click
|
90
|
+
|
91
|
+
# can't have the button in the modifiers
|
92
|
+
modifier_names.include?(button_name) and
|
93
|
+
raise Error, "can't have the button in the modifiers: #{spec.inspect}"
|
94
|
+
|
95
|
+
# create and register the click
|
96
|
+
modifiers = modifier_names.map { |n| modifier(n) }
|
97
|
+
click = Click.new(modifiers, button)
|
98
|
+
clicks_hash[click.to_spec] = click
|
99
|
+
|
100
|
+
click
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
##
|
105
|
+
# A mouse button or modifier.
|
106
|
+
|
107
|
+
class Button
|
108
|
+
|
109
|
+
attr_reader :st_name
|
110
|
+
attr_accessor :name
|
111
|
+
|
112
|
+
def initialize(st_name, name)
|
113
|
+
@st_name = st_name
|
114
|
+
@name = name || st_name
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
##
|
121
|
+
# A mouse click: button + modifiers.
|
122
|
+
|
123
|
+
class Click
|
124
|
+
|
125
|
+
attr_reader :button, :modifiers
|
126
|
+
|
127
|
+
def initialize(modifiers, button)
|
128
|
+
@modifiers = modifiers
|
129
|
+
@button = button
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_spec
|
133
|
+
[*modifiers.map(&:name), button.name].join('+')
|
134
|
+
end
|
135
|
+
|
136
|
+
alias to_s to_spec
|
137
|
+
|
138
|
+
def to_h
|
139
|
+
h = { 'button' => button.st_name }
|
140
|
+
h['modifiers'] = modifiers.map(&:st_name) unless modifiers.empty?
|
141
|
+
h
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SublimeDSL
|
4
|
+
module SublimeText
|
5
|
+
|
6
|
+
class MouseMap
|
7
|
+
|
8
|
+
def self.import(file)
|
9
|
+
name = File.basename(file, File.extname(file))
|
10
|
+
map = new(name)
|
11
|
+
list = JSON[File.read(file, encoding: 'utf-8')]
|
12
|
+
begin
|
13
|
+
map.bindings.concat list.map { |h| MouseBinding.from_json(h) }
|
14
|
+
rescue => ex
|
15
|
+
puts "file: #{file}"
|
16
|
+
raise ex
|
17
|
+
end
|
18
|
+
|
19
|
+
map
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :name, :bindings
|
23
|
+
|
24
|
+
def initialize(name)
|
25
|
+
@name = name
|
26
|
+
@bindings = []
|
27
|
+
end
|
28
|
+
|
29
|
+
def write(dir)
|
30
|
+
file = "#{dir}/#{name}.mousemap.rb"
|
31
|
+
File.open(file, 'wb') do |f|
|
32
|
+
f.puts "\nmousemap #{name.to_source} do"
|
33
|
+
f.puts
|
34
|
+
bindings.each do |b|
|
35
|
+
begin
|
36
|
+
f.puts ' ' << b.to_dsl
|
37
|
+
rescue => ex
|
38
|
+
puts "file: #{file}\nbinding: #{b.click}"
|
39
|
+
raise ex
|
40
|
+
end
|
41
|
+
end
|
42
|
+
f.puts "\nend"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def export(dir)
|
47
|
+
file = "#{dir}/#{name}.sublime-mousemap"
|
48
|
+
File.open(file, 'wb:utf-8') { |f| f.write to_json }
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_json
|
52
|
+
"[\n" <<
|
53
|
+
bindings.map { |b| JSON.generate(b.to_h) }.join(",\n").indent(2) <<
|
54
|
+
"\n]"
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
##
|
59
|
+
# A mouse binding: a click with its command(s).
|
60
|
+
|
61
|
+
class MouseBinding
|
62
|
+
|
63
|
+
def self.from_json(json_hash)
|
64
|
+
h = json_hash.dup
|
65
|
+
|
66
|
+
button = h.delete('button') or raise Error, 'no button: ' << json_hash.inspect
|
67
|
+
modifiers = h.delete('modifiers')
|
68
|
+
spec = [*modifiers, button].join('+')
|
69
|
+
click = Mouse.sublime.ensure_click(spec)
|
70
|
+
|
71
|
+
count = h.delete('count')
|
72
|
+
count = count.to_i if count
|
73
|
+
|
74
|
+
press = h.delete('press_command')
|
75
|
+
press_command = press ? Command.new(press, h.delete('press_args')) : nil
|
76
|
+
|
77
|
+
cmd = h.delete('command')
|
78
|
+
command = cmd ? Command.new(cmd, h.delete('args')) : nil
|
79
|
+
|
80
|
+
h.empty? or raise Error, 'unexpected JSON keys: ' << h.inspect
|
81
|
+
new(click, count, press_command, command)
|
82
|
+
|
83
|
+
rescue => ex
|
84
|
+
warn "error with binding #{json_hash.inspect}"
|
85
|
+
warn ex.message
|
86
|
+
raise
|
87
|
+
end
|
88
|
+
|
89
|
+
attr_reader :click, :count, :press_command, :command
|
90
|
+
attr_accessor :source_file
|
91
|
+
|
92
|
+
def initialize(click, count, press_command, command)
|
93
|
+
@click = click
|
94
|
+
@count = count
|
95
|
+
@press_command = press_command
|
96
|
+
@command = command
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_dsl
|
100
|
+
spec = click.to_spec
|
101
|
+
dsl = "click#{count} #{spec.to_source}"
|
102
|
+
dsl << ", down: #{press_command.to_dsl}" if press_command
|
103
|
+
dsl << ", up: #{command.to_dsl}" if command
|
104
|
+
|
105
|
+
dsl
|
106
|
+
end
|
107
|
+
|
108
|
+
def to_h
|
109
|
+
h = click.to_h
|
110
|
+
h['count'] = count if count
|
111
|
+
h.merge! press_command.to_h('press_command', 'press_args') if press_command
|
112
|
+
h.merge! command.to_h if command
|
113
|
+
h
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
class DSLReader < Tools::BlankSlate
|
120
|
+
|
121
|
+
def initialize(file = nil)
|
122
|
+
@mousemaps = []
|
123
|
+
@current_map = nil
|
124
|
+
@mouse = Mouse.sublime
|
125
|
+
instance_eval File.read(file, encoding: 'utf-8'), file if file
|
126
|
+
end
|
127
|
+
|
128
|
+
def _mousemaps
|
129
|
+
@mousemaps
|
130
|
+
end
|
131
|
+
|
132
|
+
def mousemap(name, &block)
|
133
|
+
@current_map and raise Error, "'mousemap' blocks cannot be nested"
|
134
|
+
@current_map = MouseMap.new(name)
|
135
|
+
instance_eval(&block)
|
136
|
+
@mousemaps << @current_map
|
137
|
+
@current_map = nil
|
138
|
+
end
|
139
|
+
|
140
|
+
def button_names(maps={})
|
141
|
+
# create a copy of the Sublime mouse
|
142
|
+
@mouse = Mouse.sublime.clone('Custom Names')
|
143
|
+
maps.each_pair do |name, st_name|
|
144
|
+
b = @mouse.modifier(st_name) or
|
145
|
+
raise Error, "no button nor modifier named '#{st_name}'"
|
146
|
+
b.name = name
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def click1(spec, options={})
|
151
|
+
click spec, options.merge({ count: 1 })
|
152
|
+
end
|
153
|
+
|
154
|
+
def click2(spec, options={})
|
155
|
+
click spec, options.merge({ count: 2 })
|
156
|
+
end
|
157
|
+
|
158
|
+
def click3(spec, options={})
|
159
|
+
click spec, options.merge({ count: 3 })
|
160
|
+
end
|
161
|
+
|
162
|
+
def click(spec, options={})
|
163
|
+
@current_map or raise Error, "'click' is invalid outside of a 'mousemap' block"
|
164
|
+
click = @mouse.ensure_click(spec)
|
165
|
+
count = options.delete(:count)
|
166
|
+
press_cmd = options.delete(:down)
|
167
|
+
press_cmd && press_cmd.error and raise Error, "click '#{spec}':#{press_cmd.error}"
|
168
|
+
cmd = options.delete(:up)
|
169
|
+
cmd && cmd.error and raise Error, "click '#{spec}':#{cmd.error}"
|
170
|
+
press_cmd || cmd or
|
171
|
+
raise Error, "click '#{spec}': no 'up' nor 'down' command"
|
172
|
+
@current_map.bindings << MouseBinding.new(click, count, press_cmd, cmd)
|
173
|
+
end
|
174
|
+
|
175
|
+
def method_missing(sym, *args, &block)
|
176
|
+
@current_map or raise Error, "'#{sym}' is invalid outside of a 'mousemap' block"
|
177
|
+
Command.from_method_missing(sym, args)
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SublimeDSL
|
4
|
+
module SublimeText
|
5
|
+
class Package
|
6
|
+
|
7
|
+
##
|
8
|
+
# 'Universal' DSL reader: reads any DSL block and updates its package.
|
9
|
+
|
10
|
+
class DSLReader
|
11
|
+
|
12
|
+
def initialize(file, package)
|
13
|
+
@file = file
|
14
|
+
@package = package
|
15
|
+
instance_eval File.read(file, encoding: 'utf-8'), file
|
16
|
+
end
|
17
|
+
|
18
|
+
def method_missing(sym, *args, &block)
|
19
|
+
raise DSLError, "'#{sym}' is not a valid Package DSL statement"
|
20
|
+
end
|
21
|
+
|
22
|
+
def theme(*args, &block)
|
23
|
+
r = TextMate::Theme::DSLReader.new
|
24
|
+
r.theme(*args, &block)
|
25
|
+
@package.themes.concat r._themes
|
26
|
+
end
|
27
|
+
|
28
|
+
def language(*args, &block)
|
29
|
+
r = TextMate::Grammar::DSLReader.new
|
30
|
+
r.language(*args, &block)
|
31
|
+
@package.grammars.concat r._grammars
|
32
|
+
end
|
33
|
+
|
34
|
+
def preferences(*args, &block)
|
35
|
+
r = TextMate::Preference::DSLReader.new
|
36
|
+
r.preferences(*args, &block)
|
37
|
+
@package.preferences.concat r._preferences
|
38
|
+
end
|
39
|
+
|
40
|
+
def snippets(*args, &block)
|
41
|
+
r = TextMate::Snippet::DSLReader.new
|
42
|
+
r.snippets(*args, &block)
|
43
|
+
@package.snippets.concat r._snippets
|
44
|
+
end
|
45
|
+
|
46
|
+
def settings(*args, &block)
|
47
|
+
r = SettingSet::DSLReader.new
|
48
|
+
r.settings(*args, &block)
|
49
|
+
@package.setting_sets.concat r._setting_sets
|
50
|
+
end
|
51
|
+
|
52
|
+
def macro(*args, &block)
|
53
|
+
r = Macro::DSLReader.new
|
54
|
+
r.macro(*args, &block)
|
55
|
+
@package.macros.concat r._macros
|
56
|
+
end
|
57
|
+
|
58
|
+
def commands(*args, &block)
|
59
|
+
r = CommandSet::DSLReader.new
|
60
|
+
r.commands(*args, &block)
|
61
|
+
@package.command_sets.concat r._command_sets
|
62
|
+
end
|
63
|
+
|
64
|
+
def menu(*args, &block)
|
65
|
+
r = Menu::DSLReader.new
|
66
|
+
r.menu(*args, &block)
|
67
|
+
@package.menus.concat r._menus
|
68
|
+
end
|
69
|
+
|
70
|
+
def mousemap(*args, &block)
|
71
|
+
r = MouseMap::DSLReader.new
|
72
|
+
r.mousemap(*args, &block)
|
73
|
+
@package.mousemaps.concat r._mousemaps
|
74
|
+
end
|
75
|
+
|
76
|
+
def keymap(*args, &block)
|
77
|
+
r = KeyMap::DSLReader.new
|
78
|
+
r._file = @file
|
79
|
+
r.keymap(*args, &block)
|
80
|
+
@package.keymaps.concat r._keymaps
|
81
|
+
end
|
82
|
+
|
83
|
+
def keyboard(*args, &block)
|
84
|
+
raise Error, "keyboards must be defined in a separate *.keyboard.rb file"
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|