mirror of
https://github.com/inkarkat/vim-ingo-library.git
synced 2026-05-29 11:18:51 +02:00
137 lines
5.1 KiB
VimL
137 lines
5.1 KiB
VimL
" ingo/plugin/marks.vim: Functions for reserving marks for plugin use.
|
|
"
|
|
" DEPENDENCIES:
|
|
"
|
|
" Copyright: (C) 2010-2019 Ingo Karkat
|
|
" The VIM LICENSE applies to this script; see ':help copyright'.
|
|
"
|
|
" Maintainer: Ingo Karkat <ingo@karkat.de>
|
|
|
|
function! ingo#plugin#marks#Reuse( pos, ... )
|
|
"******************************************************************************
|
|
"* PURPOSE:
|
|
" Locate (for reuse) an existing mark at a:pos.
|
|
"* ASSUMPTIONS / PRECONDITIONS:
|
|
" None.
|
|
"* EFFECTS / POSTCONDITIONS:
|
|
" None.
|
|
"* INPUTS:
|
|
" a:pos Position, either [lnum, col] or the full [bufnum, lnum,
|
|
" col, off].
|
|
" a:consideredMarks Optional String or List of marks that are considered.
|
|
" Defaults to lowercase and uppercase marks a-zA-Z.
|
|
"* RETURN VALUES:
|
|
" Mark name, or empty String.
|
|
"******************************************************************************
|
|
let l:consideredMarks = (a:0 ? a:1 : 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
|
let l:pos = (len(a:pos) < 4 ? [0] + a:pos[0:1] + [0] : a:pos[0:3])
|
|
|
|
for l:mark in (type(l:consideredMarks) == type([]) ? l:consideredMarks : split(l:consideredMarks, '\zs'))
|
|
let l:targetPos = l:pos
|
|
if l:mark =~# '\u'
|
|
if l:pos[0] == 0
|
|
" Uppercase marks have the buffer number as the first element.
|
|
let l:targetPos = [bufnr('')] + l:pos[1:]
|
|
endif
|
|
else
|
|
if l:pos[0] != 0 && l:pos[0] != bufnr('')
|
|
" The searched-for position is in another buffer, so local marks
|
|
" must not be considered.
|
|
continue
|
|
else
|
|
" Lowercase marks have 0 as the first element.
|
|
let l:targetPos[0] = 0
|
|
endif
|
|
endif
|
|
|
|
if getpos("'" . l:mark) == l:targetPos
|
|
return l:mark
|
|
endif
|
|
endfor
|
|
|
|
return ''
|
|
endfunction
|
|
|
|
function! ingo#plugin#marks#FindUnused( ... )
|
|
"******************************************************************************
|
|
"* PURPOSE:
|
|
" Find the next unused mark and return it.
|
|
"* ASSUMPTIONS / PRECONDITIONS:
|
|
" None.
|
|
"* EFFECTS / POSTCONDITIONS:
|
|
" Sets the mark to avoid finding them again. The client will probably override
|
|
" the mark location, anyway.
|
|
"* INPUTS:
|
|
" a:consideredMarks Optional String or List of marks that are considered.
|
|
" Defaults to lowercase and uppercase marks a-zA-Z.
|
|
"* RETURN VALUES:
|
|
" Mark name. Throws exception if no mark is available.
|
|
"******************************************************************************
|
|
let l:consideredMarks = (a:0 && ! empty(a:1) ? a:1 : 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
|
|
|
for l:mark in (type(l:consideredMarks) == type([]) ? l:consideredMarks : split(l:consideredMarks, '\zs'))
|
|
if getpos("'" . l:mark)[1:2] == [0, 0]
|
|
" Reserve mark so that the next invocation doesn't return it again.
|
|
call setpos("'" . l:mark, getpos('.'))
|
|
return l:mark
|
|
endif
|
|
endfor
|
|
throw 'ReserveMarks: Ran out of unused marks!'
|
|
endfunction
|
|
|
|
function! ingo#plugin#marks#Reserve( number, ... )
|
|
"******************************************************************************
|
|
"* PURPOSE:
|
|
" Reserve a:number of available marks for use and return undo information.
|
|
"* ASSUMPTIONS / PRECONDITIONS:
|
|
" None.
|
|
"* EFFECTS / POSTCONDITIONS:
|
|
" Sets reserved marks to avoid finding them again. The client will probably
|
|
" override the mark location, anyway.
|
|
"* INPUTS:
|
|
" a:number Number of marks to be reserved.
|
|
" a:marks Optional string of concatenated marks. If passed, those marks
|
|
" will be taken (and current positions will be saved in the undo
|
|
" information). If empty or omitted, marks from
|
|
" g:IngoLibrary_Marks (if defined) will be used. If that also is
|
|
" empty or undefined, unused marks will be used (this is the
|
|
" default).
|
|
"* RETURN VALUES:
|
|
" reservedMarksRecord. Use keys(reservedMarksRecord) to get the names of the
|
|
" reserved marks. The records object must also be passed back to
|
|
" ingo#plugin#marks#Unreserve().
|
|
" Throws exception if no mark is available (and no a:marks had been passed).
|
|
"******************************************************************************
|
|
let l:marksRecord = {}
|
|
for l:cnt in range(0, (a:number - 1))
|
|
let l:mark = strpart((a:0 ? a:1 : (exists('g:IngoLibrary_Marks') ? g:IngoLibrary_Marks : '')), l:cnt, 1)
|
|
if empty(l:mark)
|
|
let l:unusedMark = ingo#plugin#marks#FindUnused()
|
|
let l:marksRecord[l:unusedMark] = [0, 0, 0, 0]
|
|
else
|
|
let l:marksRecord[l:mark] = getpos("'" . l:mark)
|
|
endif
|
|
endfor
|
|
return l:marksRecord
|
|
endfunction
|
|
function! ingo#plugin#marks#Unreserve( marksRecord )
|
|
"******************************************************************************
|
|
"* PURPOSE:
|
|
" Unreserve marks and restore the original mark position.
|
|
"* ASSUMPTIONS / PRECONDITIONS:
|
|
" None.
|
|
"* EFFECTS / POSTCONDITIONS:
|
|
" Resets reserved marks.
|
|
"* INPUTS:
|
|
" a:marksRecord Undo information object handed out by
|
|
" ingo#plugin#marks#Reserve().
|
|
"* RETURN VALUES:
|
|
" None.
|
|
"******************************************************************************
|
|
for l:mark in keys(a:marksRecord)
|
|
call setpos("'" . l:mark, a:marksRecord[l:mark])
|
|
endfor
|
|
endfunction
|
|
|
|
" vim: set ts=8 sts=4 sw=4 noexpandtab ff=unix fdm=syntax :
|