mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-03 12:50:03 +08:00
157 lines
4.5 KiB
VimL
157 lines
4.5 KiB
VimL
" Constructor:
|
|
" ============
|
|
|
|
function! sj#argparser#ruby#Construct(start_index, end_index, line)
|
|
let parser = sj#argparser#common#Construct(a:start_index, a:end_index, a:line)
|
|
|
|
call extend(parser, {
|
|
\ 'hash_type': '',
|
|
\ 'cursor_arg': 0,
|
|
\ 'cursor_col': col('.'),
|
|
\
|
|
\ 'Process': function('sj#argparser#ruby#Process'),
|
|
\ 'PushArg': function('sj#argparser#ruby#PushArg'),
|
|
\ 'AtFunctionEnd': function('sj#argparser#ruby#AtFunctionEnd'),
|
|
\ 'ExpandOptionHash': function('sj#argparser#ruby#ExpandOptionHash'),
|
|
\ 'MarkOptionArg': function('sj#argparser#ruby#MarkOptionArg'),
|
|
\ })
|
|
|
|
return parser
|
|
endfunction
|
|
|
|
" Methods:
|
|
" ========
|
|
|
|
function! sj#argparser#ruby#Process() dict
|
|
while !self.Finished()
|
|
if self.body[0] == ','
|
|
call self.PushArg()
|
|
call self.Next()
|
|
continue
|
|
elseif self.AtFunctionEnd()
|
|
break
|
|
elseif self.body[0] =~ '[''"]'
|
|
call self.JumpPair("'\"", "'\"")
|
|
|
|
" Example: 'some key': value
|
|
if len(self.body) > 1 && self.body[1] == ':'
|
|
call self.MarkOptionArg('new')
|
|
endif
|
|
elseif self.body[0] =~ "[{\[`(/]"
|
|
call self.JumpPair("{[`(/", "}]`)/")
|
|
elseif self.body[0] == '%'
|
|
call self.PushChar()
|
|
if self.body[0] =~ '[qQrswWx]'
|
|
call self.PushChar()
|
|
endif
|
|
let delimiter = self.body[0]
|
|
if delimiter =~ '[[({<]'
|
|
call self.JumpPair('[({<', '])}>')
|
|
else
|
|
call self.JumpPair(delimiter, delimiter)
|
|
endif
|
|
elseif self.body =~ '^=>'
|
|
" Example: 'some key' => value
|
|
call self.MarkOptionArg('classic')
|
|
elseif self.body =~ '^\(\k\|[?!]\):[^:]'
|
|
" Example: some_key: value
|
|
call self.MarkOptionArg('new')
|
|
endif
|
|
|
|
call self.PushChar()
|
|
endwhile
|
|
|
|
if len(self.current_arg) > 0
|
|
call self.PushArg()
|
|
endif
|
|
endfunction
|
|
|
|
" Pushes the current argument either to the args or opts stack and initializes
|
|
" a new one.
|
|
function! sj#argparser#ruby#PushArg() dict
|
|
if self.current_arg_type == 'option'
|
|
call add(self.opts, sj#Trim(self.current_arg))
|
|
else
|
|
call add(self.args, sj#Trim(self.current_arg))
|
|
endif
|
|
|
|
let self.current_arg = ''
|
|
let self.current_arg_type = 'normal'
|
|
|
|
if self.cursor_col > self.index + 1
|
|
" cursor is after the current argument
|
|
let self.cursor_arg += 1
|
|
endif
|
|
endfunction
|
|
|
|
" If the last argument is a hash and no options have been parsed, splits the
|
|
" last argument and fills the options with it.
|
|
function! sj#argparser#ruby#ExpandOptionHash() dict
|
|
if len(self.opts) <= 0 && len(self.args) > 0
|
|
" then try parsing the last parameter
|
|
let last = self.args[-1]
|
|
let hash_pattern = '^{\(.*\(=>\|\k:\|[''"]:\).*\)}$'
|
|
|
|
if last =~ hash_pattern
|
|
" then it seems to be a hash, expand it
|
|
call remove(self.args, -1)
|
|
|
|
let hash = sj#ExtractRx(last, hash_pattern, '\1')
|
|
|
|
let [_from, _to, _args, opts, hash_type, _cursor_arg] =
|
|
\ sj#argparser#ruby#ParseArguments(0, -1, hash, { 'expand_options': 1 })
|
|
call extend(self.opts, opts)
|
|
let self.hash_type = hash_type
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
" Returns true if the parser is at the function's end, either because of a
|
|
" closing brace, a "do" clause or a "%>".
|
|
function! sj#argparser#ruby#AtFunctionEnd() dict
|
|
if self.body[0] == ')'
|
|
return 1
|
|
elseif self.body =~ '\v^\s*do(\s*\|.*\|)?(\s*-?\%\>\s*)?$'
|
|
return 1
|
|
elseif self.body =~ '^\s*-\?%>'
|
|
return 1
|
|
endif
|
|
|
|
return 0
|
|
endfunction
|
|
|
|
" Public functions:
|
|
" =================
|
|
|
|
function! sj#argparser#ruby#LocateFunction()
|
|
return sj#argparser#common#LocateRubylikeFunction(
|
|
\ '\k\+[?!]\=',
|
|
\ ['rubyInterpolationDelimiter', 'rubyString']
|
|
\ )
|
|
endfunction
|
|
|
|
function! sj#argparser#ruby#MarkOptionArg(type) dict
|
|
let self.current_arg_type = 'option'
|
|
|
|
if a:type == 'new' && sj#BlankString(self.hash_type)
|
|
let self.hash_type = 'new'
|
|
elseif a:type == 'classic' && sj#BlankString(self.hash_type)
|
|
let self.hash_type = 'classic'
|
|
elseif a:type != self.hash_type
|
|
let self.hash_type = 'mixed'
|
|
endif
|
|
endfunction
|
|
|
|
function! sj#argparser#ruby#LocateHash()
|
|
return sj#LocateBracesOnLine('{', '}', ['rubyInterpolationDelimiter', 'rubyString'])
|
|
endfunction
|
|
|
|
function! sj#argparser#ruby#ParseArguments(start_index, end_index, line, options)
|
|
let parser = sj#argparser#ruby#Construct(a:start_index, a:end_index, a:line)
|
|
call parser.Process()
|
|
if a:options.expand_options
|
|
call parser.ExpandOptionHash()
|
|
endif
|
|
return [ a:start_index, parser.index, parser.args, parser.opts, parser.hash_type, parser.cursor_arg ]
|
|
endfunction
|