nvim-rpgle/autoload/rpgle/movement.vim
2023-07-31 09:22:36 +02:00

99 lines
2.6 KiB
VimL

" Vim autoload file
" Language: Free-Form ILE RPG
" Maintainer: Andreas Louv <andreas@louv.dk>
" Last Change: Dec 04, 2018
" Version: 10
" URL: https://github.com/andlrc/rpgle.vim
function! rpgle#movement#NextSection(motion, flags, mode) range abort
let cnt = v:count1
let old_pos = line('.')
if a:mode ==# 'x'
normal! gv
endif
normal! 0
mark '
while cnt > 0
call search(a:motion, a:flags . 'W')
if old_pos == line('.')
execute 'norm!' a:flags =~# 'b' ? 'gg' : 'G'
endif
let old_pos = line('.')
let cnt = cnt - 1
endwhile
normal! ^
endfunction
function! rpgle#movement#NextNest(flags) abort
let flags = a:flags
let fn = a:flags ==# 'b' ? 'max' : 'min'
" We can get the list from ``b:match_words'' and just use first and last of
" each group
let poss = filter(map(split(b:match_words, ','),
\ { key, val ->
\ s:nextNestSearch(split(val, ':'), flags) }),
\ { key, val -> val > 0 })
let new_pos = call(fn, [poss])
if new_pos > 0
execute 'normal! ' . new_pos . 'G^'
endif
endfunction
function! s:nextNestSearch(kw, flags) abort
if a:kw[0] =~? 'if'
let middle = '\<\(else\|elseif\)\>'
elseif a:kw[0] =~? 'select'
let middle = '\<\(when\|other\)\>'
else
let middle = ''
endif
return s:findpair(a:kw[0], middle, a:kw[-1], a:flags)
endfunction
function! s:findpair(start, middle, end, flags) abort
" Find a pair which isn't inside a string nor comment
return searchpair(a:start, a:middle, a:end, a:flags . 'nW',
\ 'synIDattr(synID(line("."), col("."), 1), "name") =~? "string\\|comment"')
endfunction
function! rpgle#movement#Operator(ai) abort
let pairs = map(split(b:match_words, ','), { key, val ->
\ [split(val, ':')[0], split(val, ':')[-1]] })
" Find a pair which isn't inside a string nor comment
let poss = filter(map(pairs,
\ { key, val -> {"pair": val, "pos": s:findpair(val[0], '', val[1], 'b')} }),
\ { key, val -> val.pos > 0 })
let closest = { "index": 0, "pos": -1 }
let index = 0
for pos in poss
if pos.pos > closest.pos
let closest.pos = pos.pos
let closest.index = index
let closest.pair = pos.pair
endif
let index = index + 1
endfor
let match_words = b:match_words
let b:match_words = join(closest.pair, ':')
execute 'normal! ' . closest.pos . 'G^V'
normal %
let b:match_words = match_words
if a:ai == 'i'
normal! koj
endif
endfunction