Browse Source

vim: ++vim-signature

Maxim Likhachev 5 years ago
parent
commit
25e54cb9ec
  1. 1
      etc/soft/nvim/+plugins/vim-signature/.gitignore
  2. 22
      etc/soft/nvim/+plugins/vim-signature/LICENSE
  3. 97
      etc/soft/nvim/+plugins/vim-signature/README.md
  4. 38
      etc/soft/nvim/+plugins/vim-signature/after/plugin/signature.vim
  5. 427
      etc/soft/nvim/+plugins/vim-signature/autoload/signature/mark.vim
  6. 174
      etc/soft/nvim/+plugins/vim-signature/autoload/signature/marker.vim
  7. 375
      etc/soft/nvim/+plugins/vim-signature/autoload/signature/sign.vim
  8. 195
      etc/soft/nvim/+plugins/vim-signature/autoload/signature/utils.vim
  9. 408
      etc/soft/nvim/+plugins/vim-signature/doc/signature.txt
  10. 69
      etc/soft/nvim/+plugins/vim-signature/plugin/signature.vim

1
etc/soft/nvim/+plugins/vim-signature/.gitignore vendored

@ -0,0 +1 @@
/doc/tags

22
etc/soft/nvim/+plugins/vim-signature/LICENSE

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Kartik Shenoy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

97
etc/soft/nvim/+plugins/vim-signature/README.md

@ -0,0 +1,97 @@
#### 2017-09-23:
Changed the default value of `g:SignatureForceRemoveGlobal` to 0 since using `:wviminfo!`/`:wshada!` is a very heavy hammer and because it goes against a \*vim default.
#### 2016-07-08:
Signature used to have a mapping conflict with NERDTree as both try to map the `m` key.
To get around this, I used to delete maps whenever I detected someone entering the NERDTree pane and recreate the maps upon exit.
However, this had a lot of issues and as of [cfa6452](https://github.com/kshenoy/vim-signature/commit/cfa64525305dbb8cec7eefc16e4ea460f007cd33) I've decided to remove any code that was intended to work around this since it wasn't working anyways. Refer to the discussion [here](https://github.com/kshenoy/vim-signature/issues/3#issuecomment-222565292) for more details.
Sorry for any inconvenience. If anyone has any ideas or suggestions please let me know.
# vim-signature
vim-signature is a plugin to place, toggle and display marks.
Apart from the above, you can also
* Navigate forward/backward by position/alphabetical order
* Displaying multiple marks (upto 2, limited by the signs feature)
* Placing custom signs !@#$%^&*() as visual markers
### Screenshots
![vim-signature_marks_markers](https://github.com/kshenoy/vim-signature/blob/images/screens/vim-signature_marks_markers.png?raw=true)
Displays the marks as signs. Also place visual markers
![Mark jumps](https://github.com/kshenoy/vim-signature/blob/images/screens/vim-signature_mark_jumps.gif?raw=true)
Alphabetical mark traversal and more.
![Dynamic Highlighting](https://github.com/kshenoy/vim-signature/blob/images/screens/vim-signature_dynamic_hl.png?raw=true)
Also supports dynamic highlighting of signs. In the image above the marks are colored according to the state of the line as indicated by gitgutter.
NOTE: This feature is disabled by default
More screenshots [here](http://imgur.com/a/3KQyt)
### Vim.org mirror
If you like the plugin, spread the love and rate at http://www.vim.org/scripts/script.php?script_id=4118
## Requirements
Requires Vim to be compiled with +signs to display marks.
## Installation
I recommend using a plugin manager to do the grunt work for you.
If for some reason, you do not want to use any of them, then unzip the contents of the .zip file to your ~/.vim directory.
Once that's done, out of the box, the followings mappings are defined
````
mx Toggle mark 'x' and display it in the leftmost column
dmx Remove mark 'x' where x is a-zA-Z
m, Place the next available mark
m. If no mark on line, place the next available mark. Otherwise, remove (first) existing mark.
m- Delete all marks from the current line
m<Space> Delete all marks from the current buffer
]` Jump to next mark
[` Jump to prev mark
]' Jump to start of next line containing a mark
[' Jump to start of prev line containing a mark
`] Jump by alphabetical order to next mark
`[ Jump by alphabetical order to prev mark
'] Jump by alphabetical order to start of next line having a mark
'[ Jump by alphabetical order to start of prev line having a mark
m/ Open location list and display marks from current buffer
m[0-9] Toggle the corresponding marker !@#$%^&*()
m<S-[0-9]> Remove all markers of the same type
]- Jump to next line having a marker of the same type
[- Jump to prev line having a marker of the same type
]= Jump to next line having a marker of any type
[= Jump to prev line having a marker of any type
m? Open location list and display markers from current buffer
m<BS> Remove all markers
````
This will allow the use of default behavior of m to set marks and, if the line
already contains the mark, it'll be unset.
The default behavior of `]'`, `['`, ``]` `` and ``[` `` is supported and enhanced by
wrapping around when beginning or end of file is reached.
The command `:SignatureToggle` can be used to show/hide the signs.
Note that this does not delete any of the marks but only hides them.
This is a buffer-specific command.
If for some reason, the marks and their sign displays go out of sync,
use `:SignatureRefresh` to refresh them.
For more details on customization refer the help
## Thanks to...
* Sergey Khorev for [mark-tools](http://www.vim.org/scripts/script.php?script_id=2929)
* Zak Johnson for [vim-showmarks](https://github.com/zakj/vim-showmarks)
## ToDo:
* Tie the Signature functions to vim commands that affect mark placement

38
etc/soft/nvim/+plugins/vim-signature/after/plugin/signature.vim

@ -0,0 +1,38 @@
" vim: fdm=marker:et:ts=4:sw=2:sts=2
" Maintainer: Kartik Shenoy
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Exit if the signs feature is not available or if the app has already been loaded (or "compatible" mode set)
if ( !has('signs')
\ || &cp
\ )
finish
endif
"" Exit if vim-signature is not loaded
if !exists('g:loaded_Signature')
finish
endif
if exists('g:loaded_gitgutter')
if g:SignatureMarkTextHLDynamic
unlet g:SignatureMarkTextHL
let g:SignatureMarkTextHL = function("signature#sign#GetGitGutterHLGroup")
endif
if g:SignatureMarkerTextHLDynamic
unlet g:SignatureMarkerTextHL
let g:SignatureMarkerTextHL = function("signature#sign#GetGitGutterHLGroup")
endif
endif
if exists('g:loaded_signify')
if g:SignatureMarkTextHLDynamic
unlet g:SignatureMarkTextHL
let g:SignatureMarkTextHL = function("signature#sign#GetSignifyHLGroup")
endif
if g:SignatureMarkerTextHLDynamic
unlet g:SignatureMarkerTextHL
let g:SignatureMarkerTextHL = function("signature#sign#GetSignifyHLGroup")
endif
endif

427
etc/soft/nvim/+plugins/vim-signature/autoload/signature/mark.vim

@ -0,0 +1,427 @@
" vim: fdm=marker:et:ts=4:sw=2:sts=1
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! signature#mark#Toggle(mark) " {{{1
" Description: mark = 'next' : Place new mark on current line else toggle specified mark on current line
" Arguments: mark [a-z,A-Z]
if a:mark == "next"
" Place new mark
let l:marks_list = signature#mark#GetList('free', 'buf_all')
if empty(l:marks_list)
if (!g:SignatureRecycleMarks)
" No marks available and mark re-use not in effect
call s:ReportNoAvailableMarks()
return
endif
" Remove a local mark
let l:marks_list = signature#mark#GetList('used', 'buf_curr')[0]
call signature#mark#Remove(l:marks_list[0])
endif
call s:Place(l:marks_list[0])
else
" Toggle Mark
let l:used_marks = filter(signature#mark#GetList('used', 'buf_all'), 'v:val[0] ==# a:mark')
if (len(l:used_marks) > 0)
let l:mark_pos = l:used_marks[0][1]
let l:mark_buf = l:used_marks[0][2]
if (l:mark_buf == bufnr('%'))
" If the mark is not in use in current buffer then it's a global ==> Don't worry about deleting it
if ( (l:mark_pos == line('.'))
\ && !g:SignatureForceMarkPlacement
\ )
" Mark is present on the current line. Remove it and return
call signature#mark#Remove(a:mark)
call signature#sign#ToggleDummy()
return
else
" Mark is present elsewhere in the current buffer ==> Remove it and fall-through to place new mark.
" If g:SignatureForceMarkPlacement is set, we remove and re-place it so that the sign string can be true
" to the order in which the marks were placed.
" For eg. if we place 'a, 'b and then 'a again, the sign string changes from "ab" to "ba"
" Ask for confirmation before moving mark
if (g:SignatureDeleteConfirmation)
let choice = confirm("Mark '" . a:mark . "' has been used elsewhere. Reuse it?", "&Yes\n&No", 1)
if choice == 2 | return | endif
endif
call signature#mark#Remove(a:mark)
endif
endif
endif
" Place new mark
call s:Place(a:mark)
endif
endfunction
function! signature#mark#Remove(mark) " {{{1
" Description: Remove 'mark' and its associated sign. If called without an argument, obtain it from the user
" Arguments: mark = [a-z,A-Z]
if !signature#utils#IsValidMark(a:mark)
return
endif
let l:lnum = line("'" . a:mark)
call signature#sign#Remove(a:mark, l:lnum)
execute 'delmarks ' . a:mark
call s:ForceGlobalRemoval(a:mark)
endfunction
function! s:Place(mark) " {{{1
" Description: Place new mark at current cursor position
" Arguments: mark = [a-z,A-Z]
" If a line is deleted or mark is manipulated using any non-signature method then b:sig_marks can go out of sync
" Thus, we forcibly remove signs for the mark present on any line before proceeding
call signature#sign#Remove(a:mark, 0)
execute 'normal! m' . a:mark
call signature#sign#Place(a:mark, line('.'))
endfunction
function! signature#mark#ToggleAtLine() " {{{1
" Description: If no mark on current line, add one. If marks are on the current line, remove one.
let l:marks_here = filter(signature#mark#GetList('used', 'buf_curr'), 'v:val[1] == ' . line('.'))
if empty(l:marks_here)
" Set up for adding a mark
call signature#mark#Toggle('next')
else
" Delete first mark
call signature#mark#Remove(l:marks_here[0][0])
endif
endfunction
function! signature#mark#Purge(mode) " {{{1
" Description: Delete all marks from current line
" Arguments: mode = 'line' : Delete all marks from current line
" 'all' : Delete all marks used in the buffer
let l:used_marks = signature#mark#GetList('used', 'buf_curr')
if (a:mode ==? 'line')
call filter(l:used_marks, 'v:val[1] == ' . line('.'))
endif
if ( !empty(l:used_marks)
\ && g:SignaturePurgeConfirmation
\ )
let l:msg = 'Are you sure you want to delete all marks' . (a:mode ==? 'line' ? ' from the current line' : '') . '?'
let l:ans = confirm(l:msg . ' This cannot be undone.', "&Yes\n&No", 1)
if (l:ans != 1) | return | endif
endif
for i in l:used_marks
call signature#mark#Remove(i[0])
endfor
" If marks are modified using any non-signature method, b:sig_marks can go out of sync
if (a:mode ==? 'all')
for l:lnum in keys(b:sig_marks)
call signature#sign#Unplace(l:lnum)
endfor
endif
call signature#sign#ToggleDummy()
endfunction
function! signature#mark#Goto(dir, loc, mode) " {{{1
" Arguments:
" dir = next : Jump forward
" prev : Jump backward
" loc = line : Jump to first column of line with mark
" spot : Jump to exact column of the mark
" mode = pos : Jump to next mark by position
" alpha : Jump to next mark by alphabetical order
" global : Jump only to global marks (applies to all buffers and alphabetical order)
let l:mark = ""
let l:dir = a:dir
if a:mode ==? "global"
let l:mark = s:GotoByAlphaGlobal(a:dir)
elseif a:mode ==? "alpha"
let l:mark = s:GotoByAlpha(a:dir)
elseif a:mode ==? "pos"
let l:mark = s:GotoByPos(a:dir)
endif
" NOTE: If l:mark is an empty string then no movement will be made
if l:mark == "" | return | endif
if a:loc ==? "line"
execute "normal! '" . l:mark
elseif a:loc ==? "spot"
execute 'normal! `' . l:mark
endif
endfunction
function! s:GotoByPos(dir) " {{{1
" Description: Jump to next/prev mark by location.
" Arguments: dir = next : Jump forward
" prev : Jump backward
" We need at least one mark to be present. If not, then return an empty string so that no movement will be made
if empty(b:sig_marks) | return "" | endif
let l:lnum = line('.')
" Get list of line numbers of lines with marks.
if a:dir ==? "next"
let l:targ = min(sort(keys(b:sig_marks), "signature#utils#NumericSort"))
let l:mark_lnums = sort(keys(filter(copy(b:sig_marks), 'v:key > l:lnum')), "signature#utils#NumericSort")
elseif a:dir ==? "prev"
let l:targ = max(sort(keys(b:sig_marks), "signature#utils#NumericSort"))
let l:mark_lnums = reverse(sort(keys(filter(copy(b:sig_marks), 'v:key < l:lnum')), "signature#utils#NumericSort"))
endif
let l:targ = (empty(l:mark_lnums) ? (b:SignatureWrapJumps ? l:targ : "") : l:mark_lnums[0])
if empty(l:targ) | return "" | endif
let l:mark = signature#utils#GetChar(b:sig_marks[l:targ], 0)
return l:mark
endfunction
function! s:GotoByAlpha(dir) " {{{1
" Description: Jump to next/prev mark by alphabetical order. Direction specified as input argument
let l:used_marks = signature#mark#GetList('used', 'buf_curr')
let l:line_marks = filter(copy(l:used_marks), 'v:val[1] == ' . line('.'))
" If there is only one mark in the current file, then return the same
if (len(l:used_marks) == 1)
return l:used_marks[0][0]
endif
" Since we can place multiple marks on a line, to jump by alphabetical order we need to know what the current mark is.
" This information is kept in the b:sig_GotoByAlpha_CurrMark variable. For instance, if we have marks a, b and c
" on the current line and b:sig_GotoByAlpha_CurrMark has the value 'a' then we jump to 'b' and set the value of
" the variable to 'b'. Reinvoking this function will thus now jump to 'c'
if empty(l:line_marks)
if exists('b:sig_GotoByAlpha_CurrMark')
unlet b:sig_GotoByAlpha_CurrMark
endif
" If there are no marks present on the current line then call GotoByPos to jump to the next line with a mark
return s:GotoByPos(a:dir)
endif
if (( len(l:line_marks) == 1 ) || !exists('b:sig_GotoByAlpha_CurrMark') || (b:sig_GotoByAlpha_CurrMark ==? ""))
let b:sig_GotoByAlpha_CurrMark = l:line_marks[0][0]
endif
for i in range( 0, len(l:used_marks) - 1 )
if l:used_marks[i][0] ==# b:sig_GotoByAlpha_CurrMark
if a:dir ==? "next"
if (( i != len(l:used_marks)-1 ) || b:SignatureWrapJumps)
let b:sig_GotoByAlpha_CurrMark = l:used_marks[(i+1)%len(l:used_marks)][0]
endif
elseif a:dir ==? "prev"
if ((i != 0) || b:SignatureWrapJumps)
let b:sig_GotoByAlpha_CurrMark = l:used_marks[i-1][0]
endif
endif
return b:sig_GotoByAlpha_CurrMark
endif
endfor
endfunction
function! s:GotoByAlphaGlobal(dir) " {{{1
" Description: Jump to next/prev Global mark in any buffer by alphabetical order.
" Direction is specified as input argument
let l:used_marks = signature#mark#GetList('used', 'buf_all', 'global')
let l:line_marks = filter(copy(l:used_marks), 'v:val[1] == ' . line('.'))
" If there is only one mark in the current file, return it
if (len(l:used_marks) == 1)
return l:used_marks[0][0]
endif
" If current line does not have a global mark on it then return the first used global mark
if empty(l:line_marks)
if exists('b:sig_GotoByAlphaGlobal_CurrMark')
unlet b:sig_GotoByAlphaGlobal_CurrMark
endif
return l:used_marks[0][0]
endif
" Since we can place multiple marks on a line, to jump by alphabetical order we need to know what the current mark is.
" This information is kept in the b:sig_GotoByAlphaGlobal_CurrMark variable. For instance, if we have marks A, B & C
" on the current line and b:sig_GotoByAlphaGlobal_CurrMark has the value 'A' then we jump to 'B' and set the value of
" the variable to 'B'. Reinvoking this function will thus now jump to 'C'
if ( (len(l:line_marks) == 1)
\ || !exists('b:sig_GotoByAlpha_CurrMark')
\ || (b:sig_GotoByAlphaGlobal_CurrMark ==? "")
\ )
let b:sig_GotoByAlphaGlobal_CurrMark = l:line_marks[0][0]
endif
for i in range( 0, len(l:used_marks) - 1 )
if l:used_marks[i][0] ==# b:sig_GotoByAlphaGlobal_CurrMark
if a:dir ==? "next"
if (( i != len(l:used_marks)-1 ) || b:SignatureWrapJumps)
let b:sig_GotoByAlphaGlobal_CurrMark = l:used_marks[(i+1)%len(l:used_marks)][0]
endif
elseif a:dir ==? "prev"
if ((i != 0) || b:SignatureWrapJumps)
let b:sig_GotoByAlphaGlobal_CurrMark = l:used_marks[i-1][0]
endif
endif
return b:sig_GotoByAlphaGlobal_CurrMark
endif
endfor
endfunction
function! signature#mark#GetList(mode, scope, ...) " {{{1
" Arguments: mode = 'used' : Returns list of [ [used marks, line no., buf no.] ]
" 'free' : Returns list of [ free marks ]
" scope = 'buf_curr' : Limits scope to current buffer i.e used/free marks in current buffer
" 'buf_all' : Set scope to all buffers i.e used/free marks from all buffers
" [type] = 'global' : Return only global marks
let l:marks_list = []
let l:line_tot = line('$')
let l:buf_curr = bufnr('%')
let l:type = (a:0 ? a:1 : "")
" Respect order specified in g:SignatureIncludeMarks
for i in split(b:SignatureIncludeMarks, '\zs')
if (i =~# "[A-Z]")
let [ l:buf, l:line, l:col, l:off ] = getpos( "'" . i )
let l:marks_list = add(l:marks_list, [i, l:line, l:buf])
elseif (l:type !=? "global")
let l:marks_list = add(l:marks_list, [i, line("'" .i), l:buf_curr])
endif
endfor
if (a:mode ==? 'used')
if (a:scope ==? 'buf_curr')
call filter( l:marks_list, '(v:val[2] == l:buf_curr) && (v:val[1] > 0)' )
else
call filter( l:marks_list, 'v:val[1] > 0' )
endif
else
if (a:scope ==? 'buf_all')
call filter( l:marks_list, 'v:val[1] == 0' )
else
call filter( l:marks_list, '(v:val[1] == 0) || (v:val[2] != l:buf_curr)' )
endif
call map( l:marks_list, 'v:val[0]' )
endif
return l:marks_list
endfunction
function! s:ForceGlobalRemoval(mark) " {{{1
" Description: Edit viminfo/shada file to forcibly delete Global mark since vim's handling is iffy
" Arguments: mark - The mark to delete
if ( (a:mark !~# '[A-Z]')
\ || !g:SignatureForceRemoveGlobal
\ )
return
endif
if has('nvim')
wshada!
else
wviminfo!
endif
endfunction
function! s:ReportNoAvailableMarks() " {{{1
if g:SignatureErrorIfNoAvailableMarks
echoe "Signature: No free marks left."
else
echohl WarningMsg
echomsg "Signature: No free marks left."
echohl None
endif
endfunction
function! signature#mark#List(scope, ...) " {{{1
" Description: Opens and populates location list with marks
" Arguments: scope = 0 : List local and global marks from current buffer
" 1 : List only global marks from all buffers
" [context] = 0 : Adds context around the mark
let l:list = []
let l:buf_curr = bufnr('%')
let l:list_sep = {'bufnr': '', 'lnum' : ''}
let l:SignatureIncludeMarks = (a:scope == 0 ? b:SignatureIncludeMarks : g:SignatureIncludeMarks)
for i in split(l:SignatureIncludeMarks, '\zs')
let [l:bufnr, l:lnum, l:col, l:off] = getpos( "'" . i )
" Local marks set the buffer no. to 0, replace it with the actual buffer number
let l:bufnr = (l:bufnr == 0 ? l:buf_curr : l:bufnr)
" Check that
" 1. Mark is set (lnum > 0)
" 2. If buf_all = 0, filter out global marks from other buffers
" 3. If buf_all = 1, filter out local marks from current buffer
if ( (l:lnum == 0)
\ || ( (a:scope == 0)
\ && (l:bufnr != l:buf_curr)
\ )
\ || ( (a:scope == 1)
\ && (i =~# "[a-z]")
\ )
\ )
"echom 'DEBUG: Skipping mark ' . i
continue
endif
" If the buffer is not loaded, what's the point of showing empty context?
let l:context = (bufloaded(l:bufnr) && a:0 ? a:1 : 0)
for context_lnum in range(l:lnum - l:context, l:lnum + l:context)
let l:text = get(getbufline(l:bufnr, context_lnum), 0, "")
if (!bufloaded(l:bufnr))
" Buffer is not loaded, hence we won't be able to get the line. Opening the file should fix it
let l:text = "~~~ File is not loaded into memory. Open file and rerun to see the line ~~~"
elseif (l:text == "")
" Line does not exist. Possibly because context_lnum > total no. of lines
"echom 'DEBUG: Skipping line=' . context_lnum . ' for mark=' . i . " because line doesn't exist in buffer=" . l:bufnr
continue
endif
if (context_lnum < l:lnum) | let l:text = '-: ' . l:text
elseif (context_lnum > l:lnum) | let l:text = '+: ' . l:text
else | let l:text = i . ': ' . l:text
endif
let l:list = add(l:list,
\ { 'text' : l:text,
\ 'bufnr': l:bufnr,
\ 'lnum' : context_lnum,
\ 'col' : l:col,
\ 'type' : 'm'
\ }
\ )
endfor
" Add separator when showing context
"if (a:context > 0)
" let l:list = add(l:list, l:list_sep)
"endif
endfor
" Remove the redundant separator at the end when showing context
"if ( (a:context > 0)
" \ && (len(l:list) > 0)
" \ )
" call remove(l:list, -1)
"endif
call setloclist(0, l:list) | lopen
endfunction

174
etc/soft/nvim/+plugins/vim-signature/autoload/signature/marker.vim

@ -0,0 +1,174 @@
" vim: fdm=marker:et:ts=4:sw=2:sts=1
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! signature#marker#Toggle(marker) " {{{1
" Description: Toggle marker on current line
" Arguments: marker [!@#$%^&*()]
let l:lnum = line('.')
" If marker is found on current line, remove it, else place it
if ( (get(b:sig_markers, l:lnum, "") =~# escape(a:marker, '$^'))
\ && !g:SignatureForceMarkerPlacement
\ )
call signature#sign#Remove(a:marker, l:lnum)
call signature#sign#ToggleDummy()
else
call signature#sign#Place(a:marker, l:lnum)
endif
endfunction
function! signature#marker#Remove(lnum, marker) " {{{1
" Description: Remove marker from specified line number
" Arguments: lnum - Line no. to delete marker from. If is 0, removes marker from current line
" a:2 - Marker to delete. If not specified, obtains input from user
if (get(b:sig_markers, a:lnum, '') =~ a:marker)
call signature#sign#Remove(a:marker, a:lnum)
endif
endfunction
function! signature#marker#Purge(...) " {{{1
" Description: If argument is given, removes marker only of the specified type else all markers are removed
if empty(b:sig_markers) | return | endif
if g:SignaturePurgeConfirmation
let choice = confirm('Are you sure you want to delete all markers? This cannot be undone.', '&Yes\n&No', 1)
if choice == 2 | return | endif
endif
if a:0 > 0
let l:markers = [ a:1 ]
else
let l:markers = split(b:SignatureIncludeMarkers, '\zs')
endif
for l:marker in l:markers
for l:lnum in keys(filter(copy(b:sig_markers), 'v:val =~# l:marker'))
call signature#marker#Remove(l:lnum, l:marker)
endfor
endfor
call signature#sign#ToggleDummy()
endfunction
function! signature#marker#Goto( dir, marker_num, count ) " {{{1
" Description: Jump to next/prev marker by location.
" Arguments: dir = next : Jump forward
" prev : Jump backward
" marker = same : Jump to a marker of the same type
" any : Jump to a marker of any type
" [0-9] : Jump to the corresponding marker
let l:lnum = line('.')
let l:marker = ''
if (a:marker_num =~ '\v<[0-9]>')
let l:marker = split(b:SignatureIncludeMarkers, '\zs')[a:marker_num]
elseif ( (a:marker_num ==? 'same')
\ && has_key(b:sig_markers, l:lnum)
\ )
let l:marker = signature#utils#GetChar(b:sig_markers[l:lnum], 0)
endif
" Get list of line numbers of lines with markers.
" If current line has a marker, filter out line numbers of other markers ...
if (l:marker != '')
let l:marker_lnums = sort(keys(filter(copy(b:sig_markers),
\ 'signature#utils#GetChar(v:val, 0) == l:marker')), "signature#utils#NumericSort")
else
let l:marker_lnums = sort(keys(b:sig_markers), "signature#utils#NumericSort")
endif
if (a:dir ==? 'next')
let l:marker_lnums = filter(copy(l:marker_lnums), ' v:val > l:lnum')
\ + filter(copy(l:marker_lnums), '(v:val <= l:lnum) && b:SignatureWrapJumps')
elseif (a:dir ==? 'prev')
call reverse(l:marker_lnums)
let l:marker_lnums = filter(copy(l:marker_lnums), ' v:val < l:lnum')
\ + filter(copy(l:marker_lnums), '(v:val >= l:lnum) && b:SignatureWrapJumps')
endif
if (len(l:marker_lnums) == 0)
return
endif
let l:count = (a:count == 0 ? 1 : a:count)
if (b:SignatureWrapJumps)
let l:count = l:count % len(l:marker_lnums)
elseif (l:count > len(l:marker_lnums))
let l:count = 0
endif
let l:targ = l:marker_lnums[l:count - 1]
execute 'normal! ' . l:targ . 'G'
endfunction
function! signature#marker#List(...) " {{{1
" Description: Opens and populates location list with markers from current buffer
" Show all markers in location list if no argument is provided
" Argument: [markers] = 0-9 or any of the specified symbols : List only the specified markers
" [context] = 0 (default) : Adds context around marker
" To show all markers with 1 line of context call using arguments ("", 1)
let l:markers = (a:0 && (a:1 != "") ? a:1 : b:SignatureIncludeMarkers)
let l:context = (a:0 > 1 ? a:2 : 0)
if (l:markers =~ '^\d$')
if ( ( (l:markers == 0)
\ && (len(b:SignatureIncludeMarkers) != 10)
\ )
\ || (l:markers > len(b:SignatureIncludeMarkers))
\ )
echoe "Signature: No corresponding marker exists for " . l:markers
return
endif
let l:markers = split(b:SignatureIncludeMarkers, '\zs')[l:markers]
endif
let l:lines_tot = line('$')
let l:buf_curr = bufnr('%')
let l:list_sep = {'bufnr': '', 'lnum' : ''}
let l:list = []
" Markers not specified in b:SignatureIncludeMarkers won't be present in b:sig_markers and hence get filtered out
for l:lnum in sort(keys(filter(copy(b:sig_markers), 'v:val =~ "[" . l:markers . "]"')))
for context_lnum in range(l:lnum - l:context, l:lnum + l:context)
if ( (context_lnum < 1)
\ || (context_lnum > lines_tot)
\ )
continue
endif
if (context_lnum < l:lnum) | let l:text = '-' . ": " . getline(context_lnum)
elseif (context_lnum > l:lnum) | let l:text = '+' . ": " . getline(context_lnum)
else | let l:text = b:sig_markers[l:lnum] . ": " . getline(context_lnum)
endif
let l:list = add(l:list,
\ { 'text' : l:text,
\ 'bufnr': l:buf_curr,
\ 'lnum' : context_lnum,
\ 'type' : 'M'
\ }
\ )
endfor
" Add separator when showing context
"if (a:context > 0)
" let l:list = add(l:list, l:list_sep)
"endif
endfor
" Remove the redundant separator at the end when showing context
"if ( (a:context > 0)
" \ && (len(l:list) > 0)
" \ )
" call remove(l:list, -1)
"endif
call setloclist(0, l:list,) | lopen
endfunction

375
etc/soft/nvim/+plugins/vim-signature/autoload/signature/sign.vim

@ -0,0 +1,375 @@
" vim: fdm=marker:et:ts=4:sw=2:sts=2
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! signature#sign#Place(sign, lnum) "{{{1
" Description: Place signs for marks/markers on the specified line number
" Arguments:
" sign : The mark/marker whose sign is to be placed
" lnum : Line number on/from which the sign is to be placed/removed
"echom "DEBUG: sign = " . a:sign . ", lnum = " . a:lnum
" If Signature is not enabled, return
if !b:sig_enabled | return | endif
" FIXME: Highly inefficient. Needs work
" Place sign only if there are no signs from other plugins (eg. syntastic)
"let l:present_signs = s:GetInfo(1)
"if ( b:SignatureDeferPlacement
" \ && has_key(l:present_signs, a:lnum)
" \ && (l:present_signs[a:lnum]['name'] !~# '^sig_Sign_')
" \ )
" return
"endif
if signature#utils#IsValidMarker(a:sign)
let b:sig_markers[a:lnum] = a:sign . get(b:sig_markers, a:lnum, "")
elseif signature#utils#IsValidMark(a:sign)
let b:sig_marks[a:lnum] = a:sign . get(b:sig_marks, a:lnum, "")
else
echoerr "Unexpected sign found: " . a:sign
endif
"}}}3
call s:RefreshLine(a:lnum)
endfunction
function! signature#sign#Remove(sign, lnum) "{{{1
" Description: Remove signs for marks/markers from the specified line number
" Arguments:
" sign : The mark/marker whose sign is to be placed/removed/toggled
" lnum : Line number from which the sign is to be removed
" If sign is a marker and lnum is 0, the sign will be removed from all lines
" If sign is a mark and lnum is 0, the lnum will be found and the sign will be removed from that line
"echom "DEBUG: sign = " . a:sign . ", lnum = " . a:lnum
" If Signature is not enabled, return
if !b:sig_enabled | return | endif
" Remove sign for markers
if signature#utils#IsValidMarker(a:sign)
let b:sig_markers[a:lnum] = substitute(b:sig_markers[a:lnum], "\\C" . escape( a:sign, '$^' ), "", "")
" If there are no markers on the line, delete signs on that line
if b:sig_markers[a:lnum] == ""
call remove(b:sig_markers, a:lnum)
endif
call s:RefreshLine(a:lnum)
" Remove sign for marks
else
" For marks, if a:lnum == 0, find out the line where the mark was placed
if a:lnum == 0
let l:arr = keys(filter(copy(b:sig_marks), 'v:val =~# a:sign'))
if empty(l:arr) | return | endif
else
let l:arr = [a:lnum]
endif
if (v:version >= 800)
call assert_true(len(l:arr) == 1, "Multiple marks found where one was expected")
elseif (len(l:arr) != 1)
echoerr "Multiple marks found where one was expected"
endif
for l:lnum in l:arr
" FIXME: Placed guard to avoid triggering issue #53
if has_key(b:sig_marks, l:lnum)
let b:sig_marks[l:lnum] = substitute(b:sig_marks[l:lnum], "\\C" . a:sign, "", "")
" If there are no marks on the line, delete signs on that line
if b:sig_marks[l:lnum] == ""
call remove(b:sig_marks, l:lnum)
endif
endif
call s:RefreshLine(l:lnum)
endfor
endif
endfunction
function! s:EvaluateHL(expr, lnum, ...) "{{{1
" Description: If expr points to a function, call it and use its output as the highlight group.
" If it is a string, use it directly.
" If the optional argument is specified, use it as a fallback. If not, return an empty string
if type(a:expr) == type("")
return a:expr
elseif type(a:expr) == type(function("tr"))
let l:retval = a:expr(a:lnum)
if (l:retval != "")
return l:retval
endif
endif
return (a:0 > 0 ? a:1 : "")
endfunction
function! s:RefreshLine(lnum) "{{{1
" Description: Decides what the sign string should be based on if there are any marks or markers (using b:sig_marks
" and b:sig_markers) on the current line and the value of b:SignaturePrioritizeMarks.
" Arguments:
" lnum : Line number for which the sign string is to be modified
let l:id = abs(a:lnum * 1000 + bufnr('%'))
let l:str = ""
" Place the sign
if ( has_key(b:sig_marks, a:lnum)
\ && ( b:SignaturePrioritizeMarks
\ || !has_key(b:sig_markers, a:lnum)
\ )
\ )
let l:SignatureMarkTextHL = s:EvaluateHL(g:SignatureMarkTextHL, a:lnum, "SignatureMarkText")
let l:SignatureMarkLineHL = s:EvaluateHL(g:SignatureMarkLineHL, a:lnum, "SignatureMarkLine")
let l:str = substitute(b:SignatureMarkOrder, "\m", signature#utils#GetChar(b:sig_marks[a:lnum], 0), '')
let l:str = substitute(l:str, "\p", signature#utils#GetChar(b:sig_marks[a:lnum], 1), '')
execute 'sign define Signature_' . l:str . ' text=' . l:str . ' texthl=' . l:SignatureMarkTextHL . ' linehl=' . l:SignatureMarkLineHL
elseif has_key(b:sig_markers, a:lnum)
let l:SignatureMarkerTextHL = s:EvaluateHL(g:SignatureMarkerTextHL, a:lnum, "SignatureMarkerText")
let l:SignatureMarkerLineHL = s:EvaluateHL(g:SignatureMarkerLineHL, a:lnum, "SignatureMarkerLine")
" Since the same marker can be placed on multiple lines, we can't use the same sign for all of them.
" This is because if dynamic highlighting of markers is enabled then the sign placed on eg. a modified line should
" be highlighted differently than the one placed on an unchanged line.
" In order to support this, I append the name of the TextHL and LineHL group to the name of the sign.
let l:txt = signature#utils#GetChar(b:sig_markers[a:lnum], 0)
let l:str = l:txt . '_' . l:SignatureMarkerTextHL . '_' . l:SignatureMarkerLineHL
execute 'sign define Signature_' . l:str . ' text=' . l:txt . ' texthl=' . l:SignatureMarkerTextHL . ' linehl=' . l:SignatureMarkerLineHL
else
call signature#sign#Unplace(a:lnum)
endif
if (l:str != "")
execute 'sign place ' . l:id . ' line=' . a:lnum . ' name=Signature_' . l:str . ' buffer=' . bufnr('%')
endif
" If there is only 1 mark/marker in the file, place a dummy to prevent flickering of the gutter when it is moved
" If there are no signs left, remove the dummy
call signature#sign#ToggleDummy()
endfunction
function! signature#sign#Refresh(...) "{{{1
" Description: Add signs for new marks/markers and remove signs for deleted marks/markers
" Arguments: Specify an argument to force a sign refresh
call s:InitializeVars(a:0 && a:1)
" If Signature is not enabled, return
if !b:sig_enabled | return | endif
for i in signature#mark#GetList('free', 'buf_curr')
" ... remove it
call signature#sign#Remove(i, 0)
endfor
" Add signs for marks ...
for [l:mark, l:lnum, _] in signature#mark#GetList('used', 'buf_curr')
" ... if mark is not present in our b:sig_marks list or if it is present but at the wrong line,
" remove the old sign and add a new one
if ( !has_key(b:sig_marks, l:lnum)
\ || (b:sig_marks[l:lnum] !~# l:mark)
\ || a:0
\ )
call signature#sign#Remove(l:mark, 0)
call signature#sign#Place (l:mark, l:lnum)
endif
endfor
call signature#sign#ToggleDummy()
" We do not add signs for markers as SignRefresh is executed periodically and we don't have a way to determine if the
" marker already has a sign or not
endfunction
function! signature#sign#Unplace(lnum) "{{{1
" Description: Remove the sign from the specified line number
" FIXME: Clean-up. Undefine the sign
let l:id = abs(a:lnum * 1000 + bufnr('%'))
silent! execute 'sign unplace ' . l:id
endfunction
function! signature#sign#ToggleDummy(...) "{{{1
" Description: Places a dummy sign to prevent flickering of the gutter when the mark is moved or the line containing
" a mark/marker is deleted and then the delete is undone
" Arguments: (optional) 0 : force remove
" 1 : force place
let l:place = a:0 ? a:1 : (len(b:sig_marks) + len(b:sig_markers) == 1) && !b:sig_DummyExists
let l:remove = a:0 ? !a:1 : (len(b:sig_marks) + len(b:sig_markers) == 0) && b:sig_DummyExists
if (l:place)
sign define Signature_Dummy
execute 'sign place 666 line=1 name=Signature_Dummy buffer=' . bufnr('%')
let b:sig_DummyExists = 1
elseif (l:remove)
silent! execute 'sign unplace 666 buffer=' . bufnr('%')
let b:sig_DummyExists = 0
endif
endfunction
function! s:GetInfo(...) "{{{1
" Description: Returns a dic of filenames, each of which is a dic of line numbers on which signs are placed
" Arguments: filename (optional).
" If filename is provided, the return value will contain signs only present in the given file
" Eg. {
" 'vimrc': {
" '711': {
" 'id': '1422',
" 'name': 'sig_Sign_1422'
" },
" '676': {
" 'id': '1352',
" 'name': 'sig_Sign_1352'
" }
" }
" }
" Redirect the input to a variable
redir => l:sign_str
silent! sign place
redir END
" Create a Hash of files to store the info.
let l:signs_dic = {}
" The file that is currently being processed is stored into l:file
let l:match_file = ""
let l:file_found = 0
" Split the string into an array of sentences and filter out empty lines
for i in filter( split( l:sign_str, '\n' ), 'v:val =~ "^[S ]"' )
let l:temp_file = matchstr( i, '\v(Signs for )@<=\S+:@=' )
if l:temp_file != ""
let l:match_file = l:temp_file
let l:signs_dic[l:match_file] = {}
elseif l:match_file != ""
" Get sign info
let l:info_match = matchlist( i, '\vline\=(\d+)\s*id\=(\S+)\s*name\=(\S+)' )
if !empty( l:info_match )
let l:signs_dic[l:match_file][l:info_match[1]] = {
\ 'id' : l:info_match[2],
\ 'name' : l:info_match[3],
\ }
endif
endif
endfor
if a:0
"" Search for the full path first in the hash ...
"let l:curr_filepath = expand('%:p')
"if has_key( l:signs_dic, l:curr_filepath )
" return filter( l:signs_dic, 'v:key ==# l:curr_filepath' )[l:curr_filepath]
"else
" ... if no entry is found for the full path, search for the filename in the hash ...
" Since we're searching for the current file, if present in the hash, it'll be as a filename and not the full path
let l:curr_filename = expand('%:t')
if has_key( l:signs_dic, l:curr_filename )
return filter( l:signs_dic, 'v:key ==# l:curr_filename' )[l:curr_filename]
endif
" ... if nothing is found, then return an empty hash to indicate that no signs are present in the current file
return {}
endif
return l:signs_dic
endfunction
function! signature#sign#GetGitGutterHLGroup(lnum) "{{{1
" Description: This returns the highlight group used by vim-gitgutter depending on how the line was edited
let l:current_bufnr = bufnr('%')
let l:line_state = filter(copy(gitgutter#diff#process_hunks(l:current_bufnr, gitgutter#hunk#hunks(l:current_bufnr))), 'v:val[0] == a:lnum')
if len(l:line_state) == 0
return ""
endif
if (l:line_state[0][1]) =~ 'added' | return 'GitGutterAdd'
elseif (l:line_state[0][1]) =~ 'modified_removed' | return 'GitGutterChangeDelete'
elseif (l:line_state[0][1]) =~ 'modified' | return 'GitGutterChange'
elseif (l:line_state[0][1]) =~ 'removed' | return 'GitGutterDelete'
endif
endfunction
function! signature#sign#GetSignifyHLGroup(lnum) "{{{1
" Description: This returns the highlight group used by vim-signify depending on how the line was edited
" Thanks to @michaelmior
if !exists('b:sy')
return ""
endif
call sy#sign#get_current_signs(b:sy)
if has_key(b:sy.internal, a:lnum)
let l:line_state = b:sy.internal[a:lnum]['type']
if l:line_state =~ 'SignifyAdd' | return 'SignifySignAdd'
elseif l:line_state =~ 'SignifyChange' | return 'SignifySignChange'
elseif l:line_state =~ 'SignifyDelete' | return 'SignifySignDelete'
end
endif
return ""
endfunction
" function! signature#sign#GetMarkSignLine(mark) "{{{1
" if !signature#utils#IsValidMark(a:mark)
" echoe "Signature: Invalid mark " . a:mark
" return
" endif
" let l:sign_info=filter(split(execute('sign place'), '\n'),
" \ 'v:val =~ "\\vSignature_(.?' . a:mark . '|' . a:mark . '.?)$"')
" if (len(l:sign_info) != 1)
" echoe "Signature: Expected single match, found " . len(l:sign_info)
" return
" endif
" return matchstr(l:sign_info[0], '\v(line\=)@<=\d+')
" endfunction
function! s:InitializeVars(...) "{{{1
" Description: Initialize variables
" Arguments: Specify an argument to re-init
if !exists('b:sig_marks')
" b:sig_marks = { lnum => signs_str }
let b:sig_marks = {}
else
" Lines can be removed using an external tool. Hence, we need to filter out marks placed on line numbers that are
" now greater than the total number of lines in the file.
let l:line_tot = line('$')
call filter( b:sig_marks, 'v:key <= l:line_tot' )
endif
if !exists('b:sig_markers')
" b:sig_markers = { lnum => marker }
let b:sig_markers = {}
else
" Lines can be removed using an external tool. Hence, we need to filter out marks placed on line numbers that are
" now greater than the total number of lines in the file.
let l:line_tot = line('$')
call filter( b:sig_markers, 'v:key <= l:line_tot' )
endif
call signature#utils#Set('b:sig_DummyExists' , 0 , a:0 && a:1)
call signature#utils#Set('b:sig_enabled' , g:SignatureEnabledAtStartup, a:0 && a:1)
call signature#utils#Set('b:SignatureIncludeMarks' , g:SignatureIncludeMarks , a:0 && a:1)
call signature#utils#Set('b:SignatureIncludeMarkers' , g:SignatureIncludeMarkers , a:0 && a:1)
call signature#utils#Set('b:SignatureMarkOrder' , g:SignatureMarkOrder , a:0 && a:1)
call signature#utils#Set('b:SignaturePrioritizeMarks', g:SignaturePrioritizeMarks , a:0 && a:1)
call signature#utils#Set('b:SignatureDeferPlacement' , g:SignatureDeferPlacement , a:0 && a:1)
call signature#utils#Set('b:SignatureWrapJumps' , g:SignatureWrapJumps , a:0 && a:1)
endfunction

195
etc/soft/nvim/+plugins/vim-signature/autoload/signature/utils.vim

@ -0,0 +1,195 @@
" vim: fdm=marker:et:ts=4:sw=2:sts=2
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! signature#utils#Set(var, value, ...) " {{{1
" Description: Assign value to var if var is unset or if an optional 3rd arg is provided to force
if (!exists(a:var) || a:0 && a:1)
if type(a:value)
execute 'let' a:var '=' string(a:value)
else
execute 'let' a:var '=' a:value
endif
endif
return a:var
endfunction
function! signature#utils#NumericSort(x, y) " {{{1
return a:x - a:y
endfunction
function! s:Map(mode, key, map_lhs_default, map_rhs) " {{{1
let l:map_lhs = get(g:SignatureMap, a:key, a:map_lhs_default)
if (l:map_lhs ==? '')
return
endif
if (a:mode ==? 'create')
silent! execute 'nnoremap <silent> <unique> ' . l:map_lhs . ' ' . ':<C-U>call signature#' . a:map_rhs . '<CR>'
elseif (a:mode ==? 'remove')
silent! execute 'nunmap ' . l:map_lhs
endif
endfunction
function! signature#utils#Maps(mode) " {{{1
" We create separate mappings for PlaceNextMark, mark#Purge('all') and PurgeMarkers instead of combining it with
" Leader/Input as if the user chooses to use some weird key like <BS> or <CR> for any of these 3, we need to be able
" to identify it. Eg. the nr2char(getchar()) will fail if the user presses a <BS>
let l:SignatureMapLeader = get(g:SignatureMap, 'Leader', 'm')
if (l:SignatureMapLeader == "")
echoe "Signature: g:SignatureMap.Leader shouldn't be left blank"
endif
call s:Map(a:mode, 'Leader' , l:SignatureMapLeader , 'utils#Input()' )
call s:Map(a:mode, 'PlaceNextMark' , l:SignatureMapLeader . "," , 'mark#Toggle("next")' )
call s:Map(a:mode, 'ToggleMarkAtLine' , l:SignatureMapLeader . "." , 'mark#ToggleAtLine()' )
call s:Map(a:mode, 'PurgeMarksAtLine' , l:SignatureMapLeader . "-" , 'mark#Purge("line")' )
call s:Map(a:mode, 'PurgeMarks' , l:SignatureMapLeader . "<Space>", 'mark#Purge("all")' )
call s:Map(a:mode, 'PurgeMarkers' , l:SignatureMapLeader . "<BS>" , 'marker#Purge()' )
call s:Map(a:mode, 'DeleteMark' , "dm" , 'utils#Remove(v:count)' )
call s:Map(a:mode, 'GotoNextLineAlpha', "']" , 'mark#Goto("next", "line", "alpha")' )
call s:Map(a:mode, 'GotoPrevLineAlpha', "'[" , 'mark#Goto("prev", "line", "alpha")' )
call s:Map(a:mode, 'GotoNextSpotAlpha', "`]" , 'mark#Goto("next", "spot", "alpha")' )
call s:Map(a:mode, 'GotoPrevSpotAlpha', "`[" , 'mark#Goto("prev", "spot", "alpha")' )
call s:Map(a:mode, 'GotoNextLineByPos', "]'" , 'mark#Goto("next", "line", "pos")' )
call s:Map(a:mode, 'GotoPrevLineByPos', "['" , 'mark#Goto("prev", "line", "pos")' )
call s:Map(a:mode, 'GotoNextSpotByPos', "]`" , 'mark#Goto("next", "spot", "pos")' )
call s:Map(a:mode, 'GotoPrevSpotByPos', "[`" , 'mark#Goto("prev", "spot", "pos")' )
call s:Map(a:mode, 'GotoNextMarker' , "]-" , 'marker#Goto("next", "same", v:count)')
call s:Map(a:mode, 'GotoPrevMarker' , "[-" , 'marker#Goto("prev", "same", v:count)')
call s:Map(a:mode, 'GotoNextMarkerAny', "]=" , 'marker#Goto("next", "any", v:count)')
call s:Map(a:mode, 'GotoPrevMarkerAny', "[=" , 'marker#Goto("prev", "any", v:count)')
call s:Map(a:mode, 'ListBufferMarks' , 'm/' , 'mark#List(0, 0)' )
call s:Map(a:mode, 'ListBufferMarkers', 'm?' , 'marker#List(v:count, 0)' )
endfunction
function! signature#utils#Input() " {{{1
" Description: Grab input char
if &ft ==# "netrw"
" Workaround for #104
return
endif
" Obtain input from user ...
let l:in = nr2char(getchar())
" ... if the input is not a number eg. '!' ==> Delete all '!' markers
if signature#utils#IsValidMarker(l:in)
return signature#marker#Purge(l:in)
endif
" ... but if input is a number, convert it to corresponding marker before proceeding
if match(l:in, '\d') >= 0
let l:char = signature#utils#GetChar(b:SignatureIncludeMarkers, l:in)
else
let l:char = l:in
endif
if signature#utils#IsValidMarker(l:char)
return signature#marker#Toggle(l:char)
elseif signature#utils#IsValidMark(l:char)
return signature#mark#Toggle(l:char)
else
" l:char is probably one of `'[]<> or a space from the gap in b:SignatureIncludeMarkers
execute 'normal! m' . l:in
endif
endfunction
function! signature#utils#Remove(lnum) " {{{1
" Description: Obtain mark or marker from the user and remove it.
" There can be multiple markers of the same type on different lines. If a line no. is provided
" (non-zero), delete the marker from the specified line else delete it from the current line
" NOTE: lnum is meaningless for a mark and will be ignored
" Arguments: lnum - Line no. to delete the marker from
let l:char = nr2char(getchar())
if (l:char =~ '^\d$')
let l:lnum = (a:lnum == 0 ? line('.') : a:lnum)
let l:char = split(b:SignatureIncludeMarkers, '\zs')[l:char]
call signature#marker#Remove(lnum, l:char)
elseif (l:char =~? '^[a-z]$')
call signature#mark#Remove(l:char)
endif
endfunction
function! signature#utils#Toggle() " {{{1
" Description: Toggles and refreshes sign display in the buffer.
let b:sig_enabled = !b:sig_enabled
if b:sig_enabled
" Signature enabled ==> Refresh signs
call signature#sign#Refresh()
" Add signs for markers ...
for i in keys(b:sig_markers)
call signature#sign#Place(b:sig_markers[i], i)
endfor
else
" Signature disabled ==> Remove signs
for l:lnum in keys(b:sig_markers)
call signature#sign#Unplace(l:lnum)
endfor
for l:lnum in keys(b:sig_marks)
call signature#sign#Unplace(l:lnum)
endfor
" Force removal. Simply toggling doesn't work as we check whether b:sig_markers and b:sig_marks are empty before
" removing the dummy and b:sig_markers won't be empty
call signature#sign#ToggleDummy(0)
unlet b:sig_marks
endif
endfunction
function! signature#utils#SetupHighlightGroups() " {{{1
" Description: Sets up the highlight groups
function! CheckAndSetHL(curr_hl, prefix, attr, targ_color)
let l:curr_color = synIDattr(synIDtrans(hlID(a:curr_hl)), a:attr, a:prefix)
if ( ( (l:curr_color == "")
\ || (l:curr_color < 0)
\ )
\ && (a:targ_color != "")
\ && (a:targ_color >= 0)
\ )
" echom "DEBUG: HL=" . a:curr_hl . " (" . a:prefix . a:attr . ") Curr=" . l:curr_color . ", To=" . a:targ_color
execute 'highlight ' . a:curr_hl . ' ' . a:prefix . a:attr . '=' . a:targ_color
endif
endfunction
let l:prefix = (has('gui_running') || (has('termguicolors') && &termguicolors) ? 'gui' : 'cterm')
let l:sign_col_color = synIDattr(synIDtrans(hlID('SignColumn')), 'bg', l:prefix)
call CheckAndSetHL('SignatureMarkText', l:prefix, 'fg', 'Red')
call CheckAndSetHL('SignatureMarkText', l:prefix, 'bg', l:sign_col_color)
call CheckAndSetHL('SignatureMarkerText', l:prefix, 'fg', 'Green')
call CheckAndSetHL('SignatureMarkerText', l:prefix, 'bg', l:sign_col_color)
delfunction CheckAndSetHL
endfunction
function! signature#utils#IsValidMark(mark) " {{{1
return (b:SignatureIncludeMarks =~# a:mark)
endfunction
function! signature#utils#IsValidMarker(marker) " {{{1
return ( (b:SignatureIncludeMarkers =~# a:marker)
\ && (a:marker != ' ')
\ )
endfunction
function! signature#utils#GetChar(string, pos) " {{{1
if a:pos > strchars(a:string) - 1 | return "" | endif
let pattern = '.\{-' . a:pos . '}\(.\).*'
return substitute(a:string, pattern, '\1', '')
endfunction

408
etc/soft/nvim/+plugins/vim-signature/doc/signature.txt

@ -0,0 +1,408 @@
*signature.txt* A plugin to toggle, display and navigate marks
_________.__ __ ~
/ _____/|__| ____ ____ _____ _/ |_ __ __ _______ ____ ~
\_____ \ | | / ___\ / \ \__ \ \ __\| | \\_ __ \_/ __ \ ~
/ \| | / /_/ >| | \ / __ \_ | | | | / | | \/\ ___/ ~
/_______ /|__| \___ / |___| /(____ / |__| |____/ |__| \___ > ~
\/ /_____/ \/ \/ \/ ~
==============================================================================
Contents *Signature*
1. Mappings |SignatureMappings|
2. Commands |SignatureCommands|
3. Customization |SignatureCustomization|
4. Contributing |SignatureContributing|
5. Credits |SignatureCredits|
6. License |SignatureLicense|
==============================================================================
1. Mappings *SignatureMappings*
Out of the box, the followings mappings are defined by default
mx Toggle mark 'x' and display it in the leftmost column
dmx Remove mark 'x' where x is a-zA-Z
m, Place the next available mark
m. If no mark on line, place the next available mark. Otherwise,
remove (first) existing mark.
m- Delete all marks from the current line
m<Space> Delete all marks from the current buffer
]` Jump to next mark
[` Jump to prev mark
]' Jump to start of next line containing a mark
[' Jump to start of prev line containing a mark
`] Jump by alphabetical order to next mark
`[ Jump by alphabetical order to prev mark
'] Jump by alphabetical order to start of next line having a mark
'[ Jump by alphabetical order to start of prev line having a mark
m/ Open location list and display marks from current buffer
m[0-9] Toggle the corresponding marker !@#$%^&*()
m<S-[0-9]> Remove all markers of the same type
]- Jump to next line having a marker of the same type
[- Jump to prev line having a marker of the same type
]= Jump to next line having a marker of any type
[= Jump to prev line having a marker of any type
m? Open location list and display markers from current buffer
m<BS> Remove all markers
This will allow the use of default behavior of m to set marks and, if
the line already contains the mark, it'll be unset. The default behavior
of ]', [', ]` and [` is supported and enhanced by wrapping around when
beginning or end of file is reached. ]-, [-, ]= and [= also accept a count.
To directly jump to a given marker, the following maps can be used
>
nnoremap [1 :call signature#marker#Goto('prev', 1, v:count)
nnoremap ]1 :call signature#marker#Goto('next', 1, v:count)
nnoremap [2 :call signature#marker#Goto('prev', 2, v:count)
nnoremap ]2 :call signature#marker#Goto('next', 2, v:count)
<
etc. These are not defined by default
==============================================================================
2. Commands *SignatureCommands*
*:SignatureToggleSigns*
Toggle the display of signs. This won't affect the marks or the mappings.
*:SignatureRefresh*
Force the display of signs in the buffer to refresh. Use this to correct
the signs if things go awry
*:SignatureListBufferMarks* [n]
List all the marks used in the current buffer in the location list
Accepts an optional argument to provide 'n' lines of context
*:SignatureListGlobalMarks* [n]
List only the global marks used in all buffers in the location list
Accepts an optional argument to provide 'n' lines of context
*:SignatureListMarkers* [marker] [n]
List all instances of the specified marker(s) used in the current buffer
in the location list. If no argument is given, it lists all markers
Accepts an optional argument to provide 'n' lines of context
>
:SignatureListMarkers : List all markers
:SignatureListMarkers 1 : List only the '!' marker
:SignatureListMarkers @ : List only the '@' marker
:SignatureListMarkers 0, 2 : List only ) marker with 2 lines of context
:SignatureListMarkers '', 2 : List all markers with 2 lines of context
:SignatureListMarkers '!@', 2 : List only the '!' and '@' markers and show
2 lines of context around them
<
==============================================================================
3. Customization *SignatureCustomization*
*g:SignatureMap*
Type: Dictionary, Default:
To set up your own mappings copy the following dictionary and edit it
>
let g:SignatureMap = {
\ 'Leader' : "m",
\ 'PlaceNextMark' : "m,",
\ 'ToggleMarkAtLine' : "m.",
\ 'PurgeMarksAtLine' : "m-",
\ 'DeleteMark' : "dm",
\ 'PurgeMarks' : "m<Space>",
\ 'PurgeMarkers' : "m<BS>",
\ 'GotoNextLineAlpha' : "']",
\ 'GotoPrevLineAlpha' : "'[",
\ 'GotoNextSpotAlpha' : "`]",
\ 'GotoPrevSpotAlpha' : "`[",
\ 'GotoNextLineByPos' : "]'",
\ 'GotoPrevLineByPos' : "['",
\ 'GotoNextSpotByPos' : "]`",
\ 'GotoPrevSpotByPos' : "[`",
\ 'GotoNextMarker' : "]-",
\ 'GotoPrevMarker' : "[-",
\ 'GotoNextMarkerAny' : "]=",
\ 'GotoPrevMarkerAny' : "[=",
\ 'ListBufferMarks' : "m/",
\ 'ListBufferMarkers' : "m?"
\ }
<
By default, it defines the mappings as shown in |signature-mappings|
To disable a map entirely, specify it as an empty string.
If a key is not specified, the default value will be picked up.
These same characters will be used to invoke the shortcuts.
*g:SignatureIncludeMarks*
String, Default : 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
Specify the marks that can be controlled by this plugin.
Only supports Alphabetical marks at the moment.
'b:SignatureIncludeMarks' can be set separately for buffer-specific marks.
*g:SignatureIncludeMarkers*
String, Default : ')!@#$%^&*('
Specify the symbols that can be used by the plugin to be placed by 0-9.
Note that there's a 1:1 correspondence between the symbols and 0-9.
This string must be at most 10 chars long. Extra char will be ignored.
Also, this string must not include any alphabetical characters `[a-zA-Z]`
However, it can contain spaces to indicate blanks. Eg.
`m0` will place `)` by default
`m1` will place `!` by default
`m2` will place `@` by default etc.
If set to `')!'`, `m0` and `m1` will behave as described above but `m[2-9]` will
not be handled by this plugin.
If set to `' !'` (note the space before !), only `m1` will have any affect
while `m[0,2-9]` will not have any affect
An example of a use case is for keyboards with alternate layouts wherein
the symbols associated with 0-9 could be different than the default.
'b:SignatureIncludeMarkers' can be specified separately for each buffer
*g:SignatureMap['Leader']*
String, Default: 'm'
Set the key used to toggle marks and markers.
For eg. If this key is set to `<leader>m`,
`<leader>ma` will toggle the mark 'a' on the current line
`<leader>m,` will place the next available mark
`<leader>m.` will place the next available mark if there are no
marks already on the line; otherwise, will remove
first mark from line
`<leader>m<Space>` will delete all marks
`<leader>m1` will toggle the marker '!'
`<leader>m!` will remove all the '!' markers
`<leader>m<BS>` will remove all markers
NOTE: Currently, either marks or markers can be displayed in front of a
line. Both can't be displayed simultaenously.
To set this to mapleader or maplocalleader
`let g:SignatureMap['Leader'] = '<Leader>'`
`let g:SignatureMap['Leader'] = '<LocalLeader>'`
*g:SignatureWrapJumps*
Boolean, Default : 1
Specify if jumping to marks should wrap-around.
b:SignatureWrapJumps can be set to specify buffer-specific settings.
*g:SignatureMarkOrder*
String, Default : "\p\m"
Signature allows you to display upto marks in front of a line. This controls
the order in which marks are displayed.
'\m' indicates the current or latest mark placed on the line
'\p' indicates the previous mark placed on the line
For eg,
`g:SignatureMarkOrder="\m."` : Display last mark with '.' suffixed
`g:SignatureMarkOrder="_\m"` : Display last mark with '_' prefixed
`g:SignatureMarkOrder=">"` : Display only a ">" for a line with a mark.
The mark is not displayed
`g:SignatureMarkOrder="\m\p"` : Display last two marks placed
NOTE: The signs feature allows only 2 characters to be displayed. This limit
is imposed by vim itself and not by the plugin
*g:SignatureMarkTextHL*
String, Default : 'SignatureMarkText'
The highlight group used for mark signs. This can be set either to a string
or to a |Funcref|.
If it holds a string, it must be an expression suitable for passing to
|eval()|. In the simple case, it can be the name of a highlight group. It can
also hold more complicated expressions, in which case the expression `a:lnum`
may be helpful. It holds the number of the line where the current mark is to
be highlighted.
If it holds a |Funcref|, then the function will be called with one argument,
the line number of the mark to be highlighted. The function should return
the name of a highlight group.
Example using a string:
`let g:SignatureMarkTextHL = "Exception"`
Example of |Funcref|:
`function Example(lineno)`
`return "Exception"`
`endfunction`
`let g:SignatureMarkTextHL = function("Example")`
By default, this is set to SignatureMarkText which is a highlight group
that is linked to Exception
*g:SignatureMarkTextHLDynamic*
Boolean, Default: 0
Highlight signs of marks dynamically based upon state indicated by
vim-gitgutter. Setting this to `1` prior to plugin initialization overwrites
|g:SignatureMarkTextHL|.
vim-signify is not supported at the moment. For details, refer
https://github.com/kshenoy/vim-signature/issues/93#issuecomment-195672354
*g:SignatureMarkLineHL*
String, Default : 'SignatureMarkLine'
The highlight group used for hightlighting lines having marks. This can be a
string or |Funcref|. SignatureMarkLine links to Normal by default.
See |g:SignatureMarkTextHL| for details.
*g:SignatureMarkerTextHL*
String, Default : 'SignatureMarkerText'
The highlight group used for marker signs. This can be a string or |Funcref|.
SignatureMarkText links to WarningMsg by default.
See |g:SignatureMarkTextHL| for details.
*g:SignatureMarkerTextHLDynamic*
Boolean, Default: 0
Highlight signs of markers dynamically based upon state indicated by
vim-gitgutter or vim-signify. Setting this to `1` prior to plugin
initialization overwrites |g:SignatureMarkerTextHL|.
*g:SignatureMarkerLineHL*
String, Default : ''
The highlight group used for hightlighting lines having markers. This can be
a string or a |Funcref|. SignatureMarkerLine links to Normal by default.
See |g:SignatureMarkTextHL| for details.
*g:SignatureDeleteConfirmation*
Boolean, Default: 0
An option for the more clumsy-fingered of us. Asks for confirmation before
moving/replacing/overwriting any marks
*g:SignaturePurgeConfirmation*
Boolean, Default: 0
Similar to g:SignatureDeleteConfirmation. Asks for confirmation before
deleting all marks/markers
*g:SignaturePeriodicRefresh*
Boolean, Default: 1
Enable the display to refresh periodically. Generally a good thing to have.
This makes use of the CursorHold autocmd event to execute periodically.
The frequency of this event can be controlled by changing the value of the
updatetime variable in milliseconds
`set updatetime = 100`
*g:SignaturePrioritizeMarks*
Boolean, Default: 1
When a line has both marks and markers, display the sign for marks. If set
to 0, it will display the sign for markers instead
*g:SignatureEnabledAtStartup*
Boolean, Default: 1
Control if the signs should be shown by default. If set to 0, the signs
won't be visible until `:SignatureToggleSigns` has been called
*g:SignatureDeferPlacement*
Boolean, Default: 1
NOTE: Not supported currently. Code was highly inefficient.
Check if any other plugin has already placed a sign and if set to 1,
Signature will hold off from placing a sign. If set to 0, Signature will
overwrite any signs that are already present.
*g:SignatureUnconditionallyRecycleMarks*
Boolean, Default: 0
Controls behavior when trying to place next available mark and all marks
have been used. If set to 0, then either an error or warning message will be
emitted, depending on the setting of |g:SignatureErrorIfNoAvailableMarks|.
If set to 1, then the first local mark (e.g., 'a') will be removed from its
existing location and applied to the current line.
*g:SignatureErrorIfNoAvailableMarks*
Boolean, Default: 1
Controls behavior when unable to place a new mark. If set to 1, then an
error is raised. If set to 0, then just a warning message.
*g:SignatureForceRemoveGlobal*
Boolean, Default: 0
Vim's handling of global marks is a bit iffy. This option forces the removal
of global marks by deleting it from the viminfo (or neovim's shada) file.
Note that this is a very heavy hammer since it affects other things too.
Refer 'viminfo' or 'shada' for more information on features that could be
affected.
*g:SignatureForceMarkPlacement*
Boolean, Default: 0
When set to 1, will always place marks instead of toggling them
*g:SignatureForceMarkerPlacement*
Boolean, Default: 0
When set to 1, will always place markers instead of toggling them
==============================================================================
4. Contributing *SignatureContributing*
Please post any issues and all your suggestions on Github
https://github.com/kshenoy/vim-signature
Show some love by spreading the word and rating on
http://www.vim.org/scripts/script.php?script_id=4118
==============================================================================
5. Credits *SignatureCredits*
A great thanks to these guys for providing the idea and inspiration to develop
Signature
* Sergey Khorev for mark-tools
http://www.vim.org/scripts/script.php?script_id=2929
* Zak Johnson for vim-showmarks
https://github.com/zakj/vim-showmarks
I'd also like to thank Steve J. Losh for learningvimscriptthehardway.com
without whose detailed guide this plugin would not have seen the light of day.
==============================================================================
6. License *SignatureLicense*
Signature is MIT/X11 licensed
vim:tw=78:ts=2:et:sts=2:sw=2:ft=help

69
etc/soft/nvim/+plugins/vim-signature/plugin/signature.vim

@ -0,0 +1,69 @@
" vim: fdm=marker:et:ts=4:sw=2:sts=2
" Description: vim-signature is a plugin to toggle, display and navigate marks.
"
" Maintainer: Kartik Shenoy
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Exit if the signs feature is not available or if the app has already been loaded (or "compatible" mode set)
if !has('signs') || &cp
finish
endif
if exists('g:loaded_Signature')
finish
endif
let g:loaded_Signature = 1
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" Global variables {{{1
"
call signature#utils#Set('g:SignaturePrioritizeMarks', 1 )
call signature#utils#Set('g:SignatureIncludeMarks', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
call signature#utils#Set('g:SignatureIncludeMarkers', ')!@#$%^&*(' )
call signature#utils#Set('g:SignatureMarkTextHL', "SignatureMarkText" )
call signature#utils#Set('g:SignatureMarkTextHLDynamic', 0 )
call signature#utils#Set('g:SignatureMarkLineHL', "SignatureMarkLine" )
call signature#utils#Set('g:SignatureMarkerTextHL', "SignatureMarkerText" )
call signature#utils#Set('g:SignatureMarkerTextHLDynamic', 0 )
call signature#utils#Set('g:SignatureMarkerLineHL', "SignatureMarkerLine" )
call signature#utils#Set('g:SignatureWrapJumps', 1 )
call signature#utils#Set('g:SignatureMarkOrder', "\p\m" )
call signature#utils#Set('g:SignatureDeleteConfirmation', 0 )
call signature#utils#Set('g:SignaturePurgeConfirmation', 0 )
call signature#utils#Set('g:SignaturePeriodicRefresh', 1 )
call signature#utils#Set('g:SignatureEnabledAtStartup', 1 )
call signature#utils#Set('g:SignatureDeferPlacement', 1 )
call signature#utils#Set('g:SignatureRecycleMarks', 0 )
call signature#utils#Set('g:SignatureErrorIfNoAvailableMarks', 1 )
call signature#utils#Set('g:SignatureForceRemoveGlobal', 0 )
call signature#utils#Set('g:SignatureForceMarkPlacement', 0 )
call signature#utils#Set('g:SignatureForceMarkerPlacement', 0 )
call signature#utils#Set('g:SignatureMap', {} )
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" Commands, Autocmds and Maps {{{1
"
call signature#utils#Maps('create')
if has('autocmd')
augroup sig_autocmds
autocmd!
" This needs to be called upon loading a colorscheme
" VimEnter is kind of a backup if no colorscheme is explicitly loaded and the default is used
autocmd VimEnter,ColorScheme * call signature#utils#SetupHighlightGroups()
" This is required to remove signs for global marks that were removed when in another window
autocmd BufEnter,CmdwinEnter * call signature#sign#Refresh()
autocmd CursorHold * if (g:SignaturePeriodicRefresh) | call signature#sign#Refresh() | endif
augroup END
endif
command! -nargs=0 SignatureToggleSigns call signature#utils#Toggle()
command! -nargs=0 SignatureRefresh call signature#sign#Refresh(1)
command! -nargs=? SignatureListBufferMarks call signature#mark#List(0, <args>)
command! -nargs=? SignatureListGlobalMarks call signature#mark#List(1, <args>)
command! -nargs=* SignatureListMarkers call signature#marker#List(<args>)
Loading…
Cancel
Save