textpow1x 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. data/Gemfile.lock +1 -1
  2. data/README.rdoc +7 -4
  3. data/examples/benchmark_js.rb +4 -2
  4. data/lib/textpow/syntax/{property_list.syntax → text.plist.syntax} +1 -1
  5. data/lib/textpow/syntax.rb +36 -37
  6. data/lib/textpow/version.rb +1 -1
  7. data/lib/textpow.rb +35 -0
  8. data/spec/textpow/syntax_spec.rb +128 -2
  9. data/spec/textpow_spec.rb +46 -0
  10. data/textpow1x.gemspec +22 -0
  11. metadata +163 -163
  12. data/.gitignore +0 -3
  13. /data/lib/textpow/syntax/{actionscript.syntax → source.actionscript.syntax} +0 -0
  14. /data/lib/textpow/syntax/{active4d_library.syntax → source.active4d.library.syntax} +0 -0
  15. /data/lib/textpow/syntax/{active4d.syntax → source.active4d.syntax} +0 -0
  16. /data/lib/textpow/syntax/{ada.syntax → source.ada.syntax} +0 -0
  17. /data/lib/textpow/syntax/{antlr.syntax → source.antlr.syntax} +0 -0
  18. /data/lib/textpow/syntax/{mod_perl.syntax → source.apache-config.mod_perl.syntax} +0 -0
  19. /data/lib/textpow/syntax/{apache.syntax → source.apache-config.syntax} +0 -0
  20. /data/lib/textpow/syntax/{applescript.syntax → source.applescript.syntax} +0 -0
  21. /data/lib/textpow/syntax/{asp.syntax → source.asp.syntax} +0 -0
  22. /data/lib/textpow/syntax/{asp_vb.net.syntax → source.asp.vb.net.syntax} +0 -0
  23. /data/lib/textpow/syntax/{qt_c++.syntax → source.c++.qt.syntax} +0 -0
  24. /data/lib/textpow/syntax/{c++.syntax → source.c++.syntax} +0 -0
  25. /data/lib/textpow/syntax/{cs.syntax → source.c-sharp.syntax} +0 -0
  26. /data/lib/textpow/syntax/{ragel.syntax → source.c.ragel.syntax} +0 -0
  27. /data/lib/textpow/syntax/{c.syntax → source.c.syntax} +0 -0
  28. /data/lib/textpow/syntax/{camlp4.syntax → source.camlp4.ocaml.syntax} +0 -0
  29. /data/lib/textpow/syntax/{cm.syntax → source.cm.syntax} +0 -0
  30. /data/lib/textpow/syntax/{coffeescript.syntax → source.coffee.syntax} +0 -0
  31. /data/lib/textpow/syntax/{context_free.syntax → source.context-free.syntax} +0 -0
  32. /data/lib/textpow/syntax/{css_experimental.syntax → source.css.beta.syntax} +0 -0
  33. /data/lib/textpow/syntax/{css.syntax → source.css.syntax} +0 -0
  34. /data/lib/textpow/syntax/{d.syntax → source.d.syntax} +0 -0
  35. /data/lib/textpow/syntax/{diff.syntax → source.diff.syntax} +0 -0
  36. /data/lib/textpow/syntax/{dot.syntax → source.dot.syntax} +0 -0
  37. /data/lib/textpow/syntax/{dylan.syntax → source.dylan.syntax} +0 -0
  38. /data/lib/textpow/syntax/{eiffel.syntax → source.eiffel.syntax} +0 -0
  39. /data/lib/textpow/syntax/{erlang.syntax → source.erlang.syntax} +0 -0
  40. /data/lib/textpow/syntax/{fortran.syntax → source.fortran.syntax} +0 -0
  41. /data/lib/textpow/syntax/{f-script.syntax → source.fscript.syntax} +0 -0
  42. /data/lib/textpow/syntax/{fxscript.syntax → source.fxscript.syntax} +0 -0
  43. /data/lib/textpow/syntax/{gri.syntax → source.gri.syntax} +0 -0
  44. /data/lib/textpow/syntax/{groovy.syntax → source.groovy.groovy.syntax} +0 -0
  45. /data/lib/textpow/syntax/{haskell.syntax → source.haskell.syntax} +0 -0
  46. /data/lib/textpow/syntax/{icalendar.syntax → source.icalendar.syntax} +0 -0
  47. /data/lib/textpow/syntax/{inform.syntax → source.inform.syntax} +0 -0
  48. /data/lib/textpow/syntax/{ini.syntax → source.ini.syntax} +0 -0
  49. /data/lib/textpow/syntax/{io.syntax → source.io.syntax} +0 -0
  50. /data/lib/textpow/syntax/{javaproperties.syntax → source.java-props.syntax} +0 -0
  51. /data/lib/textpow/syntax/{java.syntax → source.java.syntax} +0 -0
  52. /data/lib/textpow/syntax/{greasemonkey.syntax → source.js.greasemonkey.syntax} +0 -0
  53. /data/lib/textpow/syntax/{jquery_javascript.syntax → source.js.jquery.syntax} +0 -0
  54. /data/lib/textpow/syntax/{mootools.syntax → source.js.mootools.syntax} +0 -0
  55. /data/lib/textpow/syntax/{javascript_+_prototype_bracketed.syntax → source.js.prototype.bracketed.syntax} +0 -0
  56. /data/lib/textpow/syntax/{javascript_+_prototype.syntax → source.js.prototype.syntax} +0 -0
  57. /data/lib/textpow/syntax/{javascript.syntax → source.js.syntax} +0 -0
  58. /data/lib/textpow/syntax/{yui_javascript.syntax → source.js.yui.syntax} +0 -0
  59. /data/lib/textpow/syntax/{json.syntax → source.json.syntax} +0 -0
  60. /data/lib/textpow/syntax/{lexflex.syntax → source.lex.syntax} +0 -0
  61. /data/lib/textpow/syntax/{lighttpd.syntax → source.lighttpd-config.syntax} +0 -0
  62. /data/lib/textpow/syntax/{lilypond.syntax → source.lilypond.syntax} +0 -0
  63. /data/lib/textpow/syntax/{lisp.syntax → source.lisp.syntax} +0 -0
  64. /data/lib/textpow/syntax/{logo.syntax → source.logo.syntax} +0 -0
  65. /data/lib/textpow/syntax/{logtalk.syntax → source.logtalk.syntax} +0 -0
  66. /data/lib/textpow/syntax/{lua.syntax → source.lua.syntax} +0 -0
  67. /data/lib/textpow/syntax/{makefile.syntax → source.makefile.syntax} +0 -0
  68. /data/lib/textpow/syntax/{m.syntax → source.matlab.syntax} +0 -0
  69. /data/lib/textpow/syntax/{mel.syntax → source.mel.syntax} +0 -0
  70. /data/lib/textpow/syntax/{mips.syntax → source.mips.syntax} +0 -0
  71. /data/lib/textpow/syntax/{standard_ml.syntax → source.ml.syntax} +0 -0
  72. /data/lib/textpow/syntax/{modula-3.syntax → source.modula-3.syntax} +0 -0
  73. /data/lib/textpow/syntax/{build.syntax → source.nant-build.syntax} +0 -0
  74. /data/lib/textpow/syntax/{objective-c++.syntax → source.objc++.syntax} +0 -0
  75. /data/lib/textpow/syntax/{objective-c.syntax → source.objc.syntax} +0 -0
  76. /data/lib/textpow/syntax/{ocaml.syntax → source.ocaml.syntax} +0 -0
  77. /data/lib/textpow/syntax/{ocamllex.syntax → source.ocamllex.syntax} +0 -0
  78. /data/lib/textpow/syntax/{ocamlyacc.syntax → source.ocamlyacc.syntax} +0 -0
  79. /data/lib/textpow/syntax/{opengl.syntax → source.open-gl.syntax} +0 -0
  80. /data/lib/textpow/syntax/{pascal.syntax → source.pascal.syntax} +0 -0
  81. /data/lib/textpow/syntax/{vectorscript.syntax → source.pascal.vectorscript.syntax} +0 -0
  82. /data/lib/textpow/syntax/{perl.syntax → source.perl.syntax} +0 -0
  83. /data/lib/textpow/syntax/{cake.syntax → source.php.cake.syntax} +0 -0
  84. /data/lib/textpow/syntax/{languagedefinition.syntax → source.plist.tm-grammar.syntax} +0 -0
  85. /data/lib/textpow/syntax/{postscript.syntax → source.postscript.syntax} +0 -0
  86. /data/lib/textpow/syntax/{processing.syntax → source.processing.syntax} +0 -0
  87. /data/lib/textpow/syntax/{prolog.syntax → source.prolog.syntax} +0 -0
  88. /data/lib/textpow/syntax/{python_django.syntax → source.python.django.syntax} +0 -0
  89. /data/lib/textpow/syntax/{python.syntax → source.python.syntax} +0 -0
  90. /data/lib/textpow/syntax/{qmake_project.syntax → source.qmake.syntax} +0 -0
  91. /data/lib/textpow/syntax/{quake3_config.syntax → source.quake-config.syntax} +0 -0
  92. /data/lib/textpow/syntax/{r_console.syntax → source.r-console.syntax} +0 -0
  93. /data/lib/textpow/syntax/{r.syntax → source.r.syntax} +0 -0
  94. /data/lib/textpow/syntax/{regular_expressions_oniguruma.syntax → source.regexp.oniguruma.syntax} +0 -0
  95. /data/lib/textpow/syntax/{regular_expressions_python.syntax → source.regexp.python.syntax} +0 -0
  96. /data/lib/textpow/syntax/{regexp.syntax → source.regexp.syntax} +0 -0
  97. /data/lib/textpow/syntax/{remind.syntax → source.remind.syntax} +0 -0
  98. /data/lib/textpow/syntax/{rez.syntax → source.rez.syntax} +0 -0
  99. /data/lib/textpow/syntax/{ruby_experimental.syntax → source.ruby.experimental.syntax} +0 -0
  100. /data/lib/textpow/syntax/{ruby_on_rails.syntax → source.ruby.rails.syntax} +0 -0
  101. /data/lib/textpow/syntax/{ruby.syntax → source.ruby.syntax} +0 -0
  102. /data/lib/textpow/syntax/{s5.syntax → source.s5.syntax} +0 -0
  103. /data/lib/textpow/syntax/{sass.syntax → source.sass.syntax} +0 -0
  104. /data/lib/textpow/syntax/{scheme.syntax → source.scheme.syntax} +0 -0
  105. /data/lib/textpow/syntax/{scilab.syntax → source.scilab.syntax} +0 -0
  106. /data/lib/textpow/syntax/{shell-unix-generic.syntax → source.shell.syntax} +0 -0
  107. /data/lib/textpow/syntax/{slate.syntax → source.slate.syntax} +0 -0
  108. /data/lib/textpow/syntax/{smarty.syntax → source.smarty.syntax} +0 -0
  109. /data/lib/textpow/syntax/{sql_rails.syntax → source.sql.ruby.syntax} +0 -0
  110. /data/lib/textpow/syntax/{sql.syntax → source.sql.syntax} +0 -0
  111. /data/lib/textpow/syntax/{ssh-config.syntax → source.ssh-config.syntax} +0 -0
  112. /data/lib/textpow/syntax/{strings_file.syntax → source.strings.syntax} +0 -0
  113. /data/lib/textpow/syntax/{swig.syntax → source.swig.syntax} +0 -0
  114. /data/lib/textpow/syntax/{macports_portfile.syntax → source.tcl.macports.syntax} +0 -0
  115. /data/lib/textpow/syntax/{tcl.syntax → source.tcl.syntax} +0 -0
  116. /data/lib/textpow/syntax/{yaml.syntax → source.yaml.syntax} +0 -0
  117. /data/lib/textpow/syntax/{active4d_ini.syntax → text.active4d-ini.syntax} +0 -0
  118. /data/lib/textpow/syntax/{bulletin_board.syntax → text.bbcode.syntax} +0 -0
  119. /data/lib/textpow/syntax/{bibtex.syntax → text.bibtex.syntax} +0 -0
  120. /data/lib/textpow/syntax/{blog_html.syntax → text.blog.html.syntax} +0 -0
  121. /data/lib/textpow/syntax/{blog_markdown.syntax → text.blog.markdown.syntax} +0 -0
  122. /data/lib/textpow/syntax/{blog_text.syntax → text.blog.syntax} +0 -0
  123. /data/lib/textpow/syntax/{blog_textile.syntax → text.blog.textile.syntax} +0 -0
  124. /data/lib/textpow/syntax/{gtdalt.syntax → text.gtdalt.syntax} +0 -0
  125. /data/lib/textpow/syntax/{haml.syntax → text.haml.syntax} +0 -0
  126. /data/lib/textpow/syntax/{html_for_asp.net.syntax → text.html.asp.net.syntax} +0 -0
  127. /data/lib/textpow/syntax/{html-asp.syntax → text.html.asp.syntax} +0 -0
  128. /data/lib/textpow/syntax/{html.syntax → text.html.basic.syntax} +0 -0
  129. /data/lib/textpow/syntax/{coldfusion.syntax → text.html.cfm.syntax} +0 -0
  130. /data/lib/textpow/syntax/{html_django.syntax → text.html.django.syntax} +0 -0
  131. /data/lib/textpow/syntax/{dokuwiki.syntax → text.html.dokuwiki.syntax} +0 -0
  132. /data/lib/textpow/syntax/{doxygen.syntax → text.html.doxygen.syntax} +0 -0
  133. /data/lib/textpow/syntax/{multimarkdown.syntax → text.html.markdown.multimarkdown.syntax} +0 -0
  134. /data/lib/textpow/syntax/{html_mason.syntax → text.html.mason.syntax} +0 -0
  135. /data/lib/textpow/syntax/{mediawiki.syntax → text.html.mediawiki.syntax} +0 -0
  136. /data/lib/textpow/syntax/{movable_type.syntax → text.html.mt.syntax} +0 -0
  137. /data/lib/textpow/syntax/{html_rails.syntax → text.html.ruby.syntax} +0 -0
  138. /data/lib/textpow/syntax/{active4d_html.syntax → text.html.strict.active4d.syntax} +0 -0
  139. /data/lib/textpow/syntax/{html_tcl.syntax → text.html.tcl.syntax} +0 -0
  140. /data/lib/textpow/syntax/{textile.syntax → text.html.textile.syntax} +0 -0
  141. /data/lib/textpow/syntax/{template_toolkit.syntax → text.html.tt.syntax} +0 -0
  142. /data/lib/textpow/syntax/{twiki.syntax → text.html.twiki.syntax} +0 -0
  143. /data/lib/textpow/syntax/{xhtml_1.0.syntax → text.html.xhtml.1-strict.syntax} +0 -0
  144. /data/lib/textpow/syntax/{latex_log.syntax → text.log.latex.syntax} +0 -0
  145. /data/lib/textpow/syntax/{mail.syntax → text.mail.markdown.syntax} +0 -0
  146. /data/lib/textpow/syntax/{man.syntax → text.man.syntax} +0 -0
  147. /data/lib/textpow/syntax/{moinmoin.syntax → text.moinmoin.syntax} +0 -0
  148. /data/lib/textpow/syntax/{gtd.syntax → text.plain.gtd.syntax} +0 -0
  149. /data/lib/textpow/syntax/{release_notes.syntax → text.plain.release-notes.syntax} +0 -0
  150. /data/lib/textpow/syntax/{plain_text.syntax → text.plain.syntax} +0 -0
  151. /data/lib/textpow/syntax/{pmwiki.syntax → text.pmwiki.syntax} +0 -0
  152. /data/lib/textpow/syntax/{restructuredtext.syntax → text.restructuredtext.syntax} +0 -0
  153. /data/lib/textpow/syntax/{setext.syntax → text.setext.syntax} +0 -0
  154. /data/lib/textpow/syntax/{subversion_commit_message.syntax → text.subversion-commit.syntax} +0 -0
  155. /data/lib/textpow/syntax/{csv.syntax → text.tabular.csv.syntax} +0 -0
  156. /data/lib/textpow/syntax/{tsv.syntax → text.tabular.tsv.syntax} +0 -0
  157. /data/lib/textpow/syntax/{latex_beamer.syntax → text.tex.latex.beamer.syntax} +0 -0
  158. /data/lib/textpow/syntax/{literate_haskell.syntax → text.tex.latex.haskell.syntax} +0 -0
  159. /data/lib/textpow/syntax/{latex_memoir.syntax → text.tex.latex.memoir.syntax} +0 -0
  160. /data/lib/textpow/syntax/{rd_r_documentation.syntax → text.tex.latex.rd.syntax} +0 -0
  161. /data/lib/textpow/syntax/{sweave.syntax → text.tex.latex.sweave.syntax} +0 -0
  162. /data/lib/textpow/syntax/{latex.syntax → text.tex.latex.syntax} +0 -0
  163. /data/lib/textpow/syntax/{tex_math.syntax → text.tex.math.syntax} +0 -0
  164. /data/lib/textpow/syntax/{tex.syntax → text.tex.syntax} +0 -0
  165. /data/lib/textpow/syntax/{txt2tags.syntax → text.txt2tags.syntax} +0 -0
  166. /data/lib/textpow/syntax/{installer_distribution_script.syntax → text.xml.apple-dist.syntax} +0 -0
  167. /data/lib/textpow/syntax/{xml_strict.syntax → text.xml.strict.syntax} +0 -0
  168. /data/lib/textpow/syntax/{xml.syntax → text.xml.syntax} +0 -0
  169. /data/lib/textpow/syntax/{xsl.syntax → text.xml.xsl.syntax} +0 -0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- textpow1x (1.1.0)
4
+ textpow1x (1.2.0)
5
5
  plist (>= 3.0.1)
6
6
 
7
7
  GEM
data/README.rdoc CHANGED
@@ -1,7 +1,10 @@
1
1
  Read {TextMate}[http://macromates.com/] syntax files and parse text with them.
2
2
 
3
- For Ruby 1.8 and 1.9.
4
-
3
+ Improvements over old textpow:
4
+ - Ruby 1.8 and 1.9 support
5
+ - Tested, documented, refactored and made +faster+
6
+ - Added tons of syntax files (li/textpow/syntax)
7
+ - Most included syntaxes work out of the box
5
8
 
6
9
  == INSTALL:
7
10
 
@@ -13,7 +16,7 @@ Install oniguruma
13
16
  # Ubuntu
14
17
  sudo apt-get -y install libonig-dev
15
18
  gem install oniguruma
16
-
19
+
17
20
  # OsX (no idea if this works...)
18
21
  port install oniguruma4
19
22
 
@@ -23,7 +26,7 @@ Install oniguruma
23
26
  1. Load a Syntax File {list of included syntax}[https://github.com/grosser/textpow/tree/master/lib/textpow/syntax]
24
27
 
25
28
  require 'textpow'
26
- syntax = Textpow::SyntaxNode.load("#{Textpow.syntax_path}/ruby.syntax")
29
+ syntax = Textpow.syntax('ruby') # or Textpow::Syntax.load(syntax_file)
27
30
 
28
31
  2. Initialize a processor:
29
32
 
@@ -1,11 +1,13 @@
1
+ # test changes for performance
2
+ # ruby examples/benchmark_js.rb 100; git co lib/textpow/syntax.rb ; ruby examples/benchmark_js.rb 100
1
3
  $LOAD_PATH.unshift 'lib'
2
4
  require 'textpow'
3
5
 
4
- syntax = Textpow::SyntaxNode.load("#{Textpow.syntax_path}/javascript.syntax")
6
+ syntax = Textpow.syntax('javascript')
5
7
  text = File.read('examples/jquery.js')
6
8
  processor = Textpow::RecordingProcessor.new
7
9
 
8
10
  start = Time.now.to_f
9
- 5.times{ syntax.parse(text, processor) }
11
+ (ARGV[0] || 1).to_i.times{ syntax.parse(text, processor) }
10
12
  puts Time.now.to_f - start
11
13
 
@@ -14,7 +14,7 @@ fileTypes:
14
14
  - scriptSuite
15
15
  - scriptTerminology
16
16
  - savedSearch
17
- scopeName: ""
17
+ scopeName: "text.plist"
18
18
  repository:
19
19
  openstep_comment:
20
20
  patterns:
@@ -4,37 +4,32 @@ end
4
4
  require 'oniguruma' unless Textpow::RUBY_19
5
5
 
6
6
  module Textpow
7
+ # at load time we do not know all patterns / all syntaxes
8
+ # so we store a proxy, that tries to find the correct syntax at runtime
7
9
  class SyntaxProxy
8
- def initialize hash, syntax
10
+ def initialize(included_name, syntax)
9
11
  @syntax = syntax
10
- @proxy = hash["include"]
12
+ @included_name = included_name
11
13
  end
12
14
 
13
15
  def method_missing method, *args, &block
14
- if @proxy
15
- @proxy_value = proxy unless @proxy_value
16
- if @proxy_value
17
- @proxy_value.send(method, *args, &block)
18
- else
19
- STDERR.puts "Failed proxying #{@proxy}.#{method}(#{args.join(', ')})"
20
- end
16
+ if @proxy ||= proxy
17
+ @proxy.send(method, *args, &block)
18
+ else
19
+ STDERR.puts "Failed proxying #{@proxy_name}.#{method}(#{args.join(', ')})"
21
20
  end
22
21
  end
23
22
 
23
+ private
24
+
24
25
  def proxy
25
- case @proxy
26
+ case @included_name
26
27
  when /^#/
27
- if @syntax.repository && @syntax.repository[@proxy[1..-1]]
28
- #puts "Repository"
29
- #@table["syntax"].repository.each_key{|k| puts k}
30
- return @syntax.repository[@proxy[1..-1]]
31
- end
32
- when "$self"
33
- return @syntax
34
- when "$base"
35
- return @syntax
28
+ @syntax.repository and @syntax.repository[@included_name[1..-1]]
29
+ when "$self", "$base"
30
+ @syntax
36
31
  else
37
- return @syntax.syntaxes[@proxy]
32
+ @syntax.syntaxes[@included_name] || Textpow.syntax(@included_name)
38
33
  end
39
34
  end
40
35
  end
@@ -103,7 +98,7 @@ module Textpow
103
98
  Oniguruma::ORegexp.new(value, :options => Oniguruma::OPTION_CAPTURE_GROUP)
104
99
  end
105
100
  instance_variable_set("@#{key}", regex)
106
- rescue ArgumentError => e
101
+ rescue RegexpError, ArgumentError => e
107
102
  raise ParsingError, "Parsing error in #{value}: #{e.to_s}"
108
103
  end
109
104
  when "content", "fileTypes", "name", "contentName", "end", "scopeName", "keyEquivalent"
@@ -143,20 +138,19 @@ module Textpow
143
138
  @repository = {}
144
139
  repository.each do |key, value|
145
140
  if value["include"]
146
- @repository[key] = SyntaxProxy.new( value, self.syntax )
141
+ @repository[key] = SyntaxProxy.new(value["include"], syntax)
147
142
  else
148
- @repository[key] = SyntaxNode.new( value, self.syntax, @name_space )
143
+ @repository[key] = SyntaxNode.new(value, syntax, @name_space)
149
144
  end
150
145
  end
151
146
  end
152
147
 
153
148
  def create_children patterns
154
- @patterns = []
155
- patterns.each do |p|
156
- if p["include"]
157
- @patterns << SyntaxProxy.new( p, self.syntax )
149
+ @patterns = patterns.map do |pattern|
150
+ if pattern["include"]
151
+ SyntaxProxy.new(pattern["include"], syntax)
158
152
  else
159
- @patterns << SyntaxNode.new( p, self.syntax, @name_space )
153
+ SyntaxNode.new(pattern, syntax, @name_space)
160
154
  end
161
155
  end
162
156
  end
@@ -239,20 +233,25 @@ module Textpow
239
233
  end
240
234
  end
241
235
 
236
+ # find earliest matching pattern
242
237
  def match_first_son(string, position)
243
238
  return if not patterns
244
239
 
245
- match = nil
246
- patterns.each do |p|
247
- tmatch = p.match_first string, position
248
- if tmatch
249
- if not match or match_offset(match[1]).first > match_offset(tmatch[1]).first
250
- match = tmatch
251
- end
252
- #break if tmatch[1].offset.first == position
240
+ earliest_match = nil
241
+ earliest_match_offset = nil
242
+ patterns.each do |pattern|
243
+ next unless match = pattern.match_first(string, position)
244
+
245
+ match_offset = match_offset(match[1]).first
246
+ return match if match_offset == 0 # no need to look any further
247
+
248
+ if not earliest_match or earliest_match_offset > match_offset
249
+ earliest_match = match
250
+ earliest_match_offset = match_offset
253
251
  end
254
252
  end
255
- match
253
+
254
+ earliest_match
256
255
  end
257
256
 
258
257
  def parse_line(stack, line, processor)
@@ -1,3 +1,3 @@
1
1
  module Textpow
2
- VERSION = Version = "1.1.0"
2
+ VERSION = Version = "1.2.0"
3
3
  end
data/lib/textpow.rb CHANGED
@@ -11,5 +11,40 @@ module Textpow
11
11
  def self.syntax_path
12
12
  File.join(File.dirname(__FILE__), 'textpow', 'syntax')
13
13
  end
14
+
15
+ @@syntax = {}
16
+ def self.syntax(syntax_name)
17
+ syntax_name = syntax_name.downcase
18
+ if @@syntax.has_key?(syntax_name)
19
+ @@syntax[syntax_name]
20
+ else
21
+ @@syntax[syntax_name] = uncached_syntax(syntax_name)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def self.uncached_syntax(name)
28
+ path = (
29
+ find_syntax_by_path(name) ||
30
+ find_syntax_by_scope_name(name) ||
31
+ find_syntax_by_fuzzy_name(name)
32
+ )
33
+ SyntaxNode.load(path) if path
34
+ end
35
+
36
+ def self.find_syntax_by_scope_name(name)
37
+ path = File.join(syntax_path, "#{name}.syntax")
38
+ path if File.exist?(path)
39
+ end
40
+
41
+ def self.find_syntax_by_fuzzy_name(name)
42
+ path = Dir.glob(File.join(syntax_path, "*.#{name}.*")).sort_by(&:size).first
43
+ path if path and File.exist?(path)
44
+ end
45
+
46
+ def self.find_syntax_by_path(path)
47
+ path if File.exist?(path)
48
+ end
14
49
  end
15
50
 
@@ -11,7 +11,7 @@ describe Textpow::SyntaxNode do
11
11
  end
12
12
 
13
13
  it "can load from yaml .syntax" do
14
- Textpow::SyntaxNode.load('lib/textpow/syntax/ruby.syntax').should_not == nil
14
+ Textpow::SyntaxNode.load('lib/textpow/syntax/source.ruby.syntax').should_not == nil
15
15
  end
16
16
 
17
17
  it "cannot load missing file" do
@@ -71,7 +71,7 @@ describe Textpow::SyntaxNode do
71
71
  end
72
72
 
73
73
  describe "#parse" do
74
- let(:node){ Textpow::SyntaxNode.load('lib/textpow/syntax/ruby.syntax') }
74
+ let(:node){ Textpow.syntax('ruby') }
75
75
 
76
76
  it "uses a RecordingProcessor by default" do
77
77
  node.parse("111").stack.should == [
@@ -95,5 +95,131 @@ describe Textpow::SyntaxNode do
95
95
  [:end_parsing, "source.ruby"]
96
96
  ]
97
97
  end
98
+
99
+ it "can parse multiline syntax via stack" do
100
+ node.parse("=begin\n111\n=end").stack.should == [
101
+ [:start_parsing, "source.ruby"],
102
+ [:new_line, "=begin\n"],
103
+ [:open_tag, "comment.block.documentation.ruby", 0],
104
+ [:open_tag, "punctuation.definition.comment.ruby", 0],
105
+ [:close_tag, "punctuation.definition.comment.ruby", 6],
106
+ [:new_line, "111\n"],
107
+ [:new_line, "=end"],
108
+ [:open_tag, "punctuation.definition.comment.ruby", 0],
109
+ [:close_tag, "punctuation.definition.comment.ruby", 4],
110
+ [:close_tag, "comment.block.documentation.ruby", 4],
111
+ [:end_parsing, "source.ruby"]
112
+ ]
113
+ end
114
+
115
+ it "loads included syntax files" do
116
+ pending
117
+ node = Textpow.syntax('html_rails')
118
+ node.parse("<br/>")
119
+ end
120
+ end
121
+
122
+ describe "#match_first_son" do
123
+ it "returns nil when patterns are empty" do
124
+ node = Textpow::SyntaxNode.new({"scopeName" => 'xxx'})
125
+ node.send(:match_first_son, "xxx", 0).should == nil
126
+ end
127
+
128
+ it "matches a pattern" do
129
+ node = Textpow::SyntaxNode.new({"scopeName" => 'xxx', 'patterns' => [
130
+ {"match" => "xxx", "name" => "foo"}
131
+ ]})
132
+ pattern, match = node.send(:match_first_son, "xxxyy", 0)
133
+ match.to_s.should == 'xxx'
134
+ pattern.name.should == 'foo'
135
+ end
136
+
137
+ it "matches the first pattern" do
138
+ node = Textpow::SyntaxNode.new({"scopeName" => 'xxx', 'patterns' => [
139
+ {"match" => "yyy", "name" => "bar"},
140
+ {"match" => "xxx", "name" => "foo"},
141
+ {"match" => "zzz", "name" => "baz"},
142
+ ]})
143
+ pattern, match = node.send(:match_first_son, "xxxyyyzzz", 0)
144
+ match.to_s.should == 'xxx'
145
+ pattern.name.should == 'foo'
146
+ end
147
+
148
+ it "matches the first pattern for equal positions" do
149
+ node = Textpow::SyntaxNode.new({"scopeName" => 'xxx', 'patterns' => [
150
+ {"match" => "xxx", "name" => "bar"},
151
+ {"match" => "xxxyyy", "name" => "foo"},
152
+ {"match" => "xxxyy", "name" => "baz"},
153
+ ]})
154
+ pattern, match = node.send(:match_first_son, "xxxyyyzzz", 0)
155
+ match.to_s.should == 'xxx'
156
+ pattern.name.should == 'bar'
157
+ end
158
+ end
159
+
160
+ describe "proxying" do
161
+ it "cannot proxy by scopeName if syntax is missing" do
162
+ STDERR.should_receive(:puts)
163
+ node = Textpow::SyntaxNode.new({"scopeName" => 'xxx', 'patterns' => [{'include' => 'foo'}]})
164
+ node.parse('bar').stack.should == [
165
+ [:start_parsing, "xxx"],
166
+ [:new_line, "bar"],
167
+ [:end_parsing, "xxx"]
168
+ ]
169
+ end
170
+
171
+ it "can proxy by scopeName if syntax is available in repo" do
172
+ node = Textpow::SyntaxNode.new({"scopeName" => 'xxx', 'patterns' => [{'include' => 'source.ruby'}]})
173
+ node.parse('1').stack.should == [
174
+ [:start_parsing, "xxx"],
175
+ [:new_line, "1"],
176
+ [:open_tag, "constant.numeric.ruby", 0],
177
+ [:close_tag, "constant.numeric.ruby", 1],
178
+ [:end_parsing, "xxx"]
179
+ ]
180
+ end
181
+
182
+ it "can proxy by scopeName if syntax is loaded (even later)" do
183
+ node = Textpow::SyntaxNode.new({"scopeName" => 'xxx', 'patterns' => [{'include' => 'foo'}]})
184
+ Textpow::SyntaxNode.new({"scopeName" => 'foo', 'patterns' => [{'name' => 'foo.1', 'match' => 'bar'}]})
185
+ node.parse('bar').stack.should == [
186
+ [:start_parsing, "xxx"],
187
+ [:new_line, "bar"],
188
+ [:open_tag, "foo.1", 0],
189
+ [:close_tag, "foo.1", 3],
190
+ [:end_parsing, "xxx"]
191
+ ]
192
+ end
193
+
194
+ it "can proxy to a pattern defined in an repository" do
195
+ node = Textpow::SyntaxNode.new({"scopeName" => 'xxx',
196
+ 'repository' => {'foo' => {'name' => 'foo.1', 'match' => 'bar'}},
197
+ 'patterns' => [{'include' => '#foo'}]
198
+ })
199
+ node.parse('bar').stack.should == [
200
+ [:start_parsing, "xxx"],
201
+ [:new_line, "bar"],
202
+ [:open_tag, "foo.1", 0],
203
+ [:close_tag, "foo.1", 3],
204
+ [:end_parsing, "xxx"]
205
+ ]
206
+ end
207
+
208
+ it "can proxy to a pattern nested included in an repository" do
209
+ node = Textpow::SyntaxNode.new({"scopeName" => 'xxx',
210
+ 'repository' => {
211
+ 'baz' => {'patterns' => [{'include' => '#foo'}]},
212
+ 'foo' => {'name' => 'foo.1', 'match' => 'bar'}
213
+ },
214
+ 'patterns' => [{'include' => '#baz'}]
215
+ })
216
+ node.parse('bar').stack.should == [
217
+ [:start_parsing, "xxx"],
218
+ [:new_line, "bar"],
219
+ [:open_tag, "foo.1", 0],
220
+ [:close_tag, "foo.1", 3],
221
+ [:end_parsing, "xxx"]
222
+ ]
223
+ end
98
224
  end
99
225
  end
data/spec/textpow_spec.rb CHANGED
@@ -1,7 +1,53 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Textpow do
4
+ before do
5
+ Textpow.send(:class_variable_set, "@@syntax", {})
6
+ end
7
+
4
8
  it "has a version" do
5
9
  Textpow::Version =~ /^\d\.\d\.\d$/
6
10
  end
11
+
12
+ it "has syntax files named after their scopeName" do
13
+ Dir["#{Textpow.syntax_path}/*"].each do |file|
14
+ next if File.directory?(file)
15
+ (YAML.load_file(file)['scopeName'] + '.syntax').should == File.basename(file)
16
+ end
17
+ end
18
+
19
+ describe "syntax" do
20
+ it "finds syntax by path" do
21
+ Textpow.syntax('lib/textpow/syntax/source.ruby.syntax').name.should == 'Ruby'
22
+ end
23
+
24
+ it "finds a syntax by scopeName" do
25
+ Textpow.syntax('source.ruby').name.should == 'Ruby'
26
+ end
27
+
28
+ it "caches found syntax" do
29
+ Textpow.syntax('ruby').name.should == 'Ruby'
30
+ Dir.should_not_receive(:glob)
31
+ Textpow.syntax('ruby').name.should == 'Ruby'
32
+ end
33
+
34
+ it "finds a syntax by name parts" do
35
+ Textpow.syntax('ruby').name.should == 'Ruby'
36
+ end
37
+
38
+ it "returns the found syntax for mixed case" do
39
+ Textpow.syntax('RuBy').name.should == 'Ruby'
40
+ end
41
+
42
+ it "returns nil for unfound syntax" do
43
+ Textpow.syntax('buby').should == nil
44
+ end
45
+
46
+ it "caches nil for unfound syntax" do
47
+ Dir.should_receive(:glob).and_return []
48
+ Textpow.syntax('buby').should == nil
49
+ Dir.should_not_receive(:glob)
50
+ Textpow.syntax('buby').should == nil
51
+ end
52
+ end
7
53
  end
data/textpow1x.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "textpow/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "textpow1x"
7
+ s.version = Textpow::Version
8
+ s.authors = ["Dizan Vasquez", "Spox", "Chris Hoffman", "Michael Grosser"]
9
+ s.email = ["michael@grosser.it"]
10
+ s.homepage = "http://github.com/grosser/textpow"
11
+ s.summary = "A library for parsing TextMate bundles on ruby 1.x"
12
+ s.description = s.summary
13
+ s.license = "MIT"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.require_paths = ["lib"]
18
+ s.executables = ["plist2yaml", "plist2syntax"]
19
+ s.rdoc_options = ["--main", "README.rdoc"]
20
+
21
+ s.add_dependency "plist", '>=3.0.1'
22
+ end