sublime_dsl 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +136 -0
  3. data/Rakefile +248 -0
  4. data/SYNTAX.md +927 -0
  5. data/bin/subdsl +4 -0
  6. data/lib/sublime_dsl/cli/export.rb +134 -0
  7. data/lib/sublime_dsl/cli/import.rb +143 -0
  8. data/lib/sublime_dsl/cli.rb +125 -0
  9. data/lib/sublime_dsl/core_ext/enumerable.rb +24 -0
  10. data/lib/sublime_dsl/core_ext/string.rb +129 -0
  11. data/lib/sublime_dsl/core_ext.rb +4 -0
  12. data/lib/sublime_dsl/sublime_text/command.rb +157 -0
  13. data/lib/sublime_dsl/sublime_text/command_set.rb +112 -0
  14. data/lib/sublime_dsl/sublime_text/keyboard.rb +659 -0
  15. data/lib/sublime_dsl/sublime_text/keymap/dsl_reader.rb +194 -0
  16. data/lib/sublime_dsl/sublime_text/keymap.rb +385 -0
  17. data/lib/sublime_dsl/sublime_text/macro.rb +91 -0
  18. data/lib/sublime_dsl/sublime_text/menu.rb +237 -0
  19. data/lib/sublime_dsl/sublime_text/mouse.rb +149 -0
  20. data/lib/sublime_dsl/sublime_text/mousemap.rb +185 -0
  21. data/lib/sublime_dsl/sublime_text/package/dsl_reader.rb +91 -0
  22. data/lib/sublime_dsl/sublime_text/package/exporter.rb +138 -0
  23. data/lib/sublime_dsl/sublime_text/package/importer.rb +127 -0
  24. data/lib/sublime_dsl/sublime_text/package/reader.rb +102 -0
  25. data/lib/sublime_dsl/sublime_text/package/writer.rb +112 -0
  26. data/lib/sublime_dsl/sublime_text/package.rb +96 -0
  27. data/lib/sublime_dsl/sublime_text/setting_set.rb +123 -0
  28. data/lib/sublime_dsl/sublime_text.rb +48 -0
  29. data/lib/sublime_dsl/textmate/custom_base_name.rb +45 -0
  30. data/lib/sublime_dsl/textmate/grammar/dsl_reader.rb +383 -0
  31. data/lib/sublime_dsl/textmate/grammar/dsl_writer.rb +178 -0
  32. data/lib/sublime_dsl/textmate/grammar/plist_reader.rb +163 -0
  33. data/lib/sublime_dsl/textmate/grammar/plist_writer.rb +153 -0
  34. data/lib/sublime_dsl/textmate/grammar.rb +252 -0
  35. data/lib/sublime_dsl/textmate/plist.rb +141 -0
  36. data/lib/sublime_dsl/textmate/preference.rb +301 -0
  37. data/lib/sublime_dsl/textmate/snippet.rb +437 -0
  38. data/lib/sublime_dsl/textmate/theme/dsl_reader.rb +87 -0
  39. data/lib/sublime_dsl/textmate/theme/item.rb +74 -0
  40. data/lib/sublime_dsl/textmate/theme/plist_writer.rb +53 -0
  41. data/lib/sublime_dsl/textmate/theme.rb +364 -0
  42. data/lib/sublime_dsl/textmate.rb +9 -0
  43. data/lib/sublime_dsl/tools/blank_slate.rb +49 -0
  44. data/lib/sublime_dsl/tools/console.rb +74 -0
  45. data/lib/sublime_dsl/tools/helpers.rb +152 -0
  46. data/lib/sublime_dsl/tools/regexp_wannabe.rb +154 -0
  47. data/lib/sublime_dsl/tools/stable_inspect.rb +20 -0
  48. data/lib/sublime_dsl/tools/value_equality.rb +37 -0
  49. data/lib/sublime_dsl/tools/xml.rb +66 -0
  50. data/lib/sublime_dsl/tools.rb +66 -0
  51. data/lib/sublime_dsl.rb +23 -0
  52. metadata +145 -0
@@ -0,0 +1,154 @@
1
+ # encoding: utf-8
2
+
3
+ module SublimeDSL
4
+ module Tools
5
+
6
+ ##
7
+ # A string that would like to be a Regexp.
8
+ # May contain back-references to another RegexpWannabe,
9
+ # stored as '§1', '§2', etc.
10
+
11
+ class RegexpWannabe
12
+
13
+ attr_reader :source
14
+ attr_reader :regexp # may be nil if error
15
+ attr_reader :backref
16
+ attr_reader :error
17
+ attr_reader :warnings
18
+
19
+ # FIXME: warnings ignored in JSON DSLs
20
+
21
+ # FIXME: 3 possible sources: PList, JSON, Ruby Regexp
22
+ # - when from PList, the current way of doing things seems ok
23
+ # - when from JSON, \t & \n should be converted to \\t and \\n
24
+ # and back to \t & \n on output (they don't use (?x))
25
+ # - when from Ruby, source should not be altered on input,
26
+ # but the output depends on JSON vs PList
27
+
28
+ def initialize(source, backref = nil)
29
+ # encode in utf-8, remove escaped newlines
30
+ @source = source.encode('utf-8').gsub(/(^|[^\\](\\\\)*+)\\\n/, '\1')
31
+ @backref = backref
32
+ @regexp = nil
33
+ @error = nil
34
+ @warnings = []
35
+ try_conversion
36
+ @error = message_only(@error) if @error
37
+ @source.gsub!("\t", " ") if extended?
38
+ end
39
+
40
+ # Returns the ruby syntax.
41
+ #
42
+ # If #source contains a '/', tries to return an r-form <tt>%r'...'</tt> or <tt>%r:...:</tt> or
43
+ # <tt>%r!...!</tt>. If it does not, or if the #source contains all 3 characters <tt>':!</tt>,
44
+ # return <tt>/.../</tt> if +rform+ is false (the default), or <tt>%r/.../</tt> if +rform+ is
45
+ # true. (The latter syntax avoids warnings when the regexp is the first argument to a method
46
+ # and parentheses are not used around arguments.)
47
+
48
+ def inspect(rform = false)
49
+ str = extended? ? source : source.gsub("\t", '\t').gsub("\n", '\n')
50
+ s = rform ? '%r' : ''
51
+ return "#{s}/#{str}/" unless str.include?('/')
52
+ %w(' : !).each { |c| return "%r#{c}#{str}#{c}" unless str.include?(c) }
53
+ # replace / with \/ unless already escaped
54
+ escaped = str.gsub( %r"(^|[^\\](\\\\)*+)(?=/)", '\1\\')
55
+ "#{s}/#{escaped}/"
56
+ end
57
+
58
+ # Returns the string syntax.
59
+ # * If +json+ == false, the string is suitable for PList.
60
+ # * If +json+ == true, the string is suitable for JSON output with String#inspect.
61
+
62
+ def to_s(for_json = false)
63
+ if regexp
64
+ # remove \/ escapes
65
+ str = regexp.source.gsub( %r"(^|[^\\](\\\\)*+)\\(?=/)", '\1')
66
+ str = str.gsub("\t", '\t').gsub("\n", '\n') unless extended?
67
+ if for_json
68
+ str.gsub!( %r"(^|[^\\](\\\\)*+)\\n", "\\1\n")
69
+ str.gsub!( %r"(^|[^\\](\\\\)*+)\\t", "\\1\t")
70
+ end
71
+ else
72
+ str = source
73
+ end
74
+ str.gsub(/§(?=[1-9])/, '\\')
75
+ end
76
+
77
+ # Returns an array of fixme comments.
78
+ def fixmes
79
+ comments = []
80
+ error and
81
+ comments << "# FIXME: (error) #{error}"
82
+ source =~ /#[@${]/ and
83
+ comments << "# FIXME: (error) '#$&' will be interpreted as interpolation: escape '#' as '\\#'"
84
+ comments.concat warnings.map { |w| "# FIXME: (warning) #{w}" }
85
+ comments
86
+ end
87
+
88
+ # Returns the fixme comments for this regexp.
89
+ # If no fixme, returns an empty string.
90
+
91
+ def fixme_comments(indent = ' ')
92
+ fixmes.map { |c| "#{indent}#{c}\n" }.join
93
+ end
94
+
95
+ private
96
+
97
+ def extended?
98
+ source =~ /\(\?[im]*x(:|[-im]*\))/
99
+ end
100
+
101
+ def try_conversion
102
+ @warnings = capture_warnings { @regexp = Regexp.new(source) }
103
+ @backref = nil unless source =~ /§[1-9]/
104
+ rescue RegexpError => ex
105
+ msg = ex.message
106
+ unless backref && msg =~ /^invalid backref|^invalid pattern in look-behind/
107
+ @error = msg
108
+ return
109
+ end
110
+
111
+ if backref.error
112
+ warnings << 'contains references to a Regexp with an error'
113
+ return
114
+ end
115
+
116
+ # replace \n with §n (but \\n remains \\n, while \\\n => \\§n, etc.)
117
+ source.gsub!(/((^|[^\\])(\\\\)*)\\(?=[1-9])/, '\1§')
118
+
119
+ unless backref.warnings.empty?
120
+ warnings << 'contains references to a Regexp with warning(s)'
121
+ return
122
+ end
123
+
124
+ begin
125
+ @warnings = capture_warnings { @regexp = Regexp.new(source) }
126
+ rescue RegexpError => ex
127
+ @error = ex.message
128
+ end
129
+ end
130
+
131
+ def capture_warnings
132
+ prev_verbose, $VERBOSE = $VERBOSE, 2
133
+ prev_stderr, $stderr = $stderr, StringIO.new('', 'wb:utf-8')
134
+ yield
135
+ msg = $stderr.string
136
+ msg.lines.grep(/ warning: /).map do |line|
137
+ line = line[/.*? warning: (.*)/, 1]
138
+ message_only(line)
139
+ end
140
+ ensure
141
+ $stderr = prev_stderr
142
+ $VERBOSE = prev_verbose
143
+ end
144
+
145
+ def message_only(msg)
146
+ line = msg.lines.first.strip
147
+ line =~ /(.*?):/ and line = $1.strip
148
+ line
149
+ end
150
+
151
+ end
152
+
153
+ end
154
+ end
@@ -0,0 +1,20 @@
1
+
2
+ module SublimeDSL
3
+ module Tools
4
+
5
+ ##
6
+ # A mix-in redefining #inspect so that it does not depend on #to_s.
7
+
8
+ module StableInspect
9
+
10
+ # Method not calling #to_s, and producing the standard #inspect output.
11
+ def inspect
12
+ '#<' << self.class.name << ':0x' << '%x' % (object_id << 1) <<
13
+ instance_variables.map { |v| " #{v}=#{instance_variable_get(v).inspect}" }.join(',') <<
14
+ '>'
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+
2
+ module SublimeDSL
3
+ module Tools
4
+
5
+ ##
6
+ # A mix-in allowing to compare objects based on value rather than identity.
7
+ #
8
+ # It redefines #eql?, #hash and #== based on a #value_id method, and
9
+ # provides a default implementation for #value_id.
10
+
11
+ module ValueEquality
12
+
13
+ # Returns true if the class of +other+ is the same or a subclass of +self.class+,
14
+ # and #value_id are the same using "==".
15
+
16
+ def eql?(other)
17
+ other.is_a?(self.class) && other.value_id == self.value_id
18
+ end
19
+
20
+ alias == eql?
21
+
22
+ # Returns #hash for #value_id.
23
+
24
+ def hash
25
+ value_id.hash
26
+ end
27
+
28
+ # Default value identity: array of instance variable values.
29
+
30
+ def value_id
31
+ instance_variables.map { |v| instance_variable_get(v) }
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+
3
+ module SublimeDSL
4
+ module Tools
5
+
6
+ ##
7
+ # Tools to process XML.
8
+
9
+ module XML
10
+
11
+ # Regexp matching forbidden control characters.
12
+ FORBIDDEN_CHARS_RE = /[\x00-\x08\x0b\x0c\x0e-\x1f]/
13
+
14
+ # Hash { 'forbidden character' => 'abbreviation' }.
15
+ FORBIDDEN_CHARS_MAP = {
16
+ "\x00" => 'NUL',
17
+ "\x01" => 'SOH',
18
+ "\x02" => 'STX',
19
+ "\x03" => 'ETX',
20
+ "\x04" => 'EOT',
21
+ "\x05" => 'ENQ',
22
+ "\x06" => 'ACK',
23
+ "\x07" => 'BEL',
24
+ "\x08" => 'BS',
25
+ # "\x09" => 'HT',
26
+ # "\x0a" => 'LF',
27
+ "\x0b" => 'VT',
28
+ "\x0c" => 'FF',
29
+ # "\x0d" => 'CR',
30
+ "\x0e" => 'SO',
31
+ "\x0f" => 'SI',
32
+ "\x10" => 'DLE',
33
+ "\x11" => 'DC1',
34
+ "\x12" => 'DC2',
35
+ "\x13" => 'DC3',
36
+ "\x14" => 'DC4',
37
+ "\x15" => 'NAK',
38
+ "\x16" => 'SYN',
39
+ "\x17" => 'ETB',
40
+ "\x18" => 'CAN',
41
+ "\x19" => 'EM',
42
+ "\x1a" => 'SUB',
43
+ "\x1b" => 'ESC',
44
+ "\x1c" => 'FS',
45
+ "\x1d" => 'GS',
46
+ "\x1e" => 'RS',
47
+ "\x1f" => 'US'
48
+ }
49
+
50
+ # Returns a Nokogiri::XML::Document.
51
+ # Raises an exception if the text contains control characters
52
+ # forbidden in an XML document.
53
+ def self.load(string_or_io)
54
+ text = string_or_io.respond_to?(:read) ? string_or_io.read : string_or_io
55
+ if text =~ FORBIDDEN_CHARS_RE
56
+ abbrev = FORBIDDEN_CHARS_MAP[$&]
57
+ raise Error, "illegal control character in XML: #{$&.inspect} (#{abbrev})"
58
+ end
59
+
60
+ Nokogiri.XML(text, &:noblanks) # I hate this API
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative 'tools/blank_slate'
4
+ require_relative 'tools/console'
5
+ require_relative 'tools/helpers'
6
+ require_relative 'tools/regexp_wannabe'
7
+ require_relative 'tools/stable_inspect.rb'
8
+ require_relative 'tools/value_equality.rb'
9
+ require_relative 'tools/xml'
10
+
11
+ module SublimeDSL
12
+
13
+ module Tools
14
+
15
+ # Zips the content of +dir+ into file +archive+.
16
+ def self.zip(dir, archive)
17
+ dir = dir + '/' unless dir.end_with?('/')
18
+ Zip::File.open(archive, Zip::File::CREATE) do |zipfile|
19
+ Dir["#{dir}**/*"].each { |f| zipfile.add(f.sub(dir, ''), f) }
20
+ end
21
+ end
22
+
23
+ # Returns the running OS: :Windows, :OSX or :Linux.
24
+ def self.os
25
+ @os ||=
26
+ case RbConfig::CONFIG['host_os']
27
+ when /mswin|mingw/
28
+ :Windows
29
+ when /darwin/
30
+ :OSX
31
+ else
32
+ :Linux
33
+ end
34
+ end
35
+
36
+ # Replacement for characters forbidden in Windows file names.
37
+ FORBIDDEN_CHARS_MAP = {
38
+ '<' => '˂', # \u02C2 - modifier letter left arrowhead
39
+ '>' => '˃', # \u02C3 - modifier letter right arrowhead
40
+ ':' => '˸', # \u02F8 - modifier letter raised colon
41
+ '"' => 'ʺ', # \u02BA - double prime
42
+ '/' => '∕', # \u2215 - division slash
43
+ '|' => '¦', # \u00A6 - broken bar
44
+ '?' => 'ʔ', # \u0294 - latin letter glottal stop
45
+ '*' => '✶', # \u2736 - six pointed black star
46
+ '\\' => 'ʅ' # \u0285 - latin small letter squat reversed esh
47
+ }
48
+
49
+ # Regexp matching characters forbidden in Windows file names.
50
+ FORBIDDEN_RE = /[#{FORBIDDEN_CHARS_MAP.keys.map { |s| '\\' << s }.join}]/
51
+
52
+ # Returns an OS-compatible file name for +text+.
53
+ #
54
+ # Maps forbidden characters in Windows file names to something
55
+ # visually close (even on OSX and Linux):
56
+ # <>:"/|?*\ => ˂˃˸ʺ∕¦ʔ✶ʅ
57
+ #--
58
+ # TODO: allow the user to control this (with a config file).
59
+
60
+ def self.filename(text)
61
+ text.gsub(FORBIDDEN_RE, FORBIDDEN_CHARS_MAP)
62
+ end
63
+
64
+ end
65
+
66
+ end
@@ -0,0 +1,23 @@
1
+ require 'rbconfig'
2
+ require 'json'
3
+ require 'nokogiri'
4
+ require 'tmpdir'
5
+ require 'zip'
6
+
7
+ require_relative 'sublime_dsl/core_ext'
8
+ require_relative 'sublime_dsl/tools'
9
+ require_relative 'sublime_dsl/textmate'
10
+ require_relative 'sublime_dsl/sublime_text'
11
+ require_relative 'sublime_dsl/cli'
12
+
13
+ module SublimeDSL
14
+
15
+ VERSION = '0.1.1'
16
+
17
+ class Error < StandardError; end
18
+ class OptionError < Error; end
19
+ class DSLError < Error; end
20
+
21
+ Console = Tools::Console.new
22
+
23
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sublime_dsl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Thierry Lambert
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubyzip
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.1'
55
+ description: |
56
+ Sublime DSL allows generating Sublime Text configuration files
57
+ from a Ruby DSL, giving the power of Ruby to develop and maintain
58
+ themes, grammars, snippets, key bindings, etc.
59
+ email: thyresias@gmail.com
60
+ executables:
61
+ - subdsl
62
+ extensions: []
63
+ extra_rdoc_files:
64
+ - README.md
65
+ - SYNTAX.md
66
+ files:
67
+ - README.md
68
+ - Rakefile
69
+ - SYNTAX.md
70
+ - bin/subdsl
71
+ - lib/sublime_dsl.rb
72
+ - lib/sublime_dsl/cli.rb
73
+ - lib/sublime_dsl/cli/export.rb
74
+ - lib/sublime_dsl/cli/import.rb
75
+ - lib/sublime_dsl/core_ext.rb
76
+ - lib/sublime_dsl/core_ext/enumerable.rb
77
+ - lib/sublime_dsl/core_ext/string.rb
78
+ - lib/sublime_dsl/sublime_text.rb
79
+ - lib/sublime_dsl/sublime_text/command.rb
80
+ - lib/sublime_dsl/sublime_text/command_set.rb
81
+ - lib/sublime_dsl/sublime_text/keyboard.rb
82
+ - lib/sublime_dsl/sublime_text/keymap.rb
83
+ - lib/sublime_dsl/sublime_text/keymap/dsl_reader.rb
84
+ - lib/sublime_dsl/sublime_text/macro.rb
85
+ - lib/sublime_dsl/sublime_text/menu.rb
86
+ - lib/sublime_dsl/sublime_text/mouse.rb
87
+ - lib/sublime_dsl/sublime_text/mousemap.rb
88
+ - lib/sublime_dsl/sublime_text/package.rb
89
+ - lib/sublime_dsl/sublime_text/package/dsl_reader.rb
90
+ - lib/sublime_dsl/sublime_text/package/exporter.rb
91
+ - lib/sublime_dsl/sublime_text/package/importer.rb
92
+ - lib/sublime_dsl/sublime_text/package/reader.rb
93
+ - lib/sublime_dsl/sublime_text/package/writer.rb
94
+ - lib/sublime_dsl/sublime_text/setting_set.rb
95
+ - lib/sublime_dsl/textmate.rb
96
+ - lib/sublime_dsl/textmate/custom_base_name.rb
97
+ - lib/sublime_dsl/textmate/grammar.rb
98
+ - lib/sublime_dsl/textmate/grammar/dsl_reader.rb
99
+ - lib/sublime_dsl/textmate/grammar/dsl_writer.rb
100
+ - lib/sublime_dsl/textmate/grammar/plist_reader.rb
101
+ - lib/sublime_dsl/textmate/grammar/plist_writer.rb
102
+ - lib/sublime_dsl/textmate/plist.rb
103
+ - lib/sublime_dsl/textmate/preference.rb
104
+ - lib/sublime_dsl/textmate/snippet.rb
105
+ - lib/sublime_dsl/textmate/theme.rb
106
+ - lib/sublime_dsl/textmate/theme/dsl_reader.rb
107
+ - lib/sublime_dsl/textmate/theme/item.rb
108
+ - lib/sublime_dsl/textmate/theme/plist_writer.rb
109
+ - lib/sublime_dsl/tools.rb
110
+ - lib/sublime_dsl/tools/blank_slate.rb
111
+ - lib/sublime_dsl/tools/console.rb
112
+ - lib/sublime_dsl/tools/helpers.rb
113
+ - lib/sublime_dsl/tools/regexp_wannabe.rb
114
+ - lib/sublime_dsl/tools/stable_inspect.rb
115
+ - lib/sublime_dsl/tools/value_equality.rb
116
+ - lib/sublime_dsl/tools/xml.rb
117
+ homepage: https://github.com/thyresias/sublime_dsl
118
+ licenses:
119
+ - MIT
120
+ metadata: {}
121
+ post_install_message:
122
+ rdoc_options:
123
+ - "--title"
124
+ - Sublime DSL
125
+ - "--main"
126
+ - README.md
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 2.4.1
142
+ signing_key:
143
+ specification_version: 4
144
+ summary: A DSL to specify Sublime Text packages.
145
+ test_files: []