...
 
Commits (6)
......@@ -530,6 +530,11 @@
let g:cpp_class_scope_highlight = 1
let g:cpp_experimental_template_highlight = 1
" }
" vim-markdown {
let g:markdown_fenced_languages = ['bash=sh', 'c', 'cpp', 'objc', 'go']
" }
" }
......
# Vim Markdown runtime files
This is the development version of Vim's included syntax highlighting and
filetype plugins for Markdown. Generally you don't need to install these if
you are running a recent version of Vim.
One difference between this repository and the upstream files in Vim is that
the former forces `*.md` as Markdown, while the latter detects it as Modula-2,
with an exception for `README.md`. If you'd like to force Markdown without
installing from this repository, add the following to your vimrc:
autocmd BufNewFile,BufReadPost *.md set filetype=markdown
If you want to enable fenced code block syntax highlighting in your markdown
documents you can enable it in your `.vimrc` like so:
let g:markdown_fenced_languages = ['html', 'python', 'bash=sh']
To disable markdown syntax concealing add the following to your vimrc:
let g:markdown_syntax_conceal = 0
Syntax highlight is synchronized in 50 lines. It may cause collapsed
highlighting at large fenced code block.
In the case, please set larger value in your vimrc:
let g:markdown_minlines = 100
Note that setting too large value may cause bad performance on highlighting.
## License
Copyright © Tim Pope. Distributed under the same terms as Vim itself.
See `:help license`.
autocmd BufNewFile,BufRead *.markdown,*.md,*.mdown,*.mkd,*.mkdn
\ if &ft =~# '^\%(conf\|modula2\)$' |
\ set ft=markdown |
\ else |
\ setf markdown |
\ endif
" Vim filetype plugin
" Language: Markdown
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
" Last Change: 2013 May 30
if exists("b:did_ftplugin")
finish
endif
runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim
setlocal comments=fb:*,fb:-,fb:+,n:> commentstring=<!--%s-->
setlocal formatoptions+=tcqln formatoptions-=r formatoptions-=o
setlocal formatlistpat=^\\s*\\d\\+\\.\\s\\+\\\|^[-*+]\\s\\+\\\|^\\[^\\ze[^\\]]\\+\\]:
if exists('b:undo_ftplugin')
let b:undo_ftplugin .= "|setl cms< com< fo< flp<"
else
let b:undo_ftplugin = "setl cms< com< fo< flp<"
endif
function! MarkdownFold()
let line = getline(v:lnum)
" Regular headers
let depth = match(line, '\(^#\+\)\@<=\( .*$\)\@=')
if depth > 0
return ">" . depth
endif
" Setext style headings
let nextline = getline(v:lnum + 1)
if (line =~ '^.\+$') && (nextline =~ '^=\+$')
return ">1"
endif
if (line =~ '^.\+$') && (nextline =~ '^-\+$')
return ">2"
endif
return "="
endfunction
function! MarkdownFoldText()
let hash_indent = s:HashIndent(v:foldstart)
let title = substitute(getline(v:foldstart), '^#\+\s*', '', '')
let foldsize = (v:foldend - v:foldstart + 1)
let linecount = '['.foldsize.' lines]'
return hash_indent.' '.title.' '.linecount
endfunction
function! s:HashIndent(lnum)
let hash_header = matchstr(getline(a:lnum), '^#\{1,6}')
if len(hash_header) > 0
" hashtag header
return hash_header
else
" == or -- header
let nextline = getline(a:lnum + 1)
if nextline =~ '^=\+\s*$'
return repeat('#', 1)
elseif nextline =~ '^-\+\s*$'
return repeat('#', 2)
endif
endif
endfunction
if has("folding") && exists("g:markdown_folding")
setlocal foldexpr=MarkdownFold()
setlocal foldmethod=expr
setlocal foldtext=MarkdownFoldText()
let b:undo_ftplugin .= " foldexpr< foldmethod< foldtext<"
endif
" vim:set sw=2:
" Vim syntax file
" Language: Markdown
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
" Filenames: *.markdown
" Last Change: 2013 May 30
if exists("b:current_syntax")
finish
endif
if !exists('main_syntax')
let main_syntax = 'markdown'
endif
runtime! syntax/html.vim
unlet! b:current_syntax
if !exists('g:markdown_fenced_languages')
let g:markdown_fenced_languages = []
endif
let s:done_include = {}
for s:type in map(copy(g:markdown_fenced_languages),'matchstr(v:val,"[^=]*$")')
if has_key(s:done_include, matchstr(s:type,'[^.]*'))
continue
endif
if s:type =~ '\.'
let b:{matchstr(s:type,'[^.]*')}_subtype = matchstr(s:type,'\.\zs.*')
endif
exe 'syn include @markdownHighlight'.substitute(s:type,'\.','','g').' syntax/'.matchstr(s:type,'[^.]*').'.vim'
unlet! b:current_syntax
let s:done_include[matchstr(s:type,'[^.]*')] = 1
endfor
unlet! s:type
unlet! s:done_include
if !exists('g:markdown_minlines')
let g:markdown_minlines = 50
endif
execute 'syn sync minlines=' . g:markdown_minlines
syn case ignore
syn match markdownValid '[<>]\c[a-z/$!]\@!'
syn match markdownValid '&\%(#\=\w*;\)\@!'
syn match markdownLineStart "^[<@]\@!" nextgroup=@markdownBlock,htmlSpecialChar
syn cluster markdownBlock contains=markdownH1,markdownH2,markdownH3,markdownH4,markdownH5,markdownH6,markdownBlockquote,markdownListMarker,markdownOrderedListMarker,markdownCodeBlock,markdownRule
syn cluster markdownInline contains=markdownLineBreak,markdownLinkText,markdownItalic,markdownBold,markdownCode,markdownEscape,@htmlTop,markdownError
syn match markdownH1 "^.\+\n=\+$" contained contains=@markdownInline,markdownHeadingRule,markdownAutomaticLink
syn match markdownH2 "^.\+\n-\+$" contained contains=@markdownInline,markdownHeadingRule,markdownAutomaticLink
syn match markdownHeadingRule "^[=-]\+$" contained
syn region markdownH1 matchgroup=markdownHeadingDelimiter start="##\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
syn region markdownH2 matchgroup=markdownHeadingDelimiter start="###\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
syn region markdownH3 matchgroup=markdownHeadingDelimiter start="####\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
syn region markdownH4 matchgroup=markdownHeadingDelimiter start="#####\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
syn region markdownH5 matchgroup=markdownHeadingDelimiter start="######\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
syn region markdownH6 matchgroup=markdownHeadingDelimiter start="#######\@!" end="#*\s*$" keepend oneline contains=@markdownInline,markdownAutomaticLink contained
syn match markdownBlockquote ">\%(\s\|$\)" contained nextgroup=@markdownBlock
syn region markdownCodeBlock start=" \|\t" end="$" contained
" TODO: real nesting
syn match markdownListMarker "\%(\t\| \{0,4\}\)[-*+]\%(\s\+\S\)\@=" contained
syn match markdownOrderedListMarker "\%(\t\| \{0,4}\)\<\d\+\.\%(\s\+\S\)\@=" contained
syn match markdownRule "\* *\* *\*[ *]*$" contained
syn match markdownRule "- *- *-[ -]*$" contained
syn match markdownLineBreak " \{2,\}$"
syn region markdownIdDeclaration matchgroup=markdownLinkDelimiter start="^ \{0,3\}!\=\[" end="\]:" oneline keepend nextgroup=markdownUrl skipwhite
syn match markdownUrl "\S\+" nextgroup=markdownUrlTitle skipwhite contained
syn region markdownUrl matchgroup=markdownUrlDelimiter start="<" end=">" oneline keepend nextgroup=markdownUrlTitle skipwhite contained
syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+"+ end=+"+ keepend contained
syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+'+ end=+'+ keepend contained
syn region markdownUrlTitle matchgroup=markdownUrlTitleDelimiter start=+(+ end=+)+ keepend contained
syn region markdownLinkText matchgroup=markdownLinkTextDelimiter start="!\=\[\%(\_[^]]*]\%( \=[[(]\)\)\@=" end="\]\%( \=[[(]\)\@=" nextgroup=markdownLink,markdownId skipwhite contains=@markdownInline,markdownLineStart
syn region markdownLink matchgroup=markdownLinkDelimiter start="(" end=")" contains=markdownUrl keepend contained
syn region markdownId matchgroup=markdownIdDelimiter start="\[" end="\]" keepend contained
syn region markdownAutomaticLink matchgroup=markdownUrlDelimiter start="<\%(\w\+:\|[[:alnum:]_+-]\+@\)\@=" end=">" keepend oneline
let s:concealends = ''
if has('conceal') && get(g:, 'markdown_syntax_conceal', 1) == 1
let s:concealends = ' concealends'
endif
exe 'syn region markdownItalic matchgroup=markdownItalicDelimiter start="\S\@<=\*\|\*\S\@=" end="\S\@<=\*\|\*\S\@=" keepend contains=markdownLineStart,@Spell' . s:concealends
exe 'syn region markdownItalic matchgroup=markdownItalicDelimiter start="\S\@<=_\|_\S\@=" end="\S\@<=_\|_\S\@=" keepend contains=markdownLineStart,@Spell' . s:concealends
exe 'syn region markdownBold matchgroup=markdownBoldDelimiter start="\S\@<=\*\*\|\*\*\S\@=" end="\S\@<=\*\*\|\*\*\S\@=" keepend contains=markdownLineStart,markdownItalic,@Spell' . s:concealends
exe 'syn region markdownBold matchgroup=markdownBoldDelimiter start="\S\@<=__\|__\S\@=" end="\S\@<=__\|__\S\@=" keepend contains=markdownLineStart,markdownItalic,@Spell' . s:concealends
exe 'syn region markdownBoldItalic matchgroup=markdownBoldItalicDelimiter start="\S\@<=\*\*\*\|\*\*\*\S\@=" end="\S\@<=\*\*\*\|\*\*\*\S\@=" keepend contains=markdownLineStart,@Spell' . s:concealends
exe 'syn region markdownBoldItalic matchgroup=markdownBoldItalicDelimiter start="\S\@<=___\|___\S\@=" end="\S\@<=___\|___\S\@=" keepend contains=markdownLineStart,@Spell' . s:concealends
syn region markdownCode matchgroup=markdownCodeDelimiter start="`" end="`" keepend contains=markdownLineStart
syn region markdownCode matchgroup=markdownCodeDelimiter start="`` \=" end=" \=``" keepend contains=markdownLineStart
syn region markdownCode matchgroup=markdownCodeDelimiter start="^\s*````*.*$" end="^\s*````*\ze\s*$" keepend
syn match markdownFootnote "\[^[^\]]\+\]"
syn match markdownFootnoteDefinition "^\[^[^\]]\+\]:"
if main_syntax ==# 'markdown'
let s:done_include = {}
for s:type in g:markdown_fenced_languages
if has_key(s:done_include, matchstr(s:type,'[^.]*'))
continue
endif
exe 'syn region markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\..*','','').' matchgroup=markdownCodeDelimiter start="^\s*````*\s*'.matchstr(s:type,'[^=]*').'\S\@!.*$" end="^\s*````*\ze\s*$" keepend contains=@markdownHighlight'.substitute(matchstr(s:type,'[^=]*$'),'\.','','g')
let s:done_include[matchstr(s:type,'[^.]*')] = 1
endfor
unlet! s:type
unlet! s:done_include
endif
syn match markdownEscape "\\[][\\`*_{}()<>#+.!-]"
syn match markdownError "\w\@<=_\w\@="
hi def link markdownH1 htmlH1
hi def link markdownH2 htmlH2
hi def link markdownH3 htmlH3
hi def link markdownH4 htmlH4
hi def link markdownH5 htmlH5
hi def link markdownH6 htmlH6
hi def link markdownHeadingRule markdownRule
hi def link markdownHeadingDelimiter Delimiter
hi def link markdownOrderedListMarker markdownListMarker
hi def link markdownListMarker htmlTagName
hi def link markdownBlockquote Comment
hi def link markdownRule PreProc
hi def link markdownFootnote Typedef
hi def link markdownFootnoteDefinition Typedef
hi def link markdownLinkText htmlLink
hi def link markdownIdDeclaration Typedef
hi def link markdownId Type
hi def link markdownAutomaticLink markdownUrl
hi def link markdownUrl Float
hi def link markdownUrlTitle String
hi def link markdownIdDelimiter markdownLinkDelimiter
hi def link markdownUrlDelimiter htmlTag
hi def link markdownUrlTitleDelimiter Delimiter
hi def link markdownItalic htmlItalic
hi def link markdownItalicDelimiter markdownItalic
hi def link markdownBold htmlBold
hi def link markdownBoldDelimiter markdownBold
hi def link markdownBoldItalic htmlBoldItalic
hi def link markdownBoldItalicDelimiter markdownBoldItalic
hi def link markdownCodeDelimiter Delimiter
hi def link markdownEscape Special
hi def link markdownError Error
let b:current_syntax = "markdown"
if main_syntax ==# 'markdown'
unlet main_syntax
endif
" vim:set sw=2:
The MIT License (MIT)
Copyright (c) 2013 Justin M. Keyes
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.
VIM = vim -N -u NORC -i NONE --cmd 'set rtp+=tests/vader rtp+=tests/repeat rtp+=$$PWD'
test: tests/vader tests/repeat
$(VIM) '+Vader! tests/*.vader'
# https://github.com/junegunn/vader.vim/pull/75
testnvim: tests/vader tests/repeat
VADER_OUTPUT_FILE=/dev/stderr n$(VIM) --headless '+Vader! tests/*.vader'
testinteractive: tests/vader tests/repeat
$(VIM) '+Vader tests/*.vader'
tests/vader:
git clone https://github.com/junegunn/vader.vim tests/vader || ( cd tests/vader && git pull --rebase; )
tests/repeat:
git clone https://github.com/tpope/vim-repeat tests/repeat || ( cd tests/repeat && git pull --rebase; )
.PHONY: test testinteractive
sneak.vim :shoe:
================
Jump to any location specified by two characters.
Sneak is a powerful, reliable, yet minimal _motion_ plugin for Vim. It works with **multiple
lines**, **operators** (including repeat `.` and [surround]), motion-repeat
(`;` and `,`), **[keymaps]**, **visual** mode, **[multibyte]** text, and
**macros**.
Try *label-mode* for a minimalist alternative to
[EasyMotion](https://github.com/Lokaltog/vim-easymotion):
```vim
let g:sneak#label = 1
```
Usage
-----
<a href="http://imgur.com/Jke0mIJ" title="Click to see a short demo"><img src="https://raw.github.com/justinmk/vim-sneak/fluff/assets/readme_diagram.png"></a>
Sneak is invoked with `s` followed by exactly two characters:
s{char}{char}
* Type `sab` to **move the cursor** immediately to the next instance of the text "ab".
* Additional matches, if any, are highlighted until the cursor is moved.
* Type `;` to go to the next match (or `s` again, if `s_next` is enabled; see [`:help sneak`](doc/sneak.txt)).
* Type `3;` to skip to the third match from the current position.
* Type `ctrl-o` or ``` `` ``` to go back to the starting point.
* This is a built-in Vim motion; Sneak adds to Vim's [jumplist](http://vimdoc.sourceforge.net/htmldoc/motion.html#jumplist)
*only* on `s` invocation—not repeats—so you can
abandon a trail of `;` or `,` by a single `ctrl-o` or ``` `` ```.
* Type `s<Enter>` at any time to repeat the last Sneak-search.
* Type `S` to search backwards.
Sneak can be limited to a **vertical scope** by prefixing `s` with a [count].
* Type `5sxy` to go immediately to the next instance of "xy" within 5 columns
of the cursor.
Sneak is invoked with [**operators**](http://vimdoc.sourceforge.net/htmldoc/motion.html#operator)
via `z` (because `s` is taken by surround.vim).
* Type `3dzqt` to delete up to the *third* instance of "qt".
* Type `.` to repeat the `3dzqt` operation.
* Type `2.` to repeat twice.
* Type `d;` to delete up to the next match.
* Type `4d;` to delete up to the *fourth* next match.
* Type `ysz))]` to surround in brackets up to `))`.
* Type `;` to go to the next `))`.
* Type `gUz\}` to upper-case the text from the cursor until the next instance
of the literal text `\}`
* Type `.` to repeat the `gUz\}` operation.
Install
-------
- [vim-plug](https://github.com/junegunn/vim-plug)
- `Plug 'justinmk/vim-sneak'`
- [Pathogen](https://github.com/tpope/vim-pathogen)
- `git clone git://github.com/justinmk/vim-sneak.git ~/.vim/bundle/vim-sneak`
- Manual installation:
- Copy the files to your `.vim` directory.
To repeat Sneak *operations* (like `dzab`) with dot `.`,
[repeat.vim](https://github.com/tpope/vim-repeat) is required.
FAQ
---
#### Why not use `/`?
For the same reason that Vim has [motions](http://vimdoc.sourceforge.net/htmldoc/motion.html#left-right-motions)
like `f` and `t`: common operations should use the fewest keystrokes.
* `/ab<cr>` requires 33% more keystrokes than `sab`
* Sets *only* the initial position in the Vim jumplist—so you can explore a
trail of matches via `;`, then return to the start with a single `ctrl-o` or ``` `` ```
* Doesn't clutter your search history
* Input is always literal (don't need to escape special characters)
* Ignores accents ("equivalence class") when matching
([#183](https://github.com/justinmk/vim-sneak/issues/183))
* Smarter, subtler highlighting
#### Why not use `f`?
* 50x more precise than `f` or `t`
* Moves vertically
* Highlights matches in the direction of your search
#### How dare you remap `s`?
You can specify any mapping for Sneak (see [`:help sneak`](doc/sneak.txt)).
By the way: `cl` is equivalent to `s`, and `cc` is equivalent to `S`.
#### How can I replace `f` with Sneak?
```vim
map f <Plug>Sneak_s
map F <Plug>Sneak_S
```
#### How can I replace `f` and/or `t` with *one-character* Sneak?
Sneak has `<Plug>` mappings for `f` and `t` 1-character-sneak.
These mappings do *not* invoke label-mode, even if you have it enabled.
```vim
map f <Plug>Sneak_f
map F <Plug>Sneak_F
map t <Plug>Sneak_t
map T <Plug>Sneak_T
```
Related
-------
* [Seek](https://github.com/goldfeld/vim-seek)
* [EasyMotion](https://github.com/Lokaltog/vim-easymotion)
* [smalls](https://github.com/t9md/vim-smalls)
* [improvedft](https://github.com/chrisbra/improvedft)
* [clever-f](https://github.com/rhysd/clever-f.vim)
* [vim-extended-ft](https://github.com/svermeulen/vim-extended-ft)
* [Fanf,ingTastic;](https://github.com/dahu/vim-fanfingtastic)
License
-------
Copyright © Justin M. Keyes. Distributed under the MIT license.
[multibyte]: http://vimdoc.sourceforge.net/htmldoc/mbyte.html#UTF-8
[keymaps]: http://vimdoc.sourceforge.net/htmldoc/mbyte.html#mbyte-keymap
[surround]: https://github.com/tpope/vim-surround
[count]: http://vimdoc.sourceforge.net/htmldoc/intro.html#[count]
func! s:dbgflag(settingname)
if !exists(a:settingname)
silent echo 'does not exist: '.a:settingname
return
endif
exec 'let value='.a:settingname
silent echo a:settingname.'='.value
endf
func! s:dbgfeat(featurename)
silent echo 'has("'.a:featurename.'")='.has(a:featurename)
endf
func! s:dbgfunc(funcname)
silent echo exists("*".a:funcname) ? "defined: ".a:funcname
\ : "not defined: ".a:funcname
endf
func! sneak#debug#profile()
profile start profile.log
profile func sneak*
"trace all sneak script files
profile file *sneak/*
autocmd VimLeavePre * profile pause
endf
func! sneak#debug#report()
redir => vimversion
silent version
redir END
let vimversion = join(split(vimversion, "\n")[0:3], "\n")
redir => output
call s:dbgfeat('autocmd')
call s:dbgflag('&magic')
call s:dbgflag('&buftype')
call s:dbgflag('&virtualedit')
call s:dbgflag('&ignorecase')
call s:dbgflag('&smartcase')
call s:dbgflag('&background')
call s:dbgflag('&keymap')
call s:dbgflag('g:mapleader')
silent echo ""
call s:dbgfunc("sneak#to")
call s:dbgfunc("sneak#rpt")
call s:dbgfunc("sneak#search#new")
call s:dbgfunc("sneak#hl#removehl")
call s:dbgfunc("sneak#util#echo")
silent echo ""
echo "sneak#opt: ".string(g:sneak#opt)
silent exec 'verbose map f | map F | map t | map T | map s | map S | map z | map Z | map ; '
redir END
enew
silent put=vimversion
silent put=output
"setlocal nomodified
endf
func! sneak#hl#removehl() abort "remove highlighting
silent! call matchdelete(w:sneak_hl_id)
silent! call matchdelete(w:sneak_sc_hl)
endf
" gets the 'links to' value of the specified highlight group, if any.
func! sneak#hl#links_to(hlgroup) abort
redir => hl | exec 'silent highlight '.a:hlgroup | redir END
let s = substitute(matchstr(hl, 'links to \zs.*'), '\s', '', 'g')
return empty(s) ? 'NONE' : s
endf
func! sneak#hl#get(hlgroup) abort "gets the definition of the specified highlight
if !hlexists(a:hlgroup)
return ""
endif
redir => hl | exec 'silent highlight '.a:hlgroup | redir END
return matchstr(hl, '\%(.*xxx\)\?\%(.*cleared\)\?\s*\zs.*')
endf
func! s:default_color(hlgroup, what, mode) abort
let c = synIDattr(synIDtrans(hlID(a:hlgroup)), a:what, a:mode)
return !empty(c) && c != -1 ? c : (a:what ==# 'bg' ? 'magenta' : 'white')
endfunc
func! s:init() abort
exec "highlight default Sneak guifg=white guibg=magenta ctermfg=white ctermbg=".(&t_Co < 256 ? "magenta" : "201")
if &background ==# 'dark'
highlight default SneakScope guifg=black guibg=white ctermfg=0 ctermbg=255
else
highlight default SneakScope guifg=white guibg=black ctermfg=255 ctermbg=0
endif
highlight default link Cursor SneakScope
let guibg = s:default_color('Sneak', 'bg', 'gui')
let guifg = s:default_color('Sneak', 'fg', 'gui')
let ctermbg = s:default_color('Sneak', 'bg', 'cterm')
let ctermfg = s:default_color('Sneak', 'fg', 'cterm')
exec 'highlight default SneakLabel gui=bold cterm=bold guifg='.guifg.' guibg='.guibg.' ctermfg='.ctermfg.' ctermbg='.ctermbg
let guibg = s:default_color('SneakLabel', 'bg', 'gui')
let ctermbg = s:default_color('SneakLabel', 'bg', 'cterm')
" fg same as bg
exec 'highlight default SneakLabelMask guifg='.guibg.' guibg='.guibg.' ctermfg='.ctermbg.' ctermbg='.ctermbg
endf
augroup sneak_colorscheme " re-init if :colorscheme is changed at runtime. #108
autocmd!
autocmd ColorScheme * call <sid>init()
augroup END
call s:init()
" NOTES:
" problem: cchar cannot be more than 1 character.
" strategy: make fg/bg the same color, then conceal the other char.
"
" problem: [before 7.4.792] keyword highlight takes priority over conceal.
" strategy: syntax clear | [do the conceal] | let &syntax=s:o_syntax
let g:sneak#target_labels = get(g:, 'sneak#target_labels', ";sftunq/SFGHLTUNRMQZ?0")
let s:clear_syntax = !has('patch-7.4.792')
let s:matchmap = {}
let s:match_ids = []
func! s:placematch(c, pos) abort
let s:matchmap[a:c] = a:pos
let pat = '\%'.a:pos[0].'l\%'.a:pos[1].'c.'
if s:clear_syntax
exec "syntax match SneakLabel '".pat."' conceal cchar=".a:c
else
let id = matchadd('Conceal', pat, 999, -1, { 'conceal': a:c })
call add(s:match_ids, id)
endif
endf
func! sneak#label#to(s, v) abort
let seq = ""
while 1
let choice = s:do_label(a:s, a:v, a:s._reverse)
let seq .= choice
if choice =~# "^\<S-Tab>\\|\<BS>$"
call a:s.init(a:s._input, a:s._repeatmotion, 1)
elseif choice ==# "\<Tab>"
call a:s.init(a:s._input, a:s._repeatmotion, 0)
else
return seq
endif
endwhile
endf
func! s:do_label(s, v, reverse) abort "{{{
let w = winsaveview()
call s:before()
let search_pattern = (a:s.prefix).(a:s.search).(a:s.get_onscreen_searchpattern(w))
let i = 0
let overflow = [0, 0] "position of the next match (if any) after we have run out of target labels.
while 1
" searchpos() is faster than 'norm! /'
let p = searchpos(search_pattern, a:s.search_options_no_s, a:s.get_stopline())
let skippedfold = sneak#util#skipfold(p[0], a:reverse) "Note: 'set foldopen-=search' does not affect search().
if 0 == p[0] || -1 == skippedfold
break
elseif 1 == skippedfold
continue
endif
if i < s:maxmarks
"TODO: multibyte-aware substring: matchstr('asdfäöü', '.\{4\}\zs.') https://github.com/Lokaltog/vim-easymotion/issues/16#issuecomment-34595066
let c = strpart(g:sneak#target_labels, i, 1)
call s:placematch(c, p)
else "we have exhausted the target labels; grab the first non-labeled match.
let overflow = p
break
endif
let i += 1
endwhile
call winrestview(w) | redraw
let choice = sneak#util#getchar()
call s:after()
let mappedto = maparg(choice, a:v ? 'x' : 'n')
let mappedtoNext = (g:sneak#opt.absolute_dir && a:reverse)
\ ? mappedto =~# '<Plug>Sneak\(_,\|Previous\)'
\ : mappedto =~# '<Plug>Sneak\(_;\|Next\)'
if choice =~# "\\v^\<Tab>|\<S-Tab>|\<BS>$" " Decorate next N matches.
if (!a:reverse && choice ==# "\<Tab>") || (a:reverse && choice =~# "^\<S-Tab>\\|\<BS>$")
call cursor(overflow[0], overflow[1])
endif " ...else we just switched directions, do not overflow.
elseif (strlen(g:sneak#opt.label_esc) && choice ==# g:sneak#opt.label_esc)
\ || -1 != index(["\<Esc>", "\<C-c>"], choice)
return "\<Esc>" "exit label-mode.
elseif !mappedtoNext && !has_key(s:matchmap, choice) "press _any_ invalid key to escape.
call feedkeys(choice) "exit label-mode and fall through to Vim.
return ""
else "valid target was selected
let p = mappedtoNext ? s:matchmap[strpart(g:sneak#target_labels, 0, 1)] : s:matchmap[choice]
call cursor(p[0], p[1])
endif
return choice
endf "}}}
func! s:after() abort
autocmd! sneak_label_cleanup
try | call matchdelete(s:sneak_cursor_hl) | catch | endtry
call map(s:match_ids, 'matchdelete(v:val)')
let s:match_ids = []
"remove temporary highlight links
exec 'hi! link Conceal '.s:orig_hl_conceal
exec 'hi! link Sneak '.s:orig_hl_sneak
if s:clear_syntax
let &l:synmaxcol=s:o_synmaxcol
" Always clear before restore, in case user has `:syntax off`. #200
syntax clear
silent! let &l:foldmethod=s:o_fdm
silent! let &l:syntax=s:o_syntax
" Force Vim to reapply 'spell' (must set 'spelllang'). #110
let [&l:spell,&l:spelllang]=[s:o_spell,s:o_spelllang]
endif
let [&l:concealcursor,&l:conceallevel]=[s:o_cocu,s:o_cole]
call s:restore_conceal_in_other_windows()
endf
func! s:disable_conceal_in_other_windows() abort
for w in range(1, winnr('$'))
if 'help' !=# getwinvar(w, '&buftype') && w != winnr()
\ && empty(getbufvar(winbufnr(w), 'dirvish'))
call setwinvar(w, 'sneak_orig_cl', getwinvar(w, '&conceallevel'))
call setwinvar(w, '&conceallevel', 0)
endif
endfor
endf
func! s:restore_conceal_in_other_windows() abort
for w in range(1, winnr('$'))
if 'help' !=# getwinvar(w, '&buftype') && w != winnr()
\ && empty(getbufvar(winbufnr(w), 'dirvish'))
call setwinvar(w, '&conceallevel', getwinvar(w, 'sneak_orig_cl'))
endif
endfor
endf
func! s:before() abort
let s:matchmap = {}
for o in ['spell', 'spelllang', 'cocu', 'cole', 'fdm', 'synmaxcol', 'syntax']
exe 'let s:o_'.o.'=&l:'.o
endfor
setlocal concealcursor=ncv conceallevel=2
" highlight the cursor location (else the cursor is not visible during getchar())
let s:sneak_cursor_hl = matchadd("Cursor", '\%#', 11, -1)
if s:clear_syntax
setlocal nospell
" Prevent highlighting in other windows showing the same buffer.
ownsyntax sneak_label
" Avoid broken folds when we clear syntax below.
if &l:foldmethod ==# 'syntax'
setlocal foldmethod=manual
endif
syntax clear
" this is fast since we cleared syntax, and it allows sneak to work on very long wrapped lines.
setlocal synmaxcol=0
endif
let s:orig_hl_conceal = sneak#hl#links_to('Conceal')
let s:orig_hl_sneak = sneak#hl#links_to('Sneak')
"set temporary link to our custom 'conceal' highlight
hi! link Conceal SneakLabel
"set temporary link to hide the sneak search targets
hi! link Sneak SneakLabelMask
call s:disable_conceal_in_other_windows()
augroup sneak_label_cleanup
autocmd!
autocmd CursorMoved * call <sid>after()
augroup END
endf
"returns 1 if a:key is invisible or special.
func! s:is_special_key(key) abort
return -1 != index(["\<Esc>", "\<C-c>", "\<Space>", "\<CR>", "\<Tab>"], a:key)
\ || maparg(a:key, 'n') =~# '<Plug>Sneak\(_;\|_,\|Next\|Previous\)'
\ || (g:sneak#opt.s_next && maparg(a:key, 'n') =~# '<Plug>Sneak\(_s\|Forward\)')
endf
"we must do this because:
" - we don't know which keys the user assigned to Sneak_;/Sneak_,
" - we need to reserve special keys like <Esc> and <Tab>
func! sneak#label#sanitize_target_labels() abort
let nrkeys = sneak#util#strlen(g:sneak#target_labels)
let i = 0
while i < nrkeys
let k = strpart(g:sneak#target_labels, i, 1)
if s:is_special_key(k) "remove the char
let g:sneak#target_labels = substitute(g:sneak#target_labels, '\%'.(i+1).'c.', '', '')
"move ; (or s if 'clever-s' is enabled) to the front.
if !g:sneak#opt.absolute_dir
\ && ((!g:sneak#opt.s_next && maparg(k, 'n') =~# '<Plug>Sneak\(_;\|Next\)')
\ || (maparg(k, 'n') =~# '<Plug>Sneak\(_s\|Forward\)'))
let g:sneak#target_labels = k . g:sneak#target_labels
else
let nrkeys -= 1
continue
endif
endif
let i += 1
endwhile
endf
call sneak#label#sanitize_target_labels()
let s:maxmarks = sneak#util#strlen(g:sneak#target_labels)
func! sneak#search#new() abort
let s = {}
func! s.init(input, repeatmotion, reverse) abort
let self._input = a:input
let self._repeatmotion = a:repeatmotion
let self._reverse = a:reverse
" search pattern modifiers (case-sensitivity, magic)
let self.prefix = sneak#search#get_cs(a:input, g:sneak#opt.use_ic_scs).'\V'
" the escaped user input to search for
let self.search = substitute(escape(a:input, '"\'), '\a', '\\[[=\0=]]', 'g')
" example: highlight string 'ab' after line 42, column 5
" matchadd('foo', 'ab\%>42l\%5c', 1)
let self.match_pattern = ''
" do not wrap search backwards
let self._search_options = 'W' . (a:reverse ? 'b' : '')
let self.search_options_no_s = self._search_options
" save the jump on the initial invocation, _not_ repeats or consecutive invocations.
if !a:repeatmotion && !sneak#is_sneaking() | let self._search_options .= 's' | endif
endf
func! s.initpattern() abort
let self._searchpattern = (self.prefix).(self.match_pattern).'\zs'.(self.search)
endf
func! s.dosearch(...) abort " a:1 : extra search options
return searchpos(self._searchpattern
\, self._search_options.(a:0 ? a:1 : '')
\, 0
\)
endf
func! s.get_onscreen_searchpattern(w) abort
if &wrap
return ''
endif
let wincol_lhs = a:w.leftcol "this is actually just to the _left_ of the first onscreen column.
let wincol_rhs = 2 + (winwidth(0) - sneak#util#wincol1()) + wincol_lhs
"restrict search to window
return '\%>'.(wincol_lhs).'v'.'\%<'.(wincol_rhs+1).'v'
endf
func! s.get_stopline() abort
return self._reverse ? line("w0") : line("w$")
endf
" returns 1 if there are n _on-screen_ matches in the search direction.
func! s.hasmatches(n) abort
let w = winsaveview()
let searchpattern = (self._searchpattern).(self.get_onscreen_searchpattern(w))
let visiblematches = 0
while 1
let matchpos = searchpos(searchpattern, self.search_options_no_s, self.get_stopline())
if 0 == matchpos[0] "no more matches
break
elseif 0 != sneak#util#skipfold(matchpos[0], self._reverse)
continue
endif
let visiblematches += 1
if visiblematches == a:n
break
endif
endwhile
call winrestview(w)
return visiblematches >= a:n
endf
return s
endf
" gets the case sensitivity modifier for the search
func! sneak#search#get_cs(input, use_ic_scs) abort
if !a:use_ic_scs || !&ignorecase || (&smartcase && sneak#util#has_upper(a:input))
return '\C'
endif
return '\c'
endf
"search object singleton
let g:sneak#search#instance = sneak#search#new()
if v:version >= 703
func! sneak#util#strlen(s) abort
return strwidth(a:s)
"return call('strdisplaywidth', a:000)
endf
else
func! sneak#util#strlen(s) abort
return strlen(substitute(a:s, ".", "x", "g"))
endf
endif
func! sneak#util#isvisualop(op) abort
return a:op =~# "^[vV\<C-v>]"
endf
func! sneak#util#getc() abort
let c = getchar()
return type(c) == type(0) ? nr2char(c) : c
endf
func! sneak#util#getchar() abort
let input = sneak#util#getc()
if 1 != &iminsert
return input
endif
"a language keymap is activated, so input must be resolved to the mapped values.
let partial_keymap_seq = mapcheck(input, "l")
while partial_keymap_seq !=# ""
let full_keymap = maparg(input, "l")
if full_keymap ==# "" && len(input) >= 3 "HACK: assume there are no keymaps longer than 3.
return input
elseif full_keymap ==# partial_keymap_seq
return full_keymap
endif
let c = sneak#util#getc()
if c == "\<Esc>" || c == "\<CR>"
"if the short sequence has a valid mapping, return that.
if !empty(full_keymap)
return full_keymap
endif
return input
endif
let input .= c
let partial_keymap_seq = mapcheck(input, "l")
endwhile
return input
endf
"returns 1 if the string contains an uppercase char. [unicode-compatible]
func! sneak#util#has_upper(s) abort
return -1 != match(a:s, '\C[[:upper:]]')
endf
"displays a message that will dissipate at the next opportunity.
func! sneak#util#echo(msg) abort
redraw | echo a:msg
augroup SneakEcho
autocmd!
autocmd CursorMoved,InsertEnter,WinLeave,BufLeave * redraw | echo '' | autocmd! SneakEcho
augroup END
endf
"returns the least possible 'wincol'
" - if 'sign' column is displayed, the least 'wincol' is 3
" - there is (apparently) no clean way to detect if 'sign' column is visible
func! sneak#util#wincol1() abort
let w = winsaveview()
norm! 0
let c = wincol()
call winrestview(w)
return c
endf
"Moves the cursor to the first line after the current folded lines.
"Returns:
" 1 if the cursor was moved
" 0 if the cursor is not in a fold
" -1 if the start/end of the fold is at/above/below the edge of the window
func! sneak#util#skipfold(current_line, reverse) abort
let foldedge = a:reverse ? foldclosed(a:current_line) : foldclosedend(a:current_line)
if -1 != foldedge
if (a:reverse && foldedge <= line("w0")) "fold starts at/above top of window.
\ || foldedge >= line("w$") "fold ends at/below bottom of window.
return -1
endif
call line(foldedge)
call col(a:reverse ? 1 : '$')
return 1
endif
return 0
endf
"Moves the cursor 1 char to the left or right; wraps at EOL, but _not_ EOF.
func! sneak#util#nudge(right) abort
let nextchar = searchpos('\_.', 'nW'.(a:right ? '' : 'b'))
if [0, 0] == nextchar
return 0
endif
call cursor(nextchar)
return 1
endf
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -23,3 +23,4 @@ git subtree pull --prefix pack/3rdparty/start/neocomplete https://github.com/Sho
git subtree pull --prefix pack/3rdparty/start/vim-cpp-enhanced-highlight https://github.com/octol/vim-cpp-enhanced-highlight master
git subtree pull --prefix pack/3rdparty/start/vim-kolor https://github.com/zeis/vim-kolor.git master --squash
git subtree pull --prefix pack/3rdparty/start/vim-ps1 https://github.com/PProvost/vim-ps1.git master --squash
git subtree pull --prefix pack/3rdparty/start/vim-sneak https://github.com/justinmk/vim-sneak.git master --squash