dot_files/vim-plugins/bundle/xptemplate/ftplugin/_common/common.xpt.vim

666 lines
14 KiB
VimL
Raw Permalink Normal View History

2017-07-09 00:26:06 +03:00
" Default settings and functions used in every snippet file.
XPTemplate priority=all
" containers
let s:f = g:XPTfuncs()
XPTvar $author $author is not set, you need to set g:xptemplate_vars="$author=your_name" in .vimrc
XPTvar $email $email is not set, you need to set g:xptemplate_vars="$email=your_email@com" in .vimrc
XPTvar $VOID
" if () ** {
" else ** {
XPTvar $BRif ' '
" } ** else {
XPTvar $BRel \n
" for () ** {
" while () ** {
" do ** {
XPTvar $BRloop ' '
" struct name ** {
XPTvar $BRstc ' '
" int fun() ** {
" class name ** {
XPTvar $BRfun ' '
" int fun ** (
" class name ** (
XPTvar $SPfun ''
" int fun( ** arg ** )
" if ( ** condition ** )
" for ( ** statement ** )
" [ ** a, b ** ]
" { ** 'k' : 'v' ** }
XPTvar $SParg ' '
" if ** (
" while ** (
" for ** (
XPTvar $SPcmd ' '
" a ** = ** b
" a = a ** + ** 1
" (a, ** b, ** )
XPTvar $SPop ' '
XPTvar $DATE_FMT '%Y %b %d'
XPTvar $TIME_FMT '"%H:%M:%S"'
XPTvar $DATETIME_FMT '%c'
XPTvar $TRUE 1
XPTvar $FALSE 0
XPTvar $NULL 0
XPTvar $UNDEFINED 0
XPTvar $VOID_LINE
XPTvar $CURSOR_PH CURSOR
XPTinclude
\ _common/personal
\ _common/inlineComplete
\ _common/common.*
let s:f_prototype = xpt#snipfunction#funcs
call extend( s:f, s:f_prototype, 'error' )
fun! s:f._xSnipName()
return self._ctx.renderContext.snipObject.name
endfunction
fun! s:f.GetWrappedText()
let wrap = self._ctx.renderContext.wrap
let [ l, r ] = self.ItemEdges()
if !has_key( wrap, 'text' )
return 0
endif
if l == '' && r == ''
return { 'nIndent' : wrap.indent,
\ 'action' : 'text',
\ 'parseIndent' : 0,
\ 'text' : wrap.text }
else
let wrap.curline = wrap.lines[ 0 ]
let wrap.lines = wrap.lines[ 1 : ]
return wrap.curline
endif
endfunction
fun! s:f.WrapAlignAfter( min )
let wrap = self._ctx.renderContext.wrap
let n = max( [ a:min, wrap.max ] ) - len( wrap.curline )
return repeat( ' ', n )
endfunction
fun! s:f.WrapAlignBefore( min )
let wrap = self._ctx.renderContext.wrap
let n = max( [ a:min, wrap.max ] ) - len( wrap.lines[ 0 ] )
return repeat( ' ', n )
endfunction
fun! s:f.Item()
return get( self._ctx.renderContext, 'item', {} )
endfunction
" current name
fun! s:f.ItemName() "{{{
return get( self.Item(), 'name', '' )
endfunction "}}}
let s:f.N = s:f.ItemName
" name with edge
fun! s:f.ItemFullname() "{{{
return get( self.Item(), 'fullname', '')
endfunction "}}}
let s:f.NN = s:f.ItemFullname
" current value user typed
fun! s:f.ItemValue() dict "{{{
return self.GetVar( '$UserInput' )
endfunction "}}}
let s:f.V = s:f.ItemValue
fun! s:f.PrevItem( n )
let hist = get( self._ctx.renderContext, 'history', [] )
return get( hist, a:n, {} )
endfunction
fun! s:f.ItemInitValue()
return get( self.Item(), 'initValue', '' )
endfunction
let s:f.IV = s:f.ItemInitValue
fun! s:f.ItemValueStripped( ... )
let ptn = a:0 == 0 || a:1 =~ 'lr'
\ ? '\V\^\s\*\|\s\*\$'
\ : ( a:1 == 'l'
\ ? '\V\^\s\*'
\ : '\V\s\*\$' )
return substitute( self.ItemValue(), ptn, '', 'g' )
endfunction
let s:f.VS = s:f.ItemValueStripped
fun! s:f.ItemPos()
return XPMposStartEnd( self._ctx.renderContext.leadingPlaceHolder.mark )
endfunction
fun! s:f.ItemInitValueWithEdge()
let [ l, r ] = self.ItemEdges()
return l . self.IV() . r
endfunction
let s:f.IVE = s:f.ItemInitValueWithEdge
" if value match one of the regexps
fun! s:f.Vmatch( ... )
let v = self.V()
for reg in a:000
if match(v, reg) != -1
return 1
endif
endfor
return 0
endfunction
" value matchstr
fun! s:f.VMS( reg )
return matchstr(self.V(), a:reg)
endfunction
" edge stripped value
fun! s:f.ItemStrippedValue()
let v = self.V()
let [edgeLeft, edgeRight] = self.ItemEdges()
let v = substitute( v, '\V\^' . edgeLeft, '', '' )
let v = substitute( v, '\V' . edgeRight . '\$', '', '' )
return v
endfunction
let s:f.V0 = s:f.ItemStrippedValue
fun! s:f.Phase() dict
return get( self._ctx.renderContext, 'phase', '' )
endfunction
" TODO this is not needed at all except as a shortcut.
" equals to expand()
fun! s:f.E(s) "{{{
return expand(a:s)
endfunction "}}}
" return the context
fun! s:f.Context() "{{{
return self._ctx.renderContext
endfunction "}}}
let s:f.C = s:f.Context
" TODO this is not needed at all except as a shortcut.
" post filter substitute
fun! s:f.S(str, ptn, rep, ...) "{{{
let flg = a:0 >= 1 ? a:1 : 'g'
return substitute(a:str, a:ptn, a:rep, flg)
endfunction "}}}
" equals to S(C().value, ...)
fun! s:f.SubstituteWithValue(ptn, rep, ...) "{{{
let flg = a:0 >= 1 ? a:1 : 'g'
return substitute(self.V(), a:ptn, a:rep, flg)
endfunction "}}}
let s:f.SV = s:f.SubstituteWithValue
fun! s:f.HasStep( name )
let namedStep = get( self._ctx.renderContext, 'namedStep', {} )
return has_key( namedStep, a:name )
endfunction
" reference to another finished item value
fun! s:f.Reference(name) "{{{
let namedStep = get( self._ctx.renderContext, 'namedStep', {} )
return get( namedStep, a:name, '' )
endfunction "}}}
let s:f.R = s:f.Reference
fun! s:f.Snippet( name )
return get( self._ctx.renderContext.ftScope.allTemplates, a:name, { 'tmpl' : '' } )[ 'tmpl' ]
endfunction
" black hole
fun! s:f.Void(...) "{{{
return ""
endfunction "}}}
let s:f.VOID = s:f.Void
" Echo several expression and concat them.
" That's the way to use normal vim script expression instead of mixed string
fun! s:f.Echo( ... )
let text = ''
if a:0 > 0
let text = a:1
endif
return { 'action': 'text', 'text': text }
endfunction
fun! s:f.EchoIf( isTrue, ... )
if a:isTrue
return join( a:000, '' )
else
return self.V()
endif
endfunction
fun! s:f.EchoIfEq( expected, ... )
if self.V() ==# a:expected
return join( a:000, '' )
else
return self.V()
endif
endfunction
fun! s:f.EchoIfNoChange( ... )
if self.V0() ==# self.ItemName()
return join( a:000, '' )
else
return self.V()
endif
endfunction
fun! s:f.Commentize( text )
if has_key( self, '$CL' )
return self[ '$CL' ] . ' ' . a:text . ' ' . self[ '$CR' ]
elseif has_key( self, '$CS' )
return self[ '$CS' ] . ' ' . a:text
endif
return a:text
endfunction
fun! s:f.VoidLine()
return self.Commentize( 'void' )
endfunction
" Same with Echo* except echoed text is to be build to generate dynamic place
" holders
fun! s:f.Build( ... )
return { 'action' : 'build', 'text' : join( a:000, '' ) }
endfunction
let s:f.Embed = s:f.Build
fun! s:f.BuildSnippet( snipname )
return { 'action' : 'build', 'snippet' : a:snipname }
endfunction
fun! s:f.BuildIfChanged( ... )
let v = substitute( self.V(), "\\V\n\\|\\s", '', 'g')
" let fn = substitute( self.ItemFullname(), "\\V\n\\|\\s", '', 'g')
let fn = substitute( self.ItemInitValueWithEdge(), "\\V\n\\|\\s", '', 'g')
if v ==# fn || v == ''
return ''
else
return { 'action' : 'build', 'text' : join( a:000, '' ) }
endif
endfunction
fun! s:f.BuildIfNoChange( ... )
let v = substitute( self.V(), "\\V\n\\|\\s", '', 'g')
" let fn = substitute( self.ItemFullname(), "\\V\n\\|\\s", '', 'g')
let fn = substitute( self.ItemInitValueWithEdge(), "\\V\n\\|\\s", '', 'g')
if v ==# fn
return { 'action' : 'build', 'text' : join( a:000, '' ) }
else
return 0
endif
endfunction
" trigger nested template
fun! s:f.Trigger( name ) "{{{
return {'action' : 'expandTmpl', 'tmplName' : a:name}
endfunction "}}}
fun! s:f.Finish(...)
let opt = {}
if a:0 > 0
let opt.text = a:1
endif
return self.Fin(opt)
endfunction
fun! s:f.FinishOuter( ... )
let opt = {"marks" : "mark"}
if a:0 > 0
let opt.text = a:1
endif
return self.Fin(opt)
endfunction
fun! s:f.FinishInner( ... )
let opt = {"marks" : "innerMarks"}
if a:0 > 0
let opt.text = a:1
endif
return self.Fin(opt)
endfunction
fun! s:f.Fin(opt)
" there is still items left
if ! empty( self._ctx.renderContext.itemList )
return get(a:opt, 'text', 0)
endif
let r = {'action' : 'finishTemplate'}
if has_key(a:opt, 'text')
let r.text = a:opt.text
endif
if has_key(a:opt, 'marks')
let r.marks = a:opt.marks
endif
return r
endfunction
fun! s:f.Next( ... )
if a:0 == 0
return { 'nav' : 'next' }
else
return { 'nav' : 'next', 'text' : join( a:000, '' ) }
endif
endfunction
fun! s:f.Remove()
return { 'action' : 'text', 'nav' : 'next', 'text' : '' }
endfunction
" This function is intended to be used for popup selection :
" XSET bidule=Choose([' ','dabadi','dabada'])
fun! s:f.Choose( lst, ... ) "{{{
let val = { 'action' : 'pum', 'pum' : a:lst }
if a:0 == 1
let val.acceptEmpty = a:1 != 0
endif
return val
endfunction "}}}
fun! s:f.ChooseStr(...) "{{{
return copy( a:000 )
endfunction "}}}
" XXX
" Fill in postType, and finish template rendering at once.
" This make nested template rendering go back to upper level, top-level
" template rendering quit.
fun! s:f.xptFinishTemplateWith(postType) dict
endfunction
" XXX
" Fill in postType, jump to next item. For creating item being able to be
" automatically filled in
fun! s:f.xptFinishItemWith(postType) dict
endfunction
" TODO test me
fun! s:f.UnescapeMarks(string) dict
let patterns = self._ctx.renderContext.snipObject.ptn
let charToEscape = '\(\[' . patterns.l . patterns.r . ']\)'
let r = substitute( a:string, '\v(\\*)\1\\?\V' . charToEscape, '\1\2', 'g')
return r
endfunction
let s:f.UE = s:f.UnescapeMarks
fun! s:f.headerSymbol(...) "{{{
let h = expand('%:t')
let h = substitute(h, '\.', '_', 'g') " replace . with _
let h = substitute(h, '.', '\U\0', 'g') " make all characters upper case
return '__'.h.'__'
endfunction "}}}
fun! s:f.date(...) "{{{
return strftime( self.GetVar( '$DATE_FMT' ) )
endfunction "}}}
fun! s:f.datetime(...) "{{{
return strftime( self.GetVar( '$DATETIME_FMT' ) )
endfunction "}}}
fun! s:f.time(...) "{{{
return strftime( self.GetVar( '$TIME_FMT' ) )
endfunction "}}}
fun! s:f.file(...) "{{{
return expand("%:t")
endfunction "}}}
fun! s:f.fileRoot(...) "{{{
return expand("%:t:r")
endfunction "}}}
fun! s:f.fileExt(...) "{{{
return expand("%:t:e")
endfunction "}}}
fun! s:f.path(...) "{{{
return expand("%:p")
endfunction "}}}
fun! s:f.UpperCase( v )
return substitute(a:v, '.', '\u&', 'g')
endfunction
fun! s:f.LowerCase( v )
return substitute(a:v, '.', '\l&', 'g')
endfunction
" Return Item Edges
fun! s:f.ItemEdges() "{{{
let leader = get( self._ctx.renderContext, 'leadingPlaceHolder', {} )
if has_key( leader, 'leftEdge' )
return [ leader.leftEdge, leader.rightEdge ]
else
return [ '', '' ]
endif
endfunction "}}}
let s:f.Edges = s:f.ItemEdges
fun! s:f.ItemCreate( name, edges, filters )
let [ ml, mr ] = XPTmark()
let item = ml . a:name
if has_key( a:edges, 'left' )
let item = ml . a:edges.left . item
endif
if has_key( a:edges, 'right' )
let item .= ml . a:edges.right
endif
let item .= mr
if has_key( a:filters, 'post' )
let item .= a:filters.post . mr . mr
endif
return item
endfunction
" {{{ Quick Repetition
" If something typed, <tab>ing to next generate another item other than the
" typed.
"
" If nothing typed but only <tab> to next, clear it.
"
" Normal clear typed, also clear it
" TODO escape mark character in a:sep or a:item
" }}}
fun! s:f.ExpandIfNotEmpty( sep, item, ... ) "{{{
let v = self.V()
let [ ml, mr ] = XPTmark()
if a:0 != 0
let r = a:1
else
let r = ''
endif
" let t = ( v == '' || v == a:item || v == ( a:sep . a:item . r ) )
let t = ( v == '' || v =~ '\V' . a:item )
\ ? ''
\ : self.Build( v
\ . ml . a:sep . ml . a:item . ml . r . mr
\ . 'ExpandIfNotEmpty(' . string( a:sep ) . ', ' . string( a:item ) . ')' . mr . mr )
return t
endfunction "}}}
fun! s:f.ExpandInsideEdge( newLeftEdge, newRightEdge )
let v = self.V()
let fullname = self.ItemFullname()
let [ el, er ] = self.ItemEdges()
if v ==# fullname || v == ''
return ''
endif
return substitute( v, '\V' . er . '\$' , '' , '' )
\. self.ItemCreate( self.ItemName(), { 'left' : a:newLeftEdge, 'right' : a:newRightEdge }, {} )
\. er
endfunction
fun! s:f.NIndent()
return &shiftwidth
endfunction
fun! s:f.ResetIndent( nIndent, text )
return { 'action' : 'resetIndent', 'resetIndent' : 1, 'nIndent' : a:nIndent, 'text' : a:text }
endfunction
fun! s:f.CmplQuoter_pre() dict
if !g:xptemplate_brace_complete
return ''
endif
let v = substitute( self.ItemStrippedValue(), '\V\^\s\*', '', '' )
let first = matchstr( v, '\V\^\[''"]' )
if first == ''
return ''
endif
let v = substitute( v, '\V\[^' . first . ']', '', 'g' )
if v == first
" only 1 quoter
return first
else
return ''
endif
endfunction
fun! s:f.AutoCmpl( keepInPost, list, ... )
if !a:keepInPost && self.Phase() == 'post'
return ''
endif
if type( a:list ) == type( [] )
let list = a:list
else
let list = [ a:list ] + a:000
endif
let v = self.V0()
if v == ''
return ''
endif
for word in list
if word =~ '\V\^' . v
return word[ len( v ) : ]
endif
endfor
return ''
endfunction
" Short names are normally not good. Some alias to those short name functions are
" made, with meaningful names.
"
" They all start with prefix 'xpt'.
"
" ================================= Snippets ===================================
" Shortcuts
call XPTdefineSnippet('Author', {}, '`$author^')
call XPTdefineSnippet('Email', {}, '`$email^')
call XPTdefineSnippet("Date", {}, "`date()^")
call XPTdefineSnippet("File", {}, "`file()^")
call XPTdefineSnippet("Path", {}, "`path()^")
call XPTdefineSnippet('"_', {'hint' : '" .. "', 'wraponly' : 'w' }, '"`w^"')
call XPTdefineSnippet("'_", {'hint' : "' .. '", 'wraponly' : 'w' }, "'`w^'")
call XPTdefineSnippet("<_", {'hint' : '< .. >', 'wraponly' : 'w' }, '<`w^>')
call XPTdefineSnippet("(_", {'hint' : '( .. )', 'wraponly' : 'w' }, '(`w^)')
call XPTdefineSnippet("[_", {'hint' : '[ .. ]', 'wraponly' : 'w' }, '[`w^]')
call XPTdefineSnippet("{_", {'hint' : '{ .. }', 'wraponly' : 'w' }, '{`w^}')
call XPTdefineSnippet("`_", {'hint' : '` .. `', 'wraponly' : 'w' }, '\``w^\`')