Skip to content

Commit

Permalink
Implemented s macro dispatcher.
Browse files Browse the repository at this point in the history
* Closes #183.
  • Loading branch information
h3rald committed Dec 4, 2010
1 parent 8a39ef4 commit a402c5e
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 12 deletions.
2 changes: 1 addition & 1 deletion lib/glyph/syntax_node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def expand(context)
self[:document] = context[:document]
self[:info] = context[:info]
self[:value] = ""
dispatched = parent_macro.dispatch(self) rescue nil
dispatched = parent_macro.dispatch(self) if parent_macro
return dispatched if dispatched
if Glyph['options.macro_set'] == "xml" || Glyph::MACROS[self[:name]].blank? && Glyph['options.xml_fallback'] then
m = Glyph::MacroNode.new
Expand Down
42 changes: 33 additions & 9 deletions macros/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,6 @@
(res_a || res_b) ? true : nil
end

macro :match do
within :condition
exact_parameters 2
val = param(0).to_s
regexp = param(1).to_s
macro_error "Invalid regular expression: #{regexp}" unless regexp.match /^\/.*\/[a-z]?$/
val.match(instance_eval(regexp)) ? true : nil
end

macro "alias:" do
exact_parameters 2
Glyph.macro_alias param(0) => param(1)
Expand Down Expand Up @@ -249,6 +240,39 @@
params.inject(1){|mult, n| mult * n.to_i}
end

macro :s do
dispatch do |node|
forbidden = [:each, :each_line, :each_byte, :upto, :intern, :to_sym, :to_f]
meth = node[:name]
infer_type = lambda do |str|
case
when str.match(/[+-]?\d+/) then
# Integer
str.to_i
when str.match(/^\/.+?\/[imoxneus]?$/) then
# Regexp
Kernel.instance_eval str
else
str
end
end
macro_error "Macro 's/#{meth}' takes at least one parameter" unless node.params.length > 0
macro_error "String method '#{meth}' is not supported" if meth.in?(forbidden) || meth.to_s.match(/\!$/)
str = node.param(0).evaluate(node, :params => true)
begin
if node.param(1) then
meth_params = node.params[1..node.params.length-1].map{|p| infer_type.call(p.evaluate(node, :params => true))}
str.send(meth, *meth_params).to_s
else
str.send(meth).to_s
end
rescue Exception => e
macro_warning "\"#{str}\".#{meth}(#{meth_params.map{|p| p.inspect}.join(', ') rescue nil}) - #{e.message}", e
""
end
end
end

macro_alias '--' => :comment
macro_alias '&' => :snippet
macro_alias '&:' => 'snippet:'
Expand Down
12 changes: 10 additions & 2 deletions spec/macros/core_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@
@p.document.output.should == ""
interpret("?[not[match[$[document.source]|/^docu/]]|em[test]]")
@p.document.output.should == ""
# Invalid regexp
lambda { interpret("?[match[$[document.source]|document]em[test]]").document.output }.should raise_error
interpret "?[%[lite?]|test]"
@p.document.output.should == ""
interpret "?[%[!lite?]|test]"
Expand Down Expand Up @@ -266,4 +264,14 @@
lambda { output_for("multiply[]").should == "1"}.should raise_error
end

it "s" do
lambda { output_for("s/each[test]") }.should raise_error
lambda { output_for("s/gsub[]") }.should raise_error
output_for("s/gsub[string|/ri/|i]").should == "sting"
output_for("s/match[test|/EST/i]").should == "est"
output_for("s/upcase[test]").should == "TEST"
output_for("s/insert[hell|4|o]").should == "hello"
output_for("s/slice[test]").should == ""
end

end

0 comments on commit a402c5e

Please sign in to comment.