textpow1x 1.1.0 → 1.2.0

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.
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