class Eggshell::Bundles::Basics::ControlMacros

Public Class Methods

new() click to toggle source
# File lib/eggshell/bundles/basics-old.rb, line 638
def initialize
        @stack = []
        @state = []
        @macstack = []
end

Public Instance Methods

process(buffer, macname, args, lines, depth) click to toggle source
# File lib/eggshell/bundles/basics-old.rb, line 649
def process(buffer, macname, args, lines, depth)
        p0 = args.is_a?(Array) ? args[0] : nil
        lines ? lines.delete('') : ''

        macname = macname.to_sym
        st = @state[depth]
        if !@state[depth]
                st = {:type => macname}

                @state[depth] = st
                # erase nested state
                @state[depth+1] = nil
        end

        if macname == :for || macname == :loop
                p0 = p0 || {}
                st[:var] = p0['var']
                st[:start] = p0['start']
                st[:stop] = p0['stop']
                st[:step] = p0['step'] || 1
                st[:iter] = p0['items'] || 'items'
                st[:item] = p0['item'] || 'item'
                st[:counter] = p0['counter'] || 'counter'
                st[:raw]  = p0['raw'] # @todo inherit if not set?
                st[:collect] = p0['collect']
                st[:agg_block] = p0['aggregate_block']

                mbuff = []
                looper = nil
                loop_is_map = false

                # in for, construct range that can be looped over
                # in loop, detect 'each' method
                if macname == :for
                        st[:item] = st[:var]
                        looper = Range.new(st[:start], st[:stop]).step(st[:step]).to_a
                elsif macname == :loop
                        begin
                                looper = st[:iter].is_a?(Array) && st[:iter][0].is_a?(Symbol) ? @proc.expr_eval(st[:iter]) : st[:iter]
                                looper = nil if !looper.respond_to?(:each)
                                loop_is_map = looper.is_a?(Hash)
                        rescue
                        end
                end

                collector = []
                if looper
                        counter = 0
                        looper.each do |i1, i2|
                                # for maps, use key as the counter
                                val = nil
                                if loop_is_map
                                        @proc.vars[st[:counter]] = i1
                                        val = i2
                                else
                                        val = i1
                                        @proc.vars[st[:counter]] = counter
                                end

                                # inject value into :item -- if it's an expression, evaluate first
                                @proc.vars[st[:item]] = val.is_a?(Array) && val[0].is_a?(Symbol) ? @proc.expr_eval(val) : val
                                # divert lines to collector
                                if st[:collect]
                                        lines.each do |_line|
                                                if _line.is_a?(String)
                                                        collector << @proc.expand_expr(_line)
                                                elsif _line.is_a?(Eggshell::Block)
                                                        _line.process(collector)
                                                end
                                        end
                                else
                                        process_lines(lines, buffer, depth + 1, st[:raw])
                                end
                                break if st[:break]

                                counter += 1
                        end
                end
                
                # since there are lines here, process collected as an aggregated set of blocks
                if collector.length > 0
                        if st[:collect] == 'aggregate'
                                if st[:agg_block]
                                        collector.unshift(st[:agg_block])
                                end
                                process_lines(collector, buffer, depth + 1, false)
                        else
                                buffer << collector.join("\n")
                        end
                end

                # clear state
                @state[depth] = nil
        elsif macname == :while
                raw = args[1]
                while @proc.expr_eval(p0)
                        process_lines(lines, buffer, depth + 1, raw)
                        break if st[:break]
                end
        elsif macname == :if || macname == :elsif || macname == :else
                cond = p0
                st[:if] = true if macname == :if
                if st[:cond_count] == nil || macname == :if
                        st[:cond_count] = 0 
                        st[:cond_eval] = false
                        st[:cond_met] = false
                end

                last_action = st[:last_action]
                st[:last_action] = macname.to_sym

                # @todo more checks (e.g. no elsif after else, no multiple else, etc.)
                if !st[:if] || (macname != :else && !cond)
                        # @todo exception?
                        return
                end

                if macname != :else
                        if !st[:cond_eval]
                                cond_struct = Eggshell::ExpressionEvaluator.struct(cond)
                                st[:cond_eval] = @proc.expr_eval(cond_struct)[0]
                        end
                else
                        st[:cond_eval] = true
                end

                if st[:cond_eval] && !st[:cond_met]
                        st[:cond_met] = true
                        process_lines(lines, buffer, depth + 1)
                end
        elsif macname == :break
                lvl = p0 || 1
                i = depth - 1

                # set breaks at each found loop until # of levels reached
                while i >= 0
                        st = @state[i]
                        i -= 1
                        next if !st
                        if st[:type] == :for || st[:type] == :while || st[:type] == :loop
                                lvl -= 1
                                st[:break] = true
                                break if lvl <= 0
                        end
                end
        elsif macname == :next
                lvl = p0 || 1
                i = depth - 1

                # set breaks at each found loop until # of levels reached
                while i >= 0
                        st = @state[i]
                        i -= 1
                        next if !st
                        if st[:type] == :for || st[:type] == :while || st[:type] == :loop
                                lvl -= 1
                                st[:next] = true
                                break if lvl <= 0
                        end
                end
        end
end
set_processor(eggshell) click to toggle source
# File lib/eggshell/bundles/basics-old.rb, line 644
def set_processor(eggshell)
        @proc = eggshell
        @proc.register_macro(self, *%w(if elsif else loop for while break next))
end

Protected Instance Methods

process_lines(lines, buffer, depth, raw = false) click to toggle source
# File lib/eggshell/bundles/basics-old.rb, line 812
def process_lines(lines, buffer, depth, raw = false)
        return if !lines
        ln = []
        lines.each do |line|
                if line.is_a?(Eggshell::Block)
                        if ln.length > 0
                                buffer << (raw ? @proc.expand_expr(ln.join("\n")) : @proc.process(ln, depth))
                                ln = []
                        end
                        line.process(buffer, depth)
                        if @state[depth-1][:next]
                                @state[depth-1][:next] = false
                                break
                        end
                else
                        ln << line
                end
        end
        if ln.length > 0
                buffer << (raw ? @proc.expand_expr(ln.join("\n")) : @proc.process(ln, depth))
        end
end