macros/core.rb in glyph-0.4.2 vs macros/core.rb in glyph-0.5.0
- old
+ new
@@ -1,24 +1,23 @@
#!/usr/bin/env ruby
+# encoding: utf-8
macro :snippet do
- no_mutual_inclusion_in 0
ident = value.to_sym
- if Glyph::SNIPPETS.has_key? ident then
+ if snippet? ident then
begin
update_source "snippet[#{ident}]"
- interpret Glyph::SNIPPETS[ident]
+ interpret snippet?(ident)
rescue Exception => e
case
when e.is_a?(Glyph::MutualInclusionError) then
raise
when e.is_a?(Glyph::MacroError) then
macro_warning e.message, e
else
macro_warning e.message, e
end
- macro_todo "Correct errors in snippet '#{ident}'"
end
else
macro_warning "Snippet '#{ident}' does not exist"
"[SNIPPET '#{ident}' NOT PROCESSED]"
end
@@ -26,11 +25,11 @@
macro "snippet:" do
exact_parameters 2
ident = param(0)
text = param(1)
- Glyph::SNIPPETS[ident.to_sym] = text
+ snippet ident, text
""
end
macro "macro:" do
safety_check
@@ -41,10 +40,23 @@
instance_eval code
end
""
end
+macro :load do
+ safety_check
+ exact_parameters 1
+ file = param 0
+ path = Glyph::PROJECT/file
+ if path.exist? then
+ file_load path
+ else
+ macro_warning "File '#{file}' no found."
+ "[FILE '#{value}' NOT FOUND]"
+ end
+end
+
macro :include do
safety_check
exact_parameters 1
no_mutual_inclusion_in 0
v = value
@@ -83,14 +95,12 @@
interpret contents
rescue Glyph::MutualInclusionError => e
raise
rescue Glyph::MacroError => e
macro_warning e.message, e
- macro_todo "Correct errors in file '#{value}'"
rescue Exception => e
macro_warning e.message, e
- macro_todo "Correct errors in file '#{value}'"
end
end
else
macro_warning "File '#{value}' no found."
"[FILE '#{value}' NOT FOUND]"
@@ -135,77 +145,197 @@
res = param(0)
(res.blank? || res == "false") ? param(2).to_s : param(1).to_s
end
macro :eq do
- within :condition
- min_parameters 1
- max_parameters 2
- (param(0).to_s == param(1).to_s) ? true : nil
+ exact_parameters 2
+ (param(0) == param(1)) ? true : nil
end
macro :not do
- within :condition
max_parameters 1
v = param(0).to_s
(v.blank? || v == "false") ? true : nil
end
macro :and do
- within :condition
- min_parameters 1
- max_parameters 2
+ exact_parameters 2
res_a = !param(0).blank?
res_b = !param(1).blank?
(res_a && res_b) ? true : nil
end
macro :or do
- within :condition
- min_parameters 1
- max_parameters 2
+ exact_parameters 2
res_a = !param(0).blank?
res_b = !param(1).blank?
(res_a || res_b) ? true : nil
end
-macro :match do
- within :condition
+macro :lt do
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
+ (param(0) < param(1)) ? true : nil
end
+macro :lte do
+ exact_parameters 2
+ (param(0) <= param(1)) ? true : nil
+end
+
+macro :gt do
+ exact_parameters 2
+ (param(0) > param(1)) ? true : nil
+end
+
+macro :gte do
+ exact_parameters 2
+ (param(0) >= param(1)) ? true : nil
+end
+
macro "alias:" do
exact_parameters 2
Glyph.macro_alias param(0) => param(1)
end
-macro "rewrite:" do
+macro "define:" do
safety_check
exact_parameters 2
- macro_name = param(0).to_sym
- @node.param(1).descend do |n, level|
- if n[:name] == macro_name then
- macro_error "Macro '#{macro_name}' cannot be defined by itself"
- end
- end
- Glyph.rewrite macro_name, raw_param(1).dup
+ Glyph.define param(0).to_sym, raw_param(1).dup
nil
end
macro "output?" do
Glyph['document.output'].in? parameters
end
+macro :layout do
+ dispatch do |node|
+ node[:name] = "layout/#{node[:name]}".to_sym
+ Glyph::Macro.new(node).expand
+ end
+end
+
+macro :let do
+ exact_parameters 1
+ param(0).to_s
+end
+
+macro :attribute do
+ exact_parameters 1
+ a = param(0).to_sym
+ macro_node = @node.find_parent do |n|
+ n.is_a?(Glyph::MacroNode) && n.attr(a)
+ end
+ if macro_node then
+ Glyph::Macro.new(macro_node).attr(a)
+ else
+ nil
+ end
+end
+
+macro "attribute:" do
+ exact_parameters 2
+ a = param(0).to_sym
+ macro_node = @node.find_parent do |n|
+ n.is_a?(Glyph::MacroNode) && n.attr(a)
+ end
+ macro_error "Undeclared attribute '#{a}'" unless macro_node
+ attr_value = param(1)
+ macro_node.attr(a).children.clear
+ macro_node.attr(a) << Glyph::TextNode.new.from(:value => attr_value)
+ nil
+end
+
+macro :add do
+ min_parameters 2
+ params.inject(0){|sum, n| sum + n.to_i}
+end
+
+macro :subtract do
+ min_parameters 2
+ params[1..params.length-1].inject(params[0].to_i){|diff, n| diff - n.to_i}
+end
+
+macro :multiply do
+ min_parameters 2
+ 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 :while do
+ exact_parameters 2
+ raw_cond = @node.parameter 0
+ raw_body = @node.parameter 1
+ cond = raw_cond.evaluate(@node, :params => true)
+ while (!cond.blank? && cond != "false") do
+ result = raw_body.evaluate(@node, :params => true)
+ cond = raw_cond.evaluate(@node, :params => true)
+ result
+ end
+end
+
+macro :fragment do
+ exact_parameters 2
+ ident, contents = param(0).to_sym, param(1)
+ macro_error "Fragment '#{ident}' is already defined" if @node[:document].fragments.has_key? ident
+ @node[:document].fragments[ident] = contents
+end
+
+macro :embed do
+ exact_parameters 1
+ ident = param(0).to_sym
+ placeholder do |document|
+ fragment = document.fragments[ident]
+ macro_error "Fragment '#{ident}' is not defined" unless fragment
+ fragment
+ end
+end
+
+
macro_alias '--' => :comment
macro_alias '&' => :snippet
macro_alias '&:' => 'snippet:'
macro_alias '%:' => 'macro:'
macro_alias '%' => :ruby
macro_alias '$' => :config
macro_alias '$:' => 'config:'
macro_alias '.' => :escape
macro_alias '?' => :condition
-macro_alias 'rw:' => 'rewrite:'
+macro_alias 'def:' => 'define:'
+macro_alias '@' => :attribute
+macro_alias :attr => :attribute
+macro_alias '@:' => "attribute:"
+macro_alias "attr:" => "attribute:"
+macro_alias "##" => :fragment
+macro_alias "<=" => :embed