frawor / plugin / frawor / fwc / constructor.vim

"▶1 Header
scriptencoding utf-8
execute frawor#Setup('0.1', {'@/resources': '0.0'}, 1)
let s:constructor={}
let s:comp={}
"▶1 string     :: a → String
function s:constructor.string(val)
    if type(a:val)==type('') && a:val=~#"[\r\n@]"
        return ('"'.substitute(substitute(substitute(escape(a:val, '\"'),
                    \          "@",  '\\x40', 'g'),
                    \          "\n", '\\n',   'g'),
                    \          "\r", '\\r',   'g')
                    \.'"')
    endif
    return substitute(substitute(substitute(string(a:val),
                \"@",      '''."\\x40".''', 'g'),
                \"\n",     '''."\\n".''',   'g'),
                \"\r",     '''."\\r".''',   'g')
endfunction
"▶1 getexpr
function s:F.getexpr(expr, l)
    if !empty(a:l)
        return call('printf', [a:expr]+map(copy(a:l), 's:F.string(v:val)'))
    endif
    return ''.a:expr
endfunction
"▶1 getstr
function s:F.getstr(s)
    return a:s
endfunction
"▶1 _add       :: item, ... + self → self + self
function s:constructor.add(...)
    let self.l+=a:000
    return self
endfunction
"▶1 _up        :: &self
function s:constructor.up()
    call remove(self.stack, -1)
    let self.l=self.stack[-1]
    return self
endfunction
"▶1 _down      :: &self(list)
function s:constructor.down(list)
    call add(self.stack, a:list)
    let self.l=a:list
    return self
endfunction
"▶1 _deeper    :: ()[, conelement1[, ...]] + self → self + self
function s:constructor.deeper(...)
    let con=copy(a:000)
    call self.add(con)
    return self.down(con)
endfunction
"▶1 _out       :: &self
function s:constructor.out()
    if type(get(self.l, 0))==type('')
        return self.up()
    endif
    return self
endfunction
"▶1 _toblock
function s:constructor.toblock(block)
    while get(self.l, 0) isnot a:block
        call self.up()
    endwhile
    return self
endfunction
"▶1 do: do, continue, break
"▶2 comp.do
function s:comp.do(r, toextend, indent, item)
    call add(a:r, repeat(' ', &sw*a:indent).remove(a:item, 0))
endfunction
"▶2 continue   :: &self
function s:constructor.continue()
    return self.out().deeper('do', 'continue').up()
endfunction
"▶2 break      :: &self
function s:constructor.break()
    return self.out().deeper('do', 'break').up()
endfunction
"▶2 do         :: &self(vimLstr)
function s:constructor.do(str)
    return self.out().deeper('do', a:str).up()
endfunction
"▶1 if block
"▶2 comp.if
function s:comp.if(r, toextend, indent, item)
    call add(a:r, repeat(' ', &sw*a:indent).'if '.remove(a:item, 0))
    if !empty(a:item)
        call extend(a:toextend,map(remove(a:item,0),'['.(a:indent+1).',v:val]'))
    endif
    while !empty(a:item)
        let type=remove(a:item, 0)
        if type is# 'elseif'
            call add(a:toextend, [a:indent, 'elseif '.remove(a:item, 0)])
        elseif type is# 'else'
            call add(a:toextend, [a:indent, 'else'])
        elseif type is# 'endif'
            break
        endif
        call extend(a:toextend,map(remove(a:item,0),'['.(a:indent+1).',v:val]'))
    endwhile
    call add(a:toextend, [a:indent, 'endif'])
endfunction
"▶2 if         :: &self(expr)
function s:constructor.if(expr, ...)
    return self.out().deeper('if', s:F.getexpr(a:expr, a:000)).deeper()
endfunction
"▶2 elseif     :: &self(expr)
function s:constructor.elseif(expr, ...)
    return self.toblock('if').add('elseif', s:F.getexpr(a:expr, a:000)).deeper()
endfunction
"▶2 else       :: &self
function s:constructor.else()
    return self.toblock('if').add('else').deeper()
endfunction
"▶2 endif      :: &self
function s:constructor.endif()
    return self.toblock('if').add('endif').up()
endfunction
"▶2 addif      :: &self(expr?)
function s:constructor.addif(...)
    if a:0
        if get(self.l, 0) is# 'if' && get(self.l, -2) isnot# 'else' &&
                    \                 get(self.l, -1) isnot# 'endif'
            return call(self.elseif, a:000, self)
        else
            return call(self.if, a:000, self)
        endif
    else
        if get(self.l, 0) is# 'if'
            return self.else()
        else
            return self
        endif
    endif
endfunction
"▶1 try block
"▶2 comp.try
function s:comp.try(r, toextend, indent, item)
    call add(a:r, repeat(' ', &sw*a:indent).'try')
    if !empty(a:item)
        call extend(a:toextend,map(remove(a:item,0),'['.(a:indent+1).',v:val]'))
    endif
    while !empty(a:item)
        let type=remove(a:item, 0)
        if type is# 'catch'
            call add(a:toextend, [a:indent, 'catch '.remove(a:item, 0)])
        elseif type is# 'finally'
            call add(a:toextend, [a:indent, 'finally'])
        elseif type is# 'endtry'
            break
        endif
        call extend(a:toextend,map(remove(a:item,0),'['.(a:indent+1).',v:val]'))
    endwhile
    call add(a:toextend, [a:indent, 'endtry'])
endfunction
"▶2 try        :: &self()
function s:constructor.try()
    return self.out().deeper('try').deeper()
endfunction
"▶2 catch      :: &self(regex?)
function s:constructor.catch(...)
    return self.toblock('try')
                \.add('catch', '/'.escape(get(a:000,0,'.*'),'/').'/').deeper()
endfunction
"▶2 finally    :: &self
function s:constructor.finally()
    return self.toblock('try').add('finally').deeper()
endfunction
"▶1 cycles: while, for; continue, break
"▶2 comp.while
function s:comp.while(r, toextend, indent, item)
    call add(a:r, repeat(' ', &sw*a:indent).'while '.remove(a:item, 0))
    call extend(a:toextend, map(remove(a:item, 0), '['.(a:indent+1).', v:val]'))
    call add(a:toextend, [a:indent, 'endwhile'])
endfunction
"▶2 while      :: &self(expr)
function s:constructor.while(expr, ...)
    return self.out().deeper('while', s:F.getexpr(a:expr, a:000)).deeper()
endfunction
"▶2 comp.for
function s:comp.for(r, toextend, indent, item)
    call add(a:r, repeat(' ', &sw*a:indent).'for '.remove(a:item, 0).' in '.
                \                                             remove(a:item, 0))
    call extend(a:toextend, map(remove(a:item, 0), '['.(a:indent+1).', v:val]'))
    call add(a:toextend, [a:indent, 'endfor'])
endfunction
"▶2 for        :: &self(vars, expr)
function s:constructor.for(vars, expr, ...)
    return self.out().deeper('for', a:vars, s:F.getexpr(a:expr, a:000)).deeper()
endfunction
"▶1 execute: call, throw, return
"▶2 comp.execute
function s:comp.execute(r, toextend, indent, item)
    call add(a:r,repeat(' ',&sw*a:indent).remove(a:item,0).' '.remove(a:item,0))
endfunction
"▶2 return, call, execute, echo, echomsg, echon
for s:type in ['return', 'call', 'execute', 'echo', 'echomsg', 'echon']
    execute      "function s:constructor.".s:type."(expr, ...)\n".
                \"    return self.out()".
                \                ".deeper('execute', ".
                \                        "'".s:type."', ".
                \                        "s:F.getexpr(a:expr, a:000))".
                \                ".up()\n".
                \"endfunction"
endfor
unlet s:type
"▶2 throw      :: &self(expr)
function s:constructor.throw(expr, ...)
    return self.out().deeper('execute', 'throw', s:F.getexpr(a:expr, a:000))
                \.up().up()
endfunction
"▶1 let: let, strappend, increment, decrement
"▶2 comp.let
function s:comp.let(r, toextend, indent, item)
    call add(a:r, repeat(' ', &sw*a:indent).'let '.remove(a:item, 0).
                \                               remove(a:item, 0).'='.
                \                                  remove(a:item, 0))
endfunction
"▶2 let, strappend
for [s:type, s:s] in [['let', ''], ['strappend', '.']]
    execute      "function s:constructor.".s:type."(var, expr, ...)\n".
                \"    return self.out()".
                \                ".deeper('let', a:var, '".s:s."', ".
                \                        "s:F.getexpr(a:expr, a:000))".
                \                ".up()\n".
                \"endfunction"
endfor
unlet s:type s:s
"▶2 increment  :: &self(var[, expr])
function s:constructor.increment(var, ...)
    let incval=get(a:000, 0, 1)
    call self.out()
    if type(incval)==type(0) && incval<0
        call self.deeper('let', a:var, '-', ''.(-incval))
    else
        call self.deeper('let', a:var, '+',  s:F.getexpr(incval, a:000[1:]))
    endif
    return self.up()
endfunction
"▶2 decrement  :: &self(var[, expr])
function s:constructor.decrement(var, ...)
    let incval=get(a:000, 0, 1)
    call self.out()
    if type(incval)==type(0) && incval<0
        call self.deeper('let', a:var, '+', ''.(-incval))
    else
        call self.deeper('let', a:var, '-',  s:F.getexpr(incval, a:000[1:]))
    endif
    return self.up()
endfunction
"▶1 unlet      :: &self(var|[var])
function s:comp.unlet(r, toextend, indent, item)
    call add(a:r, repeat(' ', &sw*a:indent).'unlet '.join(remove(a:item, 0)))
endfunction
function s:constructor.unlet(var)
    return self.out().deeper('unlet', type(a:var)==type('')?[a:var]:a:var)
                \.up()
endfunction
"▶1 _tolist    :: () + self → [String]
function s:constructor.tolist()
    let r=[]
    let items=map(deepcopy(self.tree), '[0, v:val]')
    let toextend=[]
    while !empty(items)
        let [indent, item]=remove(items, 0)
        if type(item)==type('')
            call add(r, repeat(' ', &sw*indent).item)
        else
            let type=remove(item, 0)
            if has_key(s:comp, type)
                call call(s:comp[type], [r, toextend, indent, item], {})
            endif
            if !empty(toextend)
                call extend(items, remove(toextend, 0, -1), 0)
            endif
        endif
        unlet item
    endwhile
    return r
endfunction
"▶1 new
call extend(s:constructor, {'tree': [], 'stack': [],})
function s:F.new()
    let r=deepcopy(s:constructor)
    call add(r.stack, r.tree)
    let r.l=r.stack[-1]
    return r
endfunction
call s:_f.postresource('new_constructor', s:F.new)
"▶1
call frawor#Lockvar(s:, '')
" vim: fmr=▶,▲ sw=4 ts=4 sts=4 et tw=80
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.