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,157 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SublimeDSL
|
4
|
+
module SublimeText
|
5
|
+
|
6
|
+
##
|
7
|
+
# A command.
|
8
|
+
|
9
|
+
class Command
|
10
|
+
|
11
|
+
def self.from_method_missing(sym, args)
|
12
|
+
method = sublime_method(sym.to_s)
|
13
|
+
last_word = method.split('_').last
|
14
|
+
case args.length
|
15
|
+
when 0
|
16
|
+
when 1
|
17
|
+
args = args.first.is_a?(Hash) ? args.first : { last_word => args.first }
|
18
|
+
when 2
|
19
|
+
args.last.is_a?(Hash) or
|
20
|
+
return new(sym, args, "invalid arguments to #{method}: #{cmd.args.inspect}")
|
21
|
+
args = { last_word => args.first }.merge(args.last)
|
22
|
+
else
|
23
|
+
return new(sym, args, "invalid arguments to #{method}: #{cmd.args.inspect}")
|
24
|
+
end
|
25
|
+
new(method, args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.dsl_method(name)
|
29
|
+
if ruby_keyword_hash[name]
|
30
|
+
'_' << name
|
31
|
+
elsif name.start_with?('$')
|
32
|
+
'_dollar_' << name[1..-1]
|
33
|
+
else
|
34
|
+
name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.sublime_method(name)
|
39
|
+
return name unless name.start_with?('_')
|
40
|
+
m = name[1..-1]
|
41
|
+
if m.start_with?('dollar_')
|
42
|
+
'$' << m[7..-1]
|
43
|
+
elsif ruby_keyword_hash[m]
|
44
|
+
m
|
45
|
+
else
|
46
|
+
name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.ruby_keyword_hash
|
51
|
+
@ruby_keyword_hash ||= Hash[
|
52
|
+
%w(
|
53
|
+
alias and BEGIN begin break case class def defined? do
|
54
|
+
else elsif END end ensure false for if in module
|
55
|
+
next nil not or redo rescue retry return self super
|
56
|
+
then true undef unless until when while yield
|
57
|
+
).map { |w| [w, true] }
|
58
|
+
]
|
59
|
+
end
|
60
|
+
|
61
|
+
attr_reader :name, :args, :error
|
62
|
+
|
63
|
+
def initialize(name, args, error = nil)
|
64
|
+
@name = name
|
65
|
+
@args =
|
66
|
+
if error
|
67
|
+
args
|
68
|
+
else
|
69
|
+
args ? args.to_a.map { |n,v| Argument.new(n,v) } : []
|
70
|
+
end
|
71
|
+
@error = error
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_h(command_key = 'command', args_key = 'args')
|
75
|
+
if args.empty?
|
76
|
+
{ command_key => name }
|
77
|
+
else
|
78
|
+
args_hash = {}
|
79
|
+
args.each { |a| args_hash[a.name] = a.value }
|
80
|
+
{ command_key => name, args_key => args_hash }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_dsl(statement_style = false)
|
85
|
+
method = Command.dsl_method(name)
|
86
|
+
return method if args.empty?
|
87
|
+
last = name.split('_').last
|
88
|
+
if last == args.first.name
|
89
|
+
arg_list = args.first.to_s(false)
|
90
|
+
arg_list << ', ' << args[1..-1].map(&:to_s).join(', ') if args.length > 1
|
91
|
+
else
|
92
|
+
arg_list = args.map(&:to_s).join(', ')
|
93
|
+
end
|
94
|
+
statement_style ? "#{method} #{arg_list}" : "#{method}(#{arg_list})"
|
95
|
+
end
|
96
|
+
|
97
|
+
alias to_s to_dsl
|
98
|
+
|
99
|
+
include Tools::ValueEquality
|
100
|
+
|
101
|
+
##
|
102
|
+
# A command argument.
|
103
|
+
|
104
|
+
class Argument
|
105
|
+
|
106
|
+
attr_reader :name, :value
|
107
|
+
|
108
|
+
def initialize(name, value)
|
109
|
+
@name = name
|
110
|
+
@value = value
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_s(hash_style = true)
|
114
|
+
if hash_style
|
115
|
+
"#{name}: #{display(value)}"
|
116
|
+
else
|
117
|
+
display(value)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
include Tools::ValueEquality
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def display(v)
|
126
|
+
case v
|
127
|
+
when String
|
128
|
+
v.inspect
|
129
|
+
when TrueClass, FalseClass, Numeric
|
130
|
+
v.to_s
|
131
|
+
when Array
|
132
|
+
display_array(v)
|
133
|
+
when Hash
|
134
|
+
v.inspect
|
135
|
+
when NilClass
|
136
|
+
'nil'
|
137
|
+
else
|
138
|
+
raise Error, "command argument #{name.inspect} value: #{v.inspect}"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def display_array(a)
|
143
|
+
if a.empty?
|
144
|
+
'[]'
|
145
|
+
elsif a.all? { |e| e.is_a?(String) && e =~ /\A(\S+)\z/ }
|
146
|
+
"%w(#{a.join(' ')})"
|
147
|
+
else
|
148
|
+
a.inspect
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module SublimeDSL
|
4
|
+
module SublimeText
|
5
|
+
|
6
|
+
class CommandSet
|
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
|
+
begin
|
13
|
+
set.items.concat list.map { |h| Item.from_json(h) }
|
14
|
+
rescue => ex
|
15
|
+
Console.error "file: #{file}"
|
16
|
+
raise ex
|
17
|
+
end
|
18
|
+
set
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :name, :items
|
22
|
+
|
23
|
+
def initialize(name)
|
24
|
+
@name = name
|
25
|
+
@items = []
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_dsl
|
29
|
+
dsl = "commands #{name.to_source} do\n\n"
|
30
|
+
items.each { |i| dsl << " #{i.to_dsl}\n" }
|
31
|
+
dsl << "\nend"
|
32
|
+
end
|
33
|
+
|
34
|
+
def export(dir)
|
35
|
+
file = "#{dir}/#{name}.sublime-commands"
|
36
|
+
File.open(file, 'wb:utf-8') { |f| f.write to_json }
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_json
|
40
|
+
"[\n" <<
|
41
|
+
items.map { |i| JSON.generate(i.to_h) }.join(",\n").indent(2) <<
|
42
|
+
"\n]"
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
class Item
|
47
|
+
|
48
|
+
def self.from_json(json_hash)
|
49
|
+
h = json_hash.dup
|
50
|
+
cap = h.delete('caption') or raise Error, "no caption: #{json_hash.inspect}"
|
51
|
+
cmd = h.delete('command') or raise Error, "no command: #{json_hash.inspect}"
|
52
|
+
args = h.delete('args')
|
53
|
+
h.empty? or warn "unkown keys ignored: #{h.inspect}"
|
54
|
+
new(cap, Command.new(cmd, args))
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :caption, :command
|
58
|
+
|
59
|
+
def initialize(caption, command)
|
60
|
+
@caption = caption
|
61
|
+
@command = command
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_dsl
|
65
|
+
"item #{caption.to_source}, #{command.to_dsl}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_h
|
69
|
+
{ 'caption' => caption }.merge(command.to_h)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
class DSLReader < Tools::BlankSlate
|
76
|
+
|
77
|
+
def initialize(file = nil)
|
78
|
+
@command_sets = []
|
79
|
+
@current_set = nil
|
80
|
+
instance_eval File.read(file, encoding: 'utf-8'), file if file
|
81
|
+
end
|
82
|
+
|
83
|
+
def _command_sets
|
84
|
+
@command_sets
|
85
|
+
end
|
86
|
+
|
87
|
+
def commands(name, &block)
|
88
|
+
@current_set and raise Error, "'commands' blocks cannot be nested"
|
89
|
+
@current_set = CommandSet.new(name)
|
90
|
+
instance_eval(&block)
|
91
|
+
@command_sets << @current_set
|
92
|
+
@current_set = nil
|
93
|
+
end
|
94
|
+
|
95
|
+
def item(caption, cmd)
|
96
|
+
@current_set or raise Error, "'item' is invalid outside of a 'commands' block"
|
97
|
+
cmd.error and raise Error, "item '#{caption}': #{cmd.error}"
|
98
|
+
@current_set.items << Item.new(caption, cmd)
|
99
|
+
end
|
100
|
+
|
101
|
+
def method_missing(sym, *args, &block)
|
102
|
+
@current_set or raise Error, "'#{sym}' is invalid outside of a 'commands' block"
|
103
|
+
Command.from_method_missing(sym, args)
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|