1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-23 06:50:04 +08:00

fix java neoformat config

* Add incsearch.vim into bundle dir

* Fix java neoformat config

close #3573

* Use echom instead in pull.vim
This commit is contained in:
Wang Shidong 2020-06-13 21:58:05 +08:00 committed by GitHub
parent 57da4de45d
commit cd6ea298f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
111 changed files with 12278 additions and 4 deletions

View File

@ -12,7 +12,7 @@ function! SpaceVim#dev#pull#create(branch) abort
let respons = github#api#pulls#create('SpaceVim', 'SpaceVim', username, password, pull)
normal! :
if !empty(respons) && get(respons, 'number', 0) > 0
echon 'Pull request #' . respons.number . ' has been created!'
echom 'Pull request #' . respons.number . ' has been created!'
elseif !empty(respons)
let msg = get(respons, 'message', '')
echon 'Failed to create pull request:' . msg
@ -33,7 +33,7 @@ function! SpaceVim#dev#pull#merge(id) abort
let respons = github#api#pulls#Merge('SpaceVim', 'SpaceVim', a:id, commit, username, password)
normal! :
if !empty(respons) && has_key(respons, 'sha')
echon 'Pull request #' . a:id . ' has been merged!'
echom 'Pull request #' . a:id . ' has been merged!'
elseif !empty(respons)
let msg = get(respons, 'message', '')
echon 'Failed to merge pull request ' . a:id . ':' . msg

View File

@ -34,7 +34,7 @@ let s:filename = expand('<sfile>:~')
function! SpaceVim#layers#incsearch#plugins() abort
let plugins = []
call add(plugins, ['haya14busa/incsearch.vim', {'merged' : 0}])
call add(plugins, [g:_spacevim_root_dir . 'bundle/incsearch.vim', {'merged' : 0}])
call add(plugins, ['haya14busa/incsearch-fuzzy.vim', {'merged' : 0}])
call add(plugins, ['haya14busa/vim-asterisk', {'merged' : 0}])
call add(plugins, ['osyo-manga/vim-over', {'merged' : 0}])

View File

@ -116,7 +116,7 @@ function! SpaceVim#layers#lang#java#config() abort
endif
autocmd FileType jsp call <SID>JspFileTypeInit()
augroup END
let g:neoformat_enabled_java = ['googlefmt']
let g:neoformat_enabled_java = get(g:, 'neoformat_enabled_java', ['googlefmt'])
let g:neoformat_java_googlefmt = {
\ 'exe': 'java',
\ 'args': ['-jar', get(g:,'spacevim_layer_lang_java_formatter', ''), '-'],

View File

@ -0,0 +1,27 @@
language: generic
env:
- PPA=yes
- PPA=no
install:
- if [ x"$PPA" == "xyes" ] ; then sudo add-apt-repository ppa:pi-rho/dev -y; fi
- sudo apt-get update -q
- sudo apt-get install vim-nox
- sudo pip install vim-vint
- git clone https://github.com/thinca/vim-themis --branch v1.5 --single-branch --depth 1 /tmp/vim-themis
- git clone https://github.com/syngan/vim-vimlint --depth 1 /tmp/vim-vimlint
- git clone https://github.com/ynkdir/vim-vimlparser --depth 1 /tmp/vim-vimlparser
- git clone https://github.com/vim-jp/vital.vim --depth 1 /tmp/vital.vim
- git clone https://github.com/haya14busa/vital-power-assert --depth 1 /tmp/vital-power-assert
before_script:
- vim --version
- vint --version
script:
- /tmp/vim-themis/bin/themis --runtimepath /tmp/vital.vim --runtimepath /tmp/vital-vimlcompiler --runtimepath /tmp/vital-safe-string --runtimepath /tmp/vital-power-assert --reporter spec
- vim --cmd "try | helptags doc/ | catch | cquit | endtry" --cmd quit
- sh /tmp/vim-vimlint/bin/vimlint.sh -l /tmp/vim-vimlint -p /tmp/vim-vimlparser -e EVL102.l:_=1 -c func_abort=1 autoload/incsearch.vim
- sh /tmp/vim-vimlint/bin/vimlint.sh -l /tmp/vim-vimlint -p /tmp/vim-vimlparser -e EVL102.l:_=1 -c func_abort=1 autoload/incsearch
- vint autoload/incsearch autoload/incsearch.vim plugin

View File

@ -0,0 +1,5 @@
# Config for vint
# https://github.com/Kuniwak/vint
policies:
ProhibitImplicitScopeVariable:
enabled: false

View File

@ -0,0 +1,20 @@
MIT License
Copyright (c) 2014-2016 haya14busa
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.

View File

@ -0,0 +1,163 @@
![incsearch.vim](https://raw.githubusercontent.com/haya14busa/i/master/incsearch.vim/incsearch_logo.png)
[![Build Status](https://travis-ci.org/haya14busa/incsearch.vim.svg?branch=master)](https://travis-ci.org/haya14busa/incsearch.vim)
[![Build status](https://ci.appveyor.com/api/projects/status/ks6gtsu46c1djoo6/branch/master)](https://ci.appveyor.com/project/haya14busa/incsearch-vim/branch/master)
[![](http://img.shields.io/github/tag/haya14busa/incsearch.vim.svg)](https://github.com/haya14busa/incsearch.vim/releases)
[![](http://img.shields.io/github/issues/haya14busa/incsearch.vim.svg)](https://github.com/haya14busa/incsearch.vim/issues)
[![](http://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![](http://img.shields.io/badge/doc-%3Ah%20incsearch.txt-red.svg)](doc/incsearch.txt)
![](https://raw.githubusercontent.com/haya14busa/i/master/incsearch.vim/incremental_regex_building.gif)
Introduction
------------
incsearch.vim incrementally highlights __ALL__ pattern matches unlike default
'incsearch'.
Concepts
--------
### 1. Simple
incsearch.vim provides simple improved incremental searching.
### 2. Comfortable
You can use it comfortably like the default search(`/`, `?`).
It supports all modes (normal, visual, operator-pending mode), dot-repeat `.`,
`{offset}` flags, and so on.
### 3. Useful
incsearch.vim aims to be simple, but at the same time, it offers useful features.
#### Incremental regular expression editing
You can see all patterns that the given regular expression matches all at once
while incremental searching.
Usage
-----
### Installation
[Neobundle](https://github.com/Shougo/neobundle.vim) / [Vundle](https://github.com/gmarik/Vundle.vim) / [vim-plug](https://github.com/junegunn/vim-plug)
```vim
NeoBundle 'haya14busa/incsearch.vim'
Plugin 'haya14busa/incsearch.vim'
Plug 'haya14busa/incsearch.vim'
```
[pathogen](https://github.com/tpope/vim-pathogen)
```
git clone https://github.com/haya14busa/incsearch.vim ~/.vim/bundle/incsearch.vim
```
### Basic usage
```vim
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
```
`<Plug>(incsearch-stay)` doesn't move the cursor.
### Additional usages
README introduces some features, but please see [:h incsearch.vim](doc/incsearch.txt) for more information.
#### Automatic :nohlsearch
![](https://raw.githubusercontent.com/haya14busa/i/master/incsearch.vim/incsearch_auto_nohlsearch.gif)
Farewell, `nnoremap <Esc><Esc> :<C-u>nohlsearch<CR>`!
This feature turns 'hlsearch' off automatically after searching-related motions.
```vim
" :h g:incsearch#auto_nohlsearch
set hlsearch
let g:incsearch#auto_nohlsearch = 1
map n <Plug>(incsearch-nohl-n)
map N <Plug>(incsearch-nohl-N)
map * <Plug>(incsearch-nohl-*)
map # <Plug>(incsearch-nohl-#)
map g* <Plug>(incsearch-nohl-g*)
map g# <Plug>(incsearch-nohl-g#)
```
### Emacs-like incsearch: move the cursor while incremental searching
![](https://cloud.githubusercontent.com/assets/3797062/3866152/40e11c48-1fc4-11e4-8cfd-ace452a19f90.gif)
Move the cursor to next/previous matches while incremental searching like Emacs.
| Mapping | description |
| ------------------------ | --------------------------------- |
| `<Over>(incsearch-next)` | to next match. default: `<Tab>` |
| `<Over>(incsearch-prev)` | to prev match. default: `<S-Tab>` |
### Scroll-like feature while incremental searching
![](https://raw.githubusercontent.com/haya14busa/i/master/incsearch.vim/incremental_move_and_scroll.gif)
| Mapping | description |
| ------------------------ | --------------------------------- |
| `<Over>(incsearch-scroll-f)` | scroll to the next page match. default: `<C-j>` |
| `<Over>(incsearch-scroll-b)` | scroll to the previous page match. default: `<C-k>` |
:tada: Version 2.0 :tada:
-------------------------
Now, incsearch.vim provides some (experimental) API.
You can implement or use very useful yet another search command :mag_right:
### Experimental API
- `:h incsearch#go()`
- `:h incsearch-config`
Starts incsearch.vim with your custom configuration. See help docs for more detail.
### Converter feature
- `:h incsearch-config-converters`
- The list of converter extensions: https://github.com/haya14busa/incsearch.vim/wiki/List-of-plugins-for-incsearch.vim#converter-extensions
#### Example
```vim
function! s:noregexp(pattern) abort
return '\V' . escape(a:pattern, '\')
endfunction
function! s:config() abort
return {'converters': [function('s:noregexp')]}
endfunction
noremap <silent><expr> z/ incsearch#go(<SID>config())
```
incsearch.vim x fuzzy https://github.com/haya14busa/incsearch-fuzzy.vim
![incsearch-fuzzy.gif](https://raw.githubusercontent.com/haya14busa/i/master/incsearch.vim/extensions/incsearch-fuzzy.gif)
### Module extension
- `:h incsearch-config-modules`
- The list of module extentions: https://github.com/haya14busa/incsearch.vim/wiki/List-of-plugins-for-incsearch.vim#module-extensions
incsearch.vim x fuzzy x vim-easymotion https://github.com/haya14busa/incsearch-easymotion.vim
![incsearch-fuzzy-easymotion.gif](https://raw.githubusercontent.com/haya14busa/i/master/incsearch.vim/extensions/incsearch-fuzzy-easymotion.gif)
Author
------
haya14busa (https://github.com/haya14busa)
Special thanks
--------------
osyo-manga(https://github.com/osyo-manga), the author of
the custom command line library, https://github.com/osyo-manga/vital-over,
which incsearch.vim heavily depends on.
Links
-----
### VimConf2014
- [/-improved](https://docs.google.com/presentation/d/1ie2VCSt9onXmoY3v_zxJdMjYJSbAelVR-QExdUQK-Tw/pub?start=false&loop=false&delayms=3000&slide=id.g4e7add63c_05) at [VimConf 2014](http://vimconf.vim-jp.org/2014/)
- I talked in Japanese but wrote slide in English ;)
Document
--------
[:h incsearch.vim](doc/incsearch.txt)

View File

@ -0,0 +1,35 @@
version: 1.0.{build}
build: off
test_script:
- ps: >-
git clone --quiet --depth 1 https://github.com/thinca/vim-themis.git themis
git clone --quiet --depth 1 https://github.com/vim-jp/vital.vim.git vital
git clone --quiet --depth 1 https://github.com/haya14busa/vital-vimlcompiler vital-vimlcompiler
git clone --quiet --depth 1 https://github.com/haya14busa/vital-safe-string vital-safe-string
git clone --quiet --depth 1 https://github.com/haya14busa/vital-power-assert vital-power-assert
$zip = $Env:APPVEYOR_BUILD_FOLDER + '\vim.zip'
$vim = $Env:APPVEYOR_BUILD_FOLDER + '\vim'
(New-Object Net.WebClient).DownloadFile('http://files.kaoriya.net/vim/vim74-kaoriya-win64.zip', $zip)
[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') > $null
[System.IO.Compression.ZipFile]::ExtractToDirectory($zip, $vim)
$Env:THEMIS_VIM = $vim + '\vim74-kaoriya-win64\vim.exe'
& $Env:THEMIS_VIM --version
.\themis\bin\themis.bat -r --runtimepath vital --runtimepath vital-vimlcompiler --runtimepath vital-safe-string --runtimepath vital-power-assert --reporter spec

View File

@ -0,0 +1,498 @@
"=============================================================================
" FILE: autoload/incsearch.vim
" AUTHOR: haya14busa
" License: MIT license {{{
" 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.
" }}}
"
" vimlint:
" @vimlint(EVL103, 1, a:cmdline)
" @vimlint(EVL102, 1, v:errmsg)
" @vimlint(EVL102, 1, v:warningmsg)
" @vimlint(EVL102, 1, v:searchforward)
"=============================================================================
scriptencoding utf-8
" Saving 'cpoptions' {{{
let s:save_cpo = &cpo
set cpo&vim
" }}}
let s:TRUE = !0
let s:FALSE = 0
let s:DIRECTION = { 'forward': 1, 'backward': 0 } " see :h v:searchforward
" based on: https://github.com/deris/vim-magicalize/blob/433e38c1e83b1bdea4f83ab99dc19d070932380c/autoload/magicalize.vim#L52-L53
" improve to work with repetitive espaced slash like \V\V
" NOTE: \@1<= doesn't work to detect \v\v\v\v
let s:escaped_backslash = '\m\%(^\|[^\\]\)\%(\\\\\)*'
let s:non_escaped_backslash = '\m\%(\%(^\|[^\\]\)\%(\\\\\)*\)\@<=\\'
" Option:
let g:incsearch#emacs_like_keymap = get(g: , 'incsearch#emacs_like_keymap' , s:FALSE)
let g:incsearch#highlight = get(g: , 'incsearch#highlight' , {})
let g:incsearch#separate_highlight = get(g: , 'incsearch#separate_highlight' , s:FALSE)
let g:incsearch#consistent_n_direction = get(g: , 'incsearch#consistent_n_direction' , s:FALSE)
let g:incsearch#vim_cmdline_keymap = get(g: , 'incsearch#vim_cmdline_keymap' , s:TRUE)
let g:incsearch#smart_backward_word = get(g: , 'incsearch#smart_backward_word' , s:TRUE)
let g:incsearch#no_inc_hlsearch = get(g: , 'incsearch#no_inc_hlsearch' , s:FALSE)
" This changes error and warning emulation way slightly
let g:incsearch#do_not_save_error_message_history =
\ get(g:, 'incsearch#do_not_save_error_message_history', s:FALSE)
let g:incsearch#auto_nohlsearch = get(g: , 'incsearch#auto_nohlsearch' , s:FALSE)
" assert g:incsearch#magic =~# \\[mMvV]
let g:incsearch#magic = get(g: , 'incsearch#magic' , '')
" Debug:
let g:incsearch#debug = get(g:, 'incsearch#debug', s:FALSE)
" Utility:
let s:U = incsearch#util#import()
" Main: {{{
" @return vital-over command-line interface object. [experimental]
function! incsearch#cli() abort
return incsearch#cli#get()
endfunction
"" Make vital-over command-line interface object and return it [experimental]
function! incsearch#make(...) abort
return incsearch#cli#make(incsearch#config#make(get(a:, 1, {})))
endfunction
"" NOTE: this global variable is only for handling config from go_wrap func
" It avoids to make config string temporarily
let g:incsearch#_go_config = {}
"" This is main API assuming used by <expr> mappings
" ARGS:
" @config See autoload/incsearch/config.vim
" RETURN:
" Return primitive search commands (like `3/pattern<CR>`) if config.is_expr
" is TRUE, return excute command to call incsearch.vim's inner API.
" To handle dot repeat, make sure that config.is_expr is true. If you do not
" specify config.is_expr, it automatically set config.is_expr TRUE for
" operator-pending mode
" USAGE:
" :noremap <silent><expr> <Plug>(incsearch-forward) incsearch#go({'command': '/'})
" " FIXME?: Calling this with feedkeys() is ugly... Reason: incsearch#go()
" is optimize the situation which calling from <expr> mappings, and do not
" take care from calling directly or some defined command.
" :call feedkeys(incsearch#go(), 'n')
" @api
function! incsearch#go(...) abort
let config = incsearch#config#make(get(a:, 1, {}))
" FIXME?: this condition should not be config.is_expr?
if config.is_expr
return incsearch#_go(config)
else
let g:incsearch#_go_config = config
let esc = s:U.is_visual(g:incsearch#_go_config.mode) ? "\<ESC>" : ''
return printf("%s:\<C-u>call incsearch#_go(g:incsearch#_go_config)\<CR>", esc)
endif
endfunction
"" Debuggin incsearch.vim interface for calling from function call
" USAGE:
" :call incsearch#call({'pattern': @/})
" @api for debugging
function! incsearch#call(...) abort
return incsearch#_go(incsearch#config#make(get(a:, 1, {})))
endfunction
" IMPORTANT NOTE:
" Calling `incsearch#go()` and executing command which returned from
" `incsearch#go()` have to result in the same cursor move.
" @return command: String to search
function! incsearch#_go(config) abort
if s:U.is_visual(a:config.mode) && !a:config.is_expr
normal! gv
endif
let cli = incsearch#cli#make(a:config)
let input = s:get_input(cli)
if cli._does_exit_from_incsearch
" Outer incsearch-plugin handle it so do not something in paticular
return cli._return_cmd
else
" After getting input, generate command, take aftercare, and return
" command.
let l:F = function(cli._flag is# 'n' ? 's:stay' : 's:search')
let cmd = l:F(cli, input)
if !a:config.is_expr
let should_set_jumplist = (cli._flag !=# 'n')
call s:set_search_related_stuff(cli, cmd, should_set_jumplist)
if a:config.mode is# 'no'
call s:set_vimrepeat(cmd)
endif
endif
return cmd
endif
endfunction
"" To handle recursive mapping, map command to <Plug>(_incsearch-dotrepeat)
" temporarily
" https://github.com/tpope/vim-repeat
" https://github.com/kana/vim-repeat
function! s:set_vimrepeat(cmd) abort
execute 'noremap' '<Plug>(_incsearch-dotrepeat)' a:cmd
silent! call repeat#set("\<Plug>(_incsearch-dotrepeat)")
endfunction
let g:incsearch#_view = get(g:, 'incsearch#_view', {})
noremap <silent> <Plug>(_incsearch-winrestview) <Nop>
noremap! <silent> <Plug>(_incsearch-winrestview) <Nop>
nnoremap <silent> <Plug>(_incsearch-winrestview) :<C-u>call winrestview(g:incsearch#_view)<CR>
xnoremap <silent> <Plug>(_incsearch-winrestview) :<C-u>call winrestview(g:incsearch#_view)<CR>gv
function! s:stay(cli, input) abort
let [raw_pattern, offset] = a:cli._parse_pattern()
let pattern = a:cli._convert(raw_pattern)
" NOTE: do not move cursor but need to handle {offset} for n & N ...! {{{
" FIXME: cannot set {offset} if in operator-pending mode because this
" have to use feedkeys()
let is_cancel = a:cli.exit_code()
if is_cancel
call s:cleanup_cmdline()
elseif !empty(offset) && mode(1) !=# 'no'
let cmd = incsearch#with_ignore_foldopen(
\ s:U.dictfunction(a:cli._generate_command, a:cli), a:input)
call feedkeys(cmd, 'n')
let g:incsearch#_view = a:cli._w
call feedkeys("\<Plug>(_incsearch-winrestview)", 'm')
call incsearch#autocmd#auto_nohlsearch(2)
else
" Handle last-pattern
if a:input isnot# ''
call histadd('/', a:input)
call s:set_search_reg(pattern, a:cli._base_key)
endif
call incsearch#autocmd#auto_nohlsearch(0)
endif
" }}}
return s:U.is_visual(a:cli._mode) ? "\<ESC>gv" : "\<ESC>" " just exit
endfunction
function! s:search(cli, input) abort
call incsearch#autocmd#auto_nohlsearch(1) " NOTE: `.` repeat doesn't handle this
return a:cli._generate_command(a:input)
endfunction
function! s:get_input(cli) abort
" Handle visual mode highlight
if s:U.is_visual(a:cli._mode)
let visual_hl = incsearch#highlight#get_visual_hlobj()
try
call incsearch#highlight#turn_off(visual_hl)
call incsearch#highlight#emulate_visual_highlight(a:cli._mode, visual_hl)
let input = a:cli.get(a:cli._pattern)
finally
call incsearch#highlight#turn_on(visual_hl)
endtry
else
let input = a:cli.get(a:cli._pattern)
endif
return input
endfunction
" Assume the cursor move is already done.
" This function handle search related stuff which doesn't be set by :execute
" in function like @/, hisory, jumplist, offset, error & warning emulation.
function! s:set_search_related_stuff(cli, cmd, ...) abort
" For stay motion
let should_set_jumplist = get(a:, 1, s:TRUE)
let is_cancel = a:cli.exit_code()
if is_cancel
" Restore cursor position and return
" NOTE: Should I request on_cancel event to vital-over and use it?
call winrestview(a:cli._w)
call s:cleanup_cmdline()
return
endif
let [raw_pattern, offset] = a:cli._parse_pattern()
let should_execute = !empty(offset) || empty(raw_pattern)
if should_execute
" Execute with feedkeys() to work with
" 1. :h {offset} for `n` and `N`
" 2. empty input (:h last-pattern)
" NOTE: Don't use feedkeys() as much as possible to avoid flickering
call winrestview(a:cli._w)
call feedkeys(a:cmd, 'n')
if g:incsearch#consistent_n_direction
call feedkeys("\<Plug>(_incsearch-searchforward)", 'm')
endif
else
" Add history if necessary
" Do not save converted pattern to history
let pattern = a:cli._convert(raw_pattern)
let input = a:cli._combine_pattern(raw_pattern, offset)
call histadd(a:cli._base_key, input)
call s:set_search_reg(pattern, a:cli._base_key)
let target_view = winsaveview()
call winrestview(a:cli._w) " Get back start position temporarily for emulation
" Set jump list
if should_set_jumplist
normal! m`
endif
" Emulate errors, and handling `n` and `N` preparation
call s:emulate_search_error(a:cli._direction, a:cli._w)
" winrestview() between error and wraning emulation to avoid flickering
call winrestview(target_view)
" Emulate warning
call s:emulate_search_warning(a:cli._direction, a:cli._w, target_view)
call s:silent_after_search()
" Open fold
if &foldopen =~# '\vsearch|all'
normal! zv
endif
endif
endfunction
"}}}
" Helper: {{{
" @return [pattern, offset]
function! incsearch#parse_pattern(expr, search_key) abort
" search_key : '/' or '?'
" expr : {pattern\/pattern}/{offset}
" expr : {pattern}/;/{newpattern} :h //;
" return : [{pattern\/pattern}, {offset}]
let very_magic = '\v'
let pattern = '(%(\\.|.){-})'
let slash = '(\' . a:search_key . '&[^\\"|[:alnum:][:blank:]])'
let offset = '(.*)'
let parse_pattern = very_magic . pattern . '%(' . slash . offset . ')?$'
let result = matchlist(a:expr, parse_pattern)[1:3]
if type(result) == type(0) || empty(result)
return []
endif
unlet result[1]
return result
endfunction
function! incsearch#detect_case(pattern) abort
" Ignore \%C, \%U, \%V for smartcase detection
let p = substitute(a:pattern, s:non_escaped_backslash . '%[CUV]', '', 'g')
" Explicit \c has highest priority
if p =~# s:non_escaped_backslash . 'c'
return '\c'
endif
if p =~# s:non_escaped_backslash . 'C' || &ignorecase == s:FALSE
return '\C' " noignorecase or explicit \C
endif
if &smartcase == s:FALSE
return '\c' " ignorecase & nosmartcase
endif
" Find uppercase letter which isn't escaped
if p =~# s:escaped_backslash . '[A-Z]'
return '\C' " smartcase with [A-Z]
else
return '\c' " smartcase without [A-Z]
endif
endfunction
function! s:silent_after_search(...) abort " arg: mode(1)
" :h function-search-undo
let m = get(a:, 1, mode(1))
if m !=# 'no' " guard for operator-mapping
let cmd = join([
\ (s:U.is_visual(m) ? "\<Plug>(_incsearch-esc)" : ''),
\ "\<Plug>(_incsearch-hlsearch)",
\ "\<Plug>(_incsearch-searchforward)",
\ (s:U.is_visual(m) ? "\<Plug>(_incsearch-gv)" : '')
\ ], '')
call feedkeys(cmd, 'm')
endif
endfunction
noremap <silent> <Plug>(_incsearch-gv) <Nop>
noremap! <silent> <Plug>(_incsearch-gv) <Nop>
nnoremap <silent> <Plug>(_incsearch-gv) gv
noremap <silent> <Plug>(_incsearch-esc) <Nop>
noremap! <silent> <Plug>(_incsearch-esc) <Nop>
xnoremap <silent> <Plug>(_incsearch-esc) <Esc>
noremap <silent> <Plug>(_incsearch-hlsearch) <Nop>
noremap! <silent> <Plug>(_incsearch-hlsearch) <Nop>
nnoremap <silent> <Plug>(_incsearch-hlsearch) :<C-u>let &hlsearch=&hlsearch<CR>
xnoremap <silent> <Plug>(_incsearch-hlsearch) :<C-u>let &hlsearch=&hlsearch<CR>gv
noremap <silent> <Plug>(_incsearch-searchforward) <Nop>
noremap! <silent> <Plug>(_incsearch-searchforward) <Nop>
nnoremap <silent><expr> <Plug>(_incsearch-searchforward) <SID>_searchforward_cmd()
xnoremap <silent><expr> <Plug>(_incsearch-searchforward) <SID>_searchforward_cmd()
function! s:_searchforward_cmd() abort
let d = (g:incsearch#consistent_n_direction ? s:DIRECTION.forward : (incsearch#cli()._base_key is# '/' ? 1 : 0))
return printf(":\<C-u>let v:searchforward=%d\<CR>", d)
endfunction
function! s:emulate_search_error(direction, ...) abort
let from = get(a:, 1, winsaveview())
let keyseq = (a:direction == s:DIRECTION.forward ? '/' : '?')
let old_errmsg = v:errmsg
let v:errmsg = ''
" NOTE:
" - XXX: Handle `n` and `N` preparation with s:silent_after_search()
" - silent!: Do not show error and warning message, because it also
" echo v:throwpoint for error and save messages in message-history
" - Unlike v:errmsg, v:warningmsg doesn't set if it use :silent!
" Get first error
silent! call incsearch#execute_search(keyseq . "\<CR>")
call winrestview(from)
if g:incsearch#do_not_save_error_message_history
if v:errmsg !=# ''
call s:Error(v:errmsg)
else
let v:errmsg = old_errmsg
endif
else
" NOTE: show more than two errors e.g. `/\za`
let last_error = v:errmsg
try
" Do not use silent! to show warning
call incsearch#execute_search(keyseq . "\<CR>")
catch /^Vim\%((\a\+)\)\=:E/
let first_error = matchlist(v:exception, '\v^Vim%(\(\a+\))=:(E.*)$')[1]
call s:Error(first_error, 'echom')
if last_error !=# '' && last_error !=# first_error
call s:Error(last_error, 'echom')
endif
finally
call winrestview(from)
endtry
if v:errmsg ==# ''
let v:errmsg = old_errmsg
endif
endif
endfunction
function! s:emulate_search_warning(direction, from, to) abort
" NOTE:
" - It should use :h echomsg considering emulation of default
" warning messages remain in the :h message-history, but it'll mess
" up the message-history unnecessary, so it use :h echo
" - See :h shortmess
" if &shortmess !~# 's' && g:incsearch#do_not_save_error_message_history
if &shortmess !~# 's' && g:incsearch#do_not_save_error_message_history
let from = [a:from.lnum, a:from.col]
let to = [a:to.lnum, a:to.col]
let old_warningmsg = v:warningmsg
let v:warningmsg =
\ ( a:direction == s:DIRECTION.forward && !s:U.is_pos_less_equal(from, to)
\ ? 'search hit BOTTOM, continuing at TOP'
\ : a:direction == s:DIRECTION.backward && s:U.is_pos_less_equal(from, to)
\ ? 'search hit TOP, continuing at BOTTOM'
\ : '' )
if v:warningmsg !=# ''
call s:Warning(v:warningmsg)
else
let v:warningmsg = old_warningmsg
endif
endif
endfunction
function! s:cleanup_cmdline() abort
redraw | echo ''
endfunction
" Should I use :h echoerr ? But it save the messages in message-history
function! s:Error(msg, ...) abort
return call(function('s:_echohl'), [a:msg, 'ErrorMsg'] + a:000)
endfunction
function! s:Warning(msg, ...) abort
return call(function('s:_echohl'), [a:msg, 'WarningMsg'] + a:000)
endfunction
function! s:_echohl(msg, hlgroup, ...) abort
let echocmd = get(a:, 1, 'echo')
redraw | echo ''
exec 'echohl' a:hlgroup
exec echocmd string(a:msg)
echohl None
endfunction
" Not to generate command with zv
function! incsearch#with_ignore_foldopen(F, ...) abort
let foldopen_save = &foldopen
let &foldopen=''
try
return call(a:F, a:000)
finally
let &foldopen = foldopen_save
endtry
endfunction
" Try to avoid side-effect as much as possible except cursor movement
let s:has_keeppattern = v:version > 704 || v:version == 704 && has('patch083')
let s:keeppattern = (s:has_keeppattern ? 'keeppattern' : '')
function! s:_execute_search(cmd) abort
" :nohlsearch
" Please do not highlight at the first place if you set back
" info! I'll handle it myself :h function-search-undo
execute s:keeppattern 'keepjumps' 'normal!' a:cmd | nohlsearch
endfunction
if s:has_keeppattern
function! incsearch#execute_search(...) abort
return call(function('s:_execute_search'), a:000)
endfunction
else
function! incsearch#execute_search(...) abort
" keeppattern emulation
let p = @/
let r = call(function('s:_execute_search'), a:000)
" NOTE: `let @/ = p` reset v:searchforward
let d = v:searchforward
let @/ = p
let v:searchforward = d
return r
endfunction
endif
function! incsearch#magic() abort
let m = g:incsearch#magic
return (len(m) == 2 && m =~# '\\[mMvV]' ? m : '')
endfunction
" s:set_search_reg() set pattern to @/ with ?\? handling
" @command '/' or '?'
function! s:set_search_reg(pattern, command) abort
let @/ = a:command is# '?'
\ ? substitute(a:pattern, '\\?', '?', 'g') : a:pattern
endfunction
"}}}
" Restore 'cpoptions' {{{
let &cpo = s:save_cpo
unlet s:save_cpo
" }}}
" __END__ {{{
" vim: expandtab softtabstop=2 shiftwidth=2
" vim: foldmethod=marker
" }}}

View File

@ -0,0 +1,59 @@
"=============================================================================
" FILE: autoload/incsearch/autocmd.vim
" AUTHOR: haya14busa
" License: MIT license
"=============================================================================
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
noremap <silent><expr> <Plug>(_incsearch-nohlsearch) incsearch#autocmd#auto_nohlsearch(0)
noremap! <silent><expr> <Plug>(_incsearch-nohlsearch) incsearch#autocmd#auto_nohlsearch(0)
nnoremap <silent> <Plug>(_incsearch-nohlsearch) :<C-u>nohlsearch<CR>
xnoremap <silent> <Plug>(_incsearch-nohlsearch) :<C-u>nohlsearch<CR>gv
" Make sure move cursor by search related action __after__ calling this
" function because the first move event just set nested autocmd which
" does :nohlsearch
" @expr
function! incsearch#autocmd#auto_nohlsearch(nest) abort
" NOTE: see this value inside this function in order to toggle auto
" :nohlsearch feature easily with g:incsearch#autocmd#auto_nohlsearch option
if !g:incsearch#auto_nohlsearch | return '' | endif
return s:auto_nohlsearch(a:nest)
endfunction
function! incsearch#autocmd#is_set() abort
return exists('#incsearch-auto-nohlsearch#CursorMoved')
endfunction
function! s:auto_nohlsearch(nest) abort
" NOTE: :h autocmd-searchpat
" You cannot implement this feature without feedkeys() because of
" :h autocmd-searchpat
augroup incsearch-auto-nohlsearch
autocmd!
autocmd InsertEnter * :call <SID>attach_on_insert_leave() | autocmd! incsearch-auto-nohlsearch
execute join([
\ 'autocmd CursorMoved *'
\ , repeat('autocmd incsearch-auto-nohlsearch CursorMoved * ', a:nest)
\ , 'call feedkeys("\<Plug>(_incsearch-nohlsearch)", "m")'
\ , '| autocmd! incsearch-auto-nohlsearch'
\ ], ' ')
augroup END
return ''
endfunction
function! s:attach_on_insert_leave() abort
augroup incsearch-auto-nohlsearch-on-insert-leave
autocmd!
autocmd InsertLeave * :call incsearch#autocmd#auto_nohlsearch(1)
\ | autocmd! incsearch-auto-nohlsearch-on-insert-leave
augroup END
return ''
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" __END__
" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker

View File

@ -0,0 +1,109 @@
"=============================================================================
" FILE: autoload/incsearch/cli.vim
" AUTHOR: haya14busa
" License: MIT license
"=============================================================================
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:DIRECTION = { 'forward': 1, 'backward': 0 } " see :h v:searchforward
function! incsearch#cli#get() abort
try
" It returns current cli object
return s:Doautocmd.get_cmdline()
catch /vital-over(_incsearch) Exception/
" If there are no current cli object, return default one
return incsearch#cli#make(incsearch#config#make({}))
endtry
endfunction
" @config: whole configuration
function! incsearch#cli#make(config) abort
let cli = deepcopy(s:cli)
call incsearch#cli#set(cli, a:config)
return cli
endfunction
" To reuse cli object, you should re-set configuration
" @config: whole configuration
function! incsearch#cli#set(cli, config) abort
let a:cli._base_key = a:config.command
let a:cli._vcount1 = max([1, a:config.count])
let a:cli._has_count = a:config.count > 0
let a:cli._is_expr = a:config.is_expr
let a:cli._mode = a:config.mode
let a:cli._pattern = a:config.pattern
let a:cli._prompt = a:config.prompt
let a:cli._keymap = a:config.keymap
let a:cli._converters = a:config.converters
let a:cli._flag = a:config.is_stay ? 'n'
\ : a:config.command is# '/' ? ''
\ : a:config.command is# '?' ? 'b'
\ : ''
let a:cli._direction =
\ (a:cli._base_key is# '/' ? s:DIRECTION.forward : s:DIRECTION.backward)
" TODO: provide config? but it may conflict with <expr> mapping
" NOTE: _w: default cursor view
let a:cli._w = winsaveview()
for module in a:config.modules
call a:cli.connect(module)
endfor
call a:cli.set_prompt(a:cli._prompt)
return a:cli
endfunction
let s:cli = vital#incsearch#import('Over.Commandline').make_default('/')
let s:modules = vital#incsearch#import('Over.Commandline.Modules')
" Add modules
call s:cli.connect('BufferComplete')
call s:cli.connect('Cancel')
call s:cli.connect('CursorMove')
call s:cli.connect('Digraphs')
call s:cli.connect('Delete')
call s:cli.connect('DrawCommandline')
call s:cli.connect('ExceptionExit')
call s:cli.connect('LiteralInsert')
call s:cli.connect(incsearch#over#modules#exit#make())
call s:cli.connect(incsearch#over#modules#insert_register#make())
call s:cli.connect('Paste')
let s:Doautocmd = s:modules.get('Doautocmd')
call s:cli.connect(s:Doautocmd.make('IncSearch'))
call s:cli.connect(s:modules.get('ExceptionMessage').make('incsearch.vim: ', 'echom'))
call s:cli.connect(s:modules.get('History').make('/'))
call s:cli.connect(s:modules.get('NoInsert').make_special_chars())
" Dynamic Module Loading Management
let s:KeyMapping = s:modules.get('KeyMapping')
let s:emacs_like = s:KeyMapping.make_emacs()
let s:vim_cmap = s:KeyMapping.make_vim_cmdline_mapping()
let s:smartbackword = s:modules.get('IgnoreRegexpBackwardWord').make()
function! s:emacs_like._condition() abort
return g:incsearch#emacs_like_keymap
endfunction
function! s:vim_cmap._condition() abort
return g:incsearch#vim_cmdline_keymap
endfunction
function! s:smartbackword._condition() abort
return g:incsearch#smart_backward_word
endfunction
call s:cli.connect(incsearch#over#modules#module_management#make([s:emacs_like, s:vim_cmap, s:smartbackword]))
unlet s:KeyMapping s:emacs_like s:vim_cmap s:smartbackword
call s:cli.connect(incsearch#over#modules#pattern_saver#make())
call s:cli.connect(incsearch#over#modules#bulk_input_char#make())
call s:cli.connect(incsearch#over#modules#bracketed_paste#make())
call s:cli.connect(incsearch#over#modules#incsearch#make())
function! s:cli.__keymapping__() abort
return copy(self._keymap)
endfunction
call incsearch#over#extend#enrich(s:cli)
let &cpo = s:save_cpo
unlet s:save_cpo
" __END__
" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker

View File

@ -0,0 +1,99 @@
"=============================================================================
" FILE: autoload/incsearch/config.vim
" AUTHOR: haya14busa
" License: MIT license
"=============================================================================
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:TRUE = !0
let s:FALSE = 0
lockvar s:TRUE s:FALSE
let s:U = incsearch#util#import()
"" incsearch config
" TODO: more detail documentation
" @command is equivalent with base_key TODO: fix this inconsistence
" @count default: v:count secret
" @mode default: mode(1) secret
let s:config = {
\ 'command': '/',
\ 'is_stay': s:FALSE,
\ 'is_expr': s:FALSE,
\ 'pattern': '',
\ 'mode': 'n',
\ 'count': 0,
\ 'prompt': '',
\ 'modules': [],
\ 'converters': [],
\ 'keymap': {}
\ }
" @return config for lazy value
function! s:lazy_config() abort
let m = mode(1)
return {
\ 'count': v:count,
\ 'mode': m,
\ 'is_expr': (m is# 'no'),
\ 'keymap': s:keymap()
\ }
endfunction
" @return config with default value
function! incsearch#config#make(additional) abort
let default = extend(deepcopy(s:config), s:lazy_config())
let c = s:U.deepextend(default, a:additional)
if c.prompt is# ''
let c.prompt = c.command
endif
return c
endfunction
let s:default_keymappings = {
\ "\<Tab>" : {
\ 'key' : '<Over>(incsearch-next)',
\ 'noremap' : 1,
\ },
\ "\<S-Tab>" : {
\ 'key' : '<Over>(incsearch-prev)',
\ 'noremap' : 1,
\ },
\ "\<C-j>" : {
\ 'key' : '<Over>(incsearch-scroll-f)',
\ 'noremap' : 1,
\ },
\ "\<C-k>" : {
\ 'key' : '<Over>(incsearch-scroll-b)',
\ 'noremap' : 1,
\ },
\ "\<C-l>" : {
\ 'key' : '<Over>(buffer-complete)',
\ 'noremap' : 1,
\ },
\ "\<CR>" : {
\ 'key': "\<CR>",
\ 'noremap': 1
\ },
\ }
" https://github.com/haya14busa/incsearch.vim/issues/35
if has('mac')
call extend(s:default_keymappings, {
\ '"+gP' : {
\ 'key': "\<C-r>+",
\ 'noremap': 1
\ },
\ })
endif
function! s:keymap() abort
return extend(copy(s:default_keymappings), g:incsearch_cli_key_mappings)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" __END__
" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker

View File

@ -0,0 +1,297 @@
"=============================================================================
" FILE: autoload/incsearch/highlight.vim
" AUTHOR: haya14busa
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
scriptencoding utf-8
" Saving 'cpoptions' {{{
let s:save_cpo = &cpo
set cpo&vim
" }}}
let s:TRUE = !0
let s:FALSE = 0
let s:DIRECTION = { 'forward': 1, 'backward': 0 } " see :h v:searchforward
" Utility Helper:
let s:U = incsearch#util#import()
" Management:
let s:hi = vital#incsearch#import('Coaster.Highlight').make()
let g:incsearch#highlight#_hi = s:hi
function! incsearch#highlight#update() abort
" it's intuiive to call incsearch#highlight#on() & off() but there are no
" need to execute `:nohlsearch` when updating.
call s:hi.disable_all()
call s:hi.enable_all()
endfunction
function! incsearch#highlight#on() abort
call s:hi.enable_all()
if ! g:incsearch#no_inc_hlsearch
let &hlsearch = &hlsearch
endif
endfunction
function! incsearch#highlight#off() abort
call s:hi.disable_all()
if ! g:incsearch#no_inc_hlsearch
nohlsearch
endif
endfunction
function! s:init_hl() abort
hi default link IncSearchMatch Search
hi default link IncSearchMatchReverse IncSearch
hi default link IncSearchCursor Cursor
hi default link IncSearchOnCursor IncSearch
hi default IncSearchUnderline term=underline cterm=underline gui=underline
endfunction
call s:init_hl()
augroup plugin-incsearch-highlight
autocmd!
autocmd ColorScheme * call s:init_hl()
augroup END
let s:default_highlight = {
\ 'visual' : {
\ 'group' : '_IncSearchVisual',
\ 'priority' : '10'
\ },
\ 'match' : {
\ 'group' : 'IncSearchMatch',
\ 'priority' : '49'
\ },
\ 'match_reverse' : {
\ 'group' : 'IncSearchMatchReverse',
\ 'priority' : '49'
\ },
\ 'on_cursor' : {
\ 'group' : 'IncSearchOnCursor',
\ 'priority' : '50'
\ },
\ 'cursor' : {
\ 'group' : 'IncSearchCursor',
\ 'priority' : '51'
\ },
\ }
function! incsearch#highlight#hgm() abort " highlight group management
let hgm = copy(s:default_highlight)
for key in keys(hgm)
call extend(hgm[key], get(g:incsearch#highlight, key, {}))
endfor
return hgm
endfunction
" hldict: { 'name' : lhs, 'highlight': rhs }
" Util:
" @return hldict
function! incsearch#highlight#capture(hlname) abort
" Based On: https://github.com/t9md/vim-ezbar
" https://github.com/osyo-manga/vital-over
let hlname = a:hlname
if !hlexists(hlname)
return
endif
while 1
let save_verbose = &verbose
let &verbose = 0
try
redir => HL_SAVE
execute 'silent! highlight ' . hlname
redir END
finally
let &verbose = save_verbose
endtry
if !empty(matchstr(HL_SAVE, 'xxx cleared$'))
return ''
endif
" follow highlight link
let ml = matchlist(HL_SAVE, 'links to \zs.*')
if !empty(ml)
let hlname = ml[0]
continue
endif
break
endwhile
let HL_SAVE = substitute(matchstr(HL_SAVE, 'xxx \zs.*'),
\ '[ \t\n]\+', ' ', 'g')
return { 'name': hlname, 'highlight': HL_SAVE }
endfunction
function! incsearch#highlight#turn_off(hldict) abort
execute 'highlight' a:hldict.name 'NONE'
endfunction
function! incsearch#highlight#turn_on(hldict) abort
execute 'highlight' a:hldict.name a:hldict.highlight
endfunction
" Wrapper:
" @return hlobj
function! incsearch#highlight#get_visual_hlobj() abort
if ! exists('s:_visual_hl')
let s:_visual_hl = incsearch#highlight#capture('Visual')
endif
return s:_visual_hl
endfunction
augroup incsearch-update-visual-highlight
autocmd!
autocmd ColorScheme * if exists('s:_visual_hl') | unlet s:_visual_hl | endif
augroup END
" Visual Highlighting Emulation:
let s:INT = { 'MAX': 2147483647 }
" NOTE:
" Default highlight for visual selection has always higher priority than
" defined highlight, so you have to turn off default visual highlight and
" emulate it. All this function do is pseudo highlight visual selected area
" args: mode, visual_hl, v_start_pos, v_end_pos
function! incsearch#highlight#emulate_visual_highlight(...) abort
let is_visual_now = s:U.is_visual(mode(1))
let mode = get(a:, 1, is_visual_now ? mode(1) : visualmode())
let visual_hl = get(a:, 2, incsearch#highlight#get_visual_hlobj())
" Note: the default pos value assume visual selection is not cleared.
" It uses curswant to emulate visual-block
let v_start_pos = get(a:, 3,
\ (is_visual_now ? [line('v'),col('v')] : [line("'<"), col("'<")]))
" See: https://github.com/vim-jp/issues/issues/604
" getcurpos() could be negative value, so use winsaveview() instead
let end_curswant_pos =
\ (exists('*getcurpos') ? getcurpos()[4] : winsaveview().curswant + 1)
let v_end_pos = get(a:, 4, (is_visual_now
\ ? [line('.'), end_curswant_pos < 0 ? s:INT.MAX : end_curswant_pos ]
\ : [line("'>"), col("'>")]))
let pattern = incsearch#highlight#get_visual_pattern(mode, v_start_pos, v_end_pos)
let hgm = incsearch#highlight#hgm()
let v = hgm.visual
" NOTE: Update highlight
execute 'hi' 'clear' v.group
execute 'hi' v.group visual_hl['highlight']
call s:hi.add(v.group, v.group, pattern, v.priority)
call incsearch#highlight#update()
endfunction
function! incsearch#highlight#get_visual_pattern(mode, v_start_pos, v_end_pos) abort
" NOTE: highlight doesn't work if the range is over screen height, so
" limit pattern to visible window.
let [_, v_start, v_end, _] = s:U.sort_pos([
\ a:v_start_pos,
\ a:v_end_pos,
\ [line('w0'), 1],
\ [line('w$'), s:U.get_max_col(line('w$'))]
\ ])
if a:mode ==# 'v'
if v_start[0] == v_end[0]
return printf('\v%%%dl%%%dc\_.*%%%dl%%%dc',
\ v_start[0],
\ min([v_start[1], s:U.get_max_col(v_start[0])]),
\ v_end[0],
\ min([v_end[1], s:U.get_max_col(v_end[0])]))
else
return printf('\v%%%dl%%%dc\_.{-}%%%dl|%%%dl\_.*%%%dl%%%dc',
\ v_start[0],
\ min([v_start[1], s:U.get_max_col(v_start[0])]),
\ v_end[0],
\ v_end[0],
\ v_end[0],
\ min([v_end[1], s:U.get_max_col(v_end[0])]))
endif
elseif a:mode ==# 'V'
return printf('\v%%%dl\_.*%%%dl', v_start[0], v_end[0])
elseif a:mode ==# "\<C-v>"
" @vimlint(EVL102, 1, l:min_c)
let [min_c, max_c] = s:U.sort_num([v_start[1], v_end[1]])
let max_c += 1 " increment needed
let max_c = max_c < 0 ? s:INT.MAX : max_c
let mapfunc = "
\ printf('%%%dl%%%dc.*%%%dc',
\ v:val, min_c, min([max_c, s:U.get_max_col(v:val)]))
\ "
return '\v'.join(map(range(v_start[0], v_end[0]), mapfunc), '|')
else
throw 'incsearch.vim: unexpected mode ' . a:mode
endif
endfunction
" Incremental Highlighting:
function! incsearch#highlight#incremental_highlight(pattern, ...) abort
let should_separate_highlight = get(a:, 1, s:FALSE)
let direction = get(a:, 2, s:DIRECTION.forward)
let start_pos = get(a:, 3, getpos('.')[1:2])
let hgm = incsearch#highlight#hgm()
let [m, r, o, c] = [hgm.match, hgm.match_reverse, hgm.on_cursor, hgm.cursor]
let on_cursor_pattern = '\m\%#\(' . a:pattern . '\m\)'
if '' =~# a:pattern
" Do not highlight for patterns which match everything
call s:hi.delete_all()
elseif ! should_separate_highlight
call s:hi.add(m.group, m.group, a:pattern, m.priority)
if ! g:incsearch#no_inc_hlsearch
let @/ = a:pattern
let &hlsearch = &hlsearch
endif
else
let [p1, p2] = (direction == s:DIRECTION.forward)
\ ? [incsearch#highlight#forward_pattern(a:pattern, start_pos)
\ ,incsearch#highlight#backward_pattern(a:pattern, start_pos)]
\ : [incsearch#highlight#backward_pattern(a:pattern, start_pos)
\ ,incsearch#highlight#forward_pattern(a:pattern, start_pos)]
call s:hi.add(m.group , m.group , p1 , m.priority) " right direction
call s:hi.add(r.group , r.group , p2 , r.priority) " reversed direction
endif
call s:hi.add(o.group , o.group , on_cursor_pattern , o.priority)
call s:hi.add(c.group , c.group , '\v%#' , c.priority)
call incsearch#highlight#update()
endfunction
function! incsearch#highlight#forward_pattern(pattern, from_pos) abort
let [line, col] = a:from_pos
return printf('\v(%%>%dl|%%%dl%%>%dc)\m\(%s\m\)', line, line, col, a:pattern)
endfunction
function! incsearch#highlight#backward_pattern(pattern, from_pos) abort
let [line, col] = a:from_pos
return printf('\v(%%<%dl|%%%dl%%<%dc)\m\(%s\m\)', line, line, col, a:pattern)
endfunction
" Restore 'cpoptions' {{{
let &cpo = s:save_cpo
unlet s:save_cpo
" }}}
" __END__ {{{
" vim: expandtab softtabstop=2 shiftwidth=2
" vim: foldmethod=marker
" }}}

View File

@ -0,0 +1,122 @@
"=============================================================================
" FILE: autoload/incsearch/over/extend.vim
" AUTHOR: haya14busa
" License: MIT license
"=============================================================================
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:TRUE = !0
let s:FALSE = 0
let s:non_escaped_backslash = '\m\%(\%(^\|[^\\]\)\%(\\\\\)*\)\@<=\\'
let s:U = incsearch#util#import()
function! incsearch#over#extend#enrich(cli) abort
return extend(a:cli, s:cli)
endfunction
let s:cli = {
\ '_does_exit_from_incsearch': s:FALSE,
\ '_return_cmd': '',
\ '_converter_cache': {}
\ }
function! s:cli._generate_command(input) abort
let is_cancel = self.exit_code()
if is_cancel
return s:U.is_visual(self._mode) ? '\<ESC>gv' : "\<ESC>"
else
call self._call_execute_event()
let [pattern, offset] = incsearch#parse_pattern(a:input, self._base_key)
" TODO: implement convert input method
let p = self._combine_pattern(self._convert(pattern), offset)
return self._build_search_cmd(p)
endif
endfunction
" @return search cmd
function! s:cli._build_search_cmd(pattern, ...) abort
let mode = get(a:, 1, self._mode)
let op = (mode ==# 'no') ? v:operator
\ : s:U.is_visual(mode) ? 'gv'
\ : ''
let zv = (&foldopen =~# '\vsearch|all' && mode !=# 'no' ? 'zv' : '')
" NOTE:
" Should I consider o_v, o_V, and o_CTRL-V cases and do not
" <Esc>? <Esc> exists for flexible v:count with using s:cli._vcount1,
" but, if you do not move the cursor while incremental searching,
" there are no need to use <Esc>.
let esc = self._has_count ? "\<Esc>" : ''
let register = esc is# '' ? '' : '"' . v:register
let cnt = self._vcount1 is# 1 ? '' : self._vcount1
let prefix = esc . register . (esc is# '' ? '' : op) . cnt
return printf("%s%s%s\<CR>%s", prefix, self._base_key, a:pattern, zv)
endfunction
"" Call on_execute_pre and on_execute event
" assume current position is the destination and a:cli._w is the position to
" start search
function! s:cli._call_execute_event(...) abort
let view = get(a:, 1, winsaveview())
try
call winrestview(self._w)
call self.callevent('on_execute_pre')
finally
call winrestview(view)
endtry
call self.callevent('on_execute')
endfunction
function! s:cli._parse_pattern() abort
if v:version == 704 && !has('patch421')
" Ignore \ze* which clash vim 7.4 without 421 patch
" Assume `\m`
let [p, o] = incsearch#parse_pattern(self.getline(), self._base_key)
let p = (p =~# s:non_escaped_backslash . 'z[se]\%(\*\|\\+\)' ? '' : p)
return [p, o]
else
return incsearch#parse_pattern(self.getline(), self._base_key)
endif
endfunction
function! s:cli._combine_pattern(pattern, offset) abort
return empty(a:offset) ? a:pattern : a:pattern . self._base_key . a:offset
endfunction
function! s:cli._convert(pattern) abort
if a:pattern is# ''
return a:pattern
elseif empty(self._converters)
return incsearch#magic() . a:pattern
elseif has_key(self._converter_cache, a:pattern)
return self._converter_cache[a:pattern]
else
let ps = [incsearch#magic() . a:pattern]
for l:Converter in self._converters
let l:Convert = type(l:Converter) is type(function('function'))
\ ? l:Converter : l:Converter.convert
let ps += [l:Convert(a:pattern)]
unlet l:Converter
endfor
" Converters may return upper case even if a:pattern doesn't contain upper
" case letter, so prepend case flag explicitly
" let case = incsearch#detect_case(a:pattern)
let case = incsearch#detect_case(a:pattern)
let self._converter_cache[a:pattern] = case . s:U.regexp_join(ps)
return self._converter_cache[a:pattern]
endif
endfunction
function! s:cli._exit_incsearch(...) abort
let cmd = get(a:, 1, '')
let self._return_cmd = cmd
let self._does_exit_from_incsearch = s:TRUE
call self.exit()
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" __END__
" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker

View File

@ -0,0 +1,40 @@
"=============================================================================
" FILE: autoload/incsearch/over/modules/bracketed_paste.vim
" AUTHOR: haya14busa
" License: MIT license
" @vimlint(EVL103, 1, a:cmdline)
"=============================================================================
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
" https://github.com/haya14busa/incsearch.vim/issues/131
let s:bracketed_paste = {
\ 'name' : 'BracketedPaste',
\ 't_BE' : '',
\}
function! s:bracketed_paste.on_enter(cmdline) abort
if !exists('&t_BE')
return
endif
let self.t_BE = &t_BE
set t_BE=
endfunction
function! s:bracketed_paste.on_leave(cmdline) abort
if !exists('&t_BE')
return
endif
let &t_BE = self.t_BE
endfunction
function! incsearch#over#modules#bracketed_paste#make() abort
return deepcopy(s:bracketed_paste)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" __END__
" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker

View File

@ -0,0 +1,38 @@
"=============================================================================
" FILE: autoload/incsearch/over/modules/bulk_input_char.vim
" AUTHOR: haya14busa
" License: MIT license
"=============================================================================
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
" IncsearchBulkInputChar bulk insert characters and avoid updating for each
" character input. It's useful while execution macro or pasting text clipboard.
" CAUTION: cannot test getchar(0) with themis.vim
let s:bulk_input_char = {
\ 'name': 'IncsearchBulkInputChar'
\ }
function! s:bulk_input_char.on_char_pre(cmdline) abort
let stack = []
let c = 1
while c
let c = getchar(0)
if c != 0
let stack += [nr2char(c)]
elseif !empty(stack)
call a:cmdline.set_input_key_stack(stack)
endif
endwhile
endfunction
function! incsearch#over#modules#bulk_input_char#make() abort
return deepcopy(s:bulk_input_char)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" __END__
" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker

View File

@ -0,0 +1,33 @@
"=============================================================================
" FILE: autoload/incsearch/over/modules/exit.vim
" AUTHOR: haya14busa
" License: MIT license
"=============================================================================
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
" NOTE:
" <CR> in {rhs} wil be remapped even after exiting vital-over command line
" interface, so do not use <Over>(exit)
" See also s:cli.keymapping()
let s:incsearch_exit = {
\ 'name' : 'IncsearchExit',
\ 'exit_code' : 0
\}
function! s:incsearch_exit.on_char_pre(cmdline) abort
if a:cmdline.is_input("\<CR>")
\ || a:cmdline.is_input("\<NL>")
call a:cmdline.setchar('')
call a:cmdline.exit(self.exit_code)
endif
endfunction
function! incsearch#over#modules#exit#make() abort
return deepcopy(s:incsearch_exit)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" __END__
" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker

View File

@ -0,0 +1,295 @@
"=============================================================================
" FILE: autoload/incsearch/over/modules/incsearch.vim
" AUTHOR: haya14busa
" License: MIT license
"=============================================================================
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:TRUE = !0
let s:FALSE = 0
let s:DIRECTION = { 'forward': 1, 'backward': 0 } " see :h v:searchforward
let s:hi = g:incsearch#highlight#_hi
let s:U = incsearch#util#import()
let s:inc = {
\ 'name' : 'incsearch',
\}
" NOTE: for InsertRegister handling
function! s:inc.priority(event) abort
return a:event is# 'on_char' ? 10 : 0
endfunction
function! s:inc.on_enter(cmdline) abort
nohlsearch " disable previous highlight
let a:cmdline._w = winsaveview()
let hgm = incsearch#highlight#hgm()
let c = hgm.cursor
call s:hi.add(c.group, c.group, '\%#', c.priority)
call incsearch#highlight#update()
" XXX: Manipulate search history for magic option
" In the first place, I want to omit magic flag when histadd(), but
" when returning cmd as expr mapping and feedkeys() cannot handle it, so
" remove no user intended magic flag at on_enter.
" Maybe I can also handle it with autocmd, should I use autocmd instead?
let hist = histget('/', -1)
if len(hist) > 2 && hist[:1] ==# incsearch#magic()
call histdel('/', -1)
call histadd('/', hist[2:])
endif
endfunction
function! s:inc.on_leave(cmdline) abort
call s:hi.disable_all()
call s:hi.delete_all()
" redraw: hide pseud-cursor
redraw " need to redraw for handling non-<expr> mappings
if a:cmdline.getline() ==# ''
echo ''
else
echo a:cmdline.get_prompt() . a:cmdline.getline()
endif
" NOTE:
" push rest of keymappings with feedkeys()
" FIXME: assume 'noremap' but it should take care wheter or not the
" mappings should be remapped or not
if a:cmdline.input_key_stack_string() !=# ''
call feedkeys(a:cmdline.input_key_stack_string(), 'n')
endif
endfunction
" Avoid search-related error while incremental searching
function! s:on_searching(func, ...) abort
try
return call(a:func, a:000)
catch /E16:/ " E16: Invalid range (with /\_[a- )
catch /E33:/ " E33: No previous substitute regular expression
catch /E53:/ " E53: Unmatched %(
catch /E54:/
catch /E55:/
catch /E62:/ " E62: Nested \= (with /a\=\=)
catch /E63:/ " E63: invalid use of \_
catch /E64:/ " E64: \@ follows nothing
catch /E65:/ " E65: Illegal back reference
catch /E66:/ " E66: \z( not allowed here
catch /E67:/ " E67: \z1 et al. not allowed here
catch /E68:/ " E68: Invalid character after \z (with /\za & re=1)
catch /E69:/ " E69: Missing ] after \%[
catch /E70:/ " E70: Empty \%[]
catch /E71:/ " E71: Invalid character after \%
catch /E554:/
catch /E678:/ " E678: Invalid character after \%[dxouU]
catch /E864:/ " E864: \%#= can only be followed by 0, 1, or 2. The
" automatic engine will be used
catch /E865:/ " E865: (NFA) Regexp end encountered prematurely
catch /E866:/ " E866: (NFA regexp) Misplaced @
catch /E867:/ " E867: (NFA) Unknown operator
catch /E869:/ " E869: (NFA) Unknown operator '\@m
catch /E870:/ " E870: (NFA regexp) Error reading repetition limits
catch /E871:/ " E871: (NFA regexp) Can't have a multi follow a multi !
catch /E874:/ " E874: (NFA) Could not pop the stack ! (with \&)
catch /E877:/ " E877: (NFA regexp) Invalid character class: 109
catch /E888:/ " E888: (NFA regexp) cannot repeat (with /\ze*)
call s:hi.disable_all()
catch
echohl ErrorMsg | echom v:throwpoint . ' ' . v:exception | echohl None
endtry
endfunction
function! s:on_char_pre(cmdline) abort
" NOTE:
" `:call a:cmdline.setchar('')` as soon as possible!
let [raw_pattern, offset] = a:cmdline._parse_pattern()
let pattern = a:cmdline._convert(raw_pattern)
" Interactive :h last-pattern if pattern is empty
if ( a:cmdline.is_input('<Over>(incsearch-next)')
\ || a:cmdline.is_input('<Over>(incsearch-prev)')
\ ) && empty(pattern)
call a:cmdline.setchar('')
" Use history instead of @/ to work with magic option and converter
call a:cmdline.setline(histget('/', -1) . (empty(offset) ? '' : a:cmdline._base_key) . offset)
" Just insert last-pattern and do not count up, but the incsearch-prev
" should move the cursor to reversed directly, so do not return if the
" command is prev
if a:cmdline.is_input('<Over>(incsearch-next)') | return | endif
endif
if a:cmdline.is_input('<Over>(incsearch-next)')
call a:cmdline.setchar('')
if a:cmdline._flag ==# 'n' " exit stay mode
let a:cmdline._flag = ''
else
let a:cmdline._vcount1 += 1
endif
elseif a:cmdline.is_input('<Over>(incsearch-prev)')
call a:cmdline.setchar('')
if a:cmdline._flag ==# 'n' " exit stay mode
let a:cmdline._flag = ''
endif
let a:cmdline._vcount1 -= 1
elseif (a:cmdline.is_input('<Over>(incsearch-scroll-f)')
\ && (a:cmdline._flag ==# '' || a:cmdline._flag ==# 'n'))
\ || (a:cmdline.is_input('<Over>(incsearch-scroll-b)') && a:cmdline._flag ==# 'b')
call a:cmdline.setchar('')
if a:cmdline._flag ==# 'n' | let a:cmdline._flag = '' | endif
let pos_expr = a:cmdline.is_input('<Over>(incsearch-scroll-f)') ? 'w$' : 'w0'
let to_col = a:cmdline.is_input('<Over>(incsearch-scroll-f)')
\ ? s:U.get_max_col(pos_expr) : 1
let [from, to] = [getpos('.')[1:2], [line(pos_expr), to_col]]
let cnt = s:U.count_pattern(pattern, from, to)
let a:cmdline._vcount1 += cnt
elseif (a:cmdline.is_input('<Over>(incsearch-scroll-b)')
\ && (a:cmdline._flag ==# '' || a:cmdline._flag ==# 'n'))
\ || (a:cmdline.is_input('<Over>(incsearch-scroll-f)') && a:cmdline._flag ==# 'b')
call a:cmdline.setchar('')
if a:cmdline._flag ==# 'n'
let a:cmdline._flag = ''
let a:cmdline._vcount1 -= 1
endif
let pos_expr = a:cmdline.is_input('<Over>(incsearch-scroll-f)') ? 'w$' : 'w0'
let to_col = a:cmdline.is_input('<Over>(incsearch-scroll-f)')
\ ? s:U.get_max_col(pos_expr) : 1
let [from, to] = [getpos('.')[1:2], [line(pos_expr), to_col]]
let cnt = s:U.count_pattern(pattern, from, to)
let a:cmdline._vcount1 -= cnt
endif
" Handle nowrapscan:
" if you `:set nowrapscan`, you can't move to the reversed direction
if !&wrapscan && (
\ a:cmdline.is_input('<Over>(incsearch-next)')
\ || a:cmdline.is_input('<Over>(incsearch-prev)')
\ || a:cmdline.is_input('<Over>(incsearch-scroll-f)')
\ || a:cmdline.is_input('<Over>(incsearch-scroll-b)')
\ )
if a:cmdline._vcount1 < 1
let a:cmdline._vcount1 = 1
else
call a:cmdline.setchar('')
let [from, to] = [[a:cmdline._w.lnum, a:cmdline._w.col + 1],
\ a:cmdline._flag !=# 'b'
\ ? [line('$'), s:U.get_max_col('$')]
\ : [1, 1]
\ ]
let max_cnt = s:U.count_pattern(pattern, from, to, s:TRUE)
let a:cmdline._vcount1 = min([max_cnt, a:cmdline._vcount1])
endif
endif
if &wrapscan && a:cmdline._vcount1 < 1
let a:cmdline._vcount1 += s:U.count_pattern(pattern)
endif
endfunction
function! s:on_char(cmdline) abort
if a:cmdline._does_exit_from_incsearch
return
endif
let [raw_pattern, offset] = a:cmdline._parse_pattern()
if raw_pattern ==# ''
call s:hi.disable_all()
nohlsearch
return
endif
" For InsertRegister
if a:cmdline.get_tap_key() ==# "\<C-r>"
let p = a:cmdline.getpos()
" Remove `"`
let raw_pattern = raw_pattern[:p-1] . raw_pattern[p+1:]
let w = winsaveview()
call cursor(line('.'), col('.') + len(a:cmdline.backward_word()))
call a:cmdline.get_module('InsertRegister').reset()
call winrestview(w)
endif
let pattern = a:cmdline._convert(raw_pattern)
" Improved Incremental cursor move!
call s:move_cursor(a:cmdline, pattern, offset)
" Improved Incremental highlighing!
" case: because matchadd() doesn't handle 'ignorecase' nor 'smartcase'
let case = incsearch#detect_case(raw_pattern)
let should_separate = g:incsearch#separate_highlight && a:cmdline._flag !=# 'n'
let pattern_for_hi =
\ (a:cmdline._flag is# 'b' ? s:unescape_question_for_backward(pattern) : pattern)
\ . case
call incsearch#highlight#incremental_highlight(
\ pattern_for_hi,
\ should_separate,
\ a:cmdline._direction,
\ [a:cmdline._w.lnum, a:cmdline._w.col])
" functional `normal! zz` after scroll for <expr> mappings
if ( a:cmdline.is_input('<Over>(incsearch-scroll-f)')
\ || a:cmdline.is_input('<Over>(incsearch-scroll-b)'))
call winrestview({'topline': max([1, line('.') - winheight(0) / 2])})
endif
endfunction
" Caveat: It handle :h last-pattern, so be careful if you want to pass empty
" string as a pattern
function! s:move_cursor(cli, pattern, ...) abort
let offset = get(a:, 1, '')
if a:cli._flag ==# 'n' " skip if stay mode
return
endif
call winrestview(a:cli._w)
" pseud-move cursor position: this is restored afterward if called by
" <expr> mappings
if a:cli._is_expr
for _ in range(a:cli._vcount1)
" NOTE: This cannot handle {offset} for cursor position
call search(a:pattern, a:cli._flag)
endfor
else
" More precise cursor position while searching
" Caveat:
" This block contains `normal`, please make sure <expr> mappings
" doesn't reach this block
let is_visual_mode = s:U.is_visual(mode(1))
let cmd = incsearch#with_ignore_foldopen(
\ s:U.dictfunction(a:cli._build_search_cmd, a:cli),
\ a:cli._combine_pattern(a:pattern, offset), 'n')
" NOTE:
" :silent!
" Shut up errors! because this is just for the cursor emulation
" while searching
silent! call incsearch#execute_search(cmd)
if is_visual_mode
let w = winsaveview()
normal! gv
call winrestview(w)
call incsearch#highlight#emulate_visual_highlight()
endif
endif
endfunction
function! s:inc.on_char_pre(cmdline) abort
call s:on_searching(function('s:on_char_pre'), a:cmdline)
endfunction
function! s:inc.on_char(cmdline) abort
call s:on_searching(function('s:on_char'), a:cmdline)
endfunction
function! s:unescape_question_for_backward(pattern) abort
return substitute(a:pattern, '\\?', '?', 'g')
endfunction
function! incsearch#over#modules#incsearch#make() abort
return deepcopy(s:inc)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" __END__
" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker

View File

@ -0,0 +1,41 @@
"=============================================================================
" FILE: autoload/incsearch/over/modules/insert_register.vim
" AUTHOR: haya14busa
" License: MIT license
"=============================================================================
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:modules = vital#incsearch#import('Over.Commandline.Modules')
let s:InsertRegister = s:modules.get('InsertRegister').make()
let s:InsertRegister_orig_on_char_pre = s:InsertRegister.on_char_pre
let s:InsertRegister.search_register = ''
function! s:InsertRegister.on_enter(...) abort
let self.search_register = @/
endfunction
function! s:InsertRegister.on_char_pre(cmdline) abort
if exists('self.prefix_key') && a:cmdline.get_tap_key() == self.prefix_key
call a:cmdline.setline(self.old_line)
call a:cmdline.setpos(self.old_pos)
let char = a:cmdline.input_key()
if char ==# '/'
let register = tr(self.search_register, "\n", "\r")
call a:cmdline.setchar(register)
return
endif
endif
return call(s:InsertRegister_orig_on_char_pre, [a:cmdline], self)
endfunction
function! incsearch#over#modules#insert_register#make() abort
return deepcopy(s:InsertRegister)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" __END__
" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker

View File

@ -0,0 +1,50 @@
"=============================================================================
" FILE: autoload/incsearch/over/modules/module_management.vim
" AUTHOR: haya14busa
" License: MIT license
"=============================================================================
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module_management = {
\ 'name' : 'IncsearchModuleManagement',
\ 'modules' : [ ]
\}
function! s:module_management.on_enter(cmdline) abort
if !exists('s:default_backward_word')
let s:default_backward_word = a:cmdline.backward_word
endif
for module in self.modules
if has_key(module, '_condition') && ! module._condition()
call a:cmdline.disconnect(module.name)
if module.name ==# 'IgnoreRegexpBackwardWord'
function! a:cmdline.backward_word(...) abort
return call(s:default_backward_word, a:000, self)
endfunction
endif
elseif empty(a:cmdline.get_module(module.name))
call a:cmdline.connect(module)
if has_key(module, 'on_enter')
call module.on_enter(a:cmdline)
endif
endif
endfor
endfunction
function! s:module_management.priority(event) abort
" NOTE: to overwrite backward_word() with default function
return a:event ==# 'on_enter' ? 5 : 0
endfunction
function! incsearch#over#modules#module_management#make(modules) abort
let m = deepcopy(s:module_management)
let m.modules = a:modules
return m
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" __END__
" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker

View File

@ -0,0 +1,48 @@
"=============================================================================
" FILE: autoload/incsearch/over/modules/pattern_saver.vim
" AUTHOR: haya14busa
" License: MIT license
" @vimlint(EVL103, 1, a:cmdline)
"=============================================================================
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:pattern_saver = {
\ 'name' : 'PatternSaver',
\ 'pattern' : '',
\ 'hlsearch' : &hlsearch
\}
function! s:pattern_saver.on_enter(cmdline) abort
if ! g:incsearch#no_inc_hlsearch
let self.pattern = @/
let self.hlsearch = &hlsearch
if exists('v:hlsearch')
let self.vhlsearch = v:hlsearch
endif
set hlsearch | nohlsearch
endif
endfunction
function! s:pattern_saver.on_leave(cmdline) abort
if ! g:incsearch#no_inc_hlsearch
let is_cancel = a:cmdline.exit_code()
if is_cancel
let @/ = self.pattern
endif
let &hlsearch = self.hlsearch
if exists('v:hlsearch')
let v:hlsearch = self.vhlsearch
endif
endif
endfunction
function! incsearch#over#modules#pattern_saver#make() abort
return deepcopy(s:pattern_saver)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" __END__
" vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker

View File

@ -0,0 +1,286 @@
"=============================================================================
" FILE: autoload/incsearch/util.vim
" AUTHOR: haya14busa
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
scriptencoding utf-8
" Saving 'cpoptions' {{{
let s:save_cpo = &cpo
set cpo&vim
" }}}
let s:TRUE = !0
let s:FALSE = 0
" Public Utilities:
function! incsearch#util#deepextend(...) abort
return call(function('s:deepextend'), a:000)
endfunction
" Utilities:
function! incsearch#util#import() abort
let prefix = '<SNR>' . s:SID() . '_'
let module = {}
for func in s:functions
let module[func] = function(prefix . func)
endfor
return copy(module)
endfunction
function! s:SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endfunction
let s:functions = [
\ 'is_visual'
\ , 'get_max_col'
\ , 'is_pos_less_equal'
\ , 'is_pos_more_equal'
\ , 'sort_num'
\ , 'sort_pos'
\ , 'count_pattern'
\ , 'silent_feedkeys'
\ , 'deepextend'
\ , 'dictfunction'
\ , 'regexp_join'
\ ]
function! s:is_visual(mode) abort
return a:mode =~# "[vV\<C-v>]"
endfunction
" Return max column number of given line expression
" expr: similar to line(), col()
function! s:get_max_col(expr) abort
return strlen(getline(a:expr)) + 1
endfunction
" return (x <= y)
function! s:is_pos_less_equal(x, y) abort
return (a:x[0] == a:y[0]) ? a:x[1] <= a:y[1] : a:x[0] < a:y[0]
endfunction
" return (x > y)
function! s:is_pos_more_equal(x, y) abort
return ! s:is_pos_less_equal(a:x, a:y)
endfunction
" x < y -> -1
" x = y -> 0
" x > y -> 1
function! s:compare_pos(x, y) abort
return max([-1, min([1,(a:x[0] == a:y[0]) ? a:x[1] - a:y[1] : a:x[0] - a:y[0]])])
endfunction
function! s:sort_num(xs) abort
" 7.4.341
" http://ftp.vim.org/vim/patches/7.4/7.4.341
if v:version > 704 || v:version == 704 && has('patch341')
return sort(a:xs, 'n')
else
return sort(a:xs, 's:_sort_num_func')
endif
endfunction
function! s:_sort_num_func(x, y) abort
return a:x - a:y
endfunction
function! s:sort_pos(pos_list) abort
" pos_list: [ [x1, y1], [x2, y2] ]
return sort(a:pos_list, 's:compare_pos')
endfunction
" Return the number of matched patterns in the current buffer or the specified
" region with `from` and `to` positions
" parameter: pattern, from, to
function! s:count_pattern(pattern, ...) abort
let w = winsaveview()
let [from, to] = [
\ get(a:, 1, [1, 1]),
\ get(a:, 2, [line('$'), s:get_max_col('$')])
\ ]
let ignore_at_cursor_pos = get(a:, 3, 0)
" direction flag
let d_flag = s:compare_pos(from, to) > 0 ? 'b' : ''
call cursor(from)
let cnt = 0
let base_flag = d_flag . 'W'
try
" first: accept a match at the cursor position
let pos = searchpos(a:pattern, (ignore_at_cursor_pos ? '' : 'c' ) . base_flag)
while (pos != [0, 0] && s:compare_pos(pos, to) isnot# (d_flag is# 'b' ? -1 : 1))
let cnt += 1
let pos = searchpos(a:pattern, base_flag)
endwhile
finally
call winrestview(w)
endtry
return cnt
endfunction
" NOTE: support vmap?
" It doesn't handle feedkeys() on incsert or command-line mode
function! s:silent_feedkeys(expr, name, ...) abort
" Ref:
" https://github.com/osyo-manga/vim-over/blob/d51b028c29661d4a5f5b79438ad6d69266753711/autoload/over.vim#L6
let mode = get(a:, 1, 'm')
let name = 'incsearch-' . a:name
let map = printf('<Plug>(%s)', name)
if mode ==# 'n'
let command = 'nnoremap'
else
let command = 'nmap'
endif
execute command '<silent>' map printf('%s:nunmap %s<CR>', a:expr, map)
if mode(1) !=# 'ce'
" FIXME: mode(1) !=# 'ce' exists only for the test
" :h feedkeys() doesn't work while runnning a test script
" https://github.com/kana/vim-vspec/issues/27
call feedkeys(printf("\<Plug>(%s)", name))
endif
endfunction
" deepextend (nest: 1)
function! s:deepextend(expr1, expr2) abort
let expr2 = copy(a:expr2)
for [k, V] in items(a:expr1)
if (type(V) is type({}) || type(V) is type([])) && has_key(expr2, k)
let a:expr1[k] = extend(a:expr1[k], expr2[k])
unlet expr2[k]
endif
unlet V
endfor
return extend(a:expr1, expr2)
endfunction
let s:funcmanage = {}
function! s:funcmanage() abort
return s:funcmanage
endfunction
function! s:dictfunction(dictfunc, dict) abort
if has('patch-7.4.1842')
let funcname = '_' . get(a:dictfunc, 'name')
else
let funcname = '_' . matchstr(string(a:dictfunc), '\d\+')
endif
let s:funcmanage[funcname] = {
\ 'func': a:dictfunc,
\ 'dict': a:dict
\ }
let prefix = '<SNR>' . s:SID() . '_'
let fm = printf("%sfuncmanage()['%s']", prefix, funcname)
execute join([
\ printf('function! s:%s(...) abort', funcname),
\ printf(" return call(%s['func'], a:000, %s['dict'])", fm, fm),
\ 'endfunction'
\ ], "\n")
return function(printf('%s%s', prefix, funcname))
endfunction
"--- regexp
let s:escaped_backslash = '\m\%(^\|[^\\]\)\%(\\\\\)*\zs'
function! s:regexp_join(ps) abort
let rs = map(filter(copy(a:ps), 's:_is_valid_regexp(v:val)'), 's:escape_unbalanced_left_r(v:val)')
return printf('\m\%%(%s\m\)', join(rs, '\m\|'))
endfunction
function! s:_is_valid_regexp(pattern) abort
try
if '' =~# a:pattern
endif
return s:TRUE
catch
return s:FALSE
endtry
endfunction
" \m,\v: [ -> \[
" \M,\V: \[ -> [
function! s:escape_unbalanced_left_r(pattern) abort
let rs = []
let cs = split(a:pattern, '\zs')
" escape backslash (\, \\\, \\\\\, ...)
let escape_bs = s:FALSE
let flag = &magic ? 'm' : 'M'
let i = 0
while i < len(cs)
let c = cs[i]
" characters to add to rs
let addcs = [c]
if escape_bs && s:_is_flag(c)
let flag = c
elseif c is# '[' && s:_may_replace_left_r_cond(escape_bs, flag)
let idx = s:_find_right_r(cs, i)
if idx is# -1
if s:_is_flag(flag, 'MV')
" Remove `\` before unbalanced `[`
let rs = rs[:-2]
else
" Escape unbalanced `[`
let addcs = ['\' . c]
endif
else
let addcs = cs[(i):(i+idx)]
let i += idx
endif
endif
let escape_bs = (escape_bs || c isnot# '\') ? s:FALSE : s:TRUE
let rs += addcs
let i += 1
endwhile
return join(rs, '')
endfunction
" @ return boolean
function! s:_is_flag(flag, ...) abort
let chars = get(a:, 1, 'mMvV')
return a:flag =~# printf('\m[%s]', chars)
endfunction
" @ return boolean
function! s:_may_replace_left_r_cond(escape_bs, flag) abort
return (a:escape_bs && s:_is_flag(a:flag, 'MV')) || (!a:escape_bs && s:_is_flag(a:flag, 'mv'))
endfunction
" @return index
function! s:_find_right_r(cs, i) abort
return match(join(a:cs[(a:i+1):], ''), s:escaped_backslash . ']')
endfunction
"--- end of regexp
" Restore 'cpoptions' {{{
let &cpo = s:save_cpo
unlet s:save_cpo
" }}}
" __END__ {{{
" vim: expandtab softtabstop=2 shiftwidth=2
" vim: foldmethod=marker
" }}}

View File

@ -0,0 +1,12 @@
function! vital#of(name) abort
let files = globpath(&runtimepath, 'autoload/vital/' . a:name . '.vital', 1)
let file = split(files, "\n")
if empty(file)
throw 'vital: version file not found: ' . a:name
endif
let ver = readfile(file[0], 'b')
if empty(ver)
throw 'vital: invalid version file: ' . a:name
endif
return vital#_{substitute(ver[0], '\W', '', 'g')}#new()
endfunction

View File

@ -0,0 +1,9 @@
let s:_plugin_name = expand('<sfile>:t:r')
function! vital#{s:_plugin_name}#new() abort
return vital#{s:_plugin_name[1:]}#new()
endfunction
function! vital#{s:_plugin_name}#function(funcname) abort
silent! return function(a:funcname)
endfunction

View File

@ -0,0 +1,239 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Coaster#Highlight#import() abort', printf("return map({'highlight': '', 'clear': '', 'delete': '', 'add': '', 'as_windo': '', '_vital_depends': '', 'get_hl_id': '', 'to_list': '', 'clear_all': '', 'delete_all': '', 'to_list_by': '', 'update': '', 'enable': '', 'delete_by': '', 'hl_list': '', 'make': '', 'enable_list': '', 'update_all': '', 'disable': '', 'disable_all': '', 'is_enabled': '', 'enable_all': '', 'is_added': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:Window = a:V.import("Coaster.Window")
let s:Gift = a:V.import("Gift")
call s:_init()
endfunction
function! s:_vital_depends()
return [
\ "Coaster.Window",
\ "Gift",
\ ]
endfunction
let s:base = {
\ "variables" : {
\ "hl_list" : {},
\ "id_list" : {}
\ }
\}
function! s:base.add(name, group, pattern, ...)
call self.delete(a:name)
let priority = get(a:, 1, 10)
let self.variables.hl_list[a:name] = {
\ "group" : a:group,
\ "pattern" : a:pattern,
\ "priority" : priority,
\ "name" : a:name,
\ }
endfunction
function! s:base.is_added(name)
return has_key(self.variables.hl_list, a:name)
endfunction
function! s:base.hl_list()
return keys(self.variables.hl_list)
endfunction
function! s:base.to_list()
return values(self.variables.hl_list)
endfunction
function! s:_is_equal(__expr, __hl)
let name = a:__hl.name
let group = a:__hl.group
let pattern = a:__hl.pattern
let priority = a:__hl.priority
return eval(a:__expr)
endfunction
function! s:base.to_list_by(expr)
return filter(values(self.variables.hl_list), "s:_is_equal(a:expr, v:val)")
endfunction
function! s:base.enable_list(...)
let window = get(a:, 1, s:Gift.uniq_winnr())
return keys(get(self.variables.id_list, window, {}))
endfunction
function! s:base.delete(name)
if !self.is_added(a:name)
return -1
endif
unlet! self.variables.hl_list[a:name]
endfunction
function! s:base.delete_by(expr)
return map(self.to_list_by(a:expr), "self.delete(v:val.name)")
endfunction
function! s:base.delete_all()
for name in self.hl_list()
call self.delete(name)
endfor
endfunction
function! s:base.get_hl_id(name, ...)
let window = get(a:, 1, s:Gift.uniq_winnr())
return get(get(self.variables.id_list, window, {}), a:name, "")
endfunction
function! s:base.is_enabled(name, ...)
let window = get(a:, 1, s:Gift.uniq_winnr())
return self.get_hl_id(a:name, window) != ""
endfunction
function! s:base.enable(name)
let hl = get(self.variables.hl_list, a:name, {})
if empty(hl)
return -1
endif
if self.is_enabled(a:name)
call self.disable(a:name)
endif
let winnr = s:Gift.uniq_winnr()
if !has_key(self.variables.id_list, winnr)
let self.variables.id_list[winnr] = {}
endif
let self.variables.id_list[winnr][a:name] = matchadd(hl.group, hl.pattern, hl.priority)
endfunction
function! s:base.enable_all()
for name in self.hl_list()
call self.enable(name)
endfor
endfunction
function! s:base.disable(name)
if !self.is_enabled(a:name)
return -1
endif
let id = -1
silent! let id = matchdelete(self.get_hl_id(a:name))
if id == -1
return -1
endif
let winnr = get(a:, 1, s:Gift.uniq_winnr())
unlet! self.variables.id_list[winnr][a:name]
endfunction
function! s:base.disable_all()
for name in self.enable_list()
call self.disable(name)
endfor
endfunction
function! s:base.update(name)
call self.disable(a:name)
call self.enable(a:name)
endfunction
function! s:base.update_all()
call self.disable_all()
call self.enable_all()
endfunction
function! s:base.highlight(name, group, pattern, ...)
let priority = get(a:, 1, 10)
call self.add(a:name, a:group, a:pattern, priority)
call self.enable(a:name)
endfunction
function! s:base.clear(name)
call self.disable(a:name)
call self.delete(a:name)
endfunction
function! s:base.clear_all()
call self.disable_all()
call self.delete_all()
endfunction
function! s:base.as_windo()
return self.windo
endfunction
function! s:make()
let result = deepcopy(s:base)
let result.windo = s:Window.as_windo(result)
return result
endfunction
let s:global = deepcopy(s:base)
let s:funcs = keys(filter(copy(s:global), "type(v:val) == type(function('tr'))"))
for s:name in s:funcs
execute
\ "function! s:" . s:name . "(...) \n"
\ "return call(s:global." . s:name . ", a:000, s:global) \n"
\ "endfunction"
endfor
unlet s:name
function! s:_init()
let s:global.windo = s:Window.as_windo(s:global)
endfunction
" function! s:matchadd(...)
" return {
" \ "id" : call("matchadd", a:000),
" \ "bufnr" : bufnr("%"),
" \ }
" endfunction
"
"
" function! s:matchdelete(id)
" if empty(a:id)
" return -1
" endif
" return s:Buffer.execute(a:id.bufnr, "call matchdelete(" . a:id.id . ")")
" endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,62 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Coaster#Window#import() abort', printf("return map({'as_windo': '', '_vital_depends': '', 'windo': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:Buffer = a:V.import("Vim.Buffer")
endfunction
function! s:_vital_depends()
return [
\ "Vim.Buffer",
\ ]
endfunction
function! s:windo(func, args, ...)
let dict = get(a:, 1, {})
if len(tabpagebuflist()) <= 1 || s:Buffer.is_cmdwin()
return call(a:func, a:args, dict)
endif
let pre_winnr = winnr()
noautocmd windo call call(a:func, a:args, dict)
if pre_winnr == winnr()
return
endif
execute pre_winnr . "wincmd w"
endfunction
function! s:as_windo(base)
let windo = {}
let windo.obj = a:base
for [key, Value] in items(a:base)
if type(function("tr")) == type(Value)
execute
\ "function! windo.". key. "(...)\n"
\ " return s:windo(self.obj." . key . ", a:000, self.obj)\n"
\ "endfunction"
endif
unlet Value
endfor
return windo
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,151 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Data#Dict#import() abort', printf("return map({'_vital_depends': '', 'clear': '', 'max_by': '', 'foldl': '', 'pick': '', 'from_list': '', 'swap': '', 'omit': '', 'min_by': '', 'foldr': '', 'make_index': '', 'make': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
" Utilities for dictionary.
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V) abort
let s:t = a:V.import('Vim.Type').types
endfunction
function! s:_vital_depends() abort
return ['Vim.Type']
endfunction
function! s:_ensure_key(key) abort
let t = type(a:key)
if t != s:t.string && t != s:t.number
throw 'vital: Data.Dict: Invalid key: ' . string(a:key)
endif
endfunction
function! s:from_list(list) abort
let dict = {}
let i = 0
let len = len(a:list)
while i < len
if type(a:list[i]) == s:t.list
let key_value = a:list[i]
if len(key_value) != 2
throw 'vital: Data.Dict: Invalid key-value pair index at ' . i
endif
call s:_ensure_key(key_value[0])
let dict[key_value[0]] = key_value[1]
let i += 1
else
if len <= i + 1
throw 'vital: Data.Dict: Invalid key-value pair index at ' . i
endif
call s:_ensure_key(a:list[i])
let dict[a:list[i]] = a:list[i + 1]
let i += 2
endif
endwhile
return dict
endfunction
" Makes a dict from keys and values
function! s:make(keys, values, ...) abort
let dict = {}
let fill = a:0 ? a:1 : 0
for i in range(len(a:keys))
let key = type(a:keys[i]) == s:t.string ? a:keys[i] : string(a:keys[i])
if key ==# ''
throw "vital: Data.Dict: Can't use an empty string for key."
endif
let dict[key] = get(a:values, i, fill)
endfor
return dict
endfunction
" Swaps keys and values
function! s:swap(dict) abort
return s:make(values(a:dict), keys(a:dict))
endfunction
" Makes a index dict from a list
function! s:make_index(list, ...) abort
let value = a:0 ? a:1 : 1
return s:make(a:list, [], value)
endfunction
function! s:pick(dict, keys) abort
let new_dict = {}
for key in a:keys
if has_key(a:dict, key)
let new_dict[key] = a:dict[key]
endif
endfor
return new_dict
endfunction
function! s:omit(dict, keys) abort
let new_dict = copy(a:dict)
for key in a:keys
if has_key(a:dict, key)
call remove(new_dict, key)
endif
endfor
return new_dict
endfunction
function! s:clear(dict) abort
for key in keys(a:dict)
call remove(a:dict, key)
endfor
return a:dict
endfunction
function! s:_max_by(dict, expr) abort
let dict = s:swap(map(copy(a:dict), a:expr))
let key = dict[max(keys(dict))]
return [key, a:dict[key]]
endfunction
function! s:max_by(dict, expr) abort
if empty(a:dict)
throw 'vital: Data.Dict: Empty dictionary'
endif
return s:_max_by(a:dict, a:expr)
endfunction
function! s:min_by(dict, expr) abort
if empty(a:dict)
throw 'vital: Data.Dict: Empty dictionary'
endif
return s:_max_by(a:dict, '-(' . a:expr . ')')
endfunction
function! s:_foldl(f, init, xs) abort
let memo = a:init
for [k, v] in a:xs
let expr = substitute(a:f, 'v:key', string(k), 'g')
let expr = substitute(expr, 'v:val', string(v), 'g')
let expr = substitute(expr, 'v:memo', string(memo), 'g')
unlet memo
let memo = eval(expr)
endfor
return memo
endfunction
function! s:foldl(f, init, dict) abort
return s:_foldl(a:f, a:init, items(a:dict))
endfunction
function! s:foldr(f, init, dict) abort
return s:_foldl(a:f, a:init, reverse(items(a:dict)))
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0:

View File

@ -0,0 +1,464 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Data#List#import() abort', printf("return map({'combinations': '', 'and': '', 'sort_by': '', 'foldr1': '', 'sort': '', 'flatten': '', 'has_index': '', 'find_indices': '', 'any': '', 'unshift': '', 'span': '', 'pop': '', 'binary_search': '', 'uniq_by': '', 'or': '', 'all': '', 'zip': '', 'find_last_index': '', 'find': '', 'partition': '', 'shift': '', 'permutations': '', 'break': '', 'max_by': '', 'foldl': '', 'foldr': '', 'find_index': '', 'drop_while': '', 'group_by': '', 'take_while': '', 'conj': '', 'push': '', 'char_range': '', 'cons': '', 'foldl1': '', 'intersect': '', 'concat': '', 'map_accum': '', 'clear': '', 'has_common_items': '', 'product': '', 'zip_fill': '', 'uniq': '', 'has': '', 'min_by': '', 'with_index': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
" Utilities for list.
let s:save_cpo = &cpo
set cpo&vim
function! s:pop(list) abort
return remove(a:list, -1)
endfunction
function! s:push(list, val) abort
call add(a:list, a:val)
return a:list
endfunction
function! s:shift(list) abort
return remove(a:list, 0)
endfunction
function! s:unshift(list, val) abort
return insert(a:list, a:val)
endfunction
function! s:cons(x, xs) abort
return [a:x] + a:xs
endfunction
function! s:conj(xs, x) abort
return a:xs + [a:x]
endfunction
" Removes duplicates from a list.
function! s:uniq(list) abort
return s:uniq_by(a:list, 'v:val')
endfunction
" Removes duplicates from a list.
function! s:uniq_by(list, f) abort
let list = map(copy(a:list), printf('[v:val, %s]', a:f))
let i = 0
let seen = {}
while i < len(list)
let key = string(list[i][1])
if has_key(seen, key)
call remove(list, i)
else
let seen[key] = 1
let i += 1
endif
endwhile
return map(list, 'v:val[0]')
endfunction
function! s:clear(list) abort
if !empty(a:list)
unlet! a:list[0 : len(a:list) - 1]
endif
return a:list
endfunction
" Concatenates a list of lists.
" XXX: Should we verify the input?
function! s:concat(list) abort
let memo = []
for Value in a:list
let memo += Value
endfor
return memo
endfunction
" Take each elements from lists to a new list.
function! s:flatten(list, ...) abort
let limit = a:0 > 0 ? a:1 : -1
let memo = []
if limit == 0
return a:list
endif
let limit -= 1
for Value in a:list
let memo +=
\ type(Value) == type([]) ?
\ s:flatten(Value, limit) :
\ [Value]
unlet! Value
endfor
return memo
endfunction
" Sorts a list with expression to compare each two values.
" a:a and a:b can be used in {expr}.
function! s:sort(list, expr) abort
if type(a:expr) == type(function('function'))
return sort(a:list, a:expr)
endif
let s:expr = a:expr
return sort(a:list, 's:_compare')
endfunction
function! s:_compare(a, b) abort
return eval(s:expr)
endfunction
" Sorts a list using a set of keys generated by mapping the values in the list
" through the given expr.
" v:val is used in {expr}
function! s:sort_by(list, expr) abort
let pairs = map(a:list, printf('[v:val, %s]', a:expr))
return map(s:sort(pairs,
\ 'a:a[1] ==# a:b[1] ? 0 : a:a[1] ># a:b[1] ? 1 : -1'), 'v:val[0]')
endfunction
" Returns a maximum value in {list} through given {expr}.
" Returns 0 if {list} is empty.
" v:val is used in {expr}
function! s:max_by(list, expr) abort
if empty(a:list)
return 0
endif
let list = map(copy(a:list), a:expr)
return a:list[index(list, max(list))]
endfunction
" Returns a minimum value in {list} through given {expr}.
" Returns 0 if {list} is empty.
" v:val is used in {expr}
" FIXME: -0x80000000 == 0x80000000
function! s:min_by(list, expr) abort
return s:max_by(a:list, '-(' . a:expr . ')')
endfunction
" Returns List of character sequence between [a:from, a:to]
" e.g.: s:char_range('a', 'c') returns ['a', 'b', 'c']
function! s:char_range(from, to) abort
return map(
\ range(char2nr(a:from), char2nr(a:to)),
\ 'nr2char(v:val)'
\)
endfunction
" Returns true if a:list has a:value.
" Returns false otherwise.
function! s:has(list, value) abort
return index(a:list, a:value) isnot -1
endfunction
" Returns true if a:list[a:index] exists.
" Returns false otherwise.
" NOTE: Returns false when a:index is negative number.
function! s:has_index(list, index) abort
" Return true when negative index?
" let index = a:index >= 0 ? a:index : len(a:list) + a:index
return 0 <= a:index && a:index < len(a:list)
endfunction
" similar to Haskell's Data.List.span
function! s:span(f, xs) abort
let border = len(a:xs)
for i in range(len(a:xs))
if !eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g'))
let border = i
break
endif
endfor
return border == 0 ? [[], copy(a:xs)] : [a:xs[: border - 1], a:xs[border :]]
endfunction
" similar to Haskell's Data.List.break
function! s:break(f, xs) abort
return s:span(printf('!(%s)', a:f), a:xs)
endfunction
" similar to Haskell's Data.List.takeWhile
function! s:take_while(f, xs) abort
return s:span(a:f, a:xs)[0]
endfunction
" similar to Haskell's Data.List.dropWhile
function! s:drop_while(f, xs) abort
return s:span(a:f, a:xs)[1]
endfunction
" similar to Haskell's Data.List.partition
function! s:partition(f, xs) abort
return [filter(copy(a:xs), a:f), filter(copy(a:xs), '!(' . a:f . ')')]
endfunction
" similar to Haskell's Prelude.all
function! s:all(f, xs) abort
return !s:any(printf('!(%s)', a:f), a:xs)
endfunction
" similar to Haskell's Prelude.any
function! s:any(f, xs) abort
return !empty(filter(map(copy(a:xs), a:f), 'v:val'))
endfunction
" similar to Haskell's Prelude.and
function! s:and(xs) abort
return s:all('v:val', a:xs)
endfunction
" similar to Haskell's Prelude.or
function! s:or(xs) abort
return s:any('v:val', a:xs)
endfunction
function! s:map_accum(expr, xs, init) abort
let memo = []
let init = a:init
for x in a:xs
let expr = substitute(a:expr, 'v:memo', init, 'g')
let expr = substitute(expr, 'v:val', x, 'g')
let [tmp, init] = eval(expr)
call add(memo, tmp)
endfor
return memo
endfunction
" similar to Haskell's Prelude.foldl
function! s:foldl(f, init, xs) abort
let memo = a:init
for x in a:xs
let expr = substitute(a:f, 'v:val', string(x), 'g')
let expr = substitute(expr, 'v:memo', string(memo), 'g')
unlet memo
let memo = eval(expr)
endfor
return memo
endfunction
" similar to Haskell's Prelude.foldl1
function! s:foldl1(f, xs) abort
if len(a:xs) == 0
throw 'vital: Data.List: foldl1'
endif
return s:foldl(a:f, a:xs[0], a:xs[1:])
endfunction
" similar to Haskell's Prelude.foldr
function! s:foldr(f, init, xs) abort
return s:foldl(a:f, a:init, reverse(copy(a:xs)))
endfunction
" similar to Haskell's Prelude.fold11
function! s:foldr1(f, xs) abort
if len(a:xs) == 0
throw 'vital: Data.List: foldr1'
endif
return s:foldr(a:f, a:xs[-1], a:xs[0:-2])
endfunction
" similar to python's zip()
function! s:zip(...) abort
return map(range(min(map(copy(a:000), 'len(v:val)'))), "map(copy(a:000), 'v:val['.v:val.']')")
endfunction
" similar to zip(), but goes until the longer one.
function! s:zip_fill(xs, ys, filler) abort
if empty(a:xs) && empty(a:ys)
return []
elseif empty(a:ys)
return s:cons([a:xs[0], a:filler], s:zip_fill(a:xs[1 :], [], a:filler))
elseif empty(a:xs)
return s:cons([a:filler, a:ys[0]], s:zip_fill([], a:ys[1 :], a:filler))
else
return s:cons([a:xs[0], a:ys[0]], s:zip_fill(a:xs[1 :], a:ys[1: ], a:filler))
endif
endfunction
" Inspired by Ruby's with_index method.
function! s:with_index(list, ...) abort
let base = a:0 > 0 ? a:1 : 0
return map(copy(a:list), '[v:val, v:key + base]')
endfunction
" similar to Ruby's detect or Haskell's find.
function! s:find(list, default, f) abort
let l:Call = type(a:f) is type(function('function'))
\ ? function('call')
\ : function('s:_call_string_expr')
for x in a:list
if l:Call(a:f, [x])
return x
endif
endfor
return a:default
endfunction
function! s:_call_string_expr(expr, args) abort
return map([a:args[0]], a:expr)[0]
endfunction
" Returns the index of the first element which satisfies the given expr.
function! s:find_index(xs, f, ...) abort
let len = len(a:xs)
let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : 0
let default = a:0 > 1 ? a:2 : -1
if start >=# len || start < 0
return default
endif
for i in range(start, len - 1)
if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g'))
return i
endif
endfor
return default
endfunction
" Returns the index of the last element which satisfies the given expr.
function! s:find_last_index(xs, f, ...) abort
let len = len(a:xs)
let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : len - 1
let default = a:0 > 1 ? a:2 : -1
if start >=# len || start < 0
return default
endif
for i in range(start, 0, -1)
if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g'))
return i
endif
endfor
return default
endfunction
" Similar to find_index but returns the list of indices satisfying the given expr.
function! s:find_indices(xs, f, ...) abort
let len = len(a:xs)
let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : 0
let result = []
if start >=# len || start < 0
return result
endif
for i in range(start, len - 1)
if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g'))
call add(result, i)
endif
endfor
return result
endfunction
" Return non-zero if a:list1 and a:list2 have any common item(s).
" Return zero otherwise.
function! s:has_common_items(list1, list2) abort
return !empty(filter(copy(a:list1), 'index(a:list2, v:val) isnot -1'))
endfunction
function! s:intersect(list1, list2) abort
let items = []
" for funcref
for X in a:list1
if index(a:list2, X) != -1 && index(items, X) == -1
let items += [X]
endif
endfor
return items
endfunction
" similar to Ruby's group_by.
function! s:group_by(xs, f) abort
let result = {}
let list = map(copy(a:xs), printf('[v:val, %s]', a:f))
for x in list
let Val = x[0]
let key = type(x[1]) !=# type('') ? string(x[1]) : x[1]
if has_key(result, key)
call add(result[key], Val)
else
let result[key] = [Val]
endif
unlet Val
endfor
return result
endfunction
function! s:_default_compare(a, b) abort
return a:a <# a:b ? -1 : a:a ># a:b ? 1 : 0
endfunction
function! s:binary_search(list, value, ...) abort
let Predicate = a:0 >= 1 ? a:1 : 's:_default_compare'
let dic = a:0 >= 2 ? a:2 : {}
let start = 0
let end = len(a:list) - 1
while 1
if start > end
return -1
endif
let middle = (start + end) / 2
let compared = call(Predicate, [a:value, a:list[middle]], dic)
if compared < 0
let end = middle - 1
elseif compared > 0
let start = middle + 1
else
return middle
endif
endwhile
endfunction
function! s:product(lists) abort
let result = [[]]
for pool in a:lists
let tmp = []
for x in result
let tmp += map(copy(pool), 'x + [v:val]')
endfor
let result = tmp
endfor
return result
endfunction
function! s:permutations(list, ...) abort
if a:0 > 1
throw 'vital: Data.List: too many arguments'
endif
let r = a:0 == 1 ? a:1 : len(a:list)
if r > len(a:list)
return []
elseif r < 0
throw 'vital: Data.List: {r} must be non-negative integer'
endif
let n = len(a:list)
let result = []
for indices in s:product(map(range(r), 'range(n)'))
if len(s:uniq(indices)) == r
call add(result, map(indices, 'a:list[v:val]'))
endif
endfor
return result
endfunction
function! s:combinations(list, r) abort
if a:r > len(a:list)
return []
elseif a:r < 0
throw 'vital: Data.List: {r} must be non-negative integer'
endif
let n = len(a:list)
let result = []
for indices in s:permutations(range(n), a:r)
if s:sort(copy(indices), 'a:a - a:b') == indices
call add(result, map(indices, 'a:list[v:val]'))
endif
endfor
return result
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0:

View File

@ -0,0 +1,159 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Gift#import() abort', printf("return map({'flatten': '', 'uniq_tabpagenr': '', 'tabpagewinnr_list': '', 'execute': '', 'getwinvar': '', 'winnr': '', 'jump_window': '', '_vital_depends': '', 'uniq_winnr': '', 'setwinvar': '', 'find': '', 'openable_bufnr_list': '', 'to_fullpath': '', 'bufnr': '', 'set_current_window': '', 'tabpagewinnr': '', 'close_window': '', 'close_window_by': '', 'uniq_winnr_list': '', '_vital_loaded': '', 'find_by': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:Window = s:V.import("Gift.Window")
let s:Tabpage = s:V.import("Gift.Tabpage")
endfunction
function! s:_vital_depends()
return [
\ "Gift.Window",
\ "Gift.Tabpage",
\ ]
endfunction
function! s:to_fullpath(filename)
let name = substitute(fnamemodify(a:filename, ":p"), '\', '/', "g")
if filereadable(name)
return name
else
return a:filename
endif
endfunction
function! s:flatten(list)
return eval(join(a:list, "+"))
endfunction
function! s:bufnr(expr)
return type(a:expr) == type([])
\ ? s:bufnr(s:uniq_winnr(a:expr[1], a:expr[0]))
\ : s:Window.bufnr(a:expr)
endfunction
function! s:openable_bufnr_list()
return map(s:tabpagewinnr_list(), "s:bufnr([v:val[0], v:val[1]])")
endfunction
function! s:tabpagewinnr(...)
return a:0 == 0 ? s:tabpagewinnr(s:uniq_winnr())
\ : s:Window.tabpagewinnr(a:1)
endfunction
function! s:tabpagewinnr_list()
return s:Window.tabpagewinnr_list()
" return s:flatten(map(range(1, tabpagenr("$")), "map(range(1, tabpagewinnr(v:val, '$')), '['.v:val.', v:val]')"))
endfunction
function! s:uniq_winnr(...)
return call(s:Window.uniq_nr, a:000, s:Window)
endfunction
function! s:winnr(uniqnr)
let [tabnr, winnr] = s:Window.tabpagewinnr(a:uniqnr)
return winnr
endfunction
function! s:uniq_winnr_list(...)
return map(s:tabpagewinnr_list(), "s:uniq_winnr(v:val[1], v:val[0])")
endfunction
function! s:find(expr)
let gift_find_result = []
for [tabnr, winnr] in s:tabpagewinnr_list()
let bufnr = s:bufnr([tabnr, winnr])
if eval(a:expr)
call add(gift_find_result, [tabnr, winnr])
endif
endfor
return gift_find_result
endfunction
function! s:find_by(expr)
if type(a:expr) == type(function("tr"))
return filter(s:tabpagewinnr_list(), "a:expr(s:bufnr([v:val[0], v:val[1]]), v:val[0], v:val[1])")
else
return s:find(a:expr)
endif
endfunction
function! s:jump_window(expr)
return type(a:expr) == type([])
\ ? s:jump_window(s:uniq_winnr(a:expr[1], a:expr[0]))
\ : s:Window.jump(a:expr)
endfunction
function! s:set_current_window(expr)
return s:jump_window(a:expr)
endfunction
function! s:close_window(expr, ...)
let close_cmd = get(a:, 1, "close")
return type(a:expr) == type([])
\ ? s:close_window(s:uniq_winnr(a:expr[1], a:expr[0]), close_cmd)
\ : s:Window.close(a:expr, close_cmd)
endfunction
function! s:close_window_by(expr, ...)
let close_cmd = get(a:, 1, "close")
return map(map(s:find(a:expr), "s:uniq_winnr(v:val[1], v:val[0])"), 's:close_window(v:val, close_cmd)')
endfunction
function! s:execute(expr, execute)
return type(a:expr) == type([])
\ ? s:execute(s:uniq_winnr(a:expr[1], a:expr[0]), a:execute)
\ : s:Window.execute(a:expr, a:execute)
endfunction
function! s:getwinvar(uniq_winnr, varname, ...)
let def = get(a:, 1, "")
return s:Window.getvar(a:uniq_winnr, a:varname, def)
endfunction
function! s:setwinvar(uniq_winnr, varname, val)
return s:Window.setvar(a:uniq_winnr, a:varname, a:val)
endfunction
function! s:uniq_tabpagenr(...)
return call(s:Tabpage.uniq_nr, a:000, s:Tabpage)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,47 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Gift#Tabpage#import() abort', printf("return map({'uniq_nr': '', 'make_uniq_nr': '', 'numbering': '', 'set_prefix': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:prefix = expand("<sfile>:p:h:h:t")
function! s:set_prefix(prefix)
let s:prefix = a:prefix
endfunction
let s:uniq_counter = 0
function! s:make_uniq_nr()
let s:uniq_counter += 1
return s:uniq_counter
endfunction
function! s:numbering(...)
let tabnr = get(a:, 1, tabpagenr())
let uniq_nr = s:make_uniq_nr()
call settabvar(tabnr, s:prefix . "_gift_uniq_tabpagenr", uniq_nr)
return uniq_nr
endfunction
function! s:uniq_nr(...)
let tabnr = get(a:, 1, tabpagenr())
let uniq_nr = get(gettabvar(tabnr, ""), s:prefix . "_gift_uniq_tabpagenr", -1)
if uniq_nr == -1
let uniq_nr = s:numbering(tabnr)
endif
return uniq_nr
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,153 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Gift#Window#import() abort', printf("return map({'flatten': '', 'tabpagewinnr_list': '', 'execute': '', 'close': '', 'numbering': '', 'set_prefix': '', '_vital_depends': '', 'exists': '', 'jump': '', 'setvar': '', 'bufnr': '', 'uniq_nr': '', 'make_uniq_nr': '', 'tabpagewinnr': '', 'getvar': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:Tabpage = s:V.import("Gift.Tabpage")
endfunction
function! s:_vital_depends()
return [
\ "Gift.Tabpage",
\ ]
endfunction
let s:prefix = expand("<sfile>:p:h:h:t")
function! s:set_prefix(prefix)
let s:prefix = a:prefix
endfunction
function! s:flatten(list)
return eval(join(a:list, "+"))
endfunction
function! s:tabpagewinnr_list()
return s:flatten(map(range(1, tabpagenr("$")), "map(range(1, tabpagewinnr(v:val, '$')), '['.v:val.', v:val]')"))
endfunction
if !exists("s:uniq_counter")
let s:uniq_counter = 0
endif
function! s:make_uniq_nr()
let s:uniq_counter += 1
return s:uniq_counter
endfunction
function! s:numbering(...)
let winnr = get(a:, 1, winnr())
let tabnr = get(a:, 2, tabpagenr())
let uniq_nr = s:make_uniq_nr()
call settabwinvar(tabnr, winnr, s:prefix . "_gift_uniq_winnr", uniq_nr)
return uniq_nr
endfunction
function! s:uniq_nr(...)
let winnr = get(a:, 1, winnr())
let tabnr = get(a:, 2, tabpagenr())
let uniq_nr = get(gettabwinvar(tabnr, winnr, ""), s:prefix . "_gift_uniq_winnr", -1)
if uniq_nr == -1
let uniq_nr = s:numbering(winnr, tabnr)
endif
return uniq_nr
endfunction
function! s:exists(nr)
let [tabnr, winnr] = s:tabpagewinnr(a:nr)
return tabnr != 0 && winnr != 0
endfunction
function! s:tabpagewinnr(nr)
if a:nr == 0
return s:tabpagewinnr(s:uniq_nr())
endif
let tabwinnrs = s:tabpagewinnr_list()
for [tabnr, winnr] in tabwinnrs
if s:uniq_nr(winnr, tabnr) == a:nr
return [tabnr, winnr]
endif
endfor
return [0, 0]
endfunction
function! s:getvar(nr, varname, ...)
let def = get(a:, 1, "")
let [tabnr, winnr] = s:tabpagewinnr(a:nr)
return get(gettabwinvar(tabnr, winnr, ""), a:varname, def)
endfunction
function! s:setvar(nr, varname, val)
let [tabnr, winnr] = s:tabpagewinnr(a:nr)
if tabnr == 0 || winnr == 0
return
endif
return settabwinvar(tabnr, winnr, a:varname, a:val)
endfunction
function! s:bufnr(nr)
let [tabnr, winnr] = s:tabpagewinnr(a:nr)
return winnr >= 1 ? get(tabpagebuflist(tabnr), winnr-1, -1) : -1
endfunction
function! s:jump(nr)
let [tabnr, winnr] = s:tabpagewinnr(a:nr)
if tabnr == 0 || winnr == 0
return -1
endif
execute "tabnext" tabnr
execute winnr . "wincmd w"
endfunction
function! s:close(nr, close_cmd)
call s:execute(a:nr, a:close_cmd)
" let current = gift#uniq_winnr()
" let result = s:jump(a:nr)
" if result == -1
" return -1
" endif
" execute a:close_cmd
" return s:jump(current)
endfunction
function! s:execute(nr, expr)
let current = s:uniq_nr()
let result = s:jump(a:nr)
if result == -1
return -1
endif
execute a:expr
return s:jump(current)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,61 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#import() abort', printf("return map({'_vital_depends': '', 'make_standard_search_back': '', 'get_module': '', 'make_standard_search': '', 'make_standard': '', 'make_module': '', 'make_default': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:Maker = s:V.import("Over.Commandline.Maker")
let s:Modules = s:V.import("Over.Commandline.Modules")
endfunction
function! s:_vital_depends()
return [
\ "Over.Commandline.Maker",
\ "Over.Commandline.Modules",
\ "Over.Commandline.Modules.All",
\ ]
endfunction
function! s:make_module(...)
return call(s:Modules.make, a:000, s:Modules)
endfunction
function! s:get_module(...)
return call(s:Modules.get, a:000, s:Modules)
endfunction
function! s:make_default(...)
return call(s:Maker.default, a:000, s:Maker)
endfunction
function! s:make_standard(...)
return call(s:Maker.standard, a:000, s:Maker)
endfunction
function! s:make_standard_search(...)
return call(s:Maker.standard_search, a:000, s:Maker)
endfunction
function! s:make_standard_search_back(...)
return call(s:Maker.standard_search_back, a:000, s:Maker)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,600 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Base#import() abort', printf("return map({'_vital_depends': '', 'make_plain': '', 'is_input_waiting': '', 'make': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:String = s:V.import("Over.String")
let s:Signals = s:V.import("Over.Signals")
let s:Input = s:V.import("Over.Input")
let s:Keymapping = s:V.import("Over.Keymapping")
let s:Module = s:V.import("Over.Commandline.Modules")
let s:base.variables.modules = s:Signals.make()
function! s:base.variables.modules.get_slot(val)
return a:val.slot.module
endfunction
let s:Highlight = s:V.import("Palette.Highlight")
endfunction
function! s:_vital_depends()
return [
\ "Over.String",
\ "Over.Signals",
\ "Over.Input",
\ "Over.Keymapping",
\ "Over.Commandline.Modules",
\ "Palette.Highlight",
\ ]
endfunction
function! s:make(...)
let result = deepcopy(s:base)
call result.set_prompt(get(a:, 1, ":"))
call result.connect(result, "_")
return result
endfunction
function! s:make_plain()
return deepcopy(s:base)
endfunction
let s:base = {
\ "line" : {},
\ "variables" : {
\ "prompt" : "",
\ "char" : "",
\ "input" : "",
\ "tap_key" : "",
\ "exit" : 0,
\ "keymapping" : {},
\ "suffix" : "",
\ "is_setted" : 0,
\ },
\ "highlights" : {
\ "prompt" : "NONE",
\ "cursor" : "VitalOverCommandLineCursor",
\ "cursor_on" : "VitalOverCommandLineCursorOn",
\ "cursor_insert" : "VitalOverCommandLineOnCursor",
\ },
\}
if exists("s:Signals")
let s:base.variables.modules = s:Signals.make()
function! s:base.variables.modules.get_slot(val)
return a:val.slot.module
endfunction
endif
function! s:base.getline()
return self.line.str()
endfunction
function! s:base.setline(line)
return self.line.set(a:line)
endfunction
function! s:base.char()
return self.variables.char
endfunction
function! s:base.setchar(char, ...)
" 1 の場合は既に設定されていても上書きする
" 0 の場合は既に設定されていれば上書きしない
let overwrite = get(a:, 1, 1)
if overwrite || self.variables.is_setted == 0
let self.variables.input = a:char
let self.variables.is_setted = 1
endif
endfunction
function! s:base.getpos()
return self.line.pos()
endfunction
function! s:base.setpos(pos)
return self.line.set_pos(a:pos)
endfunction
function! s:base.tap_keyinput(key)
let self.variables.tap_key = a:key
endfunction
function! s:base.untap_keyinput(key)
if self.variables.tap_key == a:key
let self.variables.tap_key = ""
return 1
endif
endfunction
function! s:base.get_tap_key()
return self.variables.tap_key
endfunction
function! s:base.is_input(key, ...)
let prekey = get(a:, 1, "")
return self.get_tap_key() ==# prekey
\ && self.char() ==# a:key
" \ && self.char() == (prekey . a:key)
endfunction
function! s:base.input_key()
return self.variables.input_key
endfunction
function! s:base.set_prompt(prompt)
let self.variables.prompt = a:prompt
endfunction
function! s:base.get_prompt()
return self.variables.prompt
endfunction
function! s:base.set_suffix(str)
let self.variables.suffix = a:str
endfunction
function! s:base.get_suffix()
return self.variables.suffix
endfunction
function! s:base.insert(word, ...)
if a:0
call self.line.set(a:1)
endif
call self.line.input(a:word)
endfunction
function! s:base.forward()
return self.line.forward()
endfunction
function! s:base.backward()
return self.line.backward()
endfunction
function! s:base.backward_word(...)
let pat = get(a:, 1, '\k\+\s*\|.')
return matchstr(self.backward(), '\%(' . pat . '\)$')
endfunction
function! s:base.connect(module, ...)
if type(a:module) == type("")
return call(self.connect, [s:Module.make(a:module)] + a:000, self)
endif
if empty(a:module)
return
endif
let name = a:0 > 0 ? a:1 : a:module.name
let slot = self.variables.modules.find_first_by("get(v:val.slot, 'name', '') == " . string(name))
if empty(slot)
call self.variables.modules.connect({ "name" : name, "module" : a:module })
else
let slot.slot.module = a:module
endif
" let self.variables.modules[name] = a:module
endfunction
function! s:base.disconnect(name)
return self.variables.modules.disconnect_by(
\ "get(v:val.slot, 'name', '') == " . string(a:name)
\ )
" unlet self.variables.modules[a:name]
endfunction
function! s:base.get_module(name)
let slot = self.variables.modules.find_first_by("get(v:val.slot, 'name', '') == " . string(a:name))
return empty(slot) ? {} : slot.slot.module
endfunction
function! s:base.callevent(event)
call self.variables.modules.sort_by("has_key(v:val.slot.module, 'priority') ? v:val.slot.module.priority('" . a:event . "') : 0")
return self.variables.modules.call(a:event, [self])
" call map(filter(copy(self.variables.modules), "has_key(v:val, a:event)"), "v:val." . a:event . "(self)")
endfunction
function! s:base.cmap(lhs, rhs)
let self.variables.keymapping[a:lhs] = a:rhs
endfunction
function! s:base.cnoremap(lhs, rhs)
let key = s:Keymapping.as_key_config(a:rhs)
let key.noremap = 1
let self.variables.keymapping[a:lhs] = key
endfunction
function! s:base.cunmap(lhs)
unlet self.variables.keymapping[a:lhs]
endfunction
function! s:base.keymapping()
return self.__keymapping__()
endfunction
function! s:base.__keymapping__()
return {}
endfunction
function! s:base.execute(...)
let command = get(a:, 1, self.getline())
call self.__execute(command)
endfunction
function! s:base.draw()
call self.callevent("on_draw_pre")
call self.callevent("on_draw")
endfunction
function! s:base.exit(...)
let self.variables.exit = 1
let self.variables.exit_code = get(a:, 1, 0)
endfunction
function! s:base.enable_keymapping()
let self.variables.enable_keymapping = 1
endfunction
function! s:base.disable_keymapping()
let self.variables.enable_keymapping = 0
endfunction
function! s:base.is_enable_keymapping()
return self.variables.enable_keymapping
endfunction
" function! s:base.cancel()
" call self.exit(1)
" call self.__on_cancel()
" endfunction
function! s:base.exit_code()
return self.variables.exit_code
endfunction
function! s:base.hl_cursor_on()
if exists("self.variables.old_guicursor")
set guicursor&
let &guicursor = self.variables.old_guicursor
unlet self.variables.old_guicursor
endif
if exists("self.variables.old_t_ve")
let &t_ve = self.variables.old_t_ve
unlet self.variables.old_t_ve
endif
endfunction
function! s:base.hl_cursor_off()
if exists("self.variables.old_t_ve")
return
endif
let self.variables.old_guicursor = &guicursor
set guicursor=n:block-NONE
let self.variables.old_t_ve = &t_ve
set t_ve=
endfunction
function! s:base.start(...)
let exit_code = call(self.__main, a:000, self)
return exit_code
endfunction
function! s:base.__empty(...)
endfunction
function! s:base.get(...)
let Old_execute = self.execute
let self.execute = self.__empty
try
let exit_code = call(self.start, a:000, self)
if exit_code == 0
return self.getline()
endif
finally
let self.execute = Old_execute
endtry
return ""
endfunction
function! s:base.input_key_stack()
return self.variables.input_key_stack
endfunction
function! s:base.input_key_stack_string()
return join(self.variables.input_key_stack, "")
endfunction
function! s:base.set_input_key_stack(stack)
let self.variables.input_key_stack = a:stack
return self.variables.input_key_stack
endfunction
function! s:base.input_key_stack_pop()
return remove(self.input_key_stack(), 0)
endfunction
function! s:base.getchar(...)
if empty(self.input_key_stack())
return call(s:Input.getchar, a:000, s:Input)
endif
return self.input_key_stack_pop()
endfunction
function! s:base.__init_variables()
let self.variables.tap_key = ""
let self.variables.char = ""
let self.variables.input = ""
let self.variables.exit = 0
let self.variables.exit_code = 1
let self.variables.enable_keymapping = 1
let self.variables.input_key_stack = []
let self.line = deepcopy(s:String.make())
endfunction
function! s:_is_valid_highlight(name)
let highlight = s:Highlight.get(a:name)
if empty(highlight)
return 0
endif
if has("gui_running")
\ && (has_key(highlight, "guifg") || has_key(highlight, "guibg"))
return 1
elseif (has_key(highlight, "ctermfg") || has_key(highlight, "ctermbg"))
return 1
endif
return 0
endfunction
function! s:base.__init()
call self.__init_variables()
call self.hl_cursor_off()
if !hlexists(self.highlights.cursor)
if s:_is_valid_highlight("Cursor")
execute "highlight link " . self.highlights.cursor . " Cursor"
else
" Workaround by CUI Vim Cursor Highlight
" issues #92
" https://github.com/osyo-manga/vital-over/issues/92
execute "highlight " . self.highlights.cursor . " term=reverse cterm=reverse gui=reverse"
endif
endif
if !hlexists(self.highlights.cursor_on)
execute "highlight link " . self.highlights.cursor_on . " " . self.highlights.cursor
endif
if !hlexists(self.highlights.cursor_insert)
execute "highlight " . self.highlights.cursor_insert . " cterm=underline term=underline gui=underline"
endif
endfunction
function! s:base.__execute(command)
call self.callevent("on_execute_pre")
try
call self.__execute__(a:command)
catch
echohl ErrorMsg
echom matchstr(v:exception, 'Vim\((\w*)\)\?:\zs.*\ze')
echohl None
call self.callevent("on_execute_failed")
finally
call self.callevent("on_execute")
endtry
endfunction
function! s:base.__execute__(cmd)
execute a:cmd
endfunction
function! s:base.__input_char(char)
let char = a:char
let self.variables.input_key = char
let self.variables.char = char
call self.setchar(self.variables.char)
let self.variables.is_setted = 0
call self.callevent("on_char_pre")
call self.insert(self.variables.input)
call self.callevent("on_char")
endfunction
function! s:base.__input(input, ...)
if a:input == ""
return
endif
let self.variables.input_key = a:input
if a:0 == 0
let keymapping = self.__get_keymapping()
else
let keymapping = a:1
endif
if self.is_enable_keymapping()
let key = s:Keymapping.unmapping(keymapping, a:input)
else
let key = a:input
endif
if key == ""
return
endif
call self.set_input_key_stack(s:String.split_by_keys(key))
while !(empty(self.input_key_stack()) || self.is_exit())
call self.__input_char(self.input_key_stack_pop())
endwhile
endfunction
function! s:is_input_waiting(keymapping, input)
let num = len(filter(copy(a:keymapping), 'stridx(v:key, a:input) == 0'))
return num > 1 || (num == 1 && !has_key(a:keymapping, a:input))
endfunction
function! s:base.__inputting()
if !self.is_enable_keymapping()
return self.__input(s:Input.getchar())
endif
let input = s:Input.getchar()
let old_line = self.getline()
let old_pos = self.getpos()
let keymapping = self.__get_keymapping()
try
let t = reltime()
while s:is_input_waiting(keymapping, input)
\ && str2nr(reltimestr(reltime(t))) * 1000 < &timeoutlen
call self.setline(old_line)
call self.insert(input)
call self.setpos(old_pos)
call self.draw()
let input .= s:Input.getchar(0)
endwhile
finally
call self.setline(old_line)
call self.setpos(old_pos)
endtry
call self.__input(input, keymapping)
endfunction
function! s:base.__update()
" call self.callevent("on_update")
" if !getchar(1)
" continue
" endif
"
" call self.__input(s:getchar(0))
" call self.draw()
call self.callevent("on_update")
call self.__inputting()
" call self.__input(s:Input.getchar())
if self.is_exit()
return -1
endif
call self.draw()
endfunction
function! s:base.__main(...)
try
call self.__init()
call self.callevent("on_enter")
call self.__input(get(a:, 1, ""))
call self.draw()
while !self.is_exit()
try
if self.__update()
break
endif
catch
call self.callevent("on_exception")
endtry
endwhile
catch
echohl ErrorMsg | echom v:throwpoint . " " . v:exception | echohl None
let self.variables.exit_code = -1
finally
call self.__finish()
call self.callevent("on_leave")
endtry
return self.exit_code()
endfunction
function! s:base.__finish()
call self.hl_cursor_on()
endfunction
function! s:base.__is_exit()
return self.is_exit()
endfunction
function! s:base.is_exit()
return self.variables.exit
endfunction
function! s:base.__get_keymapping()
let result = {}
" for module in values(self.variables.modules)
for module in self.variables.modules.slots()
if has_key(module, "keymapping")
if module isnot self
call extend(result, module.keymapping(self))
endif
endif
endfor
return extend(extend(result, self.variables.keymapping), self.keymapping())
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,97 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Maker#import() abort', printf("return map({'plain': '', '_vital_depends': '', 'standard_search': '', 'standard': '', 'standard_search_back': '', 'default': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:modules = [
\ "Scroll",
\ "CursorMove",
\ "Delete",
\ "HistAdd",
\ "History",
\ "Cancel",
\ "Execute",
\ "NoInsert",
\ "InsertRegister",
\ "Redraw",
\ "DrawCommandline",
\ "ExceptionExit",
\ "ExceptionMessage",
\]
function! s:_vital_loaded(V)
let s:V = a:V
let s:Cmdline = s:V.import("Over.Commandline.Base")
let s:Modules = s:V.import("Over.Commandline.Modules")
endfunction
function! s:_vital_depends()
return [
\ "Over.Commandline.Base",
\ "Over.Commandline.Modules",
\ ] + map(copy(s:modules), "'Over.Commandline.Modules.' . v:val")
endfunction
function! s:default(...)
return call(s:Cmdline.make, a:000, s:Cmdline)
endfunction
function! s:plain()
return s:Cmdline.plain()
endfunction
function! s:standard(...)
let result = call(s:Cmdline.make, a:000, s:Cmdline)
call result.connect("Execute")
call result.connect("Cancel")
call result.connect("Delete")
call result.connect("CursorMove")
call result.connect("HistAdd")
call result.connect("History")
call result.connect("InsertRegister")
call result.connect(s:Modules.get("NoInsert").make_special_chars())
call result.connect("Redraw")
call result.connect("DrawCommandline")
call result.connect("ExceptionExit")
call result.connect("ExceptionMessage")
call result.connect(s:Modules.get("KeyMapping").make_vim_cmdline_mapping())
call result.connect("Digraphs")
call result.connect("LiteralInsert")
return result
endfunction
function! s:standard_search(...)
let result = s:standard(get(a:, 1, "/"))
call result.connect(s:Modules.get("Execute").make_search("/"))
call result.connect(s:Modules.make("HistAdd", "/"))
call result.connect(s:Modules.make("History", "/"))
return result
endfunction
function! s:standard_search_back(...)
let result = s:standard(get(a:, 1, "?"))
call result.connect(s:Modules.get("Execute").make_search("?"))
call result.connect(s:Modules.make("HistAdd", "/"))
call result.connect(s:Modules.make("History", "/"))
return result
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,36 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#import() abort', printf("return map({'get': '', 'make': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
endfunction
function! s:get(name)
if exists("s:" . a:name)
return s:{a:name}
endif
let s:{a:name} = s:V.import('Over.Commandline.Modules.' . a:name)
return s:{a:name}
endfunction
function! s:make(name, ...)
let module = s:get(a:name)
return call(module.make, a:000, module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,24 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#All#import() abort', printf("return map({'_vital_depends': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:modules = map(split(globpath(expand("<sfile>:p:h"), "/*.vim"), "\n"), "fnamemodify(v:val, ':t:r')")
function! s:_vital_depends()
return map(copy(s:modules), "'Over.Commandline.Modules.' . v:val")
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,47 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#AsyncUpdate#import() abort', printf("return map({'make': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:Base = s:V.import("Over.Commandline.Base")
endfunction
let s:module = {
\ "name" : "AsyncUpdate"
\}
function! s:module.on_enter(cmdline)
function! a:cmdline.__update()
call self.callevent("on_update")
try
if !getchar(1)
return
endif
call self.__inputting()
catch /^Vim:Interrupt$/
call self.__input("\<C-c>")
endtry
call self.draw()
endfunction
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,173 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#BufferComplete#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_uniq(list)
let dict = {}
for _ in a:list
let dict[_] = 0
endfor
return keys(dict)
endfunction
let s:module = {
\ "name" : "BufferComplete",
\}
function! s:_buffer_complete()
return sort(s:_uniq(filter(split(join(getline(1, '$')), '\W'), '!empty(v:val)')), 1)
endfunction
function! s:_parse_line(line)
let keyword = matchstr(a:line, '\zs\w\+\ze$')
let pos = strchars(a:line) - strchars(keyword)
return [pos, keyword]
endfunction
function! s:_as_statusline(list, count)
if empty(a:list)
return
endif
let hl_none = "%#StatusLine#"
let hl_select = "%#StatusLineNC#"
let tail = " > "
let result = a:list[0]
let pos = 0
for i in range(1, len(a:list)-1)
if strdisplaywidth(result . " " . a:list[i]) > &columns - len(tail)
if a:count < i
break
else
let pos = -i
endif
let result = a:list[i]
else
let result .= (" " . a:list[i])
endif
if a:count == i
let pos = pos + i
endif
endfor
return join(map(split(result, " "), 'v:key == pos ? hl_select . v:val . hl_none : v:val'))
endfunction
function! s:module.get_complete_words()
return s:_buffer_complete()
endfunction
function! s:module.complete(cmdline)
call s:_finish()
let s:old_statusline = &statusline
let backward = a:cmdline.backward()
let [pos, keyword] = s:_parse_line(backward)
if !exists("s:complete")
let s:complete = self.get_complete_words()
endif
let s:complete_list = filter(copy(s:complete), 'v:val =~ ''^''.keyword')
if empty(s:complete_list)
return -1
endif
if pos == 0
let backward = ""
else
let backward = join(split(backward, '\zs')[ : pos-1 ], "")
endif
let s:line = backward . a:cmdline.forward()
let s:pos = pos
call a:cmdline.setline(s:line)
let s:count = 0
endfunction
function! s:_finish()
if exists("s:old_statusline")
let &statusline = s:old_statusline
unlet s:old_statusline
redrawstatus
endif
endfunction
function! s:module.on_char_pre(cmdline)
if a:cmdline.is_input("<Over>(buffer-complete)")
\ || a:cmdline.is_input("<Over>(buffer-complete-prev)")
if self.complete(a:cmdline) == -1
call s:_finish()
call a:cmdline.setchar('')
return
endif
if a:cmdline.is_input("<Over>(buffer-complete-prev)")
let s:count = len(s:complete_list) - 1
endif
call a:cmdline.setchar('')
call a:cmdline.tap_keyinput("Completion")
" elseif a:cmdline.is_input("\<Tab>", "Completion")
elseif a:cmdline.is_input("<Over>(buffer-complete)", "Completion")
\ || a:cmdline.is_input("\<Right>", "Completion")
call a:cmdline.setchar('')
let s:count += 1
if s:count >= len(s:complete_list)
let s:count = 0
endif
elseif a:cmdline.is_input("<Over>(buffer-complete-prev)", "Completion")
\ || a:cmdline.is_input("\<Left>", "Completion")
call a:cmdline.setchar('')
let s:count -= 1
if s:count < 0
let s:count = len(s:complete_list) - 1
endif
else
if a:cmdline.untap_keyinput("Completion")
call a:cmdline.callevent("on_char_pre")
endif
call s:_finish()
return
endif
call a:cmdline.setline(s:line)
call a:cmdline.insert(s:complete_list[s:count], s:pos)
if len(s:complete_list) > 1
let &statusline = s:_as_statusline(s:complete_list, s:count)
redrawstatus
endif
if len(s:complete_list) == 1
call a:cmdline.untap_keyinput("Completion")
endif
endfunction
function! s:module.on_draw_pre(...)
" redrawstatus
endfunction
function! s:module.on_leave(cmdline)
call s:_finish()
unlet! s:complete
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,34 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#Cancel#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "Cancel"
\}
function! s:module.on_char_pre(cmdline)
if a:cmdline.is_input("\<Esc>")
\ || a:cmdline.is_input("\<C-c>")
" call a:cmdline.cancel()
call a:cmdline.exit(1)
call a:cmdline.setchar("")
endif
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,52 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#CursorMove#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "CursorMove"
\}
function! s:module.on_char_pre(cmdline)
if a:cmdline.is_input("\<Right>")
call a:cmdline.line.next()
call a:cmdline.setchar('')
elseif a:cmdline.is_input("\<Left>")
call a:cmdline.line.prev()
call a:cmdline.setchar('')
elseif a:cmdline.is_input("\<C-b>")
\ || a:cmdline.is_input("\<Home>")
call a:cmdline.setline(0)
call a:cmdline.setchar('')
elseif a:cmdline.is_input("\<C-e>")
\ || a:cmdline.is_input("\<End>")
call a:cmdline.setline(a:cmdline.line.length())
call a:cmdline.setchar('')
elseif a:cmdline.is_input("\<C-Left>")
\ || a:cmdline.is_input("\<S-Left>")
call a:cmdline.setline(strridx(a:cmdline.backward()[:-2], ' ') + 1)
call a:cmdline.setchar('')
elseif a:cmdline.is_input("\<C-Right>")
\ || a:cmdline.is_input("\<S-Right>")
let p = stridx(a:cmdline.forward()[1:], ' ')
call a:cmdline.setline(p != -1 ? a:cmdline.line.pos() + p + 2 : a:cmdline.line.length())
call a:cmdline.setchar('')
endif
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,50 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#Delete#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "Delete",
\}
function! s:module.on_char_pre(cmdline)
if a:cmdline.is_input("\<C-h>")
\ || a:cmdline.is_input("\<BS>")
if a:cmdline.line.length() == 0
return a:cmdline.exit(1)
else
call a:cmdline.line.remove_prev()
call a:cmdline.setchar('')
endif
elseif a:cmdline.is_input("\<Del>")
call a:cmdline.line.remove_pos()
call a:cmdline.setchar('')
elseif a:cmdline.is_input("\<C-w>")
let word = a:cmdline.backward_word()
let backward = a:cmdline.backward()[ : -strlen(word)-1 ]
call a:cmdline.setline(backward . a:cmdline.line.pos_char() . a:cmdline.forward())
call a:cmdline.setline(strchars(backward))
call a:cmdline.setchar('')
elseif a:cmdline.is_input("\<C-u>")
call a:cmdline.setline(a:cmdline.line.pos_char() . a:cmdline.forward())
call a:cmdline.setline(0)
call a:cmdline.setchar('')
endif
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,110 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#Digraphs#import() abort', printf("return map({'capture': '', '_vital_depends': '', 'digraph': '', 'make': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:Input = a:V.import("Over.Input")
endfunction
function! s:_vital_depends()
return [
\ "Over.Input",
\ ]
endfunction
let s:module = {
\ "name" : "Digraphs",
\ "digraphs" : {}
\}
function! s:capture(cmd)
let verbose_save = &verbose
let &verbose = 0
try
redir => result
execute "silent!" a:cmd
redir END
finally
let &verbose = verbose_save
endtry
return result
endfunction
function! s:digraph() abort
let x = split(substitute(s:capture(':digraph'), "\n", ' ', 'g'),
\ '[[:graph:]]\{2}\s.\{1,4}\s\+\d\+\s*\zs')
let digraphs = map(x, "split(v:val, ' \\+')")
let r = {}
for d in digraphs
let r[d[0]] = len(d) is 3 && d[2] =~# '\d\+' ? nr2char(str2nr(d[2],10))
\ : len(d) is 2 && d[1] =~# '32' ? nr2char(str2nr(d[1],10))
\ : ''
endfor
return r
endfunction
function! s:module.on_leave(cmdline)
" Delete cache to handle additional digraphs definition
let self.digraphs = {}
endfunction
function! s:module.on_char_pre(cmdline)
if a:cmdline.is_input("\<C-k>")
if empty(self.digraphs)
" Get digraphs when inputting <C-k> instead of on_enter because it cause
" flicker in some environments #107
let self.digraphs = s:digraph()
endif
call a:cmdline.setchar('?')
let self.prefix_key = a:cmdline.input_key()
let self.old_line = a:cmdline.getline()
let self.old_pos = a:cmdline.getpos()
return
elseif exists("self.prefix_key")
\ && a:cmdline.get_tap_key() == self.prefix_key
call a:cmdline.setline(self.old_line)
call a:cmdline.setpos(self.old_pos)
let x = a:cmdline.input_key()
let y = s:Input.getchar()
" For CTRL-K, there is one general digraph: CTRL-K <Space> {char} will
" enter {char} with the highest bit set. You can use this to enter
" meta-characters.
let char = x ==# "\<Space>" ?
\ nr2char(char2nr(y) + 128) : get(self.digraphs, x . y, y)
call a:cmdline.setchar(char)
endif
endfunction
function! s:module.on_char(cmdline)
if a:cmdline.is_input("\<C-k>")
call a:cmdline.tap_keyinput(self.prefix_key)
call a:cmdline.disable_keymapping()
call a:cmdline.setpos(a:cmdline.getpos()-1)
else
if exists("self.prefix_key")
call a:cmdline.untap_keyinput(self.prefix_key)
call a:cmdline.enable_keymapping()
unlet! self.prefix_key
endif
endif
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,115 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#Doautocmd#import() abort', printf("return map({'_vital_depends': '', 'doautocmd_user': '', 'get_cmdline': '', 'make': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:E = s:V.import("Over.Exception")
endfunction
function! s:_vital_depends()
return [
\ "Over.Exception",
\ ]
endfunction
let s:cache_command = {}
function! s:doautocmd_user(prefix, command)
let group = a:prefix . "-vital-over-commandline-doautocmd-dummy"
if !has_key(s:cache_command, a:prefix)
let s:cache_command[a:prefix] = {}
endif
if !has_key(s:cache_command[a:prefix], a:command)
execute "autocmd " . group
\ . " User " . a:command." silent! execute ''"
if v:version > 703 || v:version == 703 && has("patch438")
let s:cache_command[a:prefix][a:command] = "doautocmd <nomodeline> User " . a:command
else
let s:cache_command[a:prefix][a:command] = "doautocmd User " . a:command
endif
endif
execute s:cache_command[a:prefix][a:command]
endfunction
let s:hooks = [
\ "enter",
\ "leave",
\ "char",
\ "char_pre",
\ "draw",
\ "draw_pre",
\ "execute_pre",
\ "execute_failed",
\ "execute",
\ "exception",
\]
let s:hooks_camel = [
\ "Enter",
\ "Leave",
\ "Char",
\ "CharPre",
\ "Draw",
\ "DrawPre",
\ "ExecutePre",
\ "ExecuteFailed",
\ "Execute",
\ "Exception",
\]
let s:module = {
\ "name" : "Doautocmd",
\}
for s:i in range(len(s:hooks))
execute join([
\ "function! s:module.on_" . s:hooks[s:i] . "(cmdline, ...)",
\ " let s:cmdline = a:cmdline",
\ " call s:doautocmd_user(self.prefix, self.prefix . " . string(s:hooks_camel[s:i]) . ")",
\ "endfunction",
\ ], "\n")
endfor
function! s:get_cmdline()
if !exists("s:cmdline")
execute s:E.throw_cmd("Undefined cmdline object.", "Over.Commandline.Modules.Doautocmd")
endif
return s:cmdline
endfunction
function! s:make(prefix)
if has_key(s:cache_command, a:prefix)
unlet! s:cache_command[a:prefix]
endif
execute "augroup " a:prefix . "-vital-over-commandline-doautocmd-dummy"
autocmd!
augroup END
let module = deepcopy(s:module)
let module.prefix = a:prefix
return module
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,149 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#DrawCommandline#import() abort', printf("return map({'suffix': '', 'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "DrawCommandline"
\}
let s:cmdheight = {}
function! s:cmdheight.save()
if has_key(self, "value")
return
endif
let self.value = &cmdheight
endfunction
function! s:cmdheight.restore()
if has_key(self, "value")
let &cmdheight = self.value
unlet self.value
endif
endfunction
function! s:cmdheight.get()
return self.value
endfunction
function! s:suffix(left, suffix)
let left_len = strdisplaywidth(a:left)
let len = &columns - left_len % &columns
let len = len + (&columns * (strdisplaywidth(a:suffix) > (len - 1))) - 1
return repeat(" ", len - strdisplaywidth(a:suffix)) . a:suffix
" return printf("%" . len . "S", a:suffix)
endfunction
let s:old_width = 0
function! s:_redraw(cmdline)
let left = a:cmdline.get_prompt() . a:cmdline.getline() . (empty(a:cmdline.line.pos_char()) ? " " : "")
let width = len(left) + 1
if a:cmdline.get_suffix() != ""
let width += len(s:suffix(left, a:cmdline.get_suffix())) - 1
endif
if &columns >= width && &columns <= s:old_width && s:old_width >= width
redraw
normal! :
elseif &columns <= width
normal! :
else
redraw
endif
let s:old_width = width
call s:cmdheight.save()
let height = max([(width - 1) / (&columns) + 1, s:cmdheight.get()])
if height > &cmdheight || &cmdheight > height
let &cmdheight = height
redraw
endif
endfunction
function! s:_as_echon(str)
return "echon " . strtrans(string(a:str))
endfunction
function! s:module.on_draw_pre(cmdline)
if empty(a:cmdline.line.pos_char())
let cursor = "echohl " . a:cmdline.highlights.cursor . " | echon ' '"
else
let cursor = "echohl " . a:cmdline.highlights.cursor_on . " | " . s:_as_echon(a:cmdline.line.pos_char())
endif
let suffix = ""
if a:cmdline.get_suffix() != ""
let suffix = s:_as_echon(s:suffix(a:cmdline.get_prompt() . a:cmdline.getline() . repeat(" ", empty(a:cmdline.line.pos_char())), a:cmdline.get_suffix()))
endif
let self.draw_command = join([
\ "echohl " . a:cmdline.highlights.prompt,
\ s:_as_echon(a:cmdline.get_prompt()),
\ "echohl NONE",
\ s:_as_echon(a:cmdline.backward()),
\ cursor,
\ "echohl NONE",
\ s:_as_echon(a:cmdline.forward()),
\ suffix,
\ ], " | ")
call s:_redraw(a:cmdline)
endfunction
function! s:_echon(expr)
echon strtrans(a:expr)
endfunction
function! s:module.on_draw(cmdline)
execute self.draw_command
" execute "echohl" a:cmdline.highlights.prompt
" call s:echon(a:cmdline.get_prompt())
" echohl NONE
" call s:echon(a:cmdline.backward())
" if empty(a:cmdline.line.pos_char())
" execute "echohl" a:cmdline.highlights.cursor
" call s:echon(' ')
" else
" execute "echohl" a:cmdline.highlights.cursor_on
" call s:echon(a:cmdline.line.pos_char())
" endif
" echohl NONE
" call s:echon(a:cmdline.forward())
" if a:cmdline.get_suffix() != ""
" call s:echon(s:suffix(a:cmdline.get_prompt() . a:cmdline.getline() . repeat(" ", empty(a:cmdline.line.pos_char())), a:cmdline.get_suffix()))
" endif
endfunction
function! s:module.on_execute_pre(...)
call s:cmdheight.restore()
endfunction
function! s:module.on_leave(...)
call s:cmdheight.restore()
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,31 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#ExceptionExit#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "ExceptionExit",
\}
function! s:module.on_exception(cmdline)
call a:cmdline.exit(-1)
endfunction
function! s:make(...)
let result = deepcopy(s:module)
let result.exit_code = get(a:, 1, 0)
return result
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,60 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#ExceptionMessage#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:vname = expand("<sfile>:h:h:h:h:t")
let s:module = {
\ "name" : "ExceptionMessage",
\}
function! s:module.on_exception(cmdline)
let self.exception = v:exception
let self.throwpoint = v:throwpoint
endfunction
function! s:module.on_draw_pre(cmdline)
if has_key(self, "exception")
call self.message(a:cmdline)
unlet self.exception
endif
endfunction
function! s:module.message(...)
echohl ErrorMsg
execute self.command string(self.prefix . " : " . self.throwpoint . " " . self.exception)
echohl None
endfunction
function! s:module.on_leave(cmdline)
if has_key(self, "exception")
call self.message(a:cmdline)
unlet self.exception
endif
endfunction
function! s:make(...)
let result = deepcopy(s:module)
let result.prefix = get(a:, 1, "vital-over(".s:vname.") Exception")
let result.command = get(a:, 2, "echom")
return result
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,85 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#Execute#import() abort', printf("return map({'make_search': '', 'silent_feedkeys': '', 'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:silent_feedkeys(expr, name, ...)
let mode = get(a:, 1, "m")
let map = printf("<Plug>(%s)", a:name)
if mode == "n"
let command = "nnoremap"
else
let command = "nmap"
endif
execute command "<silent>" map printf("%s:nunmap %s<CR>", a:expr, map)
call feedkeys(printf("\<Plug>(%s)", a:name))
endfunction
function! s:_is_input_enter(cmdline)
return a:cmdline.is_input("\<CR>")
\ || a:cmdline.is_input("\<NL>")
\ || a:cmdline.is_input("\<C-j>")
endfunction
let s:module = {
\ "name" : "Execute"
\}
function! s:module.on_char_pre(cmdline)
if s:_is_input_enter(a:cmdline)
call self.execute(a:cmdline)
call a:cmdline.setchar("")
call a:cmdline.exit(0)
endif
if a:cmdline.is_input("<Over>(execute-no-exit)")
call self.execute(a:cmdline)
call a:cmdline.setchar("")
endif
endfunction
function! s:module.execute(cmdline)
return a:cmdline.execute()
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let s:search = deepcopy(s:module)
let s:search.prefix = "/"
function! s:search.execute(cmdline)
call s:silent_feedkeys(":call histdel('/', -1)\<CR>", "remove_hist", "n")
let cmd = printf("call s:silent_feedkeys(\"%s%s\<CR>\", 'search', 'n')", self.prefix, a:cmdline.getline())
execute cmd
" let cmd = printf("call search('%s')", a:cmdline.getline())
" call a:cmdline.execute(cmd)
" let @/ = a:cmdline.getline()
" call s:silent_feedkeys(":let &hlsearch = &hlsearch\<CR>", "hlsearch", "n")
endfunction
function! s:make_search(...)
let result = deepcopy(s:search)
let result.prefix = get(a:, 1, "/")
return result
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,34 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#Exit#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "Exit",
\ "exit_code" : 0
\}
function! s:module.on_char_pre(cmdline)
if a:cmdline.is_input("<Over>(exit)")
call a:cmdline.setchar("")
call a:cmdline.exit(self.exit_code)
endif
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,32 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#HistAdd#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "HistAdd",
\ "mode" : "cmd"
\}
function! s:module.on_leave(cmdline)
call histadd(self.mode, a:cmdline.getline())
endfunction
function! s:make(...)
let module = deepcopy(s:module)
let module.mode = get(a:, 1, "cmd")
return module
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,69 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#History#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "History",
\ "mode" : "cmd",
\}
function! s:module.histories()
return map(range(1, &history), 'histget(self.mode, v:val * -1)')
endfunction
function! s:_should_match_cmdline(cmdline)
return a:cmdline.is_input("\<Up>")
\ || a:cmdline.is_input("\<Down>")
endfunction
function! s:_reset()
let s:cmdhist = []
let s:count = 0
let s:is_match_mode = 0 " <Up>/<Down>: true, <C-n>/<C-p>: false
endfunction
function! s:module.on_enter(...)
call s:_reset()
endfunction
function! s:module.on_char_pre(cmdline)
if !a:cmdline.is_input("\<Up>") && !a:cmdline.is_input("\<Down>")
\ && !a:cmdline.is_input("\<C-p>") && !a:cmdline.is_input("\<C-n>")
call s:_reset()
return
else
if s:count == 0 && empty(s:cmdhist)
\ || s:is_match_mode != s:_should_match_cmdline(a:cmdline)
let cmdline = '^' . a:cmdline.getline()
let s:is_match_mode = s:_should_match_cmdline(a:cmdline)
let s:cmdhist = [a:cmdline.getline()] + (s:is_match_mode ?
\ filter(self.histories(), 'v:val =~ cmdline') : self.histories())
endif
endif
call a:cmdline.setchar("")
if a:cmdline.is_input("\<Down>") || a:cmdline.is_input("\<C-n>")
let s:count = max([s:count - 1, 0])
endif
if a:cmdline.is_input("\<Up>") || a:cmdline.is_input("\<C-p>")
let s:count = min([s:count + 1, len(s:cmdhist)])
endif
call a:cmdline.setline(get(s:cmdhist, s:count, a:cmdline.getline()))
endfunction
function! s:make(...)
let module = deepcopy(s:module)
let module.mode = get(a:, 1, "cmd")
return module
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,48 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#IgnoreRegexpBackwardWord#import() abort', printf("return map({'backward_word': '', 'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
" Improved backward word detection which ignore regular expression
let s:module = {
\ "name" : "IgnoreRegexpBackwardWord"
\}
function! s:backward_word(str, ...)
let pat = get(a:, 1, '\k\+\s*\|.')
let flags = s:non_escaped_backslash .
\ '\%(' . 'z[se]' .
\ '\|' . '[iIkKfFpPsSdDxXoOwWhHaAlLuUetrbncCZmMvV]' .
\ '\|' . '%[dxouUCVlcv]' .
\ '\|' . "%'[a-zA-Z]" .
\ '\|' . '%#=\d' .
\ '\|' . 'z\=\d' .
\ '\)'
return matchstr(get(split(a:str, flags . '\s*\zs'), -1, ""),
\ '\%(' . flags . '\s*\|' . pat . '\)$')
endfunction
let s:non_escaped_backslash = '\m\%(\%(^\|[^\\]\)\%(\\\\\)*\)\@<=\\'
function! s:module.on_enter(cmdline)
function! a:cmdline.backward_word(...)
return call("s:backward_word", [self.backward()] + a:000)
endfunction
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,83 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#Incsearch#import() abort', printf("return map({'escape_regex': '', 'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:escape_regex(pattern)
return substitute(a:pattern, '^\^', '\\_^', "")
endfunction
let s:module = {
\ "name" : "Incsearch",
\ "highlights" : {
\ "incsearch" : "IncSearch"
\ },
\ "pattern" : "",
\ "search_flag" : "",
\ "mode" : "",
\}
function! s:module.search_hl_off()
if exists("self.search_hl_id")
call matchdelete(self.search_hl_id)
unlet self.search_hl_id
endif
endfunction
function! s:module.search_hl_on(pattern)
call self.search_hl_off()
let self.search_hl_id = matchadd(self.highlights.incsearch, a:pattern)
endfunction
function! s:module.on_enter(...)
let self.old_pos = getpos(".")
endfunction
function! s:module.on_leave(...)
call setpos(".", self.old_pos)
call self.search_hl_off()
endfunction
function! s:module.on_char(cmdline)
call self.search_hl_off()
let line = a:cmdline.getline()
let result = get(matchlist(line, self.pattern), 1, "")
if result != ""
let pos = searchpos(result, self.search_flag)
if pos == [0, 0]
return
endif
call self.search_hl_on('\%' . pos[0] . 'l' . (&ignorecase ? '\c' : "") . s:escape_regex(result))
redraw
endif
endfunction
function! s:make(...)
let module = deepcopy(s:module)
let module.mode = get(a:, 1, "/")
let module.pattern = get(a:, 2, '^\(.\+\)')
let module.search_flag = get(a:, 3, 'c')
return module
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,158 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#InsertRegister#import() abort', printf("return map({'_vital_depends': '', 'to_string': '', 'input': '', 'get_cmdline_cword': '', 'make': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:String = s:V.import("Over.String")
endfunction
function! s:_vital_depends()
return [
\ "Over.String",
\ ]
endfunction
function! s:to_string(expr)
return type(a:expr) == type("") ? a:expr : string(a:expr)
endfunction
function! s:input(cmdline)
let CR_index = index(a:cmdline.input_key_stack(), "\<CR>")
if CR_index != -1
let input = a:cmdline.input_key_stack_string()
let input = input[ : CR_index-1]
call a:cmdline.set_input_key_stack(a:cmdline.input_key_stack()[CR_index+1 : ])
return eval(input)
endif
let input_text = ""
if !empty(a:cmdline.input_key_stack())
let input_text = a:cmdline.input_key_stack_string()
call a:cmdline.set_input_key_stack([])
endif
call a:cmdline.hl_cursor_on()
try
redraw
let input = input("=", input_text, "expression")
if !empty(input)
let input = s:to_string(eval(input))
endif
catch
return ""
finally
call a:cmdline.hl_cursor_off()
endtry
return input
endfunction
let s:module = {
\ "name" : "InsertRegister"
\}
function! s:module.reset()
let self.cword = expand("<cword>")
let self.cWORD = expand("<cWORD>")
let self.cfile = expand("<cfile>")
endfunction
function! s:module.on_enter(...)
call self.reset()
" let self.prefix_key = ""
endfunction
function! s:get_cmdline_cword(backward, cword)
" let backward = matchstr(a:backward, '.\{-}\zs\k\+$')
let backward = a:backward
if &incsearch == 0 || a:cword == "" || a:backward == "" || s:String.index(a:cword, backward) != 0
return a:cword
endif
return a:cword[len(backward) : ]
endfunction
function! s:module.on_char_pre(cmdline)
if a:cmdline.is_input("\<C-r>")
call a:cmdline.setchar('"')
let self.prefix_key = a:cmdline.input_key()
let self.old_line = a:cmdline.getline()
let self.old_pos = a:cmdline.getpos()
return
elseif exists("self.prefix_key")
\ && a:cmdline.get_tap_key() == self.prefix_key
call a:cmdline.setline(self.old_line)
call a:cmdline.setpos(self.old_pos)
let char = a:cmdline.input_key()
if char =~ '^[0-9a-zA-z.%#:/"\-*+]$'
let register = tr(getreg(char), "\n", "\r")
call a:cmdline.setchar(register)
elseif char == "="
call a:cmdline.setchar(s:input(a:cmdline))
elseif char == "\<C-w>"
call a:cmdline.setchar(s:get_cmdline_cword(a:cmdline.backward_word(), self.cword))
elseif char == "\<C-a>"
call a:cmdline.setchar(self.cWORD)
elseif char == "\<C-f>"
call a:cmdline.setchar(self.cfile)
elseif char == "\<C-r>"
call a:cmdline.setchar('"')
else
call a:cmdline.setchar("")
endif
" elseif a:cmdline.is_input('=', self.prefix_key)
" call a:cmdline.setchar(s:input(a:cmdline))
" elseif a:cmdline.is_input("\<C-w>", self.prefix_key)
" call a:cmdline.setchar(self.cword)
" elseif a:cmdline.is_input("\<C-a>", self.prefix_key)
" call a:cmdline.setchar(self.cWORD)
" elseif a:cmdline.is_input("\<C-f>", self.prefix_key)
" call a:cmdline.setchar(self.cfile)
" elseif a:cmdline.is_input("\<C-r>", self.prefix_key)
" call a:cmdline.setchar('"')
" else
" call a:cmdline.setchar("")
" endif
endif
endfunction
function! s:module.on_char(cmdline)
if a:cmdline.is_input("\<C-r>")
call a:cmdline.tap_keyinput(self.prefix_key)
call a:cmdline.disable_keymapping()
call a:cmdline.setpos(a:cmdline.getpos()-1)
else
if exists("self.prefix_key")
call a:cmdline.untap_keyinput(self.prefix_key)
call a:cmdline.enable_keymapping()
unlet! self.prefix_key
endif
endif
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,149 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#KeyMapping#import() abort', printf("return map({'_vital_depends': '', 'make_emacs': '', 'make_vim_cmdline_mapping': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:Keymapping = a:V.import("Palette.Keymapping")
endfunction
function! s:_vital_depends()
return [
\ "Palette.Keymapping",
\ ]
endfunction
let s:emacs = {
\ "name" : "KeyMapping_emacs_like"
\}
function! s:emacs.keymapping(cmdline)
return {
\ "\<C-f>" : {
\ "key" : "\<Right>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ "\<C-b>" : {
\ "key" : "\<Left>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ "\<C-n>" : {
\ "key" : "\<Down>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ "\<C-p>" : {
\ "key" : "\<Up>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ "\<C-a>" : {
\ "key" : "\<Home>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ "\<C-e>" : {
\ "key" : "\<End>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ "\<C-d>" : {
\ "key" : "\<Del>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ "\<A-d>" : {
\ "key" : "\<C-w>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ "\<A-b>" : {
\ "key" : "\<S-Left>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ "\<A-f>" : {
\ "key" : "\<S-Right>",
\ "noremap" : 1,
\ "lock" : 1,
\ },
\ }
endfunction
function! s:make_emacs()
return deepcopy(s:emacs)
endfunction
let s:vim_cmdline_mapping = {
\ "name" : "KeyMapping_vim_cmdline_mapping",
\ "_cmaps" : {}
\}
function! s:_convert_sid(rhs, sid) abort
return substitute(a:rhs, '<SID>', '<SNR>' . a:sid . '_', 'g')
endfunction
function! s:_auto_cmap()
let cmaps = {}
let cmap_info = s:Keymapping.rhs_key_list("c", 0, 1)
" vital-over currently doesn't support <buffer> mappings
for c in filter(cmap_info, "v:val['buffer'] ==# 0")
let cmaps[s:Keymapping.escape_special_key(c['lhs'])] = {
\ 'noremap' : c['noremap'],
\ 'key' : s:Keymapping.escape_special_key(s:_convert_sid(c['rhs'], c['sid'])),
\ 'expr' : s:Keymapping.escape_special_key(c['expr']),
\ }
endfor
return cmaps
endfunction
function! s:vim_cmdline_mapping.on_enter(cmdline)
let self._cmaps = s:_auto_cmap()
if exists("*execute")
let self._old_cmap = execute("cmap")
endif
endfunction
function! s:vim_cmdline_mapping.on_update(cmdline)
if !exists("*execute")
return
endif
let cmap_ = execute("cmap")
if self._old_cmap != cmap_
let self._cmaps = s:_auto_cmap()
let self._old_cmap = cmap_
endif
endfunction
function! s:vim_cmdline_mapping.keymapping(cmdline)
return self._cmaps
endfunction
function! s:make_vim_cmdline_mapping()
return deepcopy(s:vim_cmdline_mapping)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,39 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#LiteralInsert#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "LiteralInsert",
\}
function! s:module.on_char_pre(cmdline)
if a:cmdline.is_input("\<C-v>")
\ || a:cmdline.is_input("\<C-q>")
let old_line = a:cmdline.getline()
let old_pos = a:cmdline.getpos()
call a:cmdline.insert('^')
call a:cmdline.setpos(old_pos)
call a:cmdline.draw()
let char = a:cmdline.getchar()
call a:cmdline.setline(old_line)
call a:cmdline.setpos(old_pos)
call a:cmdline.setchar(char)
endif
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,49 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#NoInsert#import() abort', printf("return map({'make_special_chars': '', 'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "NoInsert",
\ "chars" : []
\}
function! s:module.is_no_insert(char)
return index(self.chars, a:char) >= 0
endfunction
function! s:module.on_char_pre(cmdline)
if self.is_no_insert(a:cmdline.char())
call a:cmdline.setchar("", 0)
endif
endfunction
function! s:make(chars)
let module = deepcopy(s:module)
let module.chars = type(a:chars) == type([]) ? a:chars : [a:chars]
return module
endfunction
function! s:make_special_chars()
let module = s:make([])
function! module.is_no_insert(char)
return char2nr(a:char) == 128 || char2nr(a:char) < 27
endfunction
return module
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,34 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#Paste#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "Paste"
\}
function! s:module.on_char_pre(cmdline)
if a:cmdline.is_input("<Over>(paste)")
let register = v:register == "" ? '"' : v:register
call a:cmdline.insert(tr(getreg("*"), "\n", "\r"))
call a:cmdline.setchar('')
endif
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,66 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#Redraw#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "Redraw",
\}
function! s:module.on_execute_pre(cmdline)
call self.redraw(a:cmdline)
endfunction
function! s:module.on_enter(...)
let self.is_execute = 0
endfunction
function! s:module.on_execute(...)
let self.is_execute = 1
endfunction
function! s:module.on_execute_failed(...)
let self.is_execute = 0
endfunction
function! s:module.on_leave(cmdline)
if self.is_execute == 0 && a:cmdline.exit_code() != -1
call self.redraw(a:cmdline)
endif
endfunction
" function! s:module.on_draw_pre(cmdline)
" call self.redraw(a:cmdline)
" endfunction
function! s:module.redraw(cmdline)
redraw
" Workaround for the :set cedit=<C-c>
" https://github.com/osyo-manga/vital-over/issues/52
" https://github.com/Lokaltog/vim-easymotion/issues/177#issuecomment-53663431
if &cedit != "<C-c>"
\ ||(v:version > 704 || v:version == 704 && has("patch441"))
normal! :
else
execute "normal! :\<Esc>"
endif
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,46 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Commandline#Modules#Scroll#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:module = {
\ "name" : "Scroll"
\}
function! s:module.on_char_pre(cmdline)
if a:cmdline.is_input("<Over>(scroll-y)")
execute "normal! \<C-y>"
call a:cmdline.setchar('')
elseif a:cmdline.is_input("<Over>(scroll-u)")
execute "normal! \<C-u>"
call a:cmdline.setchar('')
elseif a:cmdline.is_input("<Over>(scroll-f)")
execute "normal! \<C-f>"
call a:cmdline.setchar('')
elseif a:cmdline.is_input("<Over>(scroll-e)")
execute "normal! \<C-e>"
call a:cmdline.setchar('')
elseif a:cmdline.is_input("<Over>(scroll-d)")
execute "normal! \<C-d>"
call a:cmdline.setchar('')
elseif a:cmdline.is_input("<Over>(scroll-b)")
execute "normal! \<C-b>"
call a:cmdline.setchar('')
endif
endfunction
function! s:make()
return deepcopy(s:module)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,40 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Exception#import() abort', printf("return map({'throw': '', 'throw_cmd': '', 'set_prefix': '', 'error': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:vname = expand("<sfile>:h:h:t")
let s:prefix = printf("vital-over(%s) Exception", s:vname)
function! s:set_prefix(prefix)
let s:prefix = a:prefix
endfunction
function! s:throw_cmd(exp, where)
return 'throw ' . string(s:prefix . " : " . a:exp . " in " . a:where)
endfunction
function! s:throw(exp, where)
execute s:throw_cmd(a:exp, a:where)
endfunction
function! s:error(text, where)
echohl ErrorMsg
echom s:prefix . " : " . a:text . " in " . a:where
echohl None
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,34 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Input#import() abort', printf("return map({'getchar': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:getchar(...)
let mode = get(a:, 1, 0)
while 1
" Workaround for https://github.com/osyo-manga/vital-over/issues/53
try
let char = call("getchar", a:000)
catch /^Vim:Interrupt$/
let char = 3 " <C-c>
endtry
" Workaround for the <expr> mappings
if string(char) !=# "\x80\xfd`"
return mode == 1 ? !!char
\ : type(char) == type(0) ? nr2char(char) : char
endif
endwhile
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,89 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Keymapping#import() abort', printf("return map({'_vital_depends': '', 'unmapping': '', 'as_key_config': '', 'match_key': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:String = s:V.import("Over.String")
endfunction
function! s:_vital_depends()
return [
\ "Over.String",
\ ]
endfunction
function! s:as_key_config(config)
let base = {
\ "noremap" : 0,
\ "lock" : 0,
\ "expr" : 0,
\ }
return type(a:config) == type({}) ? extend(base, a:config)
\ : extend(base, {
\ "key" : a:config,
\ })
endfunction
function! s:match_key(keymapping, key)
let keys = sort(keys(a:keymapping))
return get(filter(keys, 'stridx(a:key, v:val) == 0'), -1, '')
endfunction
function! s:_safe_eval(expr, ...)
call extend(l:, get(a:, 1, {}))
let result = get(a:, 2, "")
try
let result = eval(a:expr)
catch
echohl ErrorMsg | echom v:exception | echohl None
endtry
return result
endfunction
function! s:_get_key(conf)
" call extend(l:, a:conf)
let self = a:conf
return get(a:conf, "expr", 0) ? s:_safe_eval(a:conf.key, l:) : a:conf.key
endfunction
function! s:unmapping(keymapping, key, ...)
let is_locking = get(a:, 1, 0)
let key = s:match_key(a:keymapping, a:key)
if key == ""
return s:String.length(a:key) <= 1 ? a:key : s:unmapping(a:keymapping, a:key[0], is_locking) . s:unmapping(a:keymapping, a:key[1:], is_locking)
endif
let map_conf = s:as_key_config(a:keymapping[key])
let next_input = s:unmapping(a:keymapping, a:key[len(key) : ], is_locking)
if map_conf.lock == 0 && is_locking
return key . next_input
elseif map_conf.lock
return s:unmapping(a:keymapping, s:_get_key(map_conf), is_locking) . next_input
else
return s:unmapping(a:keymapping, s:_get_key(map_conf), map_conf.noremap) . next_input
endif
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,113 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#Signals#import() abort', printf("return map({'_vital_depends': '', 'call': '', 'make': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:L = s:V.import("Data.List")
endfunction
function! s:_vital_depends()
return ["Data.List"]
endfunction
let s:base = {
\ "variables" : {
\ "slots" : [],
\ "counter" : 0,
\ }
\}
function! s:base.connect(slot)
let self.variables.counter += 1
let slot = { "id" : self.variables.counter, "slot" : a:slot }
call add(self.variables.slots, slot)
return slot
endfunction
function! s:base.disconnect(slot)
if empty(a:slot)
return -1
endif
for i in range(len(self.variables.slots))
if self.variables.slots[i].id == a:slot.id
unlet self.variables.slots[i]
return
endif
endfor
return -1
endfunction
function! s:base.disconnect_by(expr)
return self.disconnect(self.find_first_by(a:expr))
endfunction
function! s:call(list, func, ...)
let args = get(a:, 1, [])
let def = get(a:, 2, 0)
return map(copy(a:list), "has_key(v:val, a:func) ? call(v:val.".a:func.", args, v:val) : def")
endfunction
function! s:base.call(func, ...)
return call("s:call", [self.slots(), a:func] + a:000)
endfunction
function! s:base.find_by(expr)
return filter(copy(self.variables.slots), a:expr)
endfunction
function! s:base.find_first_by(expr)
return get(self.find_by(a:expr), 0, {})
endfunction
function! s:base.sort_by(expr)
let self.variables.slots = s:L.sort_by(self.variables.slots, a:expr)
endfunction
function! s:base.get_slot(val)
return a:val.slot
endfunction
function! s:base.slots()
return map(copy(self.variables.slots), "self.get_slot(v:val)")
endfunction
" function! s:base.dict()
" let result = {}
" for _ in self.variables.slots
" let result[_.id] = _.value
" endfor
" return result
" endfunction
function! s:make()
let result = deepcopy(s:base)
return result
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,158 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Over#String#import() abort', printf("return map({'_vital_depends': '', 'length': '', 'index': '', 'split_by_keys': '', 'make': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:List = s:V.import("Data.List")
endfunction
function! s:_vital_depends()
return [
\ "Data.List",
\ ]
endfunction
function! s:_clamp(x, max, min)
return min([max([a:x, a:max]), a:min])
endfunction
let s:base = {}
function! s:base.set(item)
return type(a:item) == type("") ? self.set_str(a:item)
\ : type(a:item) == type(0) ? self.set_pos(a:item)
\ : self
endfunction
function! s:base.str()
return join(self.list, "")
endfunction
function! s:base.set_pos(pos)
let self.col = s:_clamp(a:pos, 0, self.length())
return self
endfunction
function! s:base.backward()
return self.col > 0 ? join(self.list[ : self.col-1], '') : ""
endfunction
function! s:base.forward()
return join(self.list[self.col+1 : ], '')
endfunction
function! s:base.pos_char()
return get(self.list, self.col, "")
endfunction
function! s:base.set_str(str)
let self.list = split(a:str, '\zs')
let self.col = strchars(a:str)
return self
endfunction
function! s:base.pos()
return self.col
endfunction
function! s:base.input(str)
call extend(self.list, split(a:str, '\zs'), self.col)
let self.col += len(split(a:str, '\zs'))
return self
endfunction
function! s:base.length()
return len(self.list)
endfunction
function! s:base.next()
return self.set_pos(self.col + 1)
endfunction
function! s:base.prev()
return self.set_pos(self.col - 1)
endfunction
function! s:base.remove(index)
if a:index < 0 || self.length() <= a:index
return ""
endif
let result = self.list[a:index]
unlet self.list[a:index]
if a:index < self.col
call self.set(self.col - 1)
endif
return result
endfunction
function! s:base.remove_pos()
return self.remove(self.col)
endfunction
function! s:base.remove_prev()
return self.remove(self.col - 1)
endfunction
function! s:base.remove_next()
return self.remove(self.col + 1)
endfunction
function! s:make(...)
let default = get(a:, 1, "")
let result = deepcopy(s:base)
call result.set(default)
return result
endfunction
" NOTE: old regexpengine has a bug with string which contains binary
" :echo "\x80" =~ "\\%#=1\x80" | " => 0
" But it matches correctly with :h /collection
" :echo "\x80" =~ "\\%#=1[\x80]" | " => 1
" http://lingr.com/room/vim/archives/2015/02/13#message-21261450
let s:_engine = exists("+regexpengine") ? '\%#=2' : ''
" \<A-]> => Û\xfdQ
" \<A-@> => À\xfeX
let s:_regex = exists("+regexpengine")
\ ? "\\%(Û\xfdQ\\|À\xfeX\\|\x80\xfc.\\%(\x80..\\|.\\)\\|\x80..\\|.\\)\\zs"
\ : "\\%(Û[\xfd]Q\\|À[\xfe]X\\|[\x80][\xfc].\\%([\x80]..\\|.\\)\\|[\x80]..\\|.\\)\\zs"
function! s:_split_keystring(str, ...)
return split(a:str, s:_engine . '\m\%(' . get(a:, 1, '') . s:_regex . '\)')
endfunction
function! s:split_by_keys(str)
return s:_split_keystring(a:str, "\\%(\<Plug>\\|<Over>\\)(.\\{-})\\zs\\|")
endfunction
function! s:index(haystack, needle, ...)
let start = get(a:, 1, 0)
let ignorecase = get(a:, 2, &ignorecase)
if ignorecase
return stridx(tolower(a:haystack), tolower(a:needle), start)
else
return stridx(a:haystack, a:needle, start)
endif
endfunction
function! s:length(str)
return len(s:split_by_keys(a:str))
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,68 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Palette#Capture#import() abort', printf("return map({'extend': '', 'command': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:verbosefiles = []
function! s:_verbosefile_push(file)
call add(s:verbosefiles, &verbosefile)
let &verbosefile = a:file
return a:file
endfunction
function! s:_verbosefile_pop()
let filename = &verbosefile
let &verbosefile = get(s:verbosefiles, -1)
call remove(s:verbosefiles, -1)
return filename
endfunction
function! s:_reset()
let s:verbosefiles = []
endfunction
function! s:extend(dict, src)
for [key, value] in items(a:src)
let a:dict[key] = value
unlet value
endfor
endfunction
function! s:command(cmd, ...)
" Workaround : Vim 7.3.xxx in Travis and Ubuntu
" https://github.com/osyo-manga/vital-palette/issues/5
" call extend(l:, get(a:, 1, {}))
if a:0 > 0
call s:extend(l:, a:1)
endif
call s:_verbosefile_push(tempname())
try
redir =>result
silent execute a:cmd
finally
redir END
endtry
call s:_verbosefile_pop()
" let result = substitute(result, "<SRN>", "\<SNR>", "g")
" let result = substitute(result, "<SID>", "\<SID>", "g")
return result
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,127 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Palette#Highlight#import() abort', printf("return map({'capture': '', '_vital_depends': '', 'parse': '', 'group_list': '', 'set': '', 'parse_to_name': '', 'links_to': '', 'get': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
function! s:_vital_loaded(V)
let s:V = a:V
let s:Message = s:V.import("Vim.Message")
endfunction
function! s:_vital_depends()
return [
\ "Vim.Message",
\ ]
endfunction
function! s:_execute(cmd)
execute a:cmd
endfunction
function! s:capture(name)
if hlexists(a:name) == 0
return ""
endif
return s:Message.capture("highlight " . a:name)
endfunction
function! s:links_to(highlight)
return matchstr(a:highlight, '^\S\+\s\+xxx links to \zs.*\ze$')
endfunction
function! s:parse_to_name(highlight)
return matchstr(a:highlight, '^\zs\w\+\ze')
endfunction
function! s:parse(highlight)
let highlight = a:highlight
if highlight !~# '^\w\+\s\+xxx\s'
return {}
endif
let name = s:parse_to_name(a:highlight)
let result = { "_name" : name }
if highlight =~# '^\w\+\s\+xxx cleared'
let result.cleared = 1
return result
endif
let link = s:links_to(highlight)
if link != ""
let result.link = link
return result
endif
let attrs = [
\ "term",
\ "cterm",
\ "ctermfg",
\ "ctermbg",
\ "gui",
\ "font",
\ "guifg",
\ "guibg",
\ "guisp",
\ ]
for attr in attrs
let item = matchstr(highlight, '\s' . attr . '=\zs#\?\w\+\ze')
if item != ""
let result[attr] = item
endif
endfor
return result
endfunction
function! s:get(name, ...)
if !hlexists(a:name)
return {}
endif
let result = s:parse(substitute(s:capture(a:name), "\n", "", "g"))
if has_key(result, "link") && get(a:, 1, 0)
return s:get(result.link, get(a:, 1, 0))
else
return result
endif
endfunction
function! s:set(name, config)
if type(a:config) == type("")
return s:set(a:config, s:get(a:config))
endif
if has_key(a:config, "cleared")
return s:_execute("highlight clear " . a:name)
endif
if has_key(a:config, "link")
return s:_execute("highlight link " . a:name . " " . a:config.link)
endif
return s:_execute("highlight " . a:name . " " . join(map(items(filter(a:config, "v:key !=# '_name'")), "v:val[0] . '=' . v:val[1]"), " "))
endfunction
function! s:group_list()
let highlights = split(s:Message.capture("highlight"), "\n")
return filter(map(highlights, "s:parse_to_name(v:val)"), "v:val != ''")
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,115 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Palette#Keymapping#import() abort', printf("return map({'capture': '', '_vital_depends': '', 'escape_special_key': '', 'rhs_key_list': '', 'parse_lhs_list': '', 'lhs_key_list': '', 'capture_list': '', 'parse_lhs': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
scriptencoding utf-8
let s:save_cpo = &cpo
set cpo&vim
let s:modep = "[nvoicsxl]"
function! s:_vital_loaded(V)
let s:V = a:V
let s:Capture = s:V.import("Palette.Capture")
endfunction
function! s:_vital_depends()
return [
\ "Palette.Capture",
\ ]
endfunction
function! s:_capture(mode)
let cmd = "map"
if a:mode ==# "!"
let cmd = cmd . "!"
elseif a:mode =~# "[nvoicsxl]"
let cmd = a:mode . cmd
endif
return s:Capture.command(cmd)
endfunction
function! s:capture(...)
let mode = get(a:, 1, "")
let modes = split(mode, '\zs')
return join(map(modes, "s:_capture(v:val)"), "\n")
endfunction
function! s:_keymapping(str)
return a:str =~ '^[!nvoicsxl]\s'
endfunction
function! s:capture_list(...)
let mode = get(a:, 1, "")
return filter(split(s:capture(mode), "\n"), "s:_keymapping(v:val)")
endfunction
function! s:escape_special_key(key)
" Workaround : <C-?> https://github.com/osyo-manga/vital-palette/issues/5
if a:key ==# "<^?>"
return "\<C-?>"
endif
execute 'let result = "' . substitute(escape(a:key, '\"'), '\(<.\{-}>\)', '\\\1', 'g') . '"'
return result
endfunction
function! s:parse_lhs(text, ...)
let mode = get(a:, 1, '[!nvoicsxl]')
" NOTE: :map! Surpport : https://github.com/osyo-manga/vital-palette/issues/4
if get(a:, 1, "") =~# '[!ci]'
let mode = '[!ci]'
endif
return matchstr(a:text, mode . '\{1,3\}\s*\zs\S\{-}\ze\s\+')
endfunction
function! s:parse_lhs_list(...)
let mode = get(a:, 1, "")
return map(s:capture_list(mode), "s:parse_lhs(v:val, mode)")
endfunction
function! s:lhs_key_list(...)
let mode = get(a:, 1, "")
return map(s:parse_lhs_list(mode), "s:escape_special_key(v:val)")
endfunction
function! s:_maparg(name, mode, abbr, dict)
" Workaround : <C-?> https://github.com/osyo-manga/vital-palette/issues/5
if a:name ==# "<^?>"
return maparg("\<C-?>", a:mode, a:abbr, a:dict)
endif
return maparg(a:name, a:mode, a:abbr, a:dict)
endfunction
function! s:rhs_key_list(...)
let mode = get(a:, 1, "")
let abbr = get(a:, 2, 0)
let dict = get(a:, 3, 0)
let result = []
for m in split(mode, '\zs')
let result += map(s:parse_lhs_list(m), "s:_maparg(v:val, m, abbr, dict)")
endfor
return filter(result, "empty(v:val) == 0")
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@ -0,0 +1,424 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Prelude#import() abort', printf("return map({'escape_pattern': '', 'is_funcref': '', 'path2directory': '', 'wcswidth': '', 'is_string': '', 'input_helper': '', 'is_number': '', 'is_cygwin': '', 'path2project_directory': '', 'strwidthpart_reverse': '', 'input_safe': '', 'is_list': '', 'truncate_skipping': '', 'glob': '', 'truncate': '', 'is_dict': '', 'set_default': '', 'is_numeric': '', 'getchar_safe': '', 'substitute_path_separator': '', 'is_mac': '', 'strwidthpart': '', 'getchar': '', 'is_unix': '', 'is_windows': '', 'globpath': '', 'escape_file_searching': '', 'is_float': '', 'smart_execute_command': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
let s:save_cpo = &cpo
set cpo&vim
if v:version > 703 ||
\ (v:version == 703 && has('patch465'))
function! s:glob(expr) abort
return glob(a:expr, 1, 1)
endfunction
else
function! s:glob(expr) abort
return split(glob(a:expr, 1), '\n')
endfunction
endif
if v:version > 704 ||
\ (v:version == 704 && has('patch279'))
function! s:globpath(path, expr) abort
return globpath(a:path, a:expr, 1, 1)
endfunction
else
function! s:globpath(path, expr) abort
return split(globpath(a:path, a:expr, 1), '\n')
endfunction
endif
" Wrapper functions for type().
" NOTE: __TYPE_FLOAT = -1 when -float.
" this doesn't match to anything.
if has('patch-7.4.2071')
let [
\ s:__TYPE_NUMBER,
\ s:__TYPE_STRING,
\ s:__TYPE_FUNCREF,
\ s:__TYPE_LIST,
\ s:__TYPE_DICT,
\ s:__TYPE_FLOAT] = [
\ v:t_number,
\ v:t_string,
\ v:t_func,
\ v:t_list,
\ v:t_dict,
\ v:t_float]
else
let [
\ s:__TYPE_NUMBER,
\ s:__TYPE_STRING,
\ s:__TYPE_FUNCREF,
\ s:__TYPE_LIST,
\ s:__TYPE_DICT,
\ s:__TYPE_FLOAT] = [
\ type(3),
\ type(''),
\ type(function('tr')),
\ type([]),
\ type({}),
\ has('float') ? type(str2float('0')) : -1]
endif
" Number or Float
function! s:is_numeric(Value) abort
let _ = type(a:Value)
return _ ==# s:__TYPE_NUMBER
\ || _ ==# s:__TYPE_FLOAT
endfunction
" Number
function! s:is_number(Value) abort
return type(a:Value) ==# s:__TYPE_NUMBER
endfunction
" String
function! s:is_string(Value) abort
return type(a:Value) ==# s:__TYPE_STRING
endfunction
" Funcref
function! s:is_funcref(Value) abort
return type(a:Value) ==# s:__TYPE_FUNCREF
endfunction
" List
function! s:is_list(Value) abort
return type(a:Value) ==# s:__TYPE_LIST
endfunction
" Dictionary
function! s:is_dict(Value) abort
return type(a:Value) ==# s:__TYPE_DICT
endfunction
" Float
function! s:is_float(Value) abort
return type(a:Value) ==# s:__TYPE_FLOAT
endfunction
function! s:truncate_skipping(str, max, footer_width, separator) abort
call s:_warn_deprecated('truncate_skipping', 'Data.String.truncate_skipping')
let width = s:wcswidth(a:str)
if width <= a:max
let ret = a:str
else
let header_width = a:max - s:wcswidth(a:separator) - a:footer_width
let ret = s:strwidthpart(a:str, header_width) . a:separator
\ . s:strwidthpart_reverse(a:str, a:footer_width)
endif
return s:truncate(ret, a:max)
endfunction
function! s:truncate(str, width) abort
" Original function is from mattn.
" http://github.com/mattn/googlereader-vim/tree/master
call s:_warn_deprecated('truncate', 'Data.String.truncate')
if a:str =~# '^[\x00-\x7f]*$'
return len(a:str) < a:width ?
\ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width)
endif
let ret = a:str
let width = s:wcswidth(a:str)
if width > a:width
let ret = s:strwidthpart(ret, a:width)
let width = s:wcswidth(ret)
endif
if width < a:width
let ret .= repeat(' ', a:width - width)
endif
return ret
endfunction
function! s:strwidthpart(str, width) abort
call s:_warn_deprecated('strwidthpart', 'Data.String.strwidthpart')
if a:width <= 0
return ''
endif
let ret = a:str
let width = s:wcswidth(a:str)
while width > a:width
let char = matchstr(ret, '.$')
let ret = ret[: -1 - len(char)]
let width -= s:wcswidth(char)
endwhile
return ret
endfunction
function! s:strwidthpart_reverse(str, width) abort
call s:_warn_deprecated('strwidthpart_reverse', 'Data.String.strwidthpart_reverse')
if a:width <= 0
return ''
endif
let ret = a:str
let width = s:wcswidth(a:str)
while width > a:width
let char = matchstr(ret, '^.')
let ret = ret[len(char) :]
let width -= s:wcswidth(char)
endwhile
return ret
endfunction
if v:version >= 703
" Use builtin function.
function! s:wcswidth(str) abort
call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth')
return strwidth(a:str)
endfunction
else
function! s:wcswidth(str) abort
call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth')
if a:str =~# '^[\x00-\x7f]*$'
return strlen(a:str)
end
let mx_first = '^\(.\)'
let str = a:str
let width = 0
while 1
let ucs = char2nr(substitute(str, mx_first, '\1', ''))
if ucs == 0
break
endif
let width += s:_wcwidth(ucs)
let str = substitute(str, mx_first, '', '')
endwhile
return width
endfunction
" UTF-8 only.
function! s:_wcwidth(ucs) abort
let ucs = a:ucs
if (ucs >= 0x1100
\ && (ucs <= 0x115f
\ || ucs == 0x2329
\ || ucs == 0x232a
\ || (ucs >= 0x2e80 && ucs <= 0xa4cf
\ && ucs != 0x303f)
\ || (ucs >= 0xac00 && ucs <= 0xd7a3)
\ || (ucs >= 0xf900 && ucs <= 0xfaff)
\ || (ucs >= 0xfe30 && ucs <= 0xfe6f)
\ || (ucs >= 0xff00 && ucs <= 0xff60)
\ || (ucs >= 0xffe0 && ucs <= 0xffe6)
\ || (ucs >= 0x20000 && ucs <= 0x2fffd)
\ || (ucs >= 0x30000 && ucs <= 0x3fffd)
\ ))
return 2
endif
return 1
endfunction
endif
let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95')
let s:is_cygwin = has('win32unix')
let s:is_mac = !s:is_windows && !s:is_cygwin
\ && (has('mac') || has('macunix') || has('gui_macvim') ||
\ (!isdirectory('/proc') && executable('sw_vers')))
let s:is_unix = has('unix')
function! s:is_windows() abort
return s:is_windows
endfunction
function! s:is_cygwin() abort
return s:is_cygwin
endfunction
function! s:is_mac() abort
return s:is_mac
endfunction
function! s:is_unix() abort
return s:is_unix
endfunction
function! s:_warn_deprecated(name, alternative) abort
try
echohl Error
echomsg 'Prelude.' . a:name . ' is deprecated! Please use ' . a:alternative . ' instead.'
finally
echohl None
endtry
endfunction
function! s:smart_execute_command(action, word) abort
execute a:action . ' ' . (a:word ==# '' ? '' : '`=a:word`')
endfunction
function! s:escape_file_searching(buffer_name) abort
return escape(a:buffer_name, '*[]?{}, ')
endfunction
function! s:escape_pattern(str) abort
call s:_warn_deprecated(
\ 'escape_pattern',
\ 'Data.String.escape_pattern',
\)
return escape(a:str, '~"\.^$[]*')
endfunction
function! s:getchar(...) abort
let c = call('getchar', a:000)
return type(c) == type(0) ? nr2char(c) : c
endfunction
function! s:getchar_safe(...) abort
let c = s:input_helper('getchar', a:000)
return type(c) == type('') ? c : nr2char(c)
endfunction
function! s:input_safe(...) abort
return s:input_helper('input', a:000)
endfunction
function! s:input_helper(funcname, args) abort
let success = 0
if inputsave() !=# success
throw 'vital: Prelude: inputsave() failed'
endif
try
return call(a:funcname, a:args)
finally
if inputrestore() !=# success
throw 'vital: Prelude: inputrestore() failed'
endif
endtry
endfunction
function! s:set_default(var, val) abort
if !exists(a:var) || type({a:var}) != type(a:val)
let {a:var} = a:val
endif
endfunction
function! s:substitute_path_separator(path) abort
return s:is_windows ? substitute(a:path, '\\', '/', 'g') : a:path
endfunction
function! s:path2directory(path) abort
return s:substitute_path_separator(isdirectory(a:path) ? a:path : fnamemodify(a:path, ':p:h'))
endfunction
function! s:_path2project_directory_git(path) abort
let parent = a:path
while 1
let path = parent . '/.git'
if isdirectory(path) || filereadable(path)
return parent
endif
let next = fnamemodify(parent, ':h')
if next == parent
return ''
endif
let parent = next
endwhile
endfunction
function! s:_path2project_directory_svn(path) abort
let search_directory = a:path
let directory = ''
let find_directory = s:escape_file_searching(search_directory)
let d = finddir('.svn', find_directory . ';')
if d ==# ''
return ''
endif
let directory = fnamemodify(d, ':p:h:h')
" Search parent directories.
let parent_directory = s:path2directory(
\ fnamemodify(directory, ':h'))
if parent_directory !=# ''
let d = finddir('.svn', parent_directory . ';')
if d !=# ''
let directory = s:_path2project_directory_svn(parent_directory)
endif
endif
return directory
endfunction
function! s:_path2project_directory_others(vcs, path) abort
let vcs = a:vcs
let search_directory = a:path
let find_directory = s:escape_file_searching(search_directory)
let d = finddir(vcs, find_directory . ';')
if d ==# ''
return ''
endif
return fnamemodify(d, ':p:h:h')
endfunction
function! s:path2project_directory(path, ...) abort
let is_allow_empty = get(a:000, 0, 0)
let search_directory = s:path2directory(a:path)
let directory = ''
" Search VCS directory.
for vcs in ['.git', '.bzr', '.hg', '.svn']
if vcs ==# '.git'
let directory = s:_path2project_directory_git(search_directory)
elseif vcs ==# '.svn'
let directory = s:_path2project_directory_svn(search_directory)
else
let directory = s:_path2project_directory_others(vcs, search_directory)
endif
if directory !=# ''
break
endif
endfor
" Search project file.
if directory ==# ''
for d in ['build.xml', 'prj.el', '.project', 'pom.xml', 'package.json',
\ 'Makefile', 'configure', 'Rakefile', 'NAnt.build',
\ 'P4CONFIG', 'tags', 'gtags']
let d = findfile(d, s:escape_file_searching(search_directory) . ';')
if d !=# ''
let directory = fnamemodify(d, ':p:h')
break
endif
endfor
endif
if directory ==# ''
" Search /src/ directory.
let base = s:substitute_path_separator(search_directory)
if base =~# '/src/'
let directory = base[: strridx(base, '/src/') + 3]
endif
endif
if directory ==# '' && !is_allow_empty
" Use original path.
let directory = search_directory
endif
return s:substitute_path_separator(directory)
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0:

View File

@ -0,0 +1,207 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Vim#Buffer#import() abort', printf("return map({'parse_cmdarg': '', '_vital_depends': '', 'read_content': '', 'get_selected_text': '', 'is_cmdwin': '', 'edit_content': '', 'open': '', 'get_last_selected': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
let s:save_cpo = &cpo
set cpo&vim
let s:t_funcref = type(function('tr'))
let s:t_string = type('')
let s:t_number = type(0)
function! s:_vital_loaded(V) abort
let s:V = a:V
let s:Guard = s:V.import('Vim.Guard')
endfunction
function! s:_vital_depends() abort
return ['Vim.Guard']
endfunction
if exists('*getcmdwintype')
function! s:is_cmdwin() abort
return getcmdwintype() !=# ''
endfunction
else
function! s:is_cmdwin() abort
return bufname('%') ==# '[Command Line]'
endfunction
endif
function! s:open(buffer, ...) abort
if a:0 == 1 && (type(a:1) == s:t_string || type(a:1) == s:t_funcref)
" For backward compatibility
let options = {'opener': a:1}
else
let options = get(a:000, 0, {})
endif
let options = extend({
\ 'mods': '',
\ 'cmdarg': '',
\ 'opener': empty(a:buffer) ? 'enew' : 'edit',
\}, options
\)
let guard = s:Guard.store(['&wildignore'])
try
let &wildignore = ''
if type(options.opener) == s:t_funcref
let loaded = !bufloaded(a:buffer)
call options.opener(a:buffer)
elseif a:buffer is 0 || a:buffer is# ''
let loaded = 1
silent execute options.mods options.opener
enew
else
let loaded = !bufloaded(a:buffer)
if type(a:buffer) == s:t_string
execute options.mods options.opener options.cmdarg '`=a:buffer`'
elseif type(a:buffer) == s:t_number
silent execute options.mods options.opener
execute a:buffer 'buffer'
else
throw 'vital: Vim.Buffer: Unknown {buffer} type.'
endif
endif
finally
call guard.restore()
endtry
return loaded
endfunction
function! s:get_selected_text(...) abort
echohl WarningMsg
echom "vital: Vim.Buffer: Warning: s:get_selected_text() is deprecated. Use 's:get_last_selected()'."
echohl None
return call('s:get_last_selected', a:000)
endfunction
" Get the last selected text in visual mode
" without using |gv| to avoid |textlock|.
" NOTE:
" * This function uses |gv| only when using |CTRL-V|
" because |gv| is the only way to get selected text
" when using <C-v>$ .
" Please see #192 for the details.
" * If you don't care about |textlock|,
" you can use simple version of this function.
" https://github.com/vim-jp/vital.vim/commit/39aae80f3839fdbeebd838ff14d87327a6b889a9
function! s:get_last_selected() abort
if visualmode() ==# "\<C-v>"
let save = getreg('"', 1)
let save_type = getregtype('"')
try
normal! gv""y
return @"
finally
call setreg('"', save, save_type)
endtry
else
let [begin, end] = [getpos("'<"), getpos("'>")]
let lastchar = matchstr(getline(end[1])[end[2]-1 :], '.')
if begin[1] ==# end[1]
let lines = [getline(begin[1])[begin[2]-1 : end[2]-2]]
else
let lines = [getline(begin[1])[begin[2]-1 :]]
\ + (end[1] - begin[1] <# 2 ? [] : getline(begin[1]+1, end[1]-1))
\ + [getline(end[1])[: end[2]-2]]
endif
return join(lines, "\n") . lastchar . (visualmode() ==# 'V' ? "\n" : '')
endif
endfunction
function! s:read_content(content, ...) abort
let options = extend({
\ 'tempfile': '',
\ 'fileformat': '',
\ 'encoding': '',
\ 'binary': 0,
\ 'nobinary': 0,
\ 'bad': '',
\ 'edit': 0,
\ 'line': '',
\ 'lockmarks': 0,
\}, get(a:000, 0, {}))
let tempfile = empty(options.tempfile) ? tempname() : options.tempfile
let optnames = [
\ empty(options.fileformat) ? '' : '++ff=' . options.fileformat,
\ empty(options.encoding) ? '' : '++enc=' . options.encoding,
\ empty(options.binary) ? '' : '++bin',
\ empty(options.nobinary) ? '' : '++nobin',
\ empty(options.bad) ? '' : '++bad=' . options.bad,
\ empty(options.edit) ? '' : '++edit',
\]
let optname = join(filter(optnames, '!empty(v:val)'))
try
call writefile(a:content, tempfile)
execute printf('keepalt keepjumps %s%sread %s%s',
\ options.lockmarks ? 'lockmarks ' : '',
\ options.line,
\ empty(optname) ? '' : optname . ' ',
\ fnameescape(tempfile),
\)
finally
call delete(tempfile)
" To remove 'tempfile' from unlisted-buffer #439
silent execute 'bwipeout!' fnameescape(tempfile)
endtry
endfunction
function! s:edit_content(content, ...) abort
let options = extend({
\ 'edit': 1,
\ 'lockmarks': 0,
\}, get(a:000, 0, {}))
let guard = s:Guard.store(['&l:modifiable'])
let saved_view = winsaveview()
try
let &l:modifiable=1
silent execute printf(
\ 'keepjumps %s%%delete _',
\ options.lockmarks ? 'lockmarks ' : '',
\)
silent call s:read_content(a:content, options)
silent execute printf(
\ 'keepjumps %s1delete _',
\ options.lockmarks ? 'lockmarks ' : '',
\)
finally
keepjumps call winrestview(saved_view)
call guard.restore()
endtry
setlocal nomodified
endfunction
function! s:parse_cmdarg(...) abort
let cmdarg = get(a:000, 0, v:cmdarg)
let options = {}
if cmdarg =~# '++enc='
let options.encoding = matchstr(cmdarg, '++enc=\zs[^ ]\+\ze')
endif
if cmdarg =~# '++ff='
let options.fileformat = matchstr(cmdarg, '++ff=\zs[^ ]\+\ze')
endif
if cmdarg =~# '++bad='
let options.bad = matchstr(cmdarg, '++bad=\zs[^ ]\+\ze')
endif
if cmdarg =~# '++bin'
let options.binary = 1
endif
if cmdarg =~# '++nobin'
let options.nobinary = 1
endif
if cmdarg =~# '++edit'
let options.edit = 1
endif
return options
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0:

View File

@ -0,0 +1,234 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Vim#Guard#import() abort', printf("return map({'_vital_depends': '', '_vital_created': '', 'store': '', '_vital_loaded': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
let s:save_cpo = &cpo
set cpo&vim
" Use a Funcref as a special term _UNDEFINED
function! s:_undefined() abort
return 'undefined'
endfunction
let s:_UNDEFINED = function('s:_undefined')
function! s:_vital_loaded(V) abort
let s:V = a:V
let s:Prelude = s:V.import('Prelude')
let s:List = s:V.import('Data.List')
let s:Dict = s:V.import('Data.Dict')
endfunction
function! s:_vital_depends() abort
return ['Prelude', 'Data.List', 'Data.Dict']
endfunction
function! s:_vital_created(module) abort
" define constant variables
if !exists('s:const')
let s:const = {}
let s:const.is_local_variable_supported =
\ v:version > 703 || (v:version == 703 && has('patch560'))
" NOTE:
" The third argument is available from 7.4.242 but it had bug and that
" bug was fixed from 7.4.513
let s:const.is_third_argument_of_getreg_supported = has('patch-7.4.513')
lockvar s:const
endif
call extend(a:module, s:const)
endfunction
function! s:_throw(msg) abort
throw printf('vital: Vim.Guard: %s', a:msg)
endfunction
let s:option = {}
function! s:_new_option(name) abort
if a:name !~# '^&'
call s:_throw(printf(
\'An option name "%s" requires to be started from "&"', a:name
\))
elseif !exists(a:name)
call s:_throw(printf(
\'An option name "%s" does not exist', a:name
\))
endif
let option = copy(s:option)
let option.name = a:name
let option.value = eval(a:name)
return option
endfunction
function! s:option.restore() abort
execute printf('let %s = %s', self.name, string(self.value))
endfunction
let s:register = {}
function! s:_new_register(name) abort
if len(a:name) != 2
call s:_throw(printf(
\'A register name "%s" requires to be "@" + a single character', a:name
\))
elseif a:name !~# '^@'
call s:_throw(printf(
\'A register name "%s" requires to be started from "@"', a:name
\))
elseif a:name =~# '^@[:.%]$'
call s:_throw(printf(
\'A register name "%s" is read only', a:name
\))
elseif a:name !~# '^@[@0-9a-zA-Z#=*+~_/-]$'
call s:_throw(printf(
\'A register name "%s" does not exist. See ":help let-register"', a:name
\))
endif
let name = a:name ==# '@@' ? '' : a:name[1]
let register = copy(s:register)
let register.name = name
if s:const.is_third_argument_of_getreg_supported
let register.value = getreg(name, 1, 1)
else
let register.value = getreg(name, 1)
endif
let register.type = getregtype(name)
return register
endfunction
function! s:register.restore() abort
" https://github.com/vim/vim/commit/5a50c2255c447838d08d3b4895a3be3a41cd8eda
if has('patch-7.4.243') || self.name !=# '='
call setreg(self.name, self.value, self.type)
else
let @= = self.value
endif
endfunction
let s:environment = {}
function! s:_new_environment(name) abort
if a:name !~# '^\$'
call s:_throw(printf(
\'An environment variable name "%s" requires to be started from "$"', a:name
\))
elseif !exists(a:name)
call s:_throw(printf(
\'An environment variable name "%s" does not exist. While Vim cannot unlet environment variable, it requires to exist', a:name
\))
endif
let environment = copy(s:environment)
let environment.name = a:name
let environment.value = eval(a:name)
return environment
endfunction
function! s:environment.restore() abort
execute printf('let %s = %s', self.name, string(self.value))
endfunction
let s:variable = {}
function! s:_new_variable(name, ...) abort
if a:0 == 0
let m = matchlist(a:name, '^\([bwtg]:\)\(.*\)$')
if empty(m)
call s:_throw(printf(
\ join([
\ 'An variable name "%s" requires to start from b:, w:, t:, or g:',
\ 'while no {namespace} is specified',
\ ]),
\ a:name,
\))
endif
let [prefix, name] = m[1 : 2]
let namespace = eval(prefix)
else
let name = a:name
let namespace = a:1
endif
let variable = copy(s:variable)
let variable.name = name
let variable.value = get(namespace, name, s:_UNDEFINED)
let variable.value =
\ type(variable.value) == type({}) || type(variable.value) == type([])
\ ? deepcopy(variable.value)
\ : variable.value
let variable._namespace = namespace
return variable
endfunction
function! s:variable.restore() abort
" unlet the variable to prevent variable type mis-match in case
silent! unlet! self._namespace[self.name]
if type(self.value) == type(s:_UNDEFINED) && self.value == s:_UNDEFINED
" do nothing, leave the variable as undefined
else
let self._namespace[self.name] = self.value
endif
endfunction
let s:instance = {}
function! s:_new_instance(instance, ...) abort
let shallow = get(a:000, 0, 0)
if !s:Prelude.is_list(a:instance) && !s:Prelude.is_dict(a:instance)
call s:_throw(printf(
\'An instance "%s" requires to be List or Dictionary', string(a:instance)
\))
endif
let instance = copy(s:instance)
let instance.instance = a:instance
let instance.values = shallow ? copy(a:instance) : deepcopy(a:instance)
return instance
endfunction
function! s:instance.restore() abort
if s:Prelude.is_list(self.instance)
call s:List.clear(self.instance)
else
call s:Dict.clear(self.instance)
endif
call extend(self.instance, self.values)
endfunction
let s:guard = {}
function! s:store(targets) abort
let resources = []
for meta in a:targets
if s:Prelude.is_list(meta)
if len(meta) == 1
call add(resources, s:_new_instance(meta[0]))
elseif len(meta) == 2
if s:Prelude.is_string(meta[0])
call add(resources, call('s:_new_variable', meta))
else
call add(resources, call('s:_new_instance', meta))
endif
else
call s:_throw('List assignment requires one or two elements')
endif
elseif type(meta) == type('')
if meta =~# '^[bwtgls]:'
" Note:
" To improve an error message, handle l:XXX or s:XXX as well
call add(resources, s:_new_variable(meta))
elseif meta =~# '^&'
call add(resources, s:_new_option(meta))
elseif meta =~# '^@'
call add(resources, s:_new_register(meta))
elseif meta =~# '^\$'
call add(resources, s:_new_environment(meta))
else
call s:_throw(printf(
\ 'Unknown value "%s" was specified',
\ meta
\))
endif
endif
unlet meta
endfor
let guard = copy(s:guard)
let guard._resources = resources
return guard
endfunction
function! s:guard.restore() abort
for resource in self._resources
call resource.restore()
endfor
endfunction
let &cpo = s:save_cpo
unlet! s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0 fdm=marker:

View File

@ -0,0 +1,74 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Vim#Message#import() abort', printf("return map({'capture': '', 'echomsg': '', 'echo': '', 'warn': '', 'get_hit_enter_max_length': '', 'error': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
let s:save_cpo = &cpo
set cpo&vim
function! s:echo(hl, msg) abort
execute 'echohl' a:hl
try
echo a:msg
finally
echohl None
endtry
endfunction
function! s:echomsg(hl, msg) abort
execute 'echohl' a:hl
try
for m in split(a:msg, "\n")
echomsg m
endfor
finally
echohl None
endtry
endfunction
function! s:error(msg) abort
call s:echomsg('ErrorMsg', a:msg)
endfunction
function! s:warn(msg) abort
call s:echomsg('WarningMsg', a:msg)
endfunction
function! s:capture(command) abort
try
redir => out
silent execute a:command
finally
redir END
endtry
return out
endfunction
" * Get max length of |hit-enter|.
" If a string length of a message is greater than the max length,
" Vim waits for user input according to |hit-enter|.
" XXX: Those fixed values may be different between different OSes?
" Currently tested on only Windows.
function! s:get_hit_enter_max_length() abort
let maxlen = &columns * &cmdheight - 1
if &ruler
" TODO
endif
if &showcmd
let maxlen -= 11
endif
return maxlen
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0:

View File

@ -0,0 +1,58 @@
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not mofidify the code nor insert new lines before '" ___vital___'
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_incsearch#Vim#Type#import() abort', printf("return map({'_vital_created': '', 'is_predicate': '', 'is_numeric': '', 'is_special': ''}, \"vital#_incsearch#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
let s:types = {
\ 'number': 0,
\ 'string': 1,
\ 'func': 2,
\ 'list': 3,
\ 'dict': 4,
\ 'float': 5,
\ 'bool': 6,
\ 'none': 7,
\ 'job': 8,
\ 'channel': 9,
\ }
lockvar 1 s:types
let s:type_names = {
\ '0': 'number',
\ '1': 'string',
\ '2': 'func',
\ '3': 'list',
\ '4': 'dict',
\ '5': 'float',
\ '6': 'bool',
\ '7': 'none',
\ '8': 'job',
\ '9': 'channel',
\ }
lockvar 1 s:type_names
function! s:_vital_created(module) abort
let a:module.types = s:types
let a:module.type_names = s:type_names
endfunction
function! s:is_numeric(value) abort
let t = type(a:value)
return t == s:types.number || t == s:types.float
endfunction
function! s:is_special(value) abort
let t = type(a:value)
return t == s:types.bool || t == s:types.none
endfunction
function! s:is_predicate(value) abort
let t = type(a:value)
return t == s:types.number || t == s:types.string ||
\ t == s:types.bool || t == s:types.none
endfunction

View File

@ -0,0 +1,328 @@
let s:plugin_name = expand('<sfile>:t:r')
let s:vital_base_dir = expand('<sfile>:h')
let s:project_root = expand('<sfile>:h:h:h')
let s:is_vital_vim = s:plugin_name is# 'vital'
let s:loaded = {}
let s:cache_sid = {}
" function() wrapper
if v:version > 703 || v:version == 703 && has('patch1170')
function! s:_function(fstr) abort
return function(a:fstr)
endfunction
else
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
let s:_s = '<SNR>' . s:_SID() . '_'
function! s:_function(fstr) abort
return function(substitute(a:fstr, 's:', s:_s, 'g'))
endfunction
endif
function! vital#{s:plugin_name}#new() abort
return s:new(s:plugin_name)
endfunction
function! vital#{s:plugin_name}#import(...) abort
if !exists('s:V')
let s:V = s:new(s:plugin_name)
endif
return call(s:V.import, a:000, s:V)
endfunction
let s:Vital = {}
function! s:new(plugin_name) abort
let base = deepcopy(s:Vital)
let base._plugin_name = a:plugin_name
return base
endfunction
function! s:vital_files() abort
if !exists('s:vital_files')
let s:vital_files = map(
\ s:is_vital_vim ? s:_global_vital_files() : s:_self_vital_files(),
\ 'fnamemodify(v:val, ":p:gs?[\\\\/]?/?")')
endif
return copy(s:vital_files)
endfunction
let s:Vital.vital_files = s:_function('s:vital_files')
function! s:import(name, ...) abort dict
let target = {}
let functions = []
for a in a:000
if type(a) == type({})
let target = a
elseif type(a) == type([])
let functions = a
endif
unlet a
endfor
let module = self._import(a:name)
if empty(functions)
call extend(target, module, 'keep')
else
for f in functions
if has_key(module, f) && !has_key(target, f)
let target[f] = module[f]
endif
endfor
endif
return target
endfunction
let s:Vital.import = s:_function('s:import')
function! s:load(...) abort dict
for arg in a:000
let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg]
let target = split(join(as, ''), '\W\+')
let dict = self
let dict_type = type({})
while !empty(target)
let ns = remove(target, 0)
if !has_key(dict, ns)
let dict[ns] = {}
endif
if type(dict[ns]) == dict_type
let dict = dict[ns]
else
unlet dict
break
endif
endwhile
if exists('dict')
call extend(dict, self._import(name))
endif
unlet arg
endfor
return self
endfunction
let s:Vital.load = s:_function('s:load')
function! s:unload() abort dict
let s:loaded = {}
let s:cache_sid = {}
unlet! s:vital_files
endfunction
let s:Vital.unload = s:_function('s:unload')
function! s:exists(name) abort dict
if a:name !~# '\v^\u\w*%(\.\u\w*)*$'
throw 'vital: Invalid module name: ' . a:name
endif
return s:_module_path(a:name) isnot# ''
endfunction
let s:Vital.exists = s:_function('s:exists')
function! s:search(pattern) abort dict
let paths = s:_extract_files(a:pattern, self.vital_files())
let modules = sort(map(paths, 's:_file2module(v:val)'))
return s:_uniq(modules)
endfunction
let s:Vital.search = s:_function('s:search')
function! s:plugin_name() abort dict
return self._plugin_name
endfunction
let s:Vital.plugin_name = s:_function('s:plugin_name')
function! s:_self_vital_files() abort
let builtin = printf('%s/__%s__/', s:vital_base_dir, s:plugin_name)
let installed = printf('%s/_%s/', s:vital_base_dir, s:plugin_name)
let base = builtin . ',' . installed
return split(globpath(base, '**/*.vim', 1), "\n")
endfunction
function! s:_global_vital_files() abort
let pattern = 'autoload/vital/__*__/**/*.vim'
return split(globpath(&runtimepath, pattern, 1), "\n")
endfunction
function! s:_extract_files(pattern, files) abort
let tr = {'.': '/', '*': '[^/]*', '**': '.*'}
let target = substitute(a:pattern, '\.\|\*\*\?', '\=tr[submatch(0)]', 'g')
let regexp = printf('autoload/vital/[^/]\+/%s.vim$', target)
return filter(a:files, 'v:val =~# regexp')
endfunction
function! s:_file2module(file) abort
let filename = fnamemodify(a:file, ':p:gs?[\\/]?/?')
let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$')
return join(split(tail, '[\\/]\+'), '.')
endfunction
" @param {string} name e.g. Data.List
function! s:_import(name) abort dict
if has_key(s:loaded, a:name)
return copy(s:loaded[a:name])
endif
let module = self._get_module(a:name)
if has_key(module, '_vital_created')
call module._vital_created(module)
endif
let export_module = filter(copy(module), 'v:key =~# "^\\a"')
" Cache module before calling module.vital_loaded() to avoid cyclic
" dependences but remove the cache if module._vital_loaded() fails.
" let s:loaded[a:name] = export_module
let s:loaded[a:name] = export_module
if has_key(module, '_vital_loaded')
try
call module._vital_loaded(vital#{s:plugin_name}#new())
catch
unlet s:loaded[a:name]
throw 'vital: fail to call ._vital_loaded(): ' . v:exception
endtry
endif
return copy(s:loaded[a:name])
endfunction
let s:Vital._import = s:_function('s:_import')
" s:_get_module() returns module object wihch has all script local functions.
function! s:_get_module(name) abort dict
let funcname = s:_import_func_name(self.plugin_name(), a:name)
try
return call(funcname, [])
catch /^Vim\%((\a\+)\)\?:E117/
return s:_get_builtin_module(a:name)
endtry
endfunction
function! s:_get_builtin_module(name) abort
return s:sid2sfuncs(s:_module_sid(a:name))
endfunction
if s:is_vital_vim
" For vital.vim, we can use s:_get_builtin_module directly
let s:Vital._get_module = s:_function('s:_get_builtin_module')
else
let s:Vital._get_module = s:_function('s:_get_module')
endif
function! s:_import_func_name(plugin_name, module_name) abort
return printf('vital#_%s#%s#import', a:plugin_name, s:_dot_to_sharp(a:module_name))
endfunction
function! s:_module_sid(name) abort
let path = s:_module_path(a:name)
if !filereadable(path)
throw 'vital: module not found: ' . a:name
endif
let vital_dir = s:is_vital_vim ? '__\w\+__' : printf('_\{1,2}%s\%%(__\)\?', s:plugin_name)
let base = join([vital_dir, ''], '[/\\]\+')
let p = base . substitute('' . a:name, '\.', '[/\\\\]\\+', 'g')
let sid = s:_sid(path, p)
if !sid
call s:_source(path)
let sid = s:_sid(path, p)
if !sid
throw printf('vital: cannot get <SID> from path: %s', path)
endif
endif
return sid
endfunction
function! s:_module_path(name) abort
return get(s:_extract_files(a:name, s:vital_files()), 0, '')
endfunction
function! s:_module_sid_base_dir() abort
return s:is_vital_vim ? &rtp : s:project_root
endfunction
function! s:_dot_to_sharp(name) abort
return substitute(a:name, '\.', '#', 'g')
endfunction
function! s:_source(path) abort
execute 'source' fnameescape(a:path)
endfunction
" @vimlint(EVL102, 1, l:_)
" @vimlint(EVL102, 1, l:__)
function! s:_sid(path, filter_pattern) abort
let unified_path = s:_unify_path(a:path)
if has_key(s:cache_sid, unified_path)
return s:cache_sid[unified_path]
endif
for line in filter(split(s:_execute(':scriptnames'), "\n"), 'v:val =~# a:filter_pattern')
let [_, sid, path; __] = matchlist(line, '^\s*\(\d\+\):\s\+\(.\+\)\s*$')
if s:_unify_path(path) is# unified_path
let s:cache_sid[unified_path] = sid
return s:cache_sid[unified_path]
endif
endfor
return 0
endfunction
" A bug of execute() is fixed in Vim 8.0.0264
if has('patch-8.0.0264')
let s:_execute = function('execute')
else
function! s:_execute(cmd) abort
let [save_verbose, save_verbosefile] = [&verbose, &verbosefile]
set verbose=0 verbosefile=
redir => res
silent! execute a:cmd
redir END
let [&verbose, &verbosefile] = [save_verbose, save_verbosefile]
return res
endfunction
endif
if filereadable(expand('<sfile>:r') . '.VIM') " is case-insensitive or not
let s:_unify_path_cache = {}
" resolve() is slow, so we cache results.
" Note: On windows, vim can't expand path names from 8.3 formats.
" So if getting full path via <sfile> and $HOME was set as 8.3 format,
" vital load duplicated scripts. Below's :~ avoid this issue.
function! s:_unify_path(path) abort
if has_key(s:_unify_path_cache, a:path)
return s:_unify_path_cache[a:path]
endif
let value = tolower(fnamemodify(resolve(fnamemodify(
\ a:path, ':p')), ':~:gs?[\\/]?/?'))
let s:_unify_path_cache[a:path] = value
return value
endfunction
else
function! s:_unify_path(path) abort
return resolve(fnamemodify(a:path, ':p:gs?[\\/]?/?'))
endfunction
endif
" copied and modified from Vim.ScriptLocal
let s:SNR = join(map(range(len("\<SNR>")), '"[\\x" . printf("%0x", char2nr("\<SNR>"[v:val])) . "]"'), '')
function! s:sid2sfuncs(sid) abort
let fs = split(s:_execute(printf(':function /^%s%s_', s:SNR, a:sid)), "\n")
let r = {}
let pattern = printf('\m^function\s<SNR>%d_\zs\w\{-}\ze(', a:sid)
for fname in map(fs, 'matchstr(v:val, pattern)')
let r[fname] = function(s:_sfuncname(a:sid, fname))
endfor
return r
endfunction
"" Return funcname of script local functions with SID
function! s:_sfuncname(sid, funcname) abort
return printf('<SNR>%s_%s', a:sid, a:funcname)
endfunction
if exists('*uniq')
function! s:_uniq(list) abort
return uniq(a:list)
endfunction
else
function! s:_uniq(list) abort
let i = len(a:list) - 1
while 0 < i
if a:list[i] ==# a:list[i - 1]
call remove(a:list, i)
endif
let i -= 1
endwhile
return a:list
endfunction
endif

View File

@ -0,0 +1,5 @@
incsearch
425a6a62645a9f8e497ba52bab709abaa9f185be
Over.Commandline
Coaster.Highlight

1
bundle/incsearch.vim/doc/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
tags

View File

@ -0,0 +1,724 @@
*incsearch.txt* Incrementally highlight all pattern matches
Author : haya14busa <hayabusa1419@gmail.com>
Version : 2.0.1
License : MIT license {{{
Copyright (c) 2014-2016 haya14busa
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.
}}}
CONTENTS *incsearch-contents*
Introduction |incsearch-introduction|
Install |incsearch-install|
Usage |incsearch-usage|
Basic usage |incsearch-basic-usage|
Additional usage |incsearch-additional-usage|
Command line interface |incsearch-commandline-interface|
Highlight |incsearch-highlight|
AUTOCMD |incsearch-autocmd|
API |incsearch-api|
Known Issues |incsearch-known-issues|
ChangeLog |incsearch-changelog|
==============================================================================
INTRODUCTION *incsearch-introduction*
*incsearch.vim* provides incremental highlighting for __ALL__ pattern
matches unlike default 'incsearch'.
You can use incsearch.vim as improved versions of |/| & |?|.
==============================================================================
INSTALL *incsearch-install*
Install with your favorite plugin managers like NeoBundle/Plugin/Plug
>
NeoBundle 'haya14busa/incsearch.vim'
Plugin 'haya14busa/incsearch.vim'
Plug 'haya14busa/incsearch.vim'
<
==============================================================================
USAGE *incsearch-usage*
------------------------------------------------------------------------------
Basic usage~
*incsearch-basic-usage*
*<Plug>(incsearch-forward)*
*<Plug>(incsearch-backward)*
*<Plug>(incsearch-stay)*
Write following lines to your vimrc:
>
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
<
<Plug>(incsearch-forward): Incremental searching forward
<Plug>(incsearch-backward): Incremental searching backward
<Plug>(incsearch-stay): It doesn't move the cursor unless you
explicitly use cursor move commands during
incremental search.
------------------------------------------------------------------------------
Additional usage~
*incsearch-additional-usage*
*g:incsearch#auto_nohlsearch*
<Plug>(incsearch-nohl) *<Plug>(incsearch-nohl)*
<Plug>(incsearch-nohl0) *<Plug>(incsearch-nohl0)*
<Plug>(incsearch-nohl-n) *<Plug>(incsearch-nohl-n)*
<Plug>(incsearch-nohl-N) *<Plug>(incsearch-nohl-N)*
<Plug>(incsearch-nohl-*) *<Plug>(incsearch-nohl-star)*
<Plug>(incsearch-nohl-#) *<Plug>(incsearch-nohl-#)*
<Plug>(incsearch-nohl-g*) *<Plug>(incsearch-nohl-gstar)*
<Plug>(incsearch-nohl-g#) *<Plug>(incsearch-nohl-g#)*
Let's farewell to this kind of mappings! >
nnoremap <Esc><Esc> :<C-u>nohlsearch<CR>
<
If you set |g:incsearch#auto_nohlsearch| to 1 (default: 0) and use
above mappings, 'hlsearch' will be __automatically__ turned off
after the cursor move. Example:
>
set hlsearch
let g:incsearch#auto_nohlsearch = 1
map n <Plug>(incsearch-nohl-n)
map N <Plug>(incsearch-nohl-N)
map * <Plug>(incsearch-nohl-*)
map # <Plug>(incsearch-nohl-#)
map g* <Plug>(incsearch-nohl-g*)
map g# <Plug>(incsearch-nohl-g#)
<
NOTE: |<Plug>(incsearch-nohl-n)| stuff are just aliases to
`<Plug>(incsearch-nohl)n` except |n| doesn't get remapped, so the
basic behaviour is completely same as the default one.
If you want to use this feature with other search related plugins, use
|<Plug>(incsearch-nohl)|.
Please make sure to place |<Plug>(incsearch-nohl)| before the cursor
moving mappings. |<Plug>(incsearch-nohl0)| handles search enhancement
mappings without |CursorMoved| event.
Working with |anzu.txt| example:
https://github.com/osyo-manga/vim-anzu
>
map n <Plug>(incsearch-nohl)<Plug>(anzu-n-with-echo)
map N <Plug>(incsearch-nohl)<Plug>(anzu-N-with-echo)
<
Working with |asterisk.txt| example:
https://github.com/haya14busa/vim-asterisk
>
map * <Plug>(incsearch-nohl)<Plug>(asterisk-*)
map g* <Plug>(incsearch-nohl)<Plug>(asterisk-g*)
map # <Plug>(incsearch-nohl)<Plug>(asterisk-#)
map g# <Plug>(incsearch-nohl)<Plug>(asterisk-g#)
map z* <Plug>(incsearch-nohl0)<Plug>(asterisk-z*)
map gz* <Plug>(incsearch-nohl0)<Plug>(asterisk-gz*)
map z# <Plug>(incsearch-nohl0)<Plug>(asterisk-z#)
map gz# <Plug>(incsearch-nohl0)<Plug>(asterisk-gz#)
<
*g:incsearch#consistent_n_direction*
If you set this option to 1, |n| and |N| directions are always forward
and backward respectively even after performing
|<Plug>(incsearch-backward)| which is improved motion of |?|.
>
let g:incsearch#consistent_n_direction = 1
<
default: 0
*g:incsearch#do_not_save_error_message_history*
If you set this option to 1, error and warning messages with search
command don't save into |message-history|.
|message-history| doesn't be messed up with some unneeded error and
warning messages like |E486| ,`search hit BOTTOM, continuing at TOP`
warning, and so on. Welcome clean |message-history|!
>
let g:incsearch#do_not_save_error_message_history = 1
<
default: 0
Improved 'magic' option~
*g:incsearch#magic*
This is improved 'magic' option. Also see: |/magic|
By default 'magic' option, all you can set is 'magic' or 'nomagic',
and in addition, default option has porability problem. see: 'magic'
In contrast to default 'magic' option, |g:incsearch#magic| enable
you to set 'very magic' |\v| and 'very nomagic' |\V| in adition to
'magic' |\m| and 'nomagic' |\M|.
This option doesn't cause porability problems, so you need not worry
about this problem. No other pattern related programs are affected by
this option.
Usage: >
let g:incsearch#magic = '\v' " very magic
let g:incsearch#magic = '\V' " very nomagic
let g:incsearch#magic = '\m' " magic
let g:incsearch#magic = '\M' " nomagic
<
default: ''
Smart backward word~
*g:incsearch#smart_backward_word*
If this option is set to 1, the backward word detection which is used
when |c_Ctrl-w| and |c_CTRL-R_CTRL-W| become smart. Smart backward
word doesn't include unexpected reglular expression and treats regular
expression flag as one word. For example, when the command line is
`/\vword` and type <C-w>, the vim default command line will become
`/\`, but since |\v| is not the part of word but just a regular
expression flag, it's useful not to include 'v' as a backward word.
This option fix this problem.
default: 1
------------------------------------------------------------------------------
Command line interface~
*incsearch-commandline-interface*
:IncSearchNoreMap {lhs} {rhs} *:IncSearchNoreMap*
Map the key sequence {lhs} to {rhs} for the |incsearch.vim| command
line interface. This command doesn't load while loading your vimrc,
so please call by |VimEnter| or |neobundle-hooks-on_post_source| if
you use |NeoBundle|.
*<Over>(incsearch-next)*
*<Over>(incsearch-prev)*
Emacs-like incsearch: move the cursor while incremental searching.
If the pattern in the command-line is empty, it works like
|last-pattern|
<Over>(incsearch-next) : to the next match. default: <Tab>
<Over>(incsearch-prev) : to the prev match. default: <S-Tab>
*<Over>(incsearch-scroll-f)*
*<Over>(incsearch-scroll-b)*
Scroll-like feature while incremental searching.
<Over>(incsearch-scroll-f) : scroll to the next page match.
default: <C-j>
<Over>(incsearch-scroll-b) : scroll to the previous page match.
default: <C-k>
NOTE: if you want to use |digraphs| feature, please overwrite
<C-k> or map another key to <C-k> like this. >
IncSearchNoreMap <C-k> <C-k>
<
Example:
>
augroup incsearch-keymap
autocmd!
autocmd VimEnter * call s:incsearch_keymap()
augroup END
function! s:incsearch_keymap()
IncSearchNoreMap <Right> <Over>(incsearch-next)
IncSearchNoreMap <Left> <Over>(incsearch-prev)
IncSearchNoreMap <Down> <Over>(incsearch-scroll-f)
IncSearchNoreMap <Up> <Over>(incsearch-scroll-b)
endfunction
<
*g:incsearch#vim_cmdline_keymap*
Apply vim default |:cnoremap| and |:cmap| mappings to custom command line
interface of |incsearch.vim|. |:IncSearchNoreMap| has higher priority
than :cnoremap and :cmap mappings
default: 1
*g:incsearch#emacs_like_keymap*
It enables Emacs-like keymappings if you set
|g:incsearch#emacs_like_keymap| to 1. default: 0
Emacs-like keymapping table~
{lhs} | {rhs}
-------|----------
<C-f> | |<Right>|
<C-b> | |<Left>|
<C-n> | |<Down>|
<C-p> | |<Up>|
<C-a> | |<Home>|
<C-e> | |<End>|
<C-d> | |<Del>|
<A-d> | |<C-w>|
g:incsearch_cli_key_mappings *g:incsearch_cli_key_mappings*
Define keymapping by dictionary instead of |:IncSearchNoreMap|.
You can use following expression. >
'{lhs}': '{rhs}'
< or >
'{lhs}': {
'key': '{rhs}',
'noremap': (1 or 0)
}
< Example: >
let g:incsearch_cli_key_mappings = {
\ "\<Tab>": {
\ 'key': '<Over>(buffer-complete)',
\ 'noremap': 1
\ },
\ "\<C-j>": "\<CR>",
\ }
Buffer completion *incsearch-<Over>(buffer-complete)*
*incsearch-<Over>(buffer-complete-prev)*
Completion with the buffer text.
<Over>(buffer-complete)
start buffer text completion. default: <C-l>
<Over>(buffer-complete-prev)
start buffer text completion to backward direction.
<Right>
select next candidate while completion
<Left>
select candidate while completion
Example: >
augroup incsearch-keymap
autocmd!
autocmd VimEnter * call s:incsearch_keymap()
augroup END
function! s:incsearch_keymap()
IncSearchNoreMap <Tab> <Over>(buffer-complete)
IncSearchNoreMap <S-Tab> <Over>(buffer-complete-prev)
endfunction
<
------------------------------------------------------------------------------
Highlight ~
*incsearch-highlight*
*g:incsearch#separate_highlight*
Highlight matched pattern separately with forward matches and
backward matches.
>
let g:incsearch#separate_highlight = 1
<
default: 0
Highlight Group ~
*incsearch-highlight-group*
| highlight group | description |
| ------------------- | --------------------------------------------- |
| *IncSearchMatch* | For all matched pattern. default: `Search` |
| *IncSearchMatchReverse* | For all matched pattern in reverse direction, |
| | if |g:incsearch#separate_highlight| is on. |
| | default: `IncSearch` |
| *IncSearchOnCursor* | For the matched pattern on the cursor. |
| | default: `IncSearch` |
| *IncSearchCursor* | For cursor position. default: `Cursor` |
| *IncSearchUnderline* | It's not used by default. For the customization |
Customize highlight ~
Change cursor color to red
Example: >
highlight IncSearchCursor ctermfg=0 ctermbg=9 guifg=#000000 guibg=#FF0000
<
*g:incsearch#highlight*
or use the |g:incsearch#highlight| option.
Example: >
let g:incsearch#highlight = {
\ 'match' : {
\ 'group' : 'IncSearchUnderline',
\ 'priority' : '10'
\ },
\ 'on_cursor' : {
\ 'priority' : '100'
\ },
\ 'cursor' : {
\ 'group' : 'ErrorMsg',
\ 'priority' : '1000'
\ }
\ }
<
*g:incsearch#no_inc_hlsearch*
Use 'hlsearch' incrementally to highlight matched patterns including
patterns in the other windows. The highlight of |IncSearchMatch| have
higher priority than 'hlsearch' in the current window but it doesn't
applied to other windows right now. If you do not want to highlight
with 'hlsearch', turn on this variable. >
let g:incsearch#no_inc_hlsearch = 1
< default: 0
------------------------------------------------------------------------------
AUTOCMD ~
*incsearch-autocmd*
|incsearch.vim| triggers those following |User| |autocmd|.
Name triggered by ~
IncSearchEnter triggered when you enter the command line
IncSearchLeave triggered when you leave the command line
IncSearchExecutePre triggered before a command execution
IncSearchExecute triggered after a command execution
IncSearchCharPre triggered before every character insertion
IncSearchChar triggered after every character insertion
NOTE:
incsearch.vim uses |:map-<expr>| for operator-pending mappings, so the
same restriction apply to your defined autocmd for operator-pending.
==============================================================================
API *incsearch-api*
incsearch.vim's API. It may change because it's EXPERIMENTAL but I
try to keep it as much as possible.
------------------------------------------------------------------------------
Functions ~
*incsearch-functions*
incsearch#go([{config}]) *incsearch#go()*
Starts incsearch.vim's search interface. It assumes called by <expr>
mappings. It doesn't work nicely if you call it directly, so if you
want to call from command-line, use |incsearch#call()|. It returns
command to execute search, but you have no need to execute it to move
cursor because it's handled by <expr> mapping.
See |incsearch-config| for available configuration.
Example: >
noremap <expr> z/ incsearch#go()
noremap <expr> z? incsearch#go({'command': '?'})
noremap <expr> <Space>/ incsearch#go({'pattern': histget('/', -1)})
incsearch#call([{config}]) *incsearch#call()*
Starts incsearch.vim's search interface with function call. If you
want to create mapping to start incsearch.vim's search interface,
please use |incsearch#go()|. It returns primitive command to execute
search, but you have no need to execute it explicitly because calling
this function already move the cursor to destination.
See |incsearch-config| for available configuration.
Example: >
:call incsearch#call()
:call incsearch#call({'command': '?'})
:call incsearch#call({'pattern': histget('/', -1)})
incsearch#cli() *incsearch#cli()*
Returns current |Vital.Over.Commandline-object|.
------------------------------------------------------------------------------
Config ~
*incsearch-config*
Here are available configurations you can specify to call
incsearch.vim's search interface like |incsearch#go()| and
|incsearch#call()|.
command *incsearch-config-command*
Search command to use. You can use |/| or |?|.
Type: |string|
Default: '/'
Example: >
noremap <expr> z? incsearch#go({'command': '?'})
is_stay *incsearch-config-is_stay*
Boolean option for stay feature |<Plug>(incsearch-stay)|.
If you set this option to 1, the cursor will not move while
incremental searching unless you explicitly move it.
Type: boolean (0 or 1)
Default: false (0)
Example: >
noremap <expr> g/ incsearch#go({'is_stay': 1})
is_expr *incsearch-config-is_expr*
Boolean option for calling main function with <expr> state or
not. This value is turned on by default for
|Operator-pending-mode| to support dot-repeat(|.|) without any
additional library. But <expr> has a constraint like
|textlock| and moving cursor etc... see |:map-<expr>| for
detail. So if you want to avoid these constraint, turn off
this value explicitly. As for the dot-repeat(|.|) handling, if
vim-repeat[1] is installed, use it to handle dot-repeat(|.|).
[1]:
- https://github.com/tpope/vim-repeat
- https://github.com/kana/vim-repeat
Type: boolean (0 or 1)
Default: false (0) or true (1) for |Operator-pending-mode|
Example: >
noremap <expr> z/ incsearch#go({'is_expr': 0})
pattern *incsearch-config-pattern*
Default pattern to start incsearch.vim's search interface.
Type: |string|
Default: ''
Example: >
noremap <expr> <Space>/ incsearch#go({'pattern': histget('/', -1)})
prompt *incsearch-config-prompt*
Prompt string.
Type: |string|
Default: same as |incsearch-config-command| ('/' or '?')
Example: >
noremap <expr> <Space>/ incsearch#go({'prompt': '>>>'})
modules *incsearch-config-modules*
Additional |Vital.Over.Commandline-modules| to connect.
The list of module extentions:
https://github.com/haya14busa/incsearch.vim/wiki/List-of-plugins-for-incsearch.vim#module-extensions
Type: |list| of |Vital.Over.Commandline-modules|
Default: []
Example: >
let s:pcount = {'name': 'PromptCount'}
function! s:pcount.on_char(cmdline) abort
call a:cmdline.set_prompt(len(a:cmdline.getline()) . '/')
endfunction
function! s:config() abort
return {'modules': [s:pcount]}
endfunction
noremap <expr> z/ incsearch#go(<SID>config())
keymap *incsearch-config-keymap*
Additional keymappings for commandline interface. See also
|g:incsearch_cli_key_mappings|.
Type: |dict|
Default: {}
Example: >
function! s:config() abort
return {
\ 'keymap': {
\ "\<Tab>": {
\ 'key': '<Over>(buffer-complete)',
\ 'noremap': 1
\ },
\ "\<C-j>": "\<CR>"
\ }
\ }
endfunction
noremap <expr> z/ incsearch#go(<SID>config())
converters *incsearch-config-converters*
The list of pattern converters to add internal additional patterns to
search. Converters is |Funcref| or converter object (|Dictionary| with a
|Dictionary-function| named "convert" right now). The converter
feature is experimental, so converter objects will have to have more
required methods or fields later.
Converter Feature~
incsearch.vim calls the list of convert functions with pattern. The
patterns don't contain |search-offset| nor search command(|/|, |?|).
The convert functions should return valid |regular-expression| and
incsearch.vim use their returned patterns in addition to the default
input pattern as |regular-expression| to search.
The list of converter extensions:
https://github.com/haya14busa/incsearch.vim/wiki/List-of-plugins-for-incsearch.vim#converter-extensions
Type: |list| of converter
Default: []
Example: >
function! s:noregexp(pattern) abort
return '\V' . escape(a:pattern, '\')
endfunction
function! s:config() abort
return {'converters': [function('s:noregexp')]}
endfunction
noremap <silent><expr> z/ incsearch#go(<SID>config())
==============================================================================
KNOWN ISSUES *incsearch-issues*
Issues
https://github.com/haya14busa/incsearch.vim/issues
==============================================================================
CHANGELOG *incsearch-changelog*
Version 2.0~
2.0.1 2015-10-31
1. Fix can't turn off |g:incsearch#consistent_n_direction|. ref: #95
2. Fix ? pattern handling for backward search. ref: #92
2.0.0 2015-07-06
1. |incsearch#go()| and |incsearch-config| as a API
2. Pattern converter feature |incsearch-config-converters|
3. Injection of vital-over module |incsearch-config-modules|
4. External extention plugins like fuzzy, easymotion, migemo...
- https://github.com/haya14busa/incsearch.vim/wiki/List-of-plugins-for-incsearch.vim
1.2.1 2015-06-26
1. Add |incsearch-config-keymap| option to |incsearch-config|
2. Some refactoring
1.2.0 2015-06-06
1. Now, fix unexpected key input with |feedkeys()| by auto-nohlsearch
feature (|incsearch-additional-usage|) #82
2. Avoid Unneeded loading for mappings like |<Plug>(incsearch-nohl)|
related with #81
3. Fix |nowrapscan| handling #83
4. Add |incsearch-config-prompt| option
5. auto-nohlsearch on |CursorMoved| after |InsertLeave| related with #80
6. Some refactoring
1.1.0 2015-05-03
1. Add experimental API |incsearch-api|.
- Now you can pass a default pattern |incsearch-config-pattern|
- Use |incsearch#cli()| with |incsearch-autocmd| to extend
incsearch.vim's search interface
- vim-repeat support if needed |incsearch-config-is_expr|
- You can pass additional vital-over module to connect
|incsearch-config-modules|
1.0.3 2015-05-03
1. Fix 'hlsearch' handling #74
1.0.2 2015-04-16
1. Implement experimental API (undocumented) to access vital-over
command line object
2. Add LiteralInsert module to insert special character literally
- e.g. <C-v><Tab> now inserts literal <Tab> and search them.
3. Add workaround pasting issue for MacVim #35
4. Fix to redraw commandline when leaving with <Esc> #67
5. Fix <SID> handling for <expr> mappings #51
6. Fix flicker at entering incsearch's commands #73
1.0.1 2015-01-04
1. Fix keymapping escape
2. Fix |last-pattern| with |g:incsearch#magic|
Version 1.0~
1.0.0 2014-12-14
1. Improve compatibility with default commandline behavior
- Automatically apply mappings defined with |:cnoremap| and |:cmap|
See |g:incsearch#vim_cmdline_keymap|
- Support multi {lhs} and <expr> mappings
2. Support incremental highlighting in other windows.
- See |g:incsearch#no_inc_hlsearch|
3. Add |<Over>(buffer-complete-prev)|
4. Add |IncsearchExecute| event
5. Implement |:digraph| feature
6. Fix minor problems.
0.9.9 2014-11-17
1. Smart backward word feature. See: |g:incsearch#smart_backward_word|
2. Implement |g:incsearch#vim_cmdline_keymap| option which apply
mappings defined with |:cmap| and |:cnoremap| to custome command line
interface of incsearch.vim
3. Do not highlight annoying patterns which matches everything like
`\v`, `vim\|`, etc..
4. Interactive module management (e.g. |g:incsearch#emacs_like_keymap|)
6. Fix |c_<C-r>_<C-w>| behavoir to be compatible with default one
7. Fix cancel behavior
8. Fix & improve {rhs} handling (after exit mappings, <C-r>=, etc...)
9. Fix minor problems
0.9.8 2014-10-25
1. Handle |last-pattern| incrementally. See: |<Over>(incsearch-next)|
2. Now |c_Ctrl-p| and |c_Ctrl-n| works by default and fix history
behavior to be compatible with default one
3. Fix 'smartcase' flag detection to work with like |\%V| and
repetitive escaped uppercase character like `\V\V`
0.9.7 2014-10-21
1. Minor update. Fix <C-c> interruption, use |\m| instead of |\M|, doc
fix.
0.9.6 2014-10-18
1. Implement improved 'magic' option feature. See: |g:incsearch#magic|
2. Improve highlight option to see the cursor position clearly
- ref: |incsearch-highlight-group|
3. Fix to use |keeppattern|, handle |jumplist| for stay search, and
catch some errors while searching.
4. vim.org debut, yeah!
0.9.5 2014-10-10
1. Implement automatic |:nohlsearch| feature.
- |:nohlsearch| will be called when cursor move after search
execution
- See: |g:incsearch#auto_nohlsearch|
2. Fix case handling with explicit |\C| flag
3. Fix 'hlsearch' handling
4. Fix 'nowrapscan' handling
5. CI with |vimlint.txt|
0.9.4 2014-10-01
1. Improve cursor position while incremental searching
- Now you can see cursor position working with |{offset}| unlike
default 'incsearch'
2. Fix and improve visual selection while incremental searching
3. Fix to ignore search related errors while searching
4. Handle unfolding after search execution
5. Cover more test cases
6. Start CI on windows with AppVeyor in addition to travis
0.9.3 2014-09-28
1. Do not use |:map-<expr>| for normal and visual mode mappings.
- Still use <expr> for operator-pending mappings to support |.|
(dot) repeat without depending on other repeat extention like
vim-repeat
- This change avoid flickering after search and support |:normal|
for |incsearch-autocmd|
2. Implement |g:incsearch#consistent_n_direction|
3. Implement |g:incsearch#do_not_save_error_message_history|
4. Improve stability. More comprehensive testing!
5. Improve scroll feature while searching.
- see: |<Over>(incsearch-scroll-f)| for scroll feature
6. Fix to use given |registers| with |quote| (")
7. Improve and fix some problems
0.9.2 2014-08-25
1. Add test
2. Minor fix: history emulation with |<Plug>(incsearch-stay)|
3. Improve pseud-visual highlight: consider curswant for |visual-block|
4. Minor performance improvement: do not always generate direction
specific patterns
0.9.1 2014-08-15
1. Fix visual highlight
2. Improve cursor moving
- Now, you can move the cursor to the reverse direction
- Scroll-like feature |<Over>(incsearch-scroll-f)| &
|<Over>(incsearch-scroll-b)|
- Handle |wrapscan| option
- Enable cursor moving while |<Plug>(incsearch-stay)|
3. Implement |g:incsearch#separate_highlight| option
0.9.0 2014-08-09
- Init.
1. Incremental highlight for all matched pattern
2. Cursor move while incremental searching like emacs
vim:tw=78:ts=8:ft=help:norl:noet:fen:fdl=0:fdm=marker:

View File

@ -0,0 +1,103 @@
"=============================================================================
" FILE: plugin/incsearch.vim
" AUTHOR: haya14busa
" License: MIT license {{{
" 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.
" }}}
"=============================================================================
scriptencoding utf-8
" Load Once {{{
if expand('%:p') ==# expand('<sfile>:p')
unlet! g:loaded_incsearch
endif
if exists('g:loaded_incsearch')
finish
endif
let g:loaded_incsearch = 1
" }}}
" Saving 'cpoptions' {{{
let s:save_cpo = &cpo
set cpo&vim
" }}}
" <silent>: do not show command in command line
noremap <silent><expr> <Plug>(incsearch-forward) incsearch#go({'command': '/'})
noremap <silent><expr> <Plug>(incsearch-backward) incsearch#go({'command': '?'})
noremap <silent><expr> <Plug>(incsearch-stay) incsearch#go({'command': '/', 'is_stay': 1})
" Apply automatic :h :nohlsearch with :h :autocmd
" NOTE:
" - This mappings doesn't move the cursor, please use this with other
" mappings at the same time.
" - Make sure calling this mapping __before__ moving commands
" e.g. `<Plug>(incsearch-nohl)n` works but `n<Plug>(incsearch-nohl)` doesn't
" work
noremap <expr> <Plug>(incsearch-nohl) incsearch#autocmd#auto_nohlsearch(1)
noremap <expr> <Plug>(incsearch-nohl0) incsearch#autocmd#auto_nohlsearch(0)
noremap <expr> <Plug>(incsearch-nohl2) incsearch#autocmd#auto_nohlsearch(2)
map <Plug>(incsearch-nohl-n) <Plug>(incsearch-nohl)<Plug>(_incsearch-n)
map <Plug>(incsearch-nohl-N) <Plug>(incsearch-nohl)<Plug>(_incsearch-N)
map <Plug>(incsearch-nohl-*) <Plug>(incsearch-nohl)<Plug>(_incsearch-*)
map <Plug>(incsearch-nohl-#) <Plug>(incsearch-nohl)<Plug>(_incsearch-#)
map <Plug>(incsearch-nohl-g*) <Plug>(incsearch-nohl)<Plug>(_incsearch-g*)
map <Plug>(incsearch-nohl-g#) <Plug>(incsearch-nohl)<Plug>(_incsearch-g#)
" These mappings are just alias to default mappings except they won't be
" remapped any more
noremap <expr> <Plug>(_incsearch-n) g:incsearch#consistent_n_direction && !v:searchforward ? 'N' : 'n'
noremap <expr> <Plug>(_incsearch-N) g:incsearch#consistent_n_direction && !v:searchforward ? 'n' : 'N'
noremap <Plug>(_incsearch-*) *
noremap <Plug>(_incsearch-#) #
noremap <Plug>(_incsearch-g*) g*
noremap <Plug>(_incsearch-g#) g#
" CommandLine Mapping {{{
let g:incsearch_cli_key_mappings = get(g:, 'incsearch_cli_key_mappings', {})
function! s:key_mapping(lhs, rhs, noremap) abort
let g:incsearch_cli_key_mappings[a:lhs] = {
\ 'key' : a:rhs,
\ 'noremap' : a:noremap,
\ }
endfunction
function! s:as_keymapping(key) abort
return eval('"' . substitute(escape(a:key, '\"'), '\(<.\{-}>\)', '\\\1', 'g') . '"')
endfunction
command! -nargs=* IncSearchNoreMap
\ call call('s:key_mapping', map([<f-args>], 's:as_keymapping(v:val)') + [1])
command! -nargs=* IncSearchMap
\ call call('s:key_mapping', map([<f-args>], 's:as_keymapping(v:val)') + [0])
"}}}
" Restore 'cpoptions' {{{
let &cpo = s:save_cpo
unlet s:save_cpo
" }}}
" __END__ {{{
" vim: expandtab softtabstop=2 shiftwidth=2
" vim: foldmethod=marker
" }}}

View File

@ -0,0 +1,37 @@
call themis#option('recursive', 1)
" For development
call themis#option('runtimepath', expand('~/.vim/bundle/vital.vim'))
call themis#option('runtimepath', expand('~/.vim/bundle/vital-vimlcompiler'))
call themis#option('runtimepath', expand('~/.vim/bundle/vital-safe-string'))
call themis#option('runtimepath', expand('~/.vim/bundle/vital-power-assert'))
let g:Expect = themis#helper('expect')
call themis#helper('command').with(themis#helper('assert')).with({'Expect': g:Expect})
let g:__vital_power_assert_config = {
\ '__debug__': 1,
\ '__pseudo_throw__': 0,
\ '__max_length__': -1
\ }
" mock
function! incsearch#over#modules#bulk_input_char#make() abort
return {}
endfunction
language C
" Helper Functions:
function! AddLine(str)
put! =a:str
endfunction
function! AddLines(lines)
for line in reverse(deepcopy(a:lines))
put! =line
endfor
endfunction
function! GetPosChar()
return getline('.')[col('.')-1]
endfunction

View File

@ -0,0 +1,50 @@
Describe api.config.keymap
It 'should set injected keymapping'
let map = {'a': 'b'}
let config = {'keymap': map}
let default = incsearch#make().keymapping()
let injected = incsearch#make(config).keymapping()
Assert Equals(injected, extend(copy(default), map))
End
It 'should return copied keymapping dictionary'
let map = {'a': 'b'}
let cli = incsearch#make()
let d = copy(cli.keymapping())
call extend(cli.keymapping(), map)
Assert Equals(cli.keymapping(), d)
End
It 'can override default keymapping'
let map = {"\<Tab>": "\t"}
let config = {'keymap': map}
let default = incsearch#make().keymapping()
let injected = incsearch#make(config).keymapping()
Assert Equals(injected, extend(copy(default), map))
End
It 'should support rich keymapping configuration'
let map = {
\ 'a': {
\ 'key': 'b',
\ 'noremap': 0
\ },
\ 'c': 'd'
\ }
let config = {'keymap': map}
let default = incsearch#make().keymapping()
let injected = incsearch#make(config).keymapping()
Assert Equals(injected, extend(copy(default), map))
End
It 'should not affect other object'
let map = {'a': 'b'}
let config = {'keymap': map}
let cli = incsearch#make(config)
let d = copy(cli.keymapping())
Assert NotEquals(incsearch#make().keymapping(), d)
End
End

View File

@ -0,0 +1,45 @@
Describe api.converter
Before all
function! g:ReturnU(...) abort
return 'U'
endfunction
End
After all
delfunction g:ReturnU
End
Describe converter with case handling
It should not break smartcase detection
let ignorecase_save = &ignorecase
let &ignorecase = 1
let smartcase_save = &smartcase
let &smartcase = 1
try
let config = {'converters': [function('g:ReturnU')]}
let cli = incsearch#make(config)
Assert Match('PatTern', cli._convert('pattern'))
finally
let &ignorecase = ignorecase_save
let &smartcase = smartcase_save
endtry
End
It should care smartcase
let ignorecase_save = &ignorecase
let &ignorecase = 1
let smartcase_save = &smartcase
let &smartcase = 1
try
let config = {'converters': [function('g:ReturnU')]}
let cli = incsearch#make(config)
Assert NotMatch('PatTern', cli._convert('Pattern'))
finally
let &ignorecase = ignorecase_save
let &smartcase = smartcase_save
endtry
End
End
End

View File

@ -0,0 +1,146 @@
Describe autocmd
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(deepcopy(a:lines))
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
:1,$ delete
let s:lines = ['1pattern_a', '2pattern_b', '3pattern_c', '4pattern_d', '5pattern_e']
call s:add_lines(s:lines)
normal! Gddgg0zt
endfunction
Before all
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
call s:reset_buffer()
augroup incsearch-test
autocmd!
augroup END
let g:i = 0
let g:line = ''
End
Before each
:1
normal! zt
silent! autocmd! incsearch-test
" Return to normal mode
exec "normal! \<Esc>"
let g:i = 0
let g:line = ''
End
After all
:1,$ delete
let @/ = ''
unlet g:i
unlet g:line
silent! autocmd! incsearch-test
End
Context IncSearchEnter
It should be called
autocmd incsearch-test User IncSearchEnter :let g:i += 1
exec "normal" "/vimvim\<Esc>"
Assert Equals(g:i, 1)
End
End
Context IncSearchLeave
It should be called
autocmd incsearch-test User IncSearchLeave :let g:i += 1
silent! exec "normal" "/vimvim\<CR>"
Assert Equals(g:i, 1)
End
It should be called with <Esc>
autocmd incsearch-test User IncSearchLeave :let g:i += 1
exec "normal" "/vimvim\<Esc>"
Assert Equals(g:i, 1)
End
It should be called with <C-c>
autocmd incsearch-test User IncSearchLeave :let g:i += 1
exec "normal" "/vimvim\<C-c>"
Assert Equals(g:i, 1)
End
End
Context IncSearchExecutePre
It should be called
autocmd incsearch-test User IncSearchExecutePre :let g:i += 1
silent! exec "normal" "/vimvim\<CR>"
Assert Equals(g:i, 1)
End
It should not be called with <Esc>
autocmd incsearch-test User IncSearchExecutePre :let g:i += 1
exec "normal" "/vimvim\<Esc>"
Assert Equals(g:i, 0)
End
It should not be called with <C-c>
autocmd incsearch-test User IncSearchExecutePre :let g:i += 1
exec "normal" "/vimvim\<C-c>"
Assert Equals(g:i, 0)
End
It should be called before move
autocmd incsearch-test User IncSearchExecutePre :let g:line = getline('.')
silent! exec "normal" "/2pattern_b\<CR>"
let expect = s:lines[0]
Assert Equals(g:line, expect)
let expect2 = s:lines[1]
Assert Equals(getline('.'), expect2)
End
End
Context IncSearchExecute
It should be called
autocmd incsearch-test User IncSearchExecute :let g:i += 1
silent! exec "normal" "/vimvim\<CR>"
Assert Equals(g:i, 1)
End
It should not be called with <Esc>
autocmd incsearch-test User IncSearchExecute :let g:i += 1
exec "normal" "/vimvim\<Esc>"
Assert Equals(g:i, 0)
End
It should not be called with <C-c>
autocmd incsearch-test User IncSearchExecute :let g:i += 1
exec "normal" "/vimvim\<C-c>"
Assert Equals(g:i, 0)
End
It should be called after move
autocmd incsearch-test User IncSearchExecute :let g:line = getline('.')
silent! exec "normal" "/2pattern_b\<CR>"
let expect = s:lines[1]
Assert Equals(g:line, expect)
let expect2 = s:lines[1]
Assert Equals(getline('.'), expect2)
End
End
Context IncSearchCharPre
It should be called
autocmd incsearch-test User IncSearchCharPre :let g:i += 1
silent! exec "normal" "/vimvim\<CR>"
Assert Equals(g:i, 7)
End
End
Context IncSearchChar
It should be called
autocmd incsearch-test User IncSearchChar :let g:i += 1
silent! exec "normal" "/vimvim\<CR>"
Assert Equals(g:i, 7)
End
End
End

View File

@ -0,0 +1,154 @@
let s:suite = themis#suite('autonlsearch')
let s:assert = themis#helper('assert')
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
:1,$ delete
call s:add_lines(['1pattern_a', '2pattern_b', '3pattern_c', '4pattern_d', '5pattern_e'])
normal! G
call s:add_lines(range(100))
normal! Gddgg0zt
endfunction
function! s:suite.before()
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
map n <Plug>(incsearch-nohl-n)
map N <Plug>(incsearch-nohl-N)
map * <Plug>(incsearch-nohl-*)
map # <Plug>(incsearch-nohl-#)
map g* <Plug>(incsearch-nohl-g*)
map g# <Plug>(incsearch-nohl-g#)
call s:reset_buffer()
endfunction
function! s:suite.before_each()
:1
normal! zt
silent! autocmd! incsearch-auto-nohlsearch
let g:incsearch#auto_nohlsearch = 1
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
endfunction
function! s:suite.after()
:1,$ delete
let g:incsearch#auto_nohlsearch = 0
unmap /
unmap ?
unmap g/
" :unmap workaround
noremap n n
noremap N N
noremap * *
noremap # #
noremap g* g*
noremap g# g#
unmap n
unmap N
unmap *
unmap #
unmap g*
unmap g#
endfunction
function! s:suite.function_works()
let g:incsearch#auto_nohlsearch = 0
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
call incsearch#autocmd#auto_nohlsearch(1)
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
let g:incsearch#auto_nohlsearch = 1
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
call incsearch#autocmd#auto_nohlsearch(1)
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
endfunction
function! s:suite.nolsearch_with_cursormove_0()
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
call incsearch#autocmd#auto_nohlsearch(0)
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
doautocmd CursorMoved
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
endfunction
function! s:suite.nolsearch_with_cursormove_1()
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
call incsearch#autocmd#auto_nohlsearch(1)
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
doautocmd CursorMoved
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
doautocmd CursorMoved
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
endfunction
function! s:suite.nolsearch_with_cursormove_2()
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
call incsearch#autocmd#auto_nohlsearch(2)
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
doautocmd CursorMoved
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
doautocmd CursorMoved
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
doautocmd CursorMoved
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
endfunction
function! s:suite.nolsearch_with_insert_enter()
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
call incsearch#autocmd#auto_nohlsearch(10)
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
call s:assert.equals(exists('#incsearch-auto-nohlsearch#InsertEnter'), 1)
call s:assert.equals(exists('#incsearch-auto-nohlsearch#InsertLeave'), 0, 'do not set InsertLeave until InsertEnter')
doautocmd InsertEnter
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
call s:assert.equals(exists('#incsearch-auto-nohlsearch-on-insert-leave#InsertLeave'), 1)
doautocmd InsertLeave
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1, 'trigger auto nohlsearch again')
call s:assert.equals(exists('#incsearch-auto-nohlsearch-on-insert-leave#InsertLeave'), 0, 'remove insert leave')
doautocmd CursorMoved
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
doautocmd CursorMoved
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
call s:assert.equals(exists('#incsearch-auto-nohlsearch-on-insert-leave#InsertLeave'), 0)
endfunction
function! s:suite.work_with_search()
for key in ['/', '?', 'g/']
silent! autocmd! incsearch-auto-nohlsearch
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
exec "normal" key . "pattern\<CR>"
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
endfor
endfunction
function! s:suite.work_with_search_offset()
for key in ['/', '?', 'g/']
silent! autocmd! incsearch-auto-nohlsearch
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
exec "silent! normal" key . "pattern/e\<CR>"
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
endfor
endfunction
function! s:suite.work_with_other_search_mappings()
for key in ['n', 'N', '*', '#', 'g*', 'g#']
autocmd! incsearch-auto-nohlsearch
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
exec "silent! normal!" key
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 0)
exec "silent! normal" key
call s:assert.equals(exists('#incsearch-auto-nohlsearch#CursorMoved'), 1)
endfor
endfunction

View File

@ -0,0 +1,153 @@
let s:suite = themis#suite('cancel')
let s:assert = themis#helper('assert')
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(deepcopy(a:lines))
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
:1,$ delete
let s:lines = ['1pattern_a', '2pattern_b', '3pattern_c', '4pattern_d', '5pattern_e']
call s:add_lines(s:lines)
normal! Gddgg0zt
endfunction
function! s:suite.before()
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
call s:reset_buffer()
endfunction
function! s:suite.before_each()
:1
normal! zt
" Return to normal mode
exec "normal! \<Esc>"
endfunction
function! s:suite.after()
:1,$ delete
let @/ = ''
endfunction
function! s:suite.cancel_forward_does_not_move_cursor()
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "/\\dpattern_./e\<C-c>"
call s:assert.not_equals(s:get_pos_char(), 'a')
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "/\\dpattern_./e\<Esc>"
call s:assert.not_equals(s:get_pos_char(), 'a')
call s:assert.equals(s:get_pos_char(), '1')
endfunction
function! s:suite.cancel_backward_does_not_move_cursor()
:$
normal! $
call s:assert.equals(s:get_pos_char(), 'e')
exec "normal" "?\\dpattern_d?e\<C-c>"
call s:assert.not_equals(s:get_pos_char(), 'd')
call s:assert.equals(s:get_pos_char(), 'e')
endfunction
function! s:suite.cancel_stay_does_not_move_cursor()
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "g/\\dpattern_./e\<Tab>\<C-c>"
call s:assert.not_equals(s:get_pos_char(), 'a')
call s:assert.equals(s:get_pos_char(), '1')
endfunction
function! s:suite.cancel_forward_operator_pending()
exec "normal" "d/\\dpattern_./e\<C-c>"
call s:assert.equals(getline('.'), s:lines[0])
endfunction
function! s:suite.cancel_backward_operator_pending()
:$
normal! $
exec "normal" "d?\\dpattern_d?e\<C-c>"
call s:assert.equals(getline('.'), s:lines[-1])
endfunction
function! s:suite.cancel_stay_operator_pending()
exec "normal" "dg/\\dpattern_./e\<Tab>\<C-c>"
call s:assert.equals(getline('.'), s:lines[0])
endfunction
function! s:suite.cancel_forward_visual()
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "vl/\\dpattern_./e\<C-c>"
call s:assert.not_equals(s:get_pos_char(), 'a')
call s:assert.equals(s:get_pos_char(), 'p')
call s:assert.equals(mode(1), 'v')
endfunction
function! s:suite.cancel_backward_visual()
:$
normal! $
call s:assert.equals(s:get_pos_char(), 'e')
exec "normal" "vh?\\dpattern_d?e\<C-c>"
call s:assert.not_equals(s:get_pos_char(), 'd')
call s:assert.equals(s:get_pos_char(), '_')
call s:assert.equals(getline('.'), s:lines[-1])
endfunction
function! s:suite.cancel_stay_visual()
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "vl/\\dpattern_./e\<Tab>\<C-c>"
call s:assert.not_equals(s:get_pos_char(), 'a')
call s:assert.equals(s:get_pos_char(), 'p')
call s:assert.equals(mode(1), 'v')
endfunction
function! s:suite.cancel_will_not_change_last_pattern()
for key_seq in ['/', '?', 'g/']
let p = 'vim: ' . key_seq
let @/ = p
exec "normal" key_seq . "pattern\<Tab>\<C-c>"
call s:assert.equals(@/, p)
endfor
endfunction
function! s:suite.highlight_will_not_remain()
for key_seq in ['/', '?', 'g/']
exec "normal" key_seq . "pattern\<Tab>\<C-c>"
call s:assert.equals(getmatches(), [])
endfor
endfunction
function! s:suite.default_highlight_will_not_remain()
if !exists('v:hlsearch')
call s:assert.skip("Skip because vim version are too low to test it")
endif
set hlsearch | nohlsearch
let v:hlsearch = 0
for key_seq in ['/', '?', 'g/']
exec "normal" key_seq . "pattern\<Tab>\<C-c>"
call s:assert.equals(v:hlsearch, 0)
endfor
set hlsearch& | nohlsearch
endfunction
function! s:suite.preserve_vhlsearch_with_esc()
if !exists('v:hlsearch')
call s:assert.skip("Skip because vim version are too low to test it")
endif
set hlsearch
for keyseq in ['/', '?', 'g/']
let v:hlsearch = 1
exec "normal" keyseq . "pattern\<Esc>"
call s:assert.equals(v:hlsearch, 1)
endfor
set hlsearch& | nohlsearch
endfunction

View File

@ -0,0 +1,97 @@
let s:suite = themis#suite('count')
let s:assert = themis#helper('assert')
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
normal! ggdG
call s:add_lines(['1pattern_a', '2pattern_b', '3pattern_c', '4pattern_d', '5pattern_e'])
normal! Gddgg0zt
endfunction
function! s:suite.before_each()
call s:reset_buffer()
endfunction
function! s:suite.forward_normal()
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "2/\\dpattern\<CR>"
call s:assert.equals(s:get_pos_char(), '3')
exec "normal" "2/\\dpattern_[a-z]/e\<CR>"
call s:assert.equals(s:get_pos_char(), 'd')
endfunction
function! s:suite.forward_visual()
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "v2/\\dpattern\<CR>\<Esc>"
call s:assert.equals(s:get_pos_char(), '3')
exec "normal" "v2/\\dpattern_[a-z]/e\<CR>\<Esc>"
call s:assert.equals(s:get_pos_char(), 'd')
endfunction
function! s:suite.forward_operator_pending()
call s:reset_buffer() " XXX: ???
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "2d/\\dpattern\<CR>"
call s:assert.equals(s:get_pos_char(), '3')
call s:assert.equals(getline('.'), '3pattern_c')
exec "normal" "2d/\\dpattern_/e\<CR>"
call s:assert.equals(getline('.'), 'd')
endfunction
function! s:suite.forward_operator_pending_multiply()
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "2d2/\\dpattern\<CR>"
call s:assert.equals(s:get_pos_char(), '5')
call s:assert.equals(getline('.'), '5pattern_e')
endfunction
function! s:suite.backward_normal()
call s:assert.equals(s:get_pos_char(), '1')
normal! G$
call s:assert.equals(s:get_pos_char(), 'e')
call s:assert.equals(line('.'), 5)
call s:assert.equals(getline('.'), '5pattern_e')
exec "normal" "2?\\dpattern\<CR>"
call s:assert.equals(s:get_pos_char(), '4')
endfunction
function! s:suite.backward_visual()
call s:assert.equals(s:get_pos_char(), '1')
normal! G$
call s:assert.equals(s:get_pos_char(), 'e')
exec "normal" "v2?\\dpattern\<CR>\<Esc>"
call s:assert.equals(s:get_pos_char(), '4')
endfunction
function! s:suite.backward_operator_pending()
normal! G$
call s:assert.equals(s:get_pos_char(), 'e')
exec "normal" "d2?\\dpattern_[a-z]\<CR>"
call s:assert.equals(getline('.'), 'e')
exec "normal" "d2?\\dpattern_[a-z]?e\<CR>"
call s:assert.equals(s:get_pos_char(), '_')
call s:assert.equals(getline('.'), '2pattern_')
endfunction
function! s:suite.backward_operator_pending_multiply()
normal! G$
exec "normal" "2d2?\\dpattern_[a-z]?e\<CR>"
call s:assert.equals(s:get_pos_char(), '_')
call s:assert.equals(getline('.'), '1pattern_')
endfunction

View File

@ -0,0 +1,168 @@
let s:suite = themis#suite('default_behaviors')
let s:assert = themis#helper('assert')
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:assert.eq_with_default(command, default_command, pattern)
let [x, y] = s:get_pos_with_default(a:command, a:default_command, a:pattern)
call s:assert.equals(x,y)
endfunction
function! s:assert.not_eq_with_default(command, default_command, pattern)
let [x, y] = s:get_pos_with_default(a:command, a:default_command, a:pattern)
call s:assert.not_equals(x,y)
endfunction
function! s:get_pos_with_default(command, default_command, pattern)
let w = winsaveview()
silent! exec 'normal! ' . a:default_command . a:pattern . "\<CR>"
" let x = getcurpos()
let x = winsaveview()
call winrestview(w)
silent! exec 'normal ' . a:command . a:pattern . "\<CR>"
" let y = getcurpos()
let y = winsaveview()
return [x, y]
endfunction
function! s:is_pos_less_equal(x, y) " x <= y
return (a:x[0] == a:y[0]) ? a:x[1] <= a:y[1] : a:x[0] < a:y[0]
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
:1,$ delete
call s:add_lines(copy(s:line_texts))
normal! Gddgg0zt
endfunction
function! s:suite.before()
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
let s:line_texts = [
\ 'pattern1 pattern2 pattern3'
\ , 'pattern4 pattern5 pattern6'
\ ]
call s:reset_buffer()
endfunction
function! s:suite.before_each()
:1
endfunction
function! s:suite.after()
unmap /
unmap ?
unmap g/
:1,$ delete
set wrapscan&
endfunction
" Main:
function! s:suite.forward()
set nowrapscan
call s:assert.eq_with_default('/','/','pat')
call s:assert.eq_with_default('/','/','pattern\d')
normal! gg0
call s:assert.eq_with_default('/','/','pattern1')
call s:assert.eq_with_default('/','/','pattern2')
call s:assert.eq_with_default('/','/','pattern3')
set wrapscan
normal! gg0
call s:assert.eq_with_default('/','/','pattern2')
call s:assert.eq_with_default('/','/','pattern1')
" Handle empty input
normal! gg0
call s:assert.eq_with_default('/','/','pat')
let x = getpos('.')
call s:assert.eq_with_default('/','/','')
let y = getpos('.')
call s:assert.not_equals(x, y)
call s:assert.true(s:is_pos_less_equal(x, y))
endfunction
function! s:suite.backward()
set nowrapscan
normal! G$
call s:assert.eq_with_default('?','?','pattern3')
call s:assert.eq_with_default('?','?','pattern2')
call s:assert.eq_with_default('?','?','pattern1')
normal! G$
call s:assert.not_eq_with_default('?','/','pattern3')
call s:assert.not_eq_with_default('?','/','pattern2')
call s:assert.not_eq_with_default('?','/','pattern1')
set wrapscan
normal! gg0
call s:assert.eq_with_default('?','?','pattern5')
call s:assert.eq_with_default('?','/','pattern5')
" Handle empty input
normal! G$
call s:assert.eq_with_default('?','?','pat')
let x = getpos('.')[1:2]
call s:assert.eq_with_default('?','?','')
let y = getpos('.')[1:2]
call s:assert.not_equals(x, y)
call s:assert.true(s:is_pos_less_equal(y, x))
endfunction
function! s:suite.stay()
set nowrapscan
normal! gg0
" let c = getcurpos()
let c = winsaveview()
call s:assert.not_eq_with_default('g/','/','pat')
" call s:assert.equals(getcurpos(), c)
call s:assert.equals(winsaveview(), c)
set wrapscan
call s:assert.not_eq_with_default('g/','/','pat')
" call s:assert.equals(getcurpos(), c)
call s:assert.equals(winsaveview(), c)
" History
exec "normal g/hoge\<CR>"
call s:assert.equals('hoge', @/)
call s:assert.equals('hoge', histget('/', -1))
" Handle empty input
normal! gg0
call s:assert.not_eq_with_default('g/','/','pat')
let x = getpos('.')
call s:assert.not_eq_with_default('g/','/','')
let y = getpos('.')
call s:assert.equals(x, y)
call s:assert.not_equals('', @/)
call s:assert.not_equals('', histget('/', -1))
call s:assert.equals('pat', @/)
call s:assert.equals('pat', histget('/', -1))
endfunction
function! s:suite.offset()
normal! gg0
call s:assert.eq_with_default('/','/','pattern1/e')
call s:assert.equals(s:get_pos_char(), '1')
call s:assert.eq_with_default('?','?','pat?e5+1')
call s:assert.equals(s:get_pos_char(), '6')
exec "normal g/pattern\\d/e\<CR>"
call s:assert.equals(@/, 'pattern\d')
call s:assert.equals(histget('/', -1), 'pattern\d/e')
endfunction

View File

@ -0,0 +1,88 @@
let s:suite = themis#suite('default_settings')
let s:assert = themis#helper('assert')
function! s:suite.loaded()
call s:assert.exists('g:loaded_incsearch')
call s:assert.equals(g:loaded_incsearch, 1)
endfunction
function! s:suite.config()
call s:assert.equals(g:incsearch_cli_key_mappings, {})
call s:assert.equals(g:incsearch#emacs_like_keymap, 0)
call s:assert.equals(g:incsearch#highlight, {})
call s:assert.equals(g:incsearch#separate_highlight, 0)
call s:assert.equals(g:incsearch#consistent_n_direction, 0)
call s:assert.equals(g:incsearch#vim_cmdline_keymap, 1)
call s:assert.equals(g:incsearch#smart_backward_word, 1)
call s:assert.equals(g:incsearch#do_not_save_error_message_history, 0)
call s:assert.equals(g:incsearch#auto_nohlsearch, 0)
call s:assert.equals(g:incsearch#magic, '')
call s:assert.equals(g:incsearch#no_inc_hlsearch, 0)
endfunction
function! s:suite.mappings()
" Main:
call s:assert.equals(maparg('<Plug>(incsearch-forward)' , 'nvo'), "incsearch#go({'command': '/'})")
call s:assert.equals(maparg('<Plug>(incsearch-backward)', 'nvo'), "incsearch#go({'command': '?'})")
call s:assert.equals(maparg('<Plug>(incsearch-stay)' , 'nvo'), "incsearch#go({'command': '/', 'is_stay': 1})")
" Additional:
call s:assert.equals(maparg('<Plug>(incsearch-nohl)', 'nvo'), 'incsearch#autocmd#auto_nohlsearch(1)')
call s:assert.equals(maparg('<Plug>(incsearch-nohl0)', 'nvo'), 'incsearch#autocmd#auto_nohlsearch(0)')
call s:assert.equals(maparg('<Plug>(incsearch-nohl-n)' , 'nvo'), '<Plug>(incsearch-nohl)<Plug>(_incsearch-n)')
call s:assert.equals(maparg('<Plug>(incsearch-nohl-N)' , 'nvo'), '<Plug>(incsearch-nohl)<Plug>(_incsearch-N)')
call s:assert.equals(maparg('<Plug>(incsearch-nohl-*)' , 'nvo'), '<Plug>(incsearch-nohl)<Plug>(_incsearch-*)')
call s:assert.equals(maparg('<Plug>(incsearch-nohl-#)' , 'nvo'), '<Plug>(incsearch-nohl)<Plug>(_incsearch-#)')
call s:assert.equals(maparg('<Plug>(incsearch-nohl-g*)', 'nvo'), '<Plug>(incsearch-nohl)<Plug>(_incsearch-g*)')
call s:assert.equals(maparg('<Plug>(incsearch-nohl-g#)', 'nvo'), '<Plug>(incsearch-nohl)<Plug>(_incsearch-g#)')
" Alias To The Default:
call s:assert.equals(maparg('<Plug>(_incsearch-n)' , 'nvo'), 'g:incsearch#consistent_n_direction && !v:searchforward ? ''N'' : ''n''')
call s:assert.equals(maparg('<Plug>(_incsearch-N)' , 'nvo'), 'g:incsearch#consistent_n_direction && !v:searchforward ? ''n'' : ''N''')
call s:assert.equals(maparg('<Plug>(_incsearch-*)' , 'nvo'), '*')
call s:assert.equals(maparg('<Plug>(_incsearch-#)' , 'nvo'), '#')
call s:assert.equals(maparg('<Plug>(_incsearch-g*)', 'nvo'), 'g*')
call s:assert.equals(maparg('<Plug>(_incsearch-g#)', 'nvo'), 'g#')
endfunction
function! s:suite.command_exist()
augroup incsearch-themis
autocmd!
autocmd VimEnter call s:assert.exists('IncSearchNoreMap')
autocmd VimEnter call s:assert.exists('IncSearchMap')
augroup END
endfunction
function! s:suite.highlight()
call s:assert.equals(hlexists('IncSearchMatch') , 1)
call s:assert.equals(hlexists('IncSearchMatchReverse') , 1)
call s:assert.equals(hlexists('IncSearchCursor') , 1)
call s:assert.equals(hlexists('IncSearchOnCursor') , 1)
call s:assert.equals(hlexists('IncSearchUnderline') , 1)
endfunction
function! s:suite.test_autoload_function()
try
" load autoload functions
runtime autoload/*.vim
catch
endtry
call s:assert.exists('*incsearch#go')
call s:assert.exists('*incsearch#_go')
call s:assert.exists('*incsearch#parse_pattern')
endfunction
function! s:suite.is_duplicate_helptags()
helptags ./doc
endfunction
" https://github.com/haya14busa/incsearch.vim/issues/69
function! s:suite.handle_keymapping_option()
call s:assert.equals(g:incsearch_cli_key_mappings, {})
let d = copy(incsearch#make().keymapping())
try
let g:incsearch_cli_key_mappings['a'] = 'b'
call s:assert.equals(incsearch#make().keymapping(), extend(copy(d), {'a': 'b'}))
finally
unlet g:incsearch_cli_key_mappings['a']
endtry
call s:assert.equals(incsearch#make().keymapping(), d)
endfunction

View File

@ -0,0 +1,247 @@
scriptencoding utf-8
let s:suite = themis#suite('error_warning_emulation')
let s:assert = themis#helper('assert')
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
" NOTE:
" :h v:errmsg
" :h v:warningmsg
function! s:reset_buffer()
:1,$ delete
call s:add_lines(copy(s:line_texts))
normal! Gddgg0zt
endfunction
function! s:suite.before()
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
let s:line_texts = ['1pattern', '2pattern', '3pattern', '4pattern']
call s:reset_buffer()
endfunction
function! s:suite.after()
unmap /
unmap ?
unmap g/
:1,$ delete
set wrapscan&
endfunction
function! s:suite.before_each()
:1
set wrapscan&
endfunction
function! s:suite.after_each()
set wrapscan&
endfunction
function! s:suite.error_forward_backward()
for keyseq in ['/', '?']
normal! gg0
let v:errmsg = 'old errormsg'
call s:assert.equals(s:get_pos_char(), '1')
normal! j
call s:assert.equals(s:get_pos_char(), '2')
" silent! exec "normal" keyseq . "びむぅぅぅぅ\<CR>"
" call s:assert.equals(v:errmsg, 'E486: Pattern not found: びむぅぅぅぅ')
silent! exec "normal" keyseq . "bbb\<CR>"
call s:assert.equals(v:errmsg, 'E486: Pattern not found: bbb')
" feedkeys()
silent! exec "normal" keyseq . "aaa" . keyseq . "e\<CR>"
call s:assert.equals(v:errmsg, 'E486: Pattern not found: aaa')
" silent! exec "normal" keyseq . "びむぅぅぅぅ\\(\<CR>"
silent! exec "normal" keyseq . "pattern\\(\<CR>"
call s:assert.equals(v:errmsg, 'E54: Unmatched \(')
silent! exec "normal" keyseq . "pattern\\)\<CR>"
call s:assert.equals(v:errmsg, 'E55: Unmatched \)')
silent! exec "normal" keyseq . "bbb\\zA\<CR>"
call s:assert.equals(v:errmsg, 'E68: Invalid character after \z')
endfor
endfunction
function! s:suite.error_stay()
let v:errmsg = 'old errormsg'
call s:assert.equals(s:get_pos_char(), '1')
normal! j
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "g/びむぅぅぅぅ\<CR>"
call s:assert.equals(v:errmsg, 'E486: Pattern not found: びむぅぅぅぅ')
" feedkeys()
silent! exec "normal" "g/aaa/e\<CR>"
call s:assert.equals(v:errmsg, 'E486: Pattern not found: aaa')
exec "normal" "g/びむぅぅぅぅ\\(\<CR>"
call s:assert.equals(v:errmsg, 'E54: Unmatched \(')
exec "normal" "g/びむぅぅぅぅ\\)\<CR>"
call s:assert.equals(v:errmsg, 'E55: Unmatched \)')
exec "normal" "g/びむぅぅぅぅ\\zA\<CR>"
call s:assert.equals(v:errmsg, 'E68: Invalid character after \z')
endfunction
function! s:suite.two_error_E383_and_E367()
if ! exists('&regexpengine')
call s:assert.skip("Skip because vim version are too low to test it")
endif
" NOTE: incsearch doesn't support more than three errors unfortunately
let g:incsearch#do_not_save_error_message_history = 0
let v:errmsg = ''
exec "normal" "/びむぅぅぅぅ\\zA\<CR>"
let save_verbose = &verbose
let &verbose = 0
try
redir => messages_text
messages
redir END
finally
let &verbose = save_verbose
endtry
let errmsgs = reverse(split(messages_text, "\n"))
call s:assert.equals(v:errmsg, 'E68: Invalid character after \z')
call s:assert.equals(errmsgs[0], 'E68: Invalid character after \z')
call s:assert.equals(errmsgs[1], "E867: (NFA) Unknown operator '\\zA'")
let g:incsearch#do_not_save_error_message_history = 1
endfunction
function! s:suite.nowrapscan_forward_error()
set nowrapscan
let v:errmsg = 'old errormsg'
call s:assert.equals(s:get_pos_char(), '1')
normal! j
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "/1pattern\<CR>"
call s:assert.equals(v:errmsg, 'E385: search hit BOTTOM without match for: 1pattern')
exec "normal" "/aaa\<CR>"
call s:assert.equals(v:errmsg, 'E385: search hit BOTTOM without match for: aaa')
silent! exec "normal" "/aaa/e\<CR>"
call s:assert.equals(v:errmsg, 'E385: search hit BOTTOM without match for: aaa')
endfunction
function! s:suite.nowrapscan_backward_error()
set nowrapscan
normal! G
let v:errmsg = 'old errormsg'
call s:assert.equals(s:get_pos_char(), '4')
normal! k
call s:assert.equals(s:get_pos_char(), '3')
exec "normal" "?4pattern\<CR>"
call s:assert.equals(v:errmsg, 'E384: search hit TOP without match for: 4pattern')
exec "normal" "?aaa\<CR>"
call s:assert.equals(v:errmsg, 'E384: search hit TOP without match for: aaa')
silent! exec "normal" "?aaa?e\<CR>"
call s:assert.equals(v:errmsg, 'E384: search hit TOP without match for: aaa')
endfunction
function! s:suite.nowrapscan_stay_error()
set nowrapscan
let v:errmsg = 'old errormsg'
call s:assert.equals(s:get_pos_char(), '1')
normal! j
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "g/1pattern\<CR>"
call s:assert.equals(v:errmsg, 'E385: search hit BOTTOM without match for: 1pattern')
exec "normal" "g/aaa\<CR>"
call s:assert.equals(v:errmsg, 'E385: search hit BOTTOM without match for: aaa')
silent! exec "normal" "g/aaa/e\<CR>"
call s:assert.equals(v:errmsg, 'E385: search hit BOTTOM without match for: aaa')
endfunction
function! s:suite.E888__multi_after_zs_and_ze()
" Vim will crash with version 7.4 under 421
" http://ftp.vim.org/vim/patches/7.4/7.4.421
if v:version == 704 && !has('patch421')
" Vim will clash!
" exec "normal" "/emacs\\ze*vim\<CR>"
elseif v:version == 704 && has('patch421')
set regexpengine=2
let v:errmsg = ''
exec "normal" "/emacs\\ze*vim\<CR>"
" call s:assert.equals(v:errmsg, 'E888: (NFA regexp) cannot repeat \ze')
call s:assert.match(v:errmsg, 'E888: (NFA regexp) cannot repeat')
let v:errmsg = ''
set regexpengine&
elseif v:version == 703
exec "normal" "/emacs\\ze*vim\<CR>"
endif
endfunction
" Warning
function! s:suite.warning_forward()
set wrapscan
let v:warningmsg = 'old warning'
call s:assert.equals(s:get_pos_char(), '1')
normal! j
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "/3pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '3')
call s:assert.equals(v:warningmsg, 'old warning')
exec "normal" "/1pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '1')
call s:assert.equals(v:warningmsg, 'search hit BOTTOM, continuing at TOP')
endfunction
function! s:suite.warning_backward()
set wrapscan
normal! G
let v:warningmsg = 'old warning'
call s:assert.equals(s:get_pos_char(), '4')
normal! k
call s:assert.equals(s:get_pos_char(), '3')
exec "normal" "?2pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
call s:assert.equals(v:warningmsg, 'old warning')
exec "normal" "?4pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '4')
call s:assert.equals(v:warningmsg, 'search hit TOP, continuing at BOTTOM')
endfunction
function! s:suite.do_not_show_search_hit_TOP_or_BOTTOM_warning_with_stay()
let g:incsearch#do_not_save_error_message_history = 1
set wrapscan
let v:warningmsg = 'old warning'
call s:assert.equals(s:get_pos_char(), '1')
normal! j
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "g/3pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
call s:assert.equals(v:warningmsg, 'old warning')
exec "normal" "g/1pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
call s:assert.equals(v:warningmsg, 'old warning')
let g:incsearch#do_not_save_error_message_history = 0
endfunction
function! s:suite.handle_shortmess()
" :h shortmess
set shortmess+=s
set wrapscan
call s:assert.match(&shortmess, 's')
let v:warningmsg = 'old warning'
call s:assert.equals(s:get_pos_char(), '1')
normal! j
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "/3pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '3')
call s:assert.equals(v:warningmsg, 'old warning')
exec "normal" "/1pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '1')
call s:assert.equals(v:warningmsg, 'old warning')
set shortmess&
endfunction

View File

@ -0,0 +1,160 @@
let s:suite = themis#suite('fold')
let s:assert = themis#helper('assert')
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:reset_buffer()
:1,$ delete
call s:add_lines(copy(s:line_texts))
normal! Gddgg0zt
endfunction
function! s:suite.before()
set foldmethod=marker
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
let s:line_texts = [
\ '1'
\ , '2'
\ , '3'
\ , '4fold {{{'
\ , '5 inner fold {{{'
\ , '6 destination'
\ , '7 }}}'
\ , '8}}}'
\ ]
call s:reset_buffer()
endfunction
function! s:suite.before_each()
:1
normal! zM
call s:assert.equals(foldclosed(6), 4)
endfunction
function! s:suite.after()
unmap /
unmap ?
unmap g/
:1,$ delete
set foldmethod&
endfunction
function! s:suite.unfold_after_search_forward_backward()
exec "normal" "/destination\<CR>"
call s:assert.equals(foldclosed(6), -1)
endfunction
function! s:suite.unfold_after_search_forward_offset()
exec "normal" "/destination/e\<CR>"
call s:assert.equals(foldclosed(6), -1)
endfunction
function! s:suite.unfold_after_search_backward()
exec "normal" "?destination\<CR>"
call s:assert.equals(foldclosed(6), -1)
endfunction
function! s:suite.unfold_after_search_backward()
exec "normal" "?destination?e\<CR>"
call s:assert.equals(foldclosed(6), -1)
endfunction
function! s:suite.do_not_unfold_after_just_stay()
exec "normal" "g/destination\<CR>"
call s:assert.equals(foldclosed(6), 4)
exec "normal" "g/destination/e\<CR>"
call s:assert.equals(foldclosed(6), 4)
endfunction
function! s:suite.unfold_after_exit_stay()
exec "normal" "g/destination\<Tab>\<CR>"
call s:assert.equals(foldclosed(6), -1)
endfunction
function! s:suite.unfold_after_exit_stay_offset()
exec "normal" "g/destination/e\<Tab>\<CR>"
call s:assert.equals(foldclosed(6), -1)
endfunction
function! s:suite.do_not_unfold_if_foldopen_does_not_contain_search()
set foldopen-=search
call s:assert.equals(foldclosed(6), 4)
exec "normal" "/destination\<CR>"
call s:assert.equals(foldclosed(6), 4)
normal! gg
exec "normal" "/destination/e\<CR>"
call s:assert.equals(foldclosed(6), 4)
normal! gg
exec "normal" "?destination\<CR>"
call s:assert.equals(foldclosed(6), 4)
normal! gg
exec "normal" "?destination?e\<CR>"
call s:assert.equals(foldclosed(6), 4)
normal! gg
exec "normal" "g/destination\<Tab>\<CR>"
call s:assert.equals(foldclosed(6), 4)
normal! gg
exec "normal" "g/destination/e\<Tab>\<CR>"
call s:assert.equals(foldclosed(6), 4)
normal! gg
set foldopen&
endfunction
function! s:suite.unfold_if_foldopen_does_contain_all()
set foldopen=all
call s:assert.equals(foldclosed(6), 4)
exec "normal" "/destination\<CR>"
call s:assert.equals(foldclosed(6), -1)
normal! ggzM
exec "normal" "/destination/e\<CR>"
call s:assert.equals(foldclosed(6), -1)
normal! ggzM
exec "normal" "?destination\<CR>"
call s:assert.equals(foldclosed(6), -1)
normal! ggzM
exec "normal" "?destination?e\<CR>"
call s:assert.equals(foldclosed(6), -1)
normal! ggzM
exec "normal" "g/destination\<Tab>\<CR>"
call s:assert.equals(foldclosed(6), -1)
normal! ggzM
exec "normal" "g/destination/e\<Tab>\<CR>"
call s:assert.equals(foldclosed(6), -1)
normal! ggzM
set foldopen&
endfunction
function! s:suite.do_not_unfold_when_operator_pending()
set foldopen&
call s:assert.equals(foldclosed(6), 4)
exec "normal" "gu/destination\<CR>"
call s:assert.equals(foldclosed(6), 4)
normal! gg
exec "normal" "gu/destination/e\<CR>"
call s:assert.equals(foldclosed(6), 4)
normal! gg
exec "normal" "gu?destination\<CR>"
call s:assert.equals(foldclosed(6), 4)
normal! gg
exec "normal" "gu?destination?e\<CR>"
call s:assert.equals(foldclosed(6), 4)
normal! gg
exec "normal" "gug/destination\<Tab>\<CR>"
call s:assert.equals(foldclosed(6), 4)
normal! gg
exec "normal" "gug/destination/e\<Tab>\<CR>"
call s:assert.equals(foldclosed(6), 4)
endfunction

View File

@ -0,0 +1,156 @@
let s:suite = themis#suite('highlight')
let s:assert = themis#helper('assert')
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
:1,$ delete
call s:add_lines(s:line_texts)
normal! Gddgg0zt
endfunction
function! s:suite.before()
set wrapscan&
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
let s:line_texts = ['1pattern_a', '2pattern_b', '3pattern_c', '4pattern_d', '5pattern_e']
call s:reset_buffer()
endfunction
function! s:suite.after()
:1,$ delete
endfunction
function! s:suite.before_each()
:1
call s:assert.equals(s:get_pos_char(), '1')
call clearmatches()
call s:assert.equals(getmatches(), [])
endfunction
function! s:suite.hlsearch()
if !exists('v:hlsearch')
call s:assert.skip("Skip because vim version are too low to test it")
endif
set hlsearch
" FIXME: <- why...???
for keyseq in ['/', '?', 'g/']
nohlsearch
call s:assert.equals(v:hlsearch, 0)
exec "normal" keyseq . "pattern\<CR>"
call s:assert.equals(v:hlsearch, 1)
endfor
nohlsearch
call s:assert.equals(v:hlsearch, 0)
exec "normal!" "hl" | " dummy
call s:assert.equals(v:hlsearch, 0)
set hlsearch&
endfunction
function! s:suite.preserve_nohlsearch() abort
for keyseq in ['/', '?', 'g/']
set nohlsearch
nohlsearch
call s:assert.equals(&hlsearch, 0)
exec "normal" keyseq . "pattern\<CR>"
call s:assert.equals(&hlsearch, 0)
endfor
set hlsearch&
endfunction
function! s:suite.incremental_highlight()
call incsearch#highlight#incremental_highlight('\vvimvimvim')
call s:assert.equals(len(getmatches()), 3)
let groups = map(getmatches(), 'v:val.group')
let patterns = map(getmatches(), 'v:val.pattern')
call s:assert.not_equals(index(groups, 'IncSearchMatch'), -1)
call s:assert.not_equals(index(groups, 'IncSearchCursor'), -1)
call s:assert.not_equals(index(groups, 'IncSearchOnCursor'), -1)
call s:assert.not_equals(index(patterns, '\vvimvimvim'), -1)
endfunction
function! s:suite.incremental_separate_highlight()
call incsearch#highlight#incremental_highlight('\vpattern_', 1, 1, [2,2])
call s:assert.equals(len(getmatches()), 4)
let groups = map(getmatches(), 'v:val.group')
let patterns = map(getmatches(), 'v:val.pattern')
call s:assert.not_equals(index(groups, 'IncSearchMatch'), -1)
call s:assert.not_equals(index(groups, 'IncSearchCursor'), -1)
call s:assert.not_equals(index(groups, 'IncSearchOnCursor'), -1)
call s:assert.not_equals(index(groups, 'IncSearchMatchReverse'), -1)
call s:assert.equals(index(patterns, '\vpattern_'), -1)
call s:assert.not_equals(index(patterns, '\v(%>2l|%2l%>2c)\m\(\vpattern_\m\)'), -1)
call s:assert.not_equals(index(patterns, '\v(%<2l|%2l%<2c)\m\(\vpattern_\m\)'), -1)
" Make sure all patterns valid by calling with search() and see
" it won't throw any errors
for p in patterns
normal! gg
call search(p, 'n')
endfor
endfunction
function! s:suite.forward_pattern()
let U = incsearch#util#import()
let L = vital#incsearch#new().import('Data.List')
let from = [3,3]
let pat = incsearch#highlight#forward_pattern('pattern', from)
:1
let pos = searchpos(pat, 'n')
let pos2 = searchpos('pattern', 'n')
call s:assert.true(U.is_pos_less_equal(from, pos))
call s:assert.false(U.is_pos_less_equal(from, pos2))
let poses = []
for _ in range(10)
let poses += [searchpos(pat)]
endfor
let poses = L.uniq(poses)
for p in poses
call s:assert.true(U.is_pos_less_equal(from, p))
endfor
call s:assert.equals(poses, [[4,2],[5,2]])
endfunction
function! s:suite.backward_pattern()
let U = incsearch#util#import()
let L = vital#incsearch#new().import('Data.List')
let from = [3,3]
let pat = incsearch#highlight#backward_pattern('pattern', from)
:$
let pos = searchpos(pat, 'bn')
let pos2 = searchpos('pattern', 'bn')
call s:assert.true(U.is_pos_less_equal(pos, from))
call s:assert.false(U.is_pos_less_equal(pos2, from))
let poses = []
for _ in range(10)
let poses += [searchpos(pat, 'b')]
endfor
let poses = L.uniq(poses)
for p in poses
call s:assert.true(U.is_pos_less_equal(pos, from))
endfor
call s:assert.equals(poses, [[3, 2], [2, 2], [1, 2]])
endfunction
function! s:suite.separate_highlight_with_searching()
" XXX: it just test scripts works or not
let g:incsearch#separate_highlight = 1
for keyseq in ['/', '?', 'g/']
exec "normal" keyseq . "pattern\<CR>"
endfor
let g:incsearch#separate_highlight = 0
for keyseq in ['/', '?', 'g/']
exec "normal" keyseq . "pattern\<CR>"
endfor
endfunction

View File

@ -0,0 +1,50 @@
let s:suite = themis#suite('history')
let s:assert = themis#helper('assert')
function! s:suite.before()
:1,$ delete
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
set history=5
endfunction
function! s:suite.before_each()
" call histdel('search') " Segmentation fault (core dumped)
silent! exec "normal" "/\<Space>\<CR>"
endfunction
function! s:suite.after()
unmap /
unmap ?
unmap g/
set history&
:1,$ delete
endfunction
function! s:suite.commandline_history_forward()
call s:assert.equals(histget('search', -1), ' ')
silent! exec "normal" "/pattern\<CR>"
call s:assert.equals(histget('search', -1), 'pattern')
silent! exec "normal" "/pattern/e\<CR>"
call s:assert.equals(histget('search', -1), 'pattern/e')
endfunction
function! s:suite.commandline_history_backward()
call s:assert.equals(histget('search', -1), ' ')
silent! exec "normal" "?pattern\<CR>"
call s:assert.equals(histget('search', -1), 'pattern')
silent! exec "normal" "?pattern/e\<CR>"
call s:assert.equals(histget('search', -1), 'pattern/e')
endfunction
function! s:suite.commandline_history_stay()
call s:assert.equals(histget('search', -1), ' ')
silent! exec "normal" "g/pattern\<CR>"
call s:assert.equals(histget('search', -1), 'pattern')
silent! exec "normal" "g/pattern/e\<CR>"
call s:assert.equals(histget('search', -1), 'pattern/e')
silent! exec "normal" "g/pattern/e\<Tab>\<CR>"
call s:assert.equals(histget('search', -1), 'pattern/e')
endfunction

View File

@ -0,0 +1,2 @@
" TODO:
" but difficult to test

View File

@ -0,0 +1 @@
" TODO:

View File

@ -0,0 +1,147 @@
let s:suite = themis#suite('incremental_next_prev')
let s:assert = themis#helper('assert')
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
normal! ggdG
call s:add_lines(copy(s:line_texts))
normal! Gddgg0zt
endfunction
function! s:suite.before()
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
let s:line_texts = [
\ '0'
\ , 'pattern1'
\ , 'pattern2'
\ , 'pattern3'
\ , 'pattern4'
\ , 'pattern5'
\ , '6'
\ ]
call s:reset_buffer()
endfunction
function! s:suite.before_each()
:1
set wrapscan&
endfunction
function! s:suite.after()
call s:reset_buffer()
endfunction
function! s:suite.inc_next_forward()
exec "normal" "/pattern\\zs\\d\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[2])
:1
exec "normal" "/pattern\\zs\\d\<Tab>\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[3])
endfunction
function! s:suite.inc_next_backward()
:$
call s:assert.equals(s:get_pos_char(), 6)
exec "normal" "?pattern\\zs\\d\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[4])
:$
exec "normal" "?pattern\\zs\\d\<Tab>\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[3])
endfunction
function! s:suite.inc_prev_forward()
exec "normal" "/pattern\\zs\\d\<Tab>\<S-Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[1])
:1
exec "normal" "/pattern\\zs\\d\<Tab>\<Tab>\<S-Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[2])
endfunction
function! s:suite.inc_prev_backward()
:$
call s:assert.equals(s:get_pos_char(), 6)
exec "normal" "?pattern\\zs\\d\<Tab>\<S-Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[5])
:$
exec "normal" "?pattern\\zs\\d\<Tab>\<Tab>\<S-Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[4])
endfunction
function! s:suite.inc_next_stay()
exec "normal" "g/pattern\\zs\\d\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[1])
:1
exec "normal" "g/pattern\\zs\\d\<Tab>\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[2])
endfunction
function! s:suite.inc_prev_stay()
exec "normal" "g/pattern\\zs\\d\<Tab>\<Tab>\<S-Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[1])
endfunction
" h: last-pattern
" NOTE: incsearch.vim works interactibely
function! s:suite.inc_last_pattern()
" let @/ = "pattern\\zs\\d"
call histadd('/', "pattern\\zs\\d")
exec "normal" "/\<Tab>\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[2])
call s:assert.equals(@/, "pattern\\zs\\d")
endfunction
function! s:suite.inc_last_pattern_offset()
" let @/ = "pattern\\d"
call histadd('/', "pattern\\d")
exec "normal" "//e\<Tab>\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[2])
call s:assert.equals(s:get_pos_char(), 2)
call s:assert.equals(@/, "pattern\\d")
endfunction
function! s:suite.inc_last_pattern_reset()
call s:assert.skip("Skip because Segmentation fault occurs with histdel()")
call s:assert.equals(getline('.'), s:line_texts[0])
let @/ = ''
call histdel('/')
Throws /Vim(normal):E35: No previous regular expression/
\ :exec "normal" "/\<Tab>\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[0])
endfunction
function! s:suite.match_at_cursor_pos_with_nowrapscan() abort
set nowrapscan
:3
exec "normal" "/pattern\<Tab>\<Tab>\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[5])
set wrapscan
:3
exec "normal" "/pattern\<Tab>\<Tab>\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[1])
endfunction
function! s:suite.match_at_cursor_pos_with_nowrapscan_backward() abort
set nowrapscan
:5
exec "normal" "?pattern\<Tab>\<Tab>\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[1])
set wrapscan
:5
exec "normal" "?pattern\<Tab>\<Tab>\<Tab>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[5])
endfunction

View File

@ -0,0 +1,98 @@
let s:suite = themis#suite('insert_register')
let s:assert = themis#helper('assert')
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
normal! ggdG
call s:add_lines(copy(s:line_texts))
normal! Gddgg0zt
endfunction
function! s:suite.before()
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
let s:line_texts = [
\ '0'
\ , 'pattern1'
\ , 'pattern_vim_2'
\ , 'emacs vim3'
\ , 's:4pattern4 4'
\ , 's:4pattern4 5'
\ ]
call s:reset_buffer()
endfunction
function! s:suite.before_each()
:1
set incsearch
endfunction
function! s:suite.after()
unmap /
unmap ?
unmap g/
:1,$ delete
set incsearch&
let @/ = ''
endfunction
function! s:suite.cword_noincsearch()
set noincsearch
Throws /Vim(normal):E486: Pattern not found: ppattern1/
\ :exec "normal" "/p\<C-r>\<C-w>/e\<CR>"
endfunction
function! s:suite.cword_incsearch()
exec "normal" "/p\<C-r>\<C-w>/e\<CR>"
call s:assert.equals(s:get_pos_char(), 1)
endfunction
function! s:suite.cword_incsearch_middle()
exec "normal" "/pa\<Left>\<C-r>\<C-w>\<Right>\<BS>/e\<CR>"
call s:assert.equals(s:get_pos_char(), 1)
endfunction
function! s:suite.cword_incsearch_cli_cursor_middle()
exec "normal" "/pa\<Left>\<C-r>\<C-w>\<Right>\<BS>/e\<CR>"
call s:assert.equals(s:get_pos_char(), 1)
endfunction
function! s:suite.cword_incsearch_middle_word()
Throws /Vim(normal):E486: Pattern not found: vimpattern_vim_2/
\ :exec "normal" "/vim\<C-r>\<C-w>/e\<CR>"
endfunction
function! s:suite.cword_from_last_matched_pos()
exec "normal" "/emacs \<C-r>\<C-w>/e\<CR>"
call s:assert.equals(s:get_pos_char(), 3)
endfunction
function! s:suite.cWord()
call s:assert.equals(getline('.'), s:line_texts[0])
call cursor(4 + 1, 3)
call s:assert.equals(getline('.'), s:line_texts[4])
exec "normal" "/p\<C-r>\<C-a>\<Home>\<Del>\<CR>"
call s:assert.equals(getline('.'), s:line_texts[5])
call s:assert.equals(@/, 's:4pattern4')
endfunction
function! s:suite.search()
let @/ = 'emacs'
exec "normal" "/\<C-r>/ vim3/e\<CR>"
call s:assert.equals(s:get_pos_char(), 3)
endfunction

View File

@ -0,0 +1,114 @@
let s:suite = themis#suite('jumplist')
let s:assert = themis#helper('assert')
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
normal! ggdG
call s:add_lines(copy(s:line_texts))
normal! Gddgg0zt
endfunction
function! s:suite.before()
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
let s:line_texts = ['1pattern', '2pattern', '3pattern', '4pattern']
call s:reset_buffer()
endfunction
function! s:suite.before_each()
:1
endfunction
function! s:suite.after()
unmap /
unmap ?
unmap g/
:1,$delete
endfunction
function! s:suite.forward()
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "/2pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "/3pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '3')
exec "normal! \<C-o>"
call s:assert.equals(s:get_pos_char(), '2')
exec "normal! \<C-o>"
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "/4pattern/e\<CR>"
call s:assert.equals(s:get_pos_char(), 'n')
exec "normal! \<C-o>"
call s:assert.equals(s:get_pos_char(), '1')
endfunction
function! s:suite.backward()
:$
call s:assert.equals(s:get_pos_char(), '4')
exec "normal" "?3pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '3')
exec "normal" "?2pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
exec "normal! \<C-o>"
call s:assert.equals(s:get_pos_char(), '3')
exec "normal! \<C-o>"
call s:assert.equals(s:get_pos_char(), '4')
endfunction
function! s:suite.stay_does_not_update_jumplist()
normal! m`
call s:assert.equals(s:get_pos_char(), '1')
keepjumps normal! 3j
call s:assert.equals(s:get_pos_char(), '4')
exec "normal! \<C-o>"
call s:assert.equals(s:get_pos_char(), '1')
normal! m`
keepjumps normal! j
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "g/3pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
exec "normal! \<C-o>"
call s:assert.equals(s:get_pos_char(), '1')
endfunction
function! s:suite.stay_offset()
call s:assert.skip("because you cannot set {offset} information with Vim script unless excuting search command")
call s:assert.equals(s:get_pos_char(), '1')
normal! m`
keepjumps normal! j
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "g/3pattern/e\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
exec "normal! \<C-o>"
call s:assert.equals(s:get_pos_char(), '1') " -> 2
endfunction
function! s:suite.exit_stay_does_update_jumplist()
normal! m`
call s:assert.equals(s:get_pos_char(), '1')
keepjumps normal! 3j
call s:assert.equals(s:get_pos_char(), '4')
exec "normal! \<C-o>"
call s:assert.equals(s:get_pos_char(), '1')
normal! m`
keepjumps normal! j
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "g/3pattern\<Tab>\<CR>"
call s:assert.equals(s:get_pos_char(), '3')
exec "normal! \<C-o>"
call s:assert.equals(s:get_pos_char(), '2')
endfunction

View File

@ -0,0 +1,65 @@
Describe lastpattern
" :h last-pattern
let s:lines = ['1pattern_a', '2pattern_b', '3pattern_c', '4pattern_d', '5pattern_e']
function! s:reset_buffer()
:1,$ delete
call AddLines(s:lines)
normal! Gddgg0zt
endfunction
Before all
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
call s:reset_buffer()
End
Before each
:1
normal! zt
End
After all
:1,$ delete
unmap /
unmap ?
unmap g/
let @/ = ''
let g:incsearch#magic = ''
End
Context handle last-pattern
It should handle empty pattern as last-pattern
let @/ = s:lines[1]
exec "normal" "/\<CR>"
Assert Equals(line('.'), 2)
Assert Equals(GetPosChar(), '2')
End
It should handle empty pattern with {offset} as last-pattern
let @/ = s:lines[1]
exec "normal" "//e\<CR>"
Assert Equals(line('.'), '2')
Assert Equals(GetPosChar(), 'b')
End
End
Context handle last-pattern with improved magic option
It should handle empty pattern as last-pattern
let g:incsearch#magic = '\v'
let @/ = s:lines[1]
exec "normal" "/\<CR>"
Assert Equals(line('.'), 2)
Assert Equals(GetPosChar(), '2')
End
It should handle empty pattern with {offset} as last-pattern
let g:incsearch#magic = '\v'
let @/ = s:lines[1]
exec "normal" "//e\<CR>"
Assert Equals(line('.'), '2')
Assert Equals(GetPosChar(), 'b')
End
End
End

View File

@ -0,0 +1,87 @@
let s:suite = themis#suite('magic_option')
let s:assert = themis#helper('assert')
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
normal! ggdG
call s:add_lines(copy(s:line_texts))
normal! Gddgg0zt
endfunction
function! s:suite.before()
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
let s:line_texts = [
\ 'default cursor pos'
\ , 'escape only when very magic: ()'
\ , 'no need to escape when very nomagic: $dummy'
\ , 'brace and dot matches only when magic: "{{"'
\ , 'escaped dot and end-of-line matches only when no magic: ZZ'
\ ]
call s:reset_buffer()
endfunction
function! s:suite.before_each()
:1
endfunction
function! s:suite.after()
call s:reset_buffer()
let g:incsearch#magic = ''
endfunction
function! s:suite.can_set_very_magic()
let g:incsearch#magic = '\v'
let p = "\\(\\)"
exec "normal" printf("/%s\<CR>", p)
call s:assert.equals(getline('.'), s:line_texts[1])
call s:assert.equals(@/, '\v' . p)
endfunction
function! s:suite.can_set_very_nomagic()
let g:incsearch#magic = '\V'
let p = "\\($\\)dummy"
exec "normal" printf("/%s\<CR>", p)
call s:assert.equals(getline('.'), s:line_texts[2])
call s:assert.equals(@/, '\V' . p)
endfunction
function! s:suite.can_set_magic()
let g:incsearch#magic = '\m'
let p = "{."
exec "normal" printf("/%s\<CR>", p)
call s:assert.equals(getline('.'), s:line_texts[3])
call s:assert.equals(@/, '\m' . p)
endfunction
function! s:suite.can_set_nomagic()
let g:incsearch#magic = '\M'
let p = "Z\\.$"
exec "normal" printf("/%s\<CR>", p)
call s:assert.equals(getline('.'), s:line_texts[4])
call s:assert.equals(@/, '\M' . p)
endfunction
function! s:suite.cannot_set_other_char()
" considered as '\m'
let g:incsearch#magic = '\a'
let p = "{."
exec "normal" printf("/%s\<CR>", p)
call s:assert.equals(getline('.'), s:line_texts[3])
call s:assert.equals(@/, p)
endfunction

View File

@ -0,0 +1,52 @@
let s:suite = themis#suite('cancel')
let s:assert = themis#helper('assert')
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(deepcopy(a:lines))
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
:1,$ delete
let s:lines = ['1pattern_a', '2pattern_b', '3pattern_c', '4pattern_d', '5pattern_e']
call s:add_lines(s:lines)
normal! Gddgg0zt
endfunction
function! s:suite.before()
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
call s:reset_buffer()
endfunction
function! s:suite.before_each()
:1
normal! zt
endfunction
function! s:suite.after()
:1,$ delete
let g:incsearch#smart_backward_word = 1
endfunction
function! s:suite.module_management()
call s:assert.equals(s:get_pos_char(), '1')
:1
let g:incsearch#smart_backward_word = 0
exec "normal" "/\\dpattern_.\\v\<C-w>\<Bs>/e\<CR>"
call s:assert.equals(s:get_pos_char(), 'a')
:1
let g:incsearch#smart_backward_word = 1
exec "normal" "/\\dpattern_./e\\v\<C-w>\<CR>"
call s:assert.equals(s:get_pos_char(), 'a')
endfunction

View File

@ -0,0 +1,126 @@
let s:suite = themis#suite('n_and_N')
let s:assert = themis#helper('assert')
" see: v:searchforward
let s:DIRECTION = { 'backward': 0, 'forward': 1}
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
:1,$ delete
call s:add_lines(copy(s:line_texts))
normal! Gddgg0zt
endfunction
function! s:suite.before()
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
" Explicitly map default `n` and `N`
" unmap workaround
noremap n n
noremap N N
unmap n
unmap N
let s:line_texts = ['1pattern 2pattern 3pattern 4pattern']
call s:reset_buffer()
endfunction
function! s:suite.before_each()
:1
endfunction
function! s:suite.after()
unmap /
unmap ?
unmap g/
:1,$ delete
let g:incsearch#consistent_n_direction = 0
endfunction
function! s:suite.after_forward()
let v:searchforward = s:DIRECTION.backward
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "/\\dpattern\<CR>"
call s:assert.equals(v:searchforward, s:DIRECTION.forward)
call s:assert.equals(s:get_pos_char(), '2')
normal! n
call s:assert.equals(s:get_pos_char(), '3')
normal! 2N
call s:assert.equals(s:get_pos_char(), '1')
endfunction
function! s:suite.after_backward()
" NOTE: Use feedkeys() to manipulate v:searchforward but it seems to work
" fine with this test, so it's possible that :h function-search-undo
" doesn't work with Ex-mode?
normal! $
let v:searchforward = s:DIRECTION.forward
call s:assert.equals(s:get_pos_char(), 'n')
exec "normal" "?\\dpattern\<CR>"
call s:assert.equals(s:get_pos_char(), '4')
call s:assert.equals(v:searchforward, s:DIRECTION.backward)
normal! n
call s:assert.equals(s:get_pos_char(), '3')
normal! n
call s:assert.equals(s:get_pos_char(), '2')
normal! 2N
call s:assert.equals(s:get_pos_char(), '4')
endfunction
function! s:suite.after_stay()
let v:searchforward = s:DIRECTION.backward
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "g/\\dpattern\<CR>"
call s:assert.equals(s:get_pos_char(), '1')
call s:assert.equals(v:searchforward, s:DIRECTION.forward)
normal! n
call s:assert.equals(s:get_pos_char(), '2')
normal! N
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "g/\\dpattern\<Tab>\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
normal! n
call s:assert.equals(s:get_pos_char(), '3')
endfunction
function! s:suite.consistent_n_and_N_direction()
let g:incsearch#consistent_n_direction = 1
normal! $
let v:searchforward = s:DIRECTION.forward
call s:assert.equals(s:get_pos_char(), 'n')
exec "normal" "?\\dpattern\<CR>"
call s:assert.equals(s:get_pos_char(), '4')
call s:assert.equals(v:searchforward, s:DIRECTION.forward)
normal! N
call s:assert.equals(s:get_pos_char(), '3')
normal! n
call s:assert.equals(s:get_pos_char(), '4')
:1,$ delete
call s:add_line('1pattern1 2pattern2 3pattern3 4pattern4')
normal! gg$
let v:searchforward = s:DIRECTION.forward
call s:assert.equals(s:get_pos_char(), '4')
exec "normal" "?\\dpattern\\d?e\<CR>"
call s:assert.equals(s:get_pos_char(), '3')
call s:assert.equals(v:searchforward, s:DIRECTION.forward)
normal! N
call s:assert.equals(s:get_pos_char(), '2')
normal! n
call s:assert.equals(s:get_pos_char(), '3')
let g:incsearch#consistent_n_direction = 0
endfunction

View File

@ -0,0 +1,78 @@
let s:suite = themis#suite('nomagic')
let s:assert = themis#helper('assert')
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
" Helper:
function! s:add_line(str)
put! =a:str
endfunction
function! s:add_lines(lines)
for line in reverse(a:lines)
put! =line
endfor
endfunction
function! s:get_pos_char()
return getline('.')[col('.')-1]
endfunction
function! s:reset_buffer()
:1,$ delete
call s:add_lines(copy(s:line_texts))
normal! Gddgg0zt
endfunction
function! s:suite.before()
map / <Plug>(incsearch-forward)
map ? <Plug>(incsearch-backward)
map g/ <Plug>(incsearch-stay)
let s:line_texts = ['1pattern_a', '2pattern_b', '3pattern_c', '4pattern_d', '5pattern_e']
call s:reset_buffer()
endfunction
function! s:suite.before_each()
:1
normal! zt
set nomagic
endfunction
function! s:suite.after()
unmap /
unmap ?
unmap g/
:1,$ delete
set magic&
endfunction
function! s:suite.works_with_nomagic()
exec "normal" "/\\dpattern\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "/\\dpattern_\\[a-z]/e\<CR>"
call s:assert.equals(s:get_pos_char(), 'b')
exec "normal" "?\\dpattern\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "?\\dpattern_\\[a-z]?e\<CR>"
call s:assert.equals(s:get_pos_char(), 'a')
endfunction
function! s:suite.works_with_nomagic_stay()
exec "normal" "g/\\dpattern\<CR>"
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "g/\\dpattern\<Tab>\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "g/\\dpattern_\\[a-z]/e\<CR>"
call s:assert.equals(s:get_pos_char(), '2')
exec "normal" "g/\\dpattern_\\[a-z]/e\<Tab>\<CR>"
call s:assert.equals(s:get_pos_char(), 'b')
endfunction
function! s:suite.nomagic_as_a_pattern()
exec "normal" "/.pattern\<CR>"
call s:assert.equals(s:get_pos_char(), '1')
exec "normal" "/pat*ern\<CR>"
call s:assert.equals(s:get_pos_char(), '1')
endfunction

Some files were not shown because too many files have changed in this diff Show More