sublime_dsl 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|