From cd6ea298f2dd9d94ba50d85b98b196c755d378c6 Mon Sep 17 00:00:00 2001 From: Wang Shidong Date: Sat, 13 Jun 2020 21:58:05 +0800 Subject: [PATCH] fix java neoformat config * Add incsearch.vim into bundle dir * Fix java neoformat config close #3573 * Use echom instead in pull.vim --- .SpaceVim.d/autoload/SpaceVim/dev/pull.vim | 4 +- autoload/SpaceVim/layers/incsearch.vim | 2 +- autoload/SpaceVim/layers/lang/java.vim | 2 +- bundle/incsearch.vim/.travis.yml | 27 + bundle/incsearch.vim/.vintrc.yaml | 5 + bundle/incsearch.vim/LICENSE | 20 + bundle/incsearch.vim/README.md | 163 ++++ bundle/incsearch.vim/appveyor.yml | 35 + bundle/incsearch.vim/autoload/incsearch.vim | 498 ++++++++++++ .../autoload/incsearch/autocmd.vim | 59 ++ .../incsearch.vim/autoload/incsearch/cli.vim | 109 +++ .../autoload/incsearch/config.vim | 99 +++ .../autoload/incsearch/highlight.vim | 297 +++++++ .../autoload/incsearch/over/extend.vim | 122 +++ .../over/modules/bracketed_paste.vim | 40 + .../over/modules/bulk_input_char.vim | 38 + .../autoload/incsearch/over/modules/exit.vim | 33 + .../incsearch/over/modules/incsearch.vim | 295 +++++++ .../over/modules/insert_register.vim | 41 + .../over/modules/module_management.vim | 50 ++ .../incsearch/over/modules/pattern_saver.vim | 48 ++ .../incsearch.vim/autoload/incsearch/util.vim | 286 +++++++ bundle/incsearch.vim/autoload/vital.vim | 12 + .../autoload/vital/_incsearch.vim | 9 + .../vital/_incsearch/Coaster/Highlight.vim | 239 ++++++ .../vital/_incsearch/Coaster/Window.vim | 62 ++ .../autoload/vital/_incsearch/Data/Dict.vim | 151 ++++ .../autoload/vital/_incsearch/Data/List.vim | 464 +++++++++++ .../autoload/vital/_incsearch/Gift.vim | 159 ++++ .../vital/_incsearch/Gift/Tabpage.vim | 47 ++ .../autoload/vital/_incsearch/Gift/Window.vim | 153 ++++ .../vital/_incsearch/Over/Commandline.vim | 61 ++ .../_incsearch/Over/Commandline/Base.vim | 600 +++++++++++++++ .../_incsearch/Over/Commandline/Maker.vim | 97 +++ .../_incsearch/Over/Commandline/Modules.vim | 36 + .../Over/Commandline/Modules/All.vim | 24 + .../Over/Commandline/Modules/AsyncUpdate.vim | 47 ++ .../Commandline/Modules/BufferComplete.vim | 173 +++++ .../Over/Commandline/Modules/Cancel.vim | 34 + .../Over/Commandline/Modules/CursorMove.vim | 52 ++ .../Over/Commandline/Modules/Delete.vim | 50 ++ .../Over/Commandline/Modules/Digraphs.vim | 110 +++ .../Over/Commandline/Modules/Doautocmd.vim | 115 +++ .../Commandline/Modules/DrawCommandline.vim | 149 ++++ .../Commandline/Modules/ExceptionExit.vim | 31 + .../Commandline/Modules/ExceptionMessage.vim | 60 ++ .../Over/Commandline/Modules/Execute.vim | 85 ++ .../Over/Commandline/Modules/Exit.vim | 34 + .../Over/Commandline/Modules/HistAdd.vim | 32 + .../Over/Commandline/Modules/History.vim | 69 ++ .../Modules/IgnoreRegexpBackwardWord.vim | 48 ++ .../Over/Commandline/Modules/Incsearch.vim | 83 ++ .../Commandline/Modules/InsertRegister.vim | 158 ++++ .../Over/Commandline/Modules/KeyMapping.vim | 149 ++++ .../Commandline/Modules/LiteralInsert.vim | 39 + .../Over/Commandline/Modules/NoInsert.vim | 49 ++ .../Over/Commandline/Modules/Paste.vim | 34 + .../Over/Commandline/Modules/Redraw.vim | 66 ++ .../Over/Commandline/Modules/Scroll.vim | 46 ++ .../vital/_incsearch/Over/Exception.vim | 40 + .../autoload/vital/_incsearch/Over/Input.vim | 34 + .../vital/_incsearch/Over/Keymapping.vim | 89 +++ .../vital/_incsearch/Over/Signals.vim | 113 +++ .../autoload/vital/_incsearch/Over/String.vim | 158 ++++ .../vital/_incsearch/Palette/Capture.vim | 68 ++ .../vital/_incsearch/Palette/Highlight.vim | 127 +++ .../vital/_incsearch/Palette/Keymapping.vim | 115 +++ .../autoload/vital/_incsearch/Prelude.vim | 424 ++++++++++ .../autoload/vital/_incsearch/Vim/Buffer.vim | 207 +++++ .../autoload/vital/_incsearch/Vim/Guard.vim | 234 ++++++ .../autoload/vital/_incsearch/Vim/Message.vim | 74 ++ .../autoload/vital/_incsearch/Vim/Type.vim | 58 ++ .../autoload/vital/incsearch.vim | 328 ++++++++ .../autoload/vital/incsearch.vital | 5 + bundle/incsearch.vim/doc/.gitignore | 1 + bundle/incsearch.vim/doc/incsearch.txt | 724 ++++++++++++++++++ bundle/incsearch.vim/plugin/incsearch.vim | 103 +++ bundle/incsearch.vim/test/.themisrc | 37 + .../test/api/config/keymap.vimspec | 50 ++ .../incsearch.vim/test/api/converter.vimspec | 45 ++ bundle/incsearch.vim/test/autocmd.vimspec | 146 ++++ bundle/incsearch.vim/test/autonohlsearch.vim | 154 ++++ bundle/incsearch.vim/test/cancel.vim | 153 ++++ bundle/incsearch.vim/test/count.vim | 97 +++ .../incsearch.vim/test/default_behaviors.vim | 168 ++++ .../incsearch.vim/test/default_settings.vim | 88 +++ .../test/error_warning_emulation.vim | 247 ++++++ bundle/incsearch.vim/test/fold.vim | 160 ++++ bundle/incsearch.vim/test/highlight.vim | 156 ++++ bundle/incsearch.vim/test/history.vim | 50 ++ bundle/incsearch.vim/test/inc_cursor_pos.vim | 2 + bundle/incsearch.vim/test/inc_hlsearch.vim | 1 + .../test/incremental_next_prev.vim | 147 ++++ bundle/incsearch.vim/test/insert_register.vim | 98 +++ bundle/incsearch.vim/test/jumplist.vim | 114 +++ bundle/incsearch.vim/test/lastpattern.vimspec | 65 ++ bundle/incsearch.vim/test/magic_option.vim | 87 +++ bundle/incsearch.vim/test/module.vim | 52 ++ bundle/incsearch.vim/test/n_and_N.vim | 126 +++ bundle/incsearch.vim/test/nomagic.vim | 78 ++ .../test/operator_pending_behavior.vim | 101 +++ .../test/question_pattern.vimspec | 50 ++ bundle/incsearch.vim/test/register.vim | 50 ++ bundle/incsearch.vim/test/repetition.vim | 143 ++++ bundle/incsearch.vim/test/scroll.vim | 91 +++ bundle/incsearch.vim/test/test.vimrc | 11 + bundle/incsearch.vim/test/util.vim | 87 +++ bundle/incsearch.vim/test/util/regexp.vimspec | 161 ++++ bundle/incsearch.vim/test/vimlint.sh | 13 + bundle/incsearch.vim/test/visual_behavior.vim | 90 +++ .../incsearch.vim/test/visual_emulation.vim | 162 ++++ 111 files changed, 12278 insertions(+), 4 deletions(-) create mode 100644 bundle/incsearch.vim/.travis.yml create mode 100644 bundle/incsearch.vim/.vintrc.yaml create mode 100644 bundle/incsearch.vim/LICENSE create mode 100644 bundle/incsearch.vim/README.md create mode 100644 bundle/incsearch.vim/appveyor.yml create mode 100644 bundle/incsearch.vim/autoload/incsearch.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/autocmd.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/cli.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/config.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/highlight.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/over/extend.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/over/modules/bracketed_paste.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/over/modules/bulk_input_char.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/over/modules/exit.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/over/modules/incsearch.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/over/modules/insert_register.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/over/modules/module_management.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/over/modules/pattern_saver.vim create mode 100644 bundle/incsearch.vim/autoload/incsearch/util.vim create mode 100644 bundle/incsearch.vim/autoload/vital.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Coaster/Highlight.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Coaster/Window.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Data/Dict.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Data/List.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Gift.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Gift/Tabpage.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Gift/Window.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Base.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Maker.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/All.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/AsyncUpdate.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/BufferComplete.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Cancel.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/CursorMove.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Delete.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Digraphs.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Doautocmd.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/DrawCommandline.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/ExceptionExit.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/ExceptionMessage.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Execute.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Exit.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/HistAdd.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/History.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/IgnoreRegexpBackwardWord.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Incsearch.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/InsertRegister.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/KeyMapping.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/LiteralInsert.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/NoInsert.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Paste.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Redraw.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Scroll.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Exception.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Input.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Keymapping.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/Signals.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Over/String.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Capture.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Highlight.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Keymapping.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Prelude.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Buffer.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Guard.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Message.vim create mode 100644 bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Type.vim create mode 100644 bundle/incsearch.vim/autoload/vital/incsearch.vim create mode 100644 bundle/incsearch.vim/autoload/vital/incsearch.vital create mode 100644 bundle/incsearch.vim/doc/.gitignore create mode 100644 bundle/incsearch.vim/doc/incsearch.txt create mode 100644 bundle/incsearch.vim/plugin/incsearch.vim create mode 100644 bundle/incsearch.vim/test/.themisrc create mode 100644 bundle/incsearch.vim/test/api/config/keymap.vimspec create mode 100644 bundle/incsearch.vim/test/api/converter.vimspec create mode 100644 bundle/incsearch.vim/test/autocmd.vimspec create mode 100644 bundle/incsearch.vim/test/autonohlsearch.vim create mode 100644 bundle/incsearch.vim/test/cancel.vim create mode 100644 bundle/incsearch.vim/test/count.vim create mode 100644 bundle/incsearch.vim/test/default_behaviors.vim create mode 100644 bundle/incsearch.vim/test/default_settings.vim create mode 100644 bundle/incsearch.vim/test/error_warning_emulation.vim create mode 100644 bundle/incsearch.vim/test/fold.vim create mode 100644 bundle/incsearch.vim/test/highlight.vim create mode 100644 bundle/incsearch.vim/test/history.vim create mode 100644 bundle/incsearch.vim/test/inc_cursor_pos.vim create mode 100644 bundle/incsearch.vim/test/inc_hlsearch.vim create mode 100644 bundle/incsearch.vim/test/incremental_next_prev.vim create mode 100644 bundle/incsearch.vim/test/insert_register.vim create mode 100644 bundle/incsearch.vim/test/jumplist.vim create mode 100644 bundle/incsearch.vim/test/lastpattern.vimspec create mode 100644 bundle/incsearch.vim/test/magic_option.vim create mode 100644 bundle/incsearch.vim/test/module.vim create mode 100644 bundle/incsearch.vim/test/n_and_N.vim create mode 100644 bundle/incsearch.vim/test/nomagic.vim create mode 100644 bundle/incsearch.vim/test/operator_pending_behavior.vim create mode 100644 bundle/incsearch.vim/test/question_pattern.vimspec create mode 100644 bundle/incsearch.vim/test/register.vim create mode 100644 bundle/incsearch.vim/test/repetition.vim create mode 100644 bundle/incsearch.vim/test/scroll.vim create mode 100644 bundle/incsearch.vim/test/test.vimrc create mode 100644 bundle/incsearch.vim/test/util.vim create mode 100644 bundle/incsearch.vim/test/util/regexp.vimspec create mode 100644 bundle/incsearch.vim/test/vimlint.sh create mode 100644 bundle/incsearch.vim/test/visual_behavior.vim create mode 100644 bundle/incsearch.vim/test/visual_emulation.vim diff --git a/.SpaceVim.d/autoload/SpaceVim/dev/pull.vim b/.SpaceVim.d/autoload/SpaceVim/dev/pull.vim index 3e292bb10..71785ec9a 100644 --- a/.SpaceVim.d/autoload/SpaceVim/dev/pull.vim +++ b/.SpaceVim.d/autoload/SpaceVim/dev/pull.vim @@ -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 diff --git a/autoload/SpaceVim/layers/incsearch.vim b/autoload/SpaceVim/layers/incsearch.vim index 27115942a..eb0fc9775 100644 --- a/autoload/SpaceVim/layers/incsearch.vim +++ b/autoload/SpaceVim/layers/incsearch.vim @@ -34,7 +34,7 @@ let s:filename = expand(':~') 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}]) diff --git a/autoload/SpaceVim/layers/lang/java.vim b/autoload/SpaceVim/layers/lang/java.vim index d5d70c5e9..4ee954515 100644 --- a/autoload/SpaceVim/layers/lang/java.vim +++ b/autoload/SpaceVim/layers/lang/java.vim @@ -116,7 +116,7 @@ function! SpaceVim#layers#lang#java#config() abort endif autocmd FileType jsp call 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', ''), '-'], diff --git a/bundle/incsearch.vim/.travis.yml b/bundle/incsearch.vim/.travis.yml new file mode 100644 index 000000000..08489055f --- /dev/null +++ b/bundle/incsearch.vim/.travis.yml @@ -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 diff --git a/bundle/incsearch.vim/.vintrc.yaml b/bundle/incsearch.vim/.vintrc.yaml new file mode 100644 index 000000000..b96568ad3 --- /dev/null +++ b/bundle/incsearch.vim/.vintrc.yaml @@ -0,0 +1,5 @@ +# Config for vint +# https://github.com/Kuniwak/vint +policies: + ProhibitImplicitScopeVariable: + enabled: false diff --git a/bundle/incsearch.vim/LICENSE b/bundle/incsearch.vim/LICENSE new file mode 100644 index 000000000..2f3a1b871 --- /dev/null +++ b/bundle/incsearch.vim/LICENSE @@ -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. diff --git a/bundle/incsearch.vim/README.md b/bundle/incsearch.vim/README.md new file mode 100644 index 000000000..529282a04 --- /dev/null +++ b/bundle/incsearch.vim/README.md @@ -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 / (incsearch-forward) +map ? (incsearch-backward) +map g/ (incsearch-stay) +``` + +`(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 :nohlsearch`! +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 (incsearch-nohl-n) +map N (incsearch-nohl-N) +map * (incsearch-nohl-*) +map # (incsearch-nohl-#) +map g* (incsearch-nohl-g*) +map g# (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 | +| ------------------------ | --------------------------------- | +| `(incsearch-next)` | to next match. default: `` | +| `(incsearch-prev)` | to prev match. default: `` | + +### Scroll-like feature while incremental searching + +![](https://raw.githubusercontent.com/haya14busa/i/master/incsearch.vim/incremental_move_and_scroll.gif) + +| Mapping | description | +| ------------------------ | --------------------------------- | +| `(incsearch-scroll-f)` | scroll to the next page match. default: `` | +| `(incsearch-scroll-b)` | scroll to the previous page match. default: `` | + +: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 z/ incsearch#go(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) diff --git a/bundle/incsearch.vim/appveyor.yml b/bundle/incsearch.vim/appveyor.yml new file mode 100644 index 000000000..53900cda7 --- /dev/null +++ b/bundle/incsearch.vim/appveyor.yml @@ -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 diff --git a/bundle/incsearch.vim/autoload/incsearch.vim b/bundle/incsearch.vim/autoload/incsearch.vim new file mode 100644 index 000000000..0d3ef4479 --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch.vim @@ -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 mappings +" ARGS: +" @config See autoload/incsearch/config.vim +" RETURN: +" Return primitive search commands (like `3/pattern`) 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 (incsearch-forward) incsearch#go({'command': '/'}) +" " FIXME?: Calling this with feedkeys() is ugly... Reason: incsearch#go() +" is optimize the situation which calling from 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) ? "\" : '' + return printf("%s:\call incsearch#_go(g:incsearch#_go_config)\", 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 (_incsearch-dotrepeat) +" temporarily +" https://github.com/tpope/vim-repeat +" https://github.com/kana/vim-repeat +function! s:set_vimrepeat(cmd) abort + execute 'noremap' '(_incsearch-dotrepeat)' a:cmd + silent! call repeat#set("\(_incsearch-dotrepeat)") +endfunction + +let g:incsearch#_view = get(g:, 'incsearch#_view', {}) +noremap (_incsearch-winrestview) +noremap! (_incsearch-winrestview) +nnoremap (_incsearch-winrestview) :call winrestview(g:incsearch#_view) +xnoremap (_incsearch-winrestview) :call winrestview(g:incsearch#_view)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("\(_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) ? "\gv" : "\" " 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("\(_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) ? "\(_incsearch-esc)" : ''), + \ "\(_incsearch-hlsearch)", + \ "\(_incsearch-searchforward)", + \ (s:U.is_visual(m) ? "\(_incsearch-gv)" : '') + \ ], '') + call feedkeys(cmd, 'm') + endif +endfunction + +noremap (_incsearch-gv) +noremap! (_incsearch-gv) +nnoremap (_incsearch-gv) gv + +noremap (_incsearch-esc) +noremap! (_incsearch-esc) +xnoremap (_incsearch-esc) + +noremap (_incsearch-hlsearch) +noremap! (_incsearch-hlsearch) +nnoremap (_incsearch-hlsearch) :let &hlsearch=&hlsearch +xnoremap (_incsearch-hlsearch) :let &hlsearch=&hlsearchgv + +noremap (_incsearch-searchforward) +noremap! (_incsearch-searchforward) +nnoremap (_incsearch-searchforward) _searchforward_cmd() +xnoremap (_incsearch-searchforward) _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(":\let v:searchforward=%d\", 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 . "\") + 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 . "\") + 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 +" }}} diff --git a/bundle/incsearch.vim/autoload/incsearch/autocmd.vim b/bundle/incsearch.vim/autoload/incsearch/autocmd.vim new file mode 100644 index 000000000..fabcd3357 --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/autocmd.vim @@ -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 (_incsearch-nohlsearch) incsearch#autocmd#auto_nohlsearch(0) +noremap! (_incsearch-nohlsearch) incsearch#autocmd#auto_nohlsearch(0) +nnoremap (_incsearch-nohlsearch) :nohlsearch +xnoremap (_incsearch-nohlsearch) :nohlsearchgv + +" 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 attach_on_insert_leave() | autocmd! incsearch-auto-nohlsearch + execute join([ + \ 'autocmd CursorMoved *' + \ , repeat('autocmd incsearch-auto-nohlsearch CursorMoved * ', a:nest) + \ , 'call feedkeys("\(_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 diff --git a/bundle/incsearch.vim/autoload/incsearch/cli.vim b/bundle/incsearch.vim/autoload/incsearch/cli.vim new file mode 100644 index 000000000..6b59d9dca --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/cli.vim @@ -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 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 diff --git a/bundle/incsearch.vim/autoload/incsearch/config.vim b/bundle/incsearch.vim/autoload/incsearch/config.vim new file mode 100644 index 000000000..8a4207e63 --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/config.vim @@ -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 = { +\ "\" : { +\ 'key' : '(incsearch-next)', +\ 'noremap' : 1, +\ }, +\ "\" : { +\ 'key' : '(incsearch-prev)', +\ 'noremap' : 1, +\ }, +\ "\" : { +\ 'key' : '(incsearch-scroll-f)', +\ 'noremap' : 1, +\ }, +\ "\" : { +\ 'key' : '(incsearch-scroll-b)', +\ 'noremap' : 1, +\ }, +\ "\" : { +\ 'key' : '(buffer-complete)', +\ 'noremap' : 1, +\ }, +\ "\" : { +\ 'key': "\", +\ 'noremap': 1 +\ }, +\ } + +" https://github.com/haya14busa/incsearch.vim/issues/35 +if has('mac') + call extend(s:default_keymappings, { + \ '"+gP' : { + \ 'key': "\+", + \ '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 diff --git a/bundle/incsearch.vim/autoload/incsearch/highlight.vim b/bundle/incsearch.vim/autoload/incsearch/highlight.vim new file mode 100644 index 000000000..1af94f50d --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/highlight.vim @@ -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 ==# "\" + " @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 +" }}} diff --git a/bundle/incsearch.vim/autoload/incsearch/over/extend.vim b/bundle/incsearch.vim/autoload/incsearch/over/extend.vim new file mode 100644 index 000000000..0c9d8a2bf --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/over/extend.vim @@ -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) ? '\gv' : "\" + 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 + " ? 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 . + let esc = self._has_count ? "\" : '' + 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\%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 diff --git a/bundle/incsearch.vim/autoload/incsearch/over/modules/bracketed_paste.vim b/bundle/incsearch.vim/autoload/incsearch/over/modules/bracketed_paste.vim new file mode 100644 index 000000000..90b983f8e --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/over/modules/bracketed_paste.vim @@ -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 + diff --git a/bundle/incsearch.vim/autoload/incsearch/over/modules/bulk_input_char.vim b/bundle/incsearch.vim/autoload/incsearch/over/modules/bulk_input_char.vim new file mode 100644 index 000000000..7b88c102e --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/over/modules/bulk_input_char.vim @@ -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 diff --git a/bundle/incsearch.vim/autoload/incsearch/over/modules/exit.vim b/bundle/incsearch.vim/autoload/incsearch/over/modules/exit.vim new file mode 100644 index 000000000..a191e1ab9 --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/over/modules/exit.vim @@ -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: +" in {rhs} wil be remapped even after exiting vital-over command line +" interface, so do not use (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("\") + \ || a:cmdline.is_input("\") + 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 diff --git a/bundle/incsearch.vim/autoload/incsearch/over/modules/incsearch.vim b/bundle/incsearch.vim/autoload/incsearch/over/modules/incsearch.vim new file mode 100644 index 000000000..d15af6b75 --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/over/modules/incsearch.vim @@ -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- 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('(incsearch-next)') + \ || a:cmdline.is_input('(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('(incsearch-next)') | return | endif + endif + + if a:cmdline.is_input('(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('(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('(incsearch-scroll-f)') + \ && (a:cmdline._flag ==# '' || a:cmdline._flag ==# 'n')) + \ || (a:cmdline.is_input('(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('(incsearch-scroll-f)') ? 'w$' : 'w0' + let to_col = a:cmdline.is_input('(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('(incsearch-scroll-b)') + \ && (a:cmdline._flag ==# '' || a:cmdline._flag ==# 'n')) + \ || (a:cmdline.is_input('(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('(incsearch-scroll-f)') ? 'w$' : 'w0' + let to_col = a:cmdline.is_input('(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('(incsearch-next)') + \ || a:cmdline.is_input('(incsearch-prev)') + \ || a:cmdline.is_input('(incsearch-scroll-f)') + \ || a:cmdline.is_input('(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() ==# "\" + 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 mappings + if ( a:cmdline.is_input('(incsearch-scroll-f)') + \ || a:cmdline.is_input('(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 + " 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 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 diff --git a/bundle/incsearch.vim/autoload/incsearch/over/modules/insert_register.vim b/bundle/incsearch.vim/autoload/incsearch/over/modules/insert_register.vim new file mode 100644 index 000000000..8cf3381a5 --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/over/modules/insert_register.vim @@ -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 diff --git a/bundle/incsearch.vim/autoload/incsearch/over/modules/module_management.vim b/bundle/incsearch.vim/autoload/incsearch/over/modules/module_management.vim new file mode 100644 index 000000000..fb968a31d --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/over/modules/module_management.vim @@ -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 diff --git a/bundle/incsearch.vim/autoload/incsearch/over/modules/pattern_saver.vim b/bundle/incsearch.vim/autoload/incsearch/over/modules/pattern_saver.vim new file mode 100644 index 000000000..a5ba74fd1 --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/over/modules/pattern_saver.vim @@ -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 diff --git a/bundle/incsearch.vim/autoload/incsearch/util.vim b/bundle/incsearch.vim/autoload/incsearch/util.vim new file mode 100644 index 000000000..ddd2b7807 --- /dev/null +++ b/bundle/incsearch.vim/autoload/incsearch/util.vim @@ -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 = '' . 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(''), '\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\]" +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('(%s)', name) + if mode ==# 'n' + let command = 'nnoremap' + else + let command = 'nmap' + endif + execute command '' map printf('%s:nunmap %s', 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("\(%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 = '' . 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 +" }}} diff --git a/bundle/incsearch.vim/autoload/vital.vim b/bundle/incsearch.vim/autoload/vital.vim new file mode 100644 index 000000000..f1ba849a0 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital.vim @@ -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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch.vim b/bundle/incsearch.vim/autoload/vital/_incsearch.vim new file mode 100644 index 000000000..55104952e --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch.vim @@ -0,0 +1,9 @@ +let s:_plugin_name = expand(':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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Coaster/Highlight.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Coaster/Highlight.vim new file mode 100644 index 000000000..00e2e8224 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Coaster/Highlight.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Coaster/Window.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Coaster/Window.vim new file mode 100644 index 000000000..9e7e5ae31 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Coaster/Window.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Data/Dict.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Data/Dict.vim new file mode 100644 index 000000000..7e9dae458 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Data/Dict.vim @@ -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(''), '\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('%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: diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Data/List.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Data/List.vim new file mode 100644 index 000000000..f50db7e77 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Data/List.vim @@ -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(''), '\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('%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: diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Gift.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Gift.vim new file mode 100644 index 000000000..803b80747 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Gift.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Gift/Tabpage.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Gift/Tabpage.vim new file mode 100644 index 000000000..f3c6524d6 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Gift/Tabpage.vim @@ -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(''), '\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('%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(":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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Gift/Window.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Gift/Window.vim new file mode 100644 index 000000000..6d93a15e0 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Gift/Window.vim @@ -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(''), '\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('%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(":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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline.vim new file mode 100644 index 000000000..d2d2b84e9 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Base.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Base.vim new file mode 100644 index 000000000..ba11e8699 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Base.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Maker.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Maker.vim new file mode 100644 index 000000000..5095041ec --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Maker.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules.vim new file mode 100644 index 000000000..355ca8863 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/All.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/All.vim new file mode 100644 index 000000000..ef4f92f41 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/All.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#All#import() abort', printf("return map({'_vital_depends': ''}, \"vital#_incsearch#function('%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(":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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/AsyncUpdate.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/AsyncUpdate.vim new file mode 100644 index 000000000..cb6a37abf --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/AsyncUpdate.vim @@ -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(''), '\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('%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("\") + endtry + + call self.draw() + endfunction +endfunction + + +function! s:make() + return deepcopy(s:module) +endfunction + + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/BufferComplete.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/BufferComplete.vim new file mode 100644 index 000000000..f0dbd0259 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/BufferComplete.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#BufferComplete#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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("(buffer-complete)") +\ || a:cmdline.is_input("(buffer-complete-prev)") + if self.complete(a:cmdline) == -1 + call s:_finish() + call a:cmdline.setchar('') + return + endif + if a:cmdline.is_input("(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("\", "Completion") + elseif a:cmdline.is_input("(buffer-complete)", "Completion") +\ || a:cmdline.is_input("\", "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("(buffer-complete-prev)", "Completion") +\ || a:cmdline.is_input("\", "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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Cancel.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Cancel.vim new file mode 100644 index 000000000..bae00fa24 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Cancel.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#Cancel#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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("\") +\ || a:cmdline.is_input("\") +" 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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/CursorMove.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/CursorMove.vim new file mode 100644 index 000000000..df5e00c3d --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/CursorMove.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#CursorMove#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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("\") + call a:cmdline.line.next() + call a:cmdline.setchar('') + elseif a:cmdline.is_input("\") + call a:cmdline.line.prev() + call a:cmdline.setchar('') + elseif a:cmdline.is_input("\") +\ || a:cmdline.is_input("\") + call a:cmdline.setline(0) + call a:cmdline.setchar('') + elseif a:cmdline.is_input("\") +\ || a:cmdline.is_input("\") + call a:cmdline.setline(a:cmdline.line.length()) + call a:cmdline.setchar('') + elseif a:cmdline.is_input("\") +\ || a:cmdline.is_input("\") + call a:cmdline.setline(strridx(a:cmdline.backward()[:-2], ' ') + 1) + call a:cmdline.setchar('') + elseif a:cmdline.is_input("\") +\ || a:cmdline.is_input("\") + 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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Delete.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Delete.vim new file mode 100644 index 000000000..403d081fa --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Delete.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#Delete#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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("\") +\ || a:cmdline.is_input("\") + 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("\") + call a:cmdline.line.remove_pos() + call a:cmdline.setchar('') + elseif a:cmdline.is_input("\") + 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("\") + 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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Digraphs.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Digraphs.vim new file mode 100644 index 000000000..b45cd62ff --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Digraphs.vim @@ -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(''), '\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('%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("\") + if empty(self.digraphs) + " Get digraphs when inputting 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 {char} will + " enter {char} with the highest bit set. You can use this to enter + " meta-characters. + let char = x ==# "\" ? + \ 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("\") + 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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Doautocmd.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Doautocmd.vim new file mode 100644 index 000000000..d9d1664fa --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Doautocmd.vim @@ -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(''), '\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('%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 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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/DrawCommandline.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/DrawCommandline.vim new file mode 100644 index 000000000..232cf4e99 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/DrawCommandline.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#DrawCommandline#import() abort', printf("return map({'suffix': '', 'make': ''}, \"vital#_incsearch#function('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/ExceptionExit.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/ExceptionExit.vim new file mode 100644 index 000000000..e7e0b50ca --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/ExceptionExit.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#ExceptionExit#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/ExceptionMessage.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/ExceptionMessage.vim new file mode 100644 index 000000000..0706e66f4 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/ExceptionMessage.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#ExceptionMessage#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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(":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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Execute.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Execute.vim new file mode 100644 index 000000000..369d8f676 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Execute.vim @@ -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(''), '\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('%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("(%s)", a:name) + if mode == "n" + let command = "nnoremap" + else + let command = "nmap" + endif + execute command "" map printf("%s:nunmap %s", a:expr, map) + call feedkeys(printf("\(%s)", a:name)) +endfunction + + +function! s:_is_input_enter(cmdline) + return a:cmdline.is_input("\") +\ || a:cmdline.is_input("\") +\ || a:cmdline.is_input("\") +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("(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)\", "remove_hist", "n") + let cmd = printf("call s:silent_feedkeys(\"%s%s\\", '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\", "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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Exit.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Exit.vim new file mode 100644 index 000000000..06edfe5e1 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Exit.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#Exit#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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("(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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/HistAdd.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/HistAdd.vim new file mode 100644 index 000000000..70a152549 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/HistAdd.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#HistAdd#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/History.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/History.vim new file mode 100644 index 000000000..fae71aa6f --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/History.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#History#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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("\") +\ || a:cmdline.is_input("\") +endfunction + +function! s:_reset() + let s:cmdhist = [] + let s:count = 0 + let s:is_match_mode = 0 " /: true, /: false +endfunction + +function! s:module.on_enter(...) + call s:_reset() +endfunction + +function! s:module.on_char_pre(cmdline) + if !a:cmdline.is_input("\") && !a:cmdline.is_input("\") + \ && !a:cmdline.is_input("\") && !a:cmdline.is_input("\") + 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("\") || a:cmdline.is_input("\") + let s:count = max([s:count - 1, 0]) + endif + if a:cmdline.is_input("\") || a:cmdline.is_input("\") + 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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/IgnoreRegexpBackwardWord.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/IgnoreRegexpBackwardWord.vim new file mode 100644 index 000000000..799b8244e --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/IgnoreRegexpBackwardWord.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Incsearch.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Incsearch.vim new file mode 100644 index 000000000..2d56d7367 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Incsearch.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/InsertRegister.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/InsertRegister.vim new file mode 100644 index 000000000..5ff310534 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/InsertRegister.vim @@ -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(''), '\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('%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(), "\") + 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("") + let self.cWORD = expand("") + let self.cfile = expand("") +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("\") + 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 == "\" + call a:cmdline.setchar(s:get_cmdline_cword(a:cmdline.backward_word(), self.cword)) + elseif char == "\" + call a:cmdline.setchar(self.cWORD) + elseif char == "\" + call a:cmdline.setchar(self.cfile) + elseif char == "\" + 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("\", self.prefix_key) +" call a:cmdline.setchar(self.cword) +" elseif a:cmdline.is_input("\", self.prefix_key) +" call a:cmdline.setchar(self.cWORD) +" elseif a:cmdline.is_input("\", self.prefix_key) +" call a:cmdline.setchar(self.cfile) +" elseif a:cmdline.is_input("\", 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("\") + 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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/KeyMapping.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/KeyMapping.vim new file mode 100644 index 000000000..3aa042349 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/KeyMapping.vim @@ -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(''), '\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('%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 { +\ "\" : { +\ "key" : "\", +\ "noremap" : 1, +\ "lock" : 1, +\ }, +\ "\" : { +\ "key" : "\", +\ "noremap" : 1, +\ "lock" : 1, +\ }, +\ "\" : { +\ "key" : "\", +\ "noremap" : 1, +\ "lock" : 1, +\ }, +\ "\" : { +\ "key" : "\", +\ "noremap" : 1, +\ "lock" : 1, +\ }, +\ "\" : { +\ "key" : "\", +\ "noremap" : 1, +\ "lock" : 1, +\ }, +\ "\" : { +\ "key" : "\", +\ "noremap" : 1, +\ "lock" : 1, +\ }, +\ "\" : { +\ "key" : "\", +\ "noremap" : 1, +\ "lock" : 1, +\ }, +\ "\" : { +\ "key" : "\", +\ "noremap" : 1, +\ "lock" : 1, +\ }, +\ "\" : { +\ "key" : "\", +\ "noremap" : 1, +\ "lock" : 1, +\ }, +\ "\" : { +\ "key" : "\", +\ "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, '', '' . 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 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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/LiteralInsert.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/LiteralInsert.vim new file mode 100644 index 000000000..d598009ca --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/LiteralInsert.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#LiteralInsert#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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("\") +\ || a:cmdline.is_input("\") + 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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/NoInsert.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/NoInsert.vim new file mode 100644 index 000000000..c90763de8 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/NoInsert.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Paste.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Paste.vim new file mode 100644 index 000000000..b6df2b68b --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Paste.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#Paste#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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("(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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Redraw.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Redraw.vim new file mode 100644 index 000000000..7b56652c8 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Redraw.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#Redraw#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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= + " https://github.com/osyo-manga/vital-over/issues/52 + " https://github.com/Lokaltog/vim-easymotion/issues/177#issuecomment-53663431 + if &cedit != "" +\ ||(v:version > 704 || v:version == 704 && has("patch441")) + normal! : + else + execute "normal! :\" + endif +endfunction + +function! s:make() + return deepcopy(s:module) +endfunction + + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Scroll.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Scroll.vim new file mode 100644 index 000000000..e705a77f0 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Commandline/Modules/Scroll.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Commandline#Modules#Scroll#import() abort', printf("return map({'make': ''}, \"vital#_incsearch#function('%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("(scroll-y)") + execute "normal! \" + call a:cmdline.setchar('') + elseif a:cmdline.is_input("(scroll-u)") + execute "normal! \" + call a:cmdline.setchar('') + elseif a:cmdline.is_input("(scroll-f)") + execute "normal! \" + call a:cmdline.setchar('') + elseif a:cmdline.is_input("(scroll-e)") + execute "normal! \" + call a:cmdline.setchar('') + elseif a:cmdline.is_input("(scroll-d)") + execute "normal! \" + call a:cmdline.setchar('') + elseif a:cmdline.is_input("(scroll-b)") + execute "normal! \" + call a:cmdline.setchar('') + endif +endfunction + + +function! s:make() + return deepcopy(s:module) +endfunction + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Exception.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Exception.vim new file mode 100644 index 000000000..62ad3c998 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Exception.vim @@ -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(''), '\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('%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(":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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Input.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Input.vim new file mode 100644 index 000000000..dbaadc172 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Input.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Over#Input#import() abort', printf("return map({'getchar': ''}, \"vital#_incsearch#function('%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 " + endtry + " Workaround for the 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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Keymapping.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Keymapping.vim new file mode 100644 index 000000000..85e763c4f --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Keymapping.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Signals.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Signals.vim new file mode 100644 index 000000000..4dc306925 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/Signals.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Over/String.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/String.vim new file mode 100644 index 000000000..2f888d971 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Over/String.vim @@ -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(''), '\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('%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' : '' +" \ => Û\xfdQ +" \ => À\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, "\\%(\\\|\\)(.\\{-})\\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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Capture.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Capture.vim new file mode 100644 index 000000000..ca8220d58 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Capture.vim @@ -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(''), '\zs\d\+\ze__SID$') +endfunction +execute join(['function! vital#_incsearch#Palette#Capture#import() abort', printf("return map({'extend': '', 'command': ''}, \"vital#_incsearch#function('%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, "", "\", "g") +" let result = substitute(result, "", "\", "g") + return result +endfunction + + +let &cpo = s:save_cpo +unlet s:save_cpo diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Highlight.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Highlight.vim new file mode 100644 index 000000000..b7b823b98 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Highlight.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Keymapping.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Keymapping.vim new file mode 100644 index 000000000..3d2cd9065 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Palette/Keymapping.vim @@ -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(''), '\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('%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 : https://github.com/osyo-manga/vital-palette/issues/5 + if a:key ==# "<^?>" + return "\" + 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 : https://github.com/osyo-manga/vital-palette/issues/5 + if a:name ==# "<^?>" + return maparg("\", 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 diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Prelude.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Prelude.vim new file mode 100644 index 000000000..a5cc9ec09 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Prelude.vim @@ -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(''), '\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('%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: diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Buffer.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Buffer.vim new file mode 100644 index 000000000..c3fcb9937 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Buffer.vim @@ -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(''), '\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('%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 $ . +" 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() ==# "\" + 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: diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Guard.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Guard.vim new file mode 100644 index 000000000..3f23d02b0 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Guard.vim @@ -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(''), '\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('%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: diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Message.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Message.vim new file mode 100644 index 000000000..9e44e9a25 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Message.vim @@ -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(''), '\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('%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: diff --git a/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Type.vim b/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Type.vim new file mode 100644 index 000000000..ed3be78d6 --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/_incsearch/Vim/Type.vim @@ -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(''), '\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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/incsearch.vim b/bundle/incsearch.vim/autoload/vital/incsearch.vim new file mode 100644 index 000000000..b622a97ea --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/incsearch.vim @@ -0,0 +1,328 @@ +let s:plugin_name = expand(':t:r') +let s:vital_base_dir = expand(':h') +let s:project_root = expand(':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(''), '\zs\d\+\ze__SID$') + endfunction + let s:_s = '' . 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 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(':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 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("\")), '"[\\x" . printf("%0x", char2nr("\"[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%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('%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 diff --git a/bundle/incsearch.vim/autoload/vital/incsearch.vital b/bundle/incsearch.vim/autoload/vital/incsearch.vital new file mode 100644 index 000000000..6a251893f --- /dev/null +++ b/bundle/incsearch.vim/autoload/vital/incsearch.vital @@ -0,0 +1,5 @@ +incsearch +425a6a62645a9f8e497ba52bab709abaa9f185be + +Over.Commandline +Coaster.Highlight diff --git a/bundle/incsearch.vim/doc/.gitignore b/bundle/incsearch.vim/doc/.gitignore new file mode 100644 index 000000000..6e92f57d4 --- /dev/null +++ b/bundle/incsearch.vim/doc/.gitignore @@ -0,0 +1 @@ +tags diff --git a/bundle/incsearch.vim/doc/incsearch.txt b/bundle/incsearch.vim/doc/incsearch.txt new file mode 100644 index 000000000..538d4a6ad --- /dev/null +++ b/bundle/incsearch.vim/doc/incsearch.txt @@ -0,0 +1,724 @@ +*incsearch.txt* Incrementally highlight all pattern matches + +Author : haya14busa +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* + *(incsearch-forward)* + *(incsearch-backward)* + *(incsearch-stay)* + Write following lines to your vimrc: +> + map / (incsearch-forward) + map ? (incsearch-backward) + map g/ (incsearch-stay) +< + (incsearch-forward): Incremental searching forward + (incsearch-backward): Incremental searching backward + (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* +(incsearch-nohl) *(incsearch-nohl)* +(incsearch-nohl0) *(incsearch-nohl0)* +(incsearch-nohl-n) *(incsearch-nohl-n)* +(incsearch-nohl-N) *(incsearch-nohl-N)* +(incsearch-nohl-*) *(incsearch-nohl-star)* +(incsearch-nohl-#) *(incsearch-nohl-#)* +(incsearch-nohl-g*) *(incsearch-nohl-gstar)* +(incsearch-nohl-g#) *(incsearch-nohl-g#)* + + Let's farewell to this kind of mappings! > + nnoremap :nohlsearch +< + 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 (incsearch-nohl-n) + map N (incsearch-nohl-N) + map * (incsearch-nohl-*) + map # (incsearch-nohl-#) + map g* (incsearch-nohl-g*) + map g# (incsearch-nohl-g#) +< + NOTE: |(incsearch-nohl-n)| stuff are just aliases to + `(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 + |(incsearch-nohl)|. + Please make sure to place |(incsearch-nohl)| before the cursor + moving mappings. |(incsearch-nohl0)| handles search enhancement + mappings without |CursorMoved| event. + + Working with |anzu.txt| example: + https://github.com/osyo-manga/vim-anzu +> + map n (incsearch-nohl)(anzu-n-with-echo) + map N (incsearch-nohl)(anzu-N-with-echo) +< + Working with |asterisk.txt| example: + https://github.com/haya14busa/vim-asterisk +> + map * (incsearch-nohl)(asterisk-*) + map g* (incsearch-nohl)(asterisk-g*) + map # (incsearch-nohl)(asterisk-#) + map g# (incsearch-nohl)(asterisk-g#) + + map z* (incsearch-nohl0)(asterisk-z*) + map gz* (incsearch-nohl0)(asterisk-gz*) + map z# (incsearch-nohl0)(asterisk-z#) + map gz# (incsearch-nohl0)(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 + |(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 , 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|. + + *(incsearch-next)* + *(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| + + (incsearch-next) : to the next match. default: + (incsearch-prev) : to the prev match. default: + + *(incsearch-scroll-f)* + *(incsearch-scroll-b)* + + Scroll-like feature while incremental searching. + + (incsearch-scroll-f) : scroll to the next page match. + default: + (incsearch-scroll-b) : scroll to the previous page match. + default: + NOTE: if you want to use |digraphs| feature, please overwrite + or map another key to like this. > + IncSearchNoreMap +< + + Example: +> + augroup incsearch-keymap + autocmd! + autocmd VimEnter * call s:incsearch_keymap() + augroup END + function! s:incsearch_keymap() + IncSearchNoreMap (incsearch-next) + IncSearchNoreMap (incsearch-prev) + IncSearchNoreMap (incsearch-scroll-f) + IncSearchNoreMap (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} + -------|---------- + | || + | || + | || + | || + | || + | || + | || + | || + +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 = { + \ "\": { + \ 'key': '(buffer-complete)', + \ 'noremap': 1 + \ }, + \ "\": "\", + \ } + +Buffer completion *incsearch-(buffer-complete)* + *incsearch-(buffer-complete-prev)* + Completion with the buffer text. + + (buffer-complete) + start buffer text completion. default: + (buffer-complete-prev) + start buffer text completion to backward direction. + + select next candidate while completion + + select candidate while completion + + Example: > + augroup incsearch-keymap + autocmd! + autocmd VimEnter * call s:incsearch_keymap() + augroup END + function! s:incsearch_keymap() + IncSearchNoreMap (buffer-complete) + IncSearchNoreMap (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-| 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 + 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 mapping. + See |incsearch-config| for available configuration. + + Example: > + noremap z/ incsearch#go() + noremap z? incsearch#go({'command': '?'}) + noremap / 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 z? incsearch#go({'command': '?'}) + +is_stay *incsearch-config-is_stay* + Boolean option for stay feature |(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 g/ incsearch#go({'is_stay': 1}) + +is_expr *incsearch-config-is_expr* + Boolean option for calling main function with state or + not. This value is turned on by default for + |Operator-pending-mode| to support dot-repeat(|.|) without any + additional library. But has a constraint like + |textlock| and moving cursor etc... see |:map-| 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 z/ incsearch#go({'is_expr': 0}) + +pattern *incsearch-config-pattern* + Default pattern to start incsearch.vim's search interface. + Type: |string| + Default: '' + Example: > + noremap / incsearch#go({'pattern': histget('/', -1)}) + +prompt *incsearch-config-prompt* + Prompt string. + Type: |string| + Default: same as |incsearch-config-command| ('/' or '?') + Example: > + noremap / 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 z/ incsearch#go(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': { + \ "\": { + \ 'key': '(buffer-complete)', + \ 'noremap': 1 + \ }, + \ "\": "\" + \ } + \ } + endfunction + + noremap z/ incsearch#go(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 z/ incsearch#go(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 |(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. now inserts literal and search them. + 3. Add workaround pasting issue for MacVim #35 + 4. Fix to redraw commandline when leaving with #67 + 5. Fix handling for 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 mappings + 2. Support incremental highlighting in other windows. + - See |g:incsearch#no_inc_hlsearch| + 3. Add |(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__| behavoir to be compatible with default one + 7. Fix cancel behavior + 8. Fix & improve {rhs} handling (after exit mappings, =, etc...) + 9. Fix minor problems + +0.9.8 2014-10-25 + 1. Handle |last-pattern| incrementally. See: |(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 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-| for normal and visual mode mappings. + - Still use 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: |(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 |(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 |(incsearch-scroll-f)| & + |(incsearch-scroll-b)| + - Handle |wrapscan| option + - Enable cursor moving while |(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: diff --git a/bundle/incsearch.vim/plugin/incsearch.vim b/bundle/incsearch.vim/plugin/incsearch.vim new file mode 100644 index 000000000..5af5047bf --- /dev/null +++ b/bundle/incsearch.vim/plugin/incsearch.vim @@ -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(':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 +" }}} + +" : do not show command in command line +noremap (incsearch-forward) incsearch#go({'command': '/'}) +noremap (incsearch-backward) incsearch#go({'command': '?'}) +noremap (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. `(incsearch-nohl)n` works but `n(incsearch-nohl)` doesn't +" work +noremap (incsearch-nohl) incsearch#autocmd#auto_nohlsearch(1) +noremap (incsearch-nohl0) incsearch#autocmd#auto_nohlsearch(0) +noremap (incsearch-nohl2) incsearch#autocmd#auto_nohlsearch(2) + + +map (incsearch-nohl-n) (incsearch-nohl)(_incsearch-n) +map (incsearch-nohl-N) (incsearch-nohl)(_incsearch-N) +map (incsearch-nohl-*) (incsearch-nohl)(_incsearch-*) +map (incsearch-nohl-#) (incsearch-nohl)(_incsearch-#) +map (incsearch-nohl-g*) (incsearch-nohl)(_incsearch-g*) +map (incsearch-nohl-g#) (incsearch-nohl)(_incsearch-g#) + +" These mappings are just alias to default mappings except they won't be +" remapped any more +noremap (_incsearch-n) g:incsearch#consistent_n_direction && !v:searchforward ? 'N' : 'n' +noremap (_incsearch-N) g:incsearch#consistent_n_direction && !v:searchforward ? 'n' : 'N' +noremap (_incsearch-*) * +noremap (_incsearch-#) # +noremap (_incsearch-g*) g* +noremap (_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([], 's:as_keymapping(v:val)') + [1]) + +command! -nargs=* IncSearchMap +\ call call('s:key_mapping', map([], '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 +" }}} diff --git a/bundle/incsearch.vim/test/.themisrc b/bundle/incsearch.vim/test/.themisrc new file mode 100644 index 000000000..fcb4610eb --- /dev/null +++ b/bundle/incsearch.vim/test/.themisrc @@ -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 + diff --git a/bundle/incsearch.vim/test/api/config/keymap.vimspec b/bundle/incsearch.vim/test/api/config/keymap.vimspec new file mode 100644 index 000000000..b06e5961a --- /dev/null +++ b/bundle/incsearch.vim/test/api/config/keymap.vimspec @@ -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 = {"\": "\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 + diff --git a/bundle/incsearch.vim/test/api/converter.vimspec b/bundle/incsearch.vim/test/api/converter.vimspec new file mode 100644 index 000000000..614100dfc --- /dev/null +++ b/bundle/incsearch.vim/test/api/converter.vimspec @@ -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 diff --git a/bundle/incsearch.vim/test/autocmd.vimspec b/bundle/incsearch.vim/test/autocmd.vimspec new file mode 100644 index 000000000..2a8ef46c3 --- /dev/null +++ b/bundle/incsearch.vim/test/autocmd.vimspec @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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! \" + 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\" + 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\" + Assert Equals(g:i, 1) + End + It should be called with + autocmd incsearch-test User IncSearchLeave :let g:i += 1 + exec "normal" "/vimvim\" + Assert Equals(g:i, 1) + End + It should be called with + autocmd incsearch-test User IncSearchLeave :let g:i += 1 + exec "normal" "/vimvim\" + 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\" + Assert Equals(g:i, 1) + End + It should not be called with + autocmd incsearch-test User IncSearchExecutePre :let g:i += 1 + exec "normal" "/vimvim\" + Assert Equals(g:i, 0) + End + It should not be called with + autocmd incsearch-test User IncSearchExecutePre :let g:i += 1 + exec "normal" "/vimvim\" + 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\" + 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\" + Assert Equals(g:i, 1) + End + It should not be called with + autocmd incsearch-test User IncSearchExecute :let g:i += 1 + exec "normal" "/vimvim\" + Assert Equals(g:i, 0) + End + It should not be called with + autocmd incsearch-test User IncSearchExecute :let g:i += 1 + exec "normal" "/vimvim\" + 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\" + 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\" + 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\" + Assert Equals(g:i, 7) + End + End + +End diff --git a/bundle/incsearch.vim/test/autonohlsearch.vim b/bundle/incsearch.vim/test/autonohlsearch.vim new file mode 100644 index 000000000..90e0bb40c --- /dev/null +++ b/bundle/incsearch.vim/test/autonohlsearch.vim @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (incsearch-stay) + map n (incsearch-nohl-n) + map N (incsearch-nohl-N) + map * (incsearch-nohl-*) + map # (incsearch-nohl-#) + map g* (incsearch-nohl-g*) + map g# (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\" + 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\" + 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 diff --git a/bundle/incsearch.vim/test/cancel.vim b/bundle/incsearch.vim/test/cancel.vim new file mode 100644 index 000000000..f506d8b4d --- /dev/null +++ b/bundle/incsearch.vim/test/cancel.vim @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (incsearch-stay) + call s:reset_buffer() +endfunction + +function! s:suite.before_each() + :1 + normal! zt + " Return to normal mode + exec "normal! \" +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\" + call s:assert.not_equals(s:get_pos_char(), 'a') + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "/\\dpattern_./e\" + 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\" + 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\\" + 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\" + call s:assert.equals(getline('.'), s:lines[0]) +endfunction + +function! s:suite.cancel_backward_operator_pending() + :$ + normal! $ + exec "normal" "d?\\dpattern_d?e\" + call s:assert.equals(getline('.'), s:lines[-1]) +endfunction + +function! s:suite.cancel_stay_operator_pending() + exec "normal" "dg/\\dpattern_./e\\" + 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\" + 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\" + 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\\" + 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\\" + call s:assert.equals(@/, p) + endfor +endfunction + +function! s:suite.highlight_will_not_remain() + for key_seq in ['/', '?', 'g/'] + exec "normal" key_seq . "pattern\\" + 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\\" + 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\" + call s:assert.equals(v:hlsearch, 1) + endfor + set hlsearch& | nohlsearch +endfunction + diff --git a/bundle/incsearch.vim/test/count.vim b/bundle/incsearch.vim/test/count.vim new file mode 100644 index 000000000..8db6ef16a --- /dev/null +++ b/bundle/incsearch.vim/test/count.vim @@ -0,0 +1,97 @@ +let s:suite = themis#suite('count') +let s:assert = themis#helper('assert') + +map / (incsearch-forward) +map ? (incsearch-backward) +map g/ (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\" + call s:assert.equals(s:get_pos_char(), '3') + exec "normal" "2/\\dpattern_[a-z]/e\" + 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\\" + call s:assert.equals(s:get_pos_char(), '3') + exec "normal" "v2/\\dpattern_[a-z]/e\\" + 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\" + call s:assert.equals(s:get_pos_char(), '3') + call s:assert.equals(getline('.'), '3pattern_c') + exec "normal" "2d/\\dpattern_/e\" + 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\" + 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\" + 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\\" + 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]\" + call s:assert.equals(getline('.'), 'e') + exec "normal" "d2?\\dpattern_[a-z]?e\" + 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\" + call s:assert.equals(s:get_pos_char(), '_') + call s:assert.equals(getline('.'), '1pattern_') +endfunction diff --git a/bundle/incsearch.vim/test/default_behaviors.vim b/bundle/incsearch.vim/test/default_behaviors.vim new file mode 100644 index 000000000..4bb9704f6 --- /dev/null +++ b/bundle/incsearch.vim/test/default_behaviors.vim @@ -0,0 +1,168 @@ +let s:suite = themis#suite('default_behaviors') +let s:assert = themis#helper('assert') + +map / (incsearch-forward) +map ? (incsearch-backward) +map g/ (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 . "\" + " let x = getcurpos() + let x = winsaveview() + call winrestview(w) + silent! exec 'normal ' . a:command . a:pattern . "\" + " 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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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\" + 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\" + call s:assert.equals(@/, 'pattern\d') + call s:assert.equals(histget('/', -1), 'pattern\d/e') +endfunction diff --git a/bundle/incsearch.vim/test/default_settings.vim b/bundle/incsearch.vim/test/default_settings.vim new file mode 100644 index 000000000..2d7d51813 --- /dev/null +++ b/bundle/incsearch.vim/test/default_settings.vim @@ -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('(incsearch-forward)' , 'nvo'), "incsearch#go({'command': '/'})") + call s:assert.equals(maparg('(incsearch-backward)', 'nvo'), "incsearch#go({'command': '?'})") + call s:assert.equals(maparg('(incsearch-stay)' , 'nvo'), "incsearch#go({'command': '/', 'is_stay': 1})") + " Additional: + call s:assert.equals(maparg('(incsearch-nohl)', 'nvo'), 'incsearch#autocmd#auto_nohlsearch(1)') + call s:assert.equals(maparg('(incsearch-nohl0)', 'nvo'), 'incsearch#autocmd#auto_nohlsearch(0)') + call s:assert.equals(maparg('(incsearch-nohl-n)' , 'nvo'), '(incsearch-nohl)(_incsearch-n)') + call s:assert.equals(maparg('(incsearch-nohl-N)' , 'nvo'), '(incsearch-nohl)(_incsearch-N)') + call s:assert.equals(maparg('(incsearch-nohl-*)' , 'nvo'), '(incsearch-nohl)(_incsearch-*)') + call s:assert.equals(maparg('(incsearch-nohl-#)' , 'nvo'), '(incsearch-nohl)(_incsearch-#)') + call s:assert.equals(maparg('(incsearch-nohl-g*)', 'nvo'), '(incsearch-nohl)(_incsearch-g*)') + call s:assert.equals(maparg('(incsearch-nohl-g#)', 'nvo'), '(incsearch-nohl)(_incsearch-g#)') + " Alias To The Default: + call s:assert.equals(maparg('(_incsearch-n)' , 'nvo'), 'g:incsearch#consistent_n_direction && !v:searchforward ? ''N'' : ''n''') + call s:assert.equals(maparg('(_incsearch-N)' , 'nvo'), 'g:incsearch#consistent_n_direction && !v:searchforward ? ''n'' : ''N''') + call s:assert.equals(maparg('(_incsearch-*)' , 'nvo'), '*') + call s:assert.equals(maparg('(_incsearch-#)' , 'nvo'), '#') + call s:assert.equals(maparg('(_incsearch-g*)', 'nvo'), 'g*') + call s:assert.equals(maparg('(_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 diff --git a/bundle/incsearch.vim/test/error_warning_emulation.vim b/bundle/incsearch.vim/test/error_warning_emulation.vim new file mode 100644 index 000000000..3b7f6df0c --- /dev/null +++ b/bundle/incsearch.vim/test/error_warning_emulation.vim @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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 . "びむぅぅぅぅ\" + " call s:assert.equals(v:errmsg, 'E486: Pattern not found: びむぅぅぅぅ') + silent! exec "normal" keyseq . "bbb\" + call s:assert.equals(v:errmsg, 'E486: Pattern not found: bbb') + " feedkeys() + silent! exec "normal" keyseq . "aaa" . keyseq . "e\" + call s:assert.equals(v:errmsg, 'E486: Pattern not found: aaa') + " silent! exec "normal" keyseq . "びむぅぅぅぅ\\(\" + silent! exec "normal" keyseq . "pattern\\(\" + call s:assert.equals(v:errmsg, 'E54: Unmatched \(') + silent! exec "normal" keyseq . "pattern\\)\" + call s:assert.equals(v:errmsg, 'E55: Unmatched \)') + silent! exec "normal" keyseq . "bbb\\zA\" + 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/びむぅぅぅぅ\" + call s:assert.equals(v:errmsg, 'E486: Pattern not found: びむぅぅぅぅ') + " feedkeys() + silent! exec "normal" "g/aaa/e\" + call s:assert.equals(v:errmsg, 'E486: Pattern not found: aaa') + exec "normal" "g/びむぅぅぅぅ\\(\" + call s:assert.equals(v:errmsg, 'E54: Unmatched \(') + exec "normal" "g/びむぅぅぅぅ\\)\" + call s:assert.equals(v:errmsg, 'E55: Unmatched \)') + exec "normal" "g/びむぅぅぅぅ\\zA\" + call s:assert.equals(v:errmsg, 'E68: Invalid character after \z') +endfunction + +function! s:suite.two_error_E383_and_E367() + if ! exists('®expengine') + 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\" + 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\" + call s:assert.equals(v:errmsg, 'E385: search hit BOTTOM without match for: 1pattern') + exec "normal" "/aaa\" + call s:assert.equals(v:errmsg, 'E385: search hit BOTTOM without match for: aaa') + silent! exec "normal" "/aaa/e\" + 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\" + call s:assert.equals(v:errmsg, 'E384: search hit TOP without match for: 4pattern') + exec "normal" "?aaa\" + call s:assert.equals(v:errmsg, 'E384: search hit TOP without match for: aaa') + silent! exec "normal" "?aaa?e\" + 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\" + call s:assert.equals(v:errmsg, 'E385: search hit BOTTOM without match for: 1pattern') + exec "normal" "g/aaa\" + call s:assert.equals(v:errmsg, 'E385: search hit BOTTOM without match for: aaa') + silent! exec "normal" "g/aaa/e\" + 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\" + elseif v:version == 704 && has('patch421') + set regexpengine=2 + let v:errmsg = '' + exec "normal" "/emacs\\ze*vim\" + " 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\" + 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\" + call s:assert.equals(s:get_pos_char(), '3') + call s:assert.equals(v:warningmsg, 'old warning') + exec "normal" "/1pattern\" + 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\" + call s:assert.equals(s:get_pos_char(), '2') + call s:assert.equals(v:warningmsg, 'old warning') + exec "normal" "?4pattern\" + 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\" + call s:assert.equals(s:get_pos_char(), '2') + call s:assert.equals(v:warningmsg, 'old warning') + exec "normal" "g/1pattern\" + 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\" + call s:assert.equals(s:get_pos_char(), '3') + call s:assert.equals(v:warningmsg, 'old warning') + exec "normal" "/1pattern\" + call s:assert.equals(s:get_pos_char(), '1') + call s:assert.equals(v:warningmsg, 'old warning') + set shortmess& +endfunction + diff --git a/bundle/incsearch.vim/test/fold.vim b/bundle/incsearch.vim/test/fold.vim new file mode 100644 index 000000000..ece80f21a --- /dev/null +++ b/bundle/incsearch.vim/test/fold.vim @@ -0,0 +1,160 @@ +let s:suite = themis#suite('fold') +let s:assert = themis#helper('assert') + +map / (incsearch-forward) +map ? (incsearch-backward) +map g/ (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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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\" + call s:assert.equals(foldclosed(6), -1) +endfunction + +function! s:suite.unfold_after_search_forward_offset() + exec "normal" "/destination/e\" + call s:assert.equals(foldclosed(6), -1) +endfunction + +function! s:suite.unfold_after_search_backward() + exec "normal" "?destination\" + call s:assert.equals(foldclosed(6), -1) +endfunction + +function! s:suite.unfold_after_search_backward() + exec "normal" "?destination?e\" + call s:assert.equals(foldclosed(6), -1) +endfunction + +function! s:suite.do_not_unfold_after_just_stay() + exec "normal" "g/destination\" + call s:assert.equals(foldclosed(6), 4) + exec "normal" "g/destination/e\" + call s:assert.equals(foldclosed(6), 4) +endfunction + +function! s:suite.unfold_after_exit_stay() + exec "normal" "g/destination\\" + call s:assert.equals(foldclosed(6), -1) +endfunction + +function! s:suite.unfold_after_exit_stay_offset() + exec "normal" "g/destination/e\\" + 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\" + call s:assert.equals(foldclosed(6), 4) + normal! gg + exec "normal" "/destination/e\" + call s:assert.equals(foldclosed(6), 4) + normal! gg + exec "normal" "?destination\" + call s:assert.equals(foldclosed(6), 4) + normal! gg + exec "normal" "?destination?e\" + call s:assert.equals(foldclosed(6), 4) + normal! gg + exec "normal" "g/destination\\" + call s:assert.equals(foldclosed(6), 4) + normal! gg + exec "normal" "g/destination/e\\" + 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\" + call s:assert.equals(foldclosed(6), -1) + normal! ggzM + exec "normal" "/destination/e\" + call s:assert.equals(foldclosed(6), -1) + normal! ggzM + exec "normal" "?destination\" + call s:assert.equals(foldclosed(6), -1) + normal! ggzM + exec "normal" "?destination?e\" + call s:assert.equals(foldclosed(6), -1) + normal! ggzM + exec "normal" "g/destination\\" + call s:assert.equals(foldclosed(6), -1) + normal! ggzM + exec "normal" "g/destination/e\\" + 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\" + call s:assert.equals(foldclosed(6), 4) + normal! gg + exec "normal" "gu/destination/e\" + call s:assert.equals(foldclosed(6), 4) + normal! gg + exec "normal" "gu?destination\" + call s:assert.equals(foldclosed(6), 4) + normal! gg + exec "normal" "gu?destination?e\" + call s:assert.equals(foldclosed(6), 4) + normal! gg + exec "normal" "gug/destination\\" + call s:assert.equals(foldclosed(6), 4) + normal! gg + exec "normal" "gug/destination/e\\" + call s:assert.equals(foldclosed(6), 4) +endfunction + + diff --git a/bundle/incsearch.vim/test/highlight.vim b/bundle/incsearch.vim/test/highlight.vim new file mode 100644 index 000000000..48e3a9c4c --- /dev/null +++ b/bundle/incsearch.vim/test/highlight.vim @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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\" + 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\" + 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\" + endfor + let g:incsearch#separate_highlight = 0 + for keyseq in ['/', '?', 'g/'] + exec "normal" keyseq . "pattern\" + endfor +endfunction diff --git a/bundle/incsearch.vim/test/history.vim b/bundle/incsearch.vim/test/history.vim new file mode 100644 index 000000000..d4ccfba66 --- /dev/null +++ b/bundle/incsearch.vim/test/history.vim @@ -0,0 +1,50 @@ +let s:suite = themis#suite('history') +let s:assert = themis#helper('assert') + +function! s:suite.before() + :1,$ delete + map / (incsearch-forward) + map ? (incsearch-backward) + map g/ (incsearch-stay) + set history=5 +endfunction + +function! s:suite.before_each() + " call histdel('search') " Segmentation fault (core dumped) + silent! exec "normal" "/\\" +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\" + call s:assert.equals(histget('search', -1), 'pattern') + silent! exec "normal" "/pattern/e\" + 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\" + call s:assert.equals(histget('search', -1), 'pattern') + silent! exec "normal" "?pattern/e\" + 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\" + call s:assert.equals(histget('search', -1), 'pattern') + silent! exec "normal" "g/pattern/e\" + call s:assert.equals(histget('search', -1), 'pattern/e') + silent! exec "normal" "g/pattern/e\\" + call s:assert.equals(histget('search', -1), 'pattern/e') +endfunction + diff --git a/bundle/incsearch.vim/test/inc_cursor_pos.vim b/bundle/incsearch.vim/test/inc_cursor_pos.vim new file mode 100644 index 000000000..a0e980ac4 --- /dev/null +++ b/bundle/incsearch.vim/test/inc_cursor_pos.vim @@ -0,0 +1,2 @@ +" TODO: +" but difficult to test diff --git a/bundle/incsearch.vim/test/inc_hlsearch.vim b/bundle/incsearch.vim/test/inc_hlsearch.vim new file mode 100644 index 000000000..dcfcf5e12 --- /dev/null +++ b/bundle/incsearch.vim/test/inc_hlsearch.vim @@ -0,0 +1 @@ +" TODO: diff --git a/bundle/incsearch.vim/test/incremental_next_prev.vim b/bundle/incsearch.vim/test/incremental_next_prev.vim new file mode 100644 index 000000000..4615226bc --- /dev/null +++ b/bundle/incsearch.vim/test/incremental_next_prev.vim @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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\\" + call s:assert.equals(getline('.'), s:line_texts[2]) + :1 + exec "normal" "/pattern\\zs\\d\\\" + 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\\" + call s:assert.equals(getline('.'), s:line_texts[4]) + :$ + exec "normal" "?pattern\\zs\\d\\\" + call s:assert.equals(getline('.'), s:line_texts[3]) +endfunction + +function! s:suite.inc_prev_forward() + exec "normal" "/pattern\\zs\\d\\\" + call s:assert.equals(getline('.'), s:line_texts[1]) + :1 + exec "normal" "/pattern\\zs\\d\\\\" + 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\\\" + call s:assert.equals(getline('.'), s:line_texts[5]) + :$ + exec "normal" "?pattern\\zs\\d\\\\" + call s:assert.equals(getline('.'), s:line_texts[4]) +endfunction + +function! s:suite.inc_next_stay() + exec "normal" "g/pattern\\zs\\d\\" + call s:assert.equals(getline('.'), s:line_texts[1]) + :1 + exec "normal" "g/pattern\\zs\\d\\\" + call s:assert.equals(getline('.'), s:line_texts[2]) +endfunction + +function! s:suite.inc_prev_stay() + exec "normal" "g/pattern\\zs\\d\\\\" + 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" "/\\\" + 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\\\" + 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" "/\\\" + 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\\\\" + call s:assert.equals(getline('.'), s:line_texts[5]) + set wrapscan + :3 + exec "normal" "/pattern\\\\" + 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\\\\" + call s:assert.equals(getline('.'), s:line_texts[1]) + set wrapscan + :5 + exec "normal" "?pattern\\\\" + call s:assert.equals(getline('.'), s:line_texts[5]) +endfunction diff --git a/bundle/incsearch.vim/test/insert_register.vim b/bundle/incsearch.vim/test/insert_register.vim new file mode 100644 index 000000000..4aa66847a --- /dev/null +++ b/bundle/incsearch.vim/test/insert_register.vim @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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\\/e\" +endfunction + +function! s:suite.cword_incsearch() + exec "normal" "/p\\/e\" + call s:assert.equals(s:get_pos_char(), 1) +endfunction + +function! s:suite.cword_incsearch_middle() + exec "normal" "/pa\\\\\/e\" + call s:assert.equals(s:get_pos_char(), 1) +endfunction + +function! s:suite.cword_incsearch_cli_cursor_middle() + exec "normal" "/pa\\\\\/e\" + 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\\/e\" +endfunction + +function! s:suite.cword_from_last_matched_pos() + exec "normal" "/emacs \\/e\" + 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\\\\\" + call s:assert.equals(getline('.'), s:line_texts[5]) + call s:assert.equals(@/, 's:4pattern4') +endfunction + +function! s:suite.search() + let @/ = 'emacs' + exec "normal" "/\/ vim3/e\" + call s:assert.equals(s:get_pos_char(), 3) +endfunction + diff --git a/bundle/incsearch.vim/test/jumplist.vim b/bundle/incsearch.vim/test/jumplist.vim new file mode 100644 index 000000000..709eb4ff2 --- /dev/null +++ b/bundle/incsearch.vim/test/jumplist.vim @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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\" + call s:assert.equals(s:get_pos_char(), '2') + exec "normal" "/3pattern\" + call s:assert.equals(s:get_pos_char(), '3') + exec "normal! \" + call s:assert.equals(s:get_pos_char(), '2') + exec "normal! \" + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "/4pattern/e\" + call s:assert.equals(s:get_pos_char(), 'n') + exec "normal! \" + 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\" + call s:assert.equals(s:get_pos_char(), '3') + exec "normal" "?2pattern\" + call s:assert.equals(s:get_pos_char(), '2') + exec "normal! \" + call s:assert.equals(s:get_pos_char(), '3') + exec "normal! \" + 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! \" + 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\" + call s:assert.equals(s:get_pos_char(), '2') + exec "normal! \" + 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\" + call s:assert.equals(s:get_pos_char(), '2') + exec "normal! \" + 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! \" + 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\\" + call s:assert.equals(s:get_pos_char(), '3') + exec "normal! \" + call s:assert.equals(s:get_pos_char(), '2') +endfunction diff --git a/bundle/incsearch.vim/test/lastpattern.vimspec b/bundle/incsearch.vim/test/lastpattern.vimspec new file mode 100644 index 000000000..6f580c125 --- /dev/null +++ b/bundle/incsearch.vim/test/lastpattern.vimspec @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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" "/\" + 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\" + 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" "/\" + 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\" + Assert Equals(line('.'), '2') + Assert Equals(GetPosChar(), 'b') + End + End + +End diff --git a/bundle/incsearch.vim/test/magic_option.vim b/bundle/incsearch.vim/test/magic_option.vim new file mode 100644 index 000000000..1a67db677 --- /dev/null +++ b/bundle/incsearch.vim/test/magic_option.vim @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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\", 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\", 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\", 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\", 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\", p) + call s:assert.equals(getline('.'), s:line_texts[3]) + call s:assert.equals(@/, p) +endfunction diff --git a/bundle/incsearch.vim/test/module.vim b/bundle/incsearch.vim/test/module.vim new file mode 100644 index 000000000..80e06b2ee --- /dev/null +++ b/bundle/incsearch.vim/test/module.vim @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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\\/e\" + call s:assert.equals(s:get_pos_char(), 'a') + :1 + let g:incsearch#smart_backward_word = 1 + exec "normal" "/\\dpattern_./e\\v\\" + call s:assert.equals(s:get_pos_char(), 'a') +endfunction + diff --git a/bundle/incsearch.vim/test/n_and_N.vim b/bundle/incsearch.vim/test/n_and_N.vim new file mode 100644 index 000000000..415722f1e --- /dev/null +++ b/bundle/incsearch.vim/test/n_and_N.vim @@ -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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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\" + 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\" + 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\" + 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\\" + 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\" + 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\" + 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 + + diff --git a/bundle/incsearch.vim/test/nomagic.vim b/bundle/incsearch.vim/test/nomagic.vim new file mode 100644 index 000000000..ae247229f --- /dev/null +++ b/bundle/incsearch.vim/test/nomagic.vim @@ -0,0 +1,78 @@ +let s:suite = themis#suite('nomagic') +let s:assert = themis#helper('assert') + +map / (incsearch-forward) +map ? (incsearch-backward) +map g/ (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 / (incsearch-forward) + map ? (incsearch-backward) + map g/ (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\" + call s:assert.equals(s:get_pos_char(), '2') + exec "normal" "/\\dpattern_\\[a-z]/e\" + call s:assert.equals(s:get_pos_char(), 'b') + exec "normal" "?\\dpattern\" + call s:assert.equals(s:get_pos_char(), '2') + exec "normal" "?\\dpattern_\\[a-z]?e\" + call s:assert.equals(s:get_pos_char(), 'a') +endfunction + +function! s:suite.works_with_nomagic_stay() + exec "normal" "g/\\dpattern\" + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "g/\\dpattern\\" + call s:assert.equals(s:get_pos_char(), '2') + exec "normal" "g/\\dpattern_\\[a-z]/e\" + call s:assert.equals(s:get_pos_char(), '2') + exec "normal" "g/\\dpattern_\\[a-z]/e\\" + call s:assert.equals(s:get_pos_char(), 'b') +endfunction + +function! s:suite.nomagic_as_a_pattern() + exec "normal" "/.pattern\" + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "/pat*ern\" + call s:assert.equals(s:get_pos_char(), '1') +endfunction + diff --git a/bundle/incsearch.vim/test/operator_pending_behavior.vim b/bundle/incsearch.vim/test/operator_pending_behavior.vim new file mode 100644 index 000000000..67e36d286 --- /dev/null +++ b/bundle/incsearch.vim/test/operator_pending_behavior.vim @@ -0,0 +1,101 @@ +let s:suite = themis#suite('operator_pending_behavior') +let s:assert = themis#helper('assert') + +map / (incsearch-forward) +map ? (incsearch-backward) +map g/ (incsearch-stay) + +" NOTE: Also see repetition.vim spec +" :h o_v +" :h o_V +" :h o_CTRL-V + +" 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_each() + call s:reset_buffer() + :1 + call s:assert.equals(s:get_pos_char(), '1') +endfunction + +function! s:suite.before() + map / (incsearch-forward) + map ? (incsearch-backward) + map g/ (incsearch-stay) + let s:line_texts = ['1pattern_a', '2pattern_b', '3pattern_c', '4pattern_d', '5pattern_e'] +endfunction + +function! s:suite.after() + unmap / + unmap ? + unmap g/ + :1,$ delete +endfunction + +function! s:suite.force_exclusive() + call s:assert.skip("because it seems vim has no way to restore o_v, o_V, and o_Ctrl-V information once Escaping") + " NOTE: + " - http://lingr.com/room/vim/archives/2014/09/22#message-20239719 + " - https://groups.google.com/forum/#!topic/vim_dev/MNtX3jHkNWw + " - https://groups.google.com/forum/#!msg/vim_dev/lR5rONDwgs8/iLsVCrxo_WsJ + :1,$ delete + call s:add_line('1pattern 2pattern 3pattern 4pattern 5pattern') + normal! gg0 + call s:assert.equals(getline('.'), '1pattern 2pattern 3pattern 4pattern 5pattern') + exec "normal" "dv/\\dpattern\" + call s:assert.equals(getline('.'), 'pattern 3pattern 4pattern 5pattern') +endfunction + +function! s:suite.operator_c() + call s:assert.equals(getline('.'), '1pattern_a') + exec "normal" "c/_a\vimvim\" + call s:assert.equals(getline('.'), 'vimvim_a') + normal! j0 + call s:assert.equals(getline('.'), '2pattern_b') + exec "normal" "c/_b/e\vimvimvim~?\" + call s:assert.equals(getline('.'), 'vimvimvim~?') + normal! j$ + call s:assert.equals(getline('.'), '3pattern_c') + exec "normal" "c?pattern\vimvimvim\" + call s:assert.equals(getline('.'), '3vimvimvimc') + normal! j$ + call s:assert.equals(getline('.'), '4pattern_d') + exec "normal" "c?pattern?b3\vim\" + call s:assert.equals(getline('.'), '4patvimd') +endfunction + +function! s:suite.stay_cancell_operator_c() + call s:assert.equals(getline('.'), '1pattern_a') + exec "normal" "cg/_a\e\" + call s:assert.not_equals(getline('.'), 'e_a') + call s:assert.equals(s:get_pos_char(), 'a') +endfunction + +function! s:suite.exit_stay_works_with_operator_c() + call s:assert.equals(getline('.'), '1pattern_a') + exec "normal" "cg/_a\\e\" + call s:assert.equals(getline('.'), 'e_a') +endfunction + +function! s:suite.another_search_offset() + call s:assert.equals(getline('.'), '1pattern_a') + exec "normal" "c/b/;/pattern_/e\vim\" + call s:assert.equals(getline('.'), 'vimc') +endfunction diff --git a/bundle/incsearch.vim/test/question_pattern.vimspec b/bundle/incsearch.vim/test/question_pattern.vimspec new file mode 100644 index 000000000..a3577e8e5 --- /dev/null +++ b/bundle/incsearch.vim/test/question_pattern.vimspec @@ -0,0 +1,50 @@ +Describe question_pattern + 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_?', '2pattern_??', '3?pattern_c'] + call s:add_lines(s:lines) + normal! Gddgg0zt + endfunction + + Before all + let PowerAssert = powerassert#import() + execute PowerAssert.define('PowerAssert') + let s:assert = PowerAssert.assert + + map / (incsearch-forward) + map ? (incsearch-backward) + map g/ (incsearch-stay) + call s:reset_buffer() + End + + Before each + :1 + normal! zt + End + + Describe search register @/ + It @/ should be ? with `?\?` + :$ + exec "normal" "?\\?\" + PowerAssert @/ is# '?' + End + + It @/ should be \/ with `/\/` + exec "normal" "/\\/\" + PowerAssert @/ is# '\/' + End + End + +End diff --git a/bundle/incsearch.vim/test/register.vim b/bundle/incsearch.vim/test/register.vim new file mode 100644 index 000000000..0a0a875b6 --- /dev/null +++ b/bundle/incsearch.vim/test/register.vim @@ -0,0 +1,50 @@ +let s:suite = themis#suite('register') +let s:assert = themis#helper('assert') + +map / (incsearch-forward) +map ? (incsearch-backward) +map g/ (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! G + call s:add_lines(range(100)) + normal! Gddgg0zt +endfunction + +function! s:suite.before_each() + call s:reset_buffer() +endfunction + +function! s:suite.unnamed_register() + call s:add_line('1pattern 2pattern 3pattern 4pattern') + normal! gg0 + call setreg(v:register, '') + call s:assert.equals(getreg(v:register), '') + exec "normal" "d/\\dpattern\" + call s:assert.equals(s:get_pos_char(), '2') + call s:assert.equals(getreg(v:register), '1pattern ') +endfunction + +function! s:suite.quote_register() + call s:add_line('1pattern 2pattern 3pattern 4pattern') + normal! gg0 + call setreg('a', '') + call s:assert.equals(getreg('a'), '') + exec "normal" "\"ad/\\dpattern\" + call s:assert.equals(getreg('a'), '1pattern ') +endfunction diff --git a/bundle/incsearch.vim/test/repetition.vim b/bundle/incsearch.vim/test/repetition.vim new file mode 100644 index 000000000..5791fc8e1 --- /dev/null +++ b/bundle/incsearch.vim/test/repetition.vim @@ -0,0 +1,143 @@ +let s:suite = themis#suite('repetition') +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:suite.before() + map / (incsearch-forward) + map ? (incsearch-backward) + map g/ (incsearch-stay) +endfunction + +function! s:suite.before_each() + :1,$ delete +endfunction + +function! s:suite.after() + unmap / + unmap ? + unmap g/ + :1,$ delete +endfunction + +function! s:suite.repetition_forward() + call s:add_line('1pattern 2pattern 3pattern 4pattern') + normal! gg0 + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "d/\\dpattern\" + call s:assert.equals(s:get_pos_char(), '2') + normal! . + call s:assert.equals(s:get_pos_char(), '3') + normal! . + call s:assert.equals(s:get_pos_char(), '4') +endfunction + +function! s:suite.repetition_backward() + call s:add_line('pattern4 pattern3 pattern2 pattern1') + normal! gg$ + call s:assert.equals(getline('.'), 'pattern4 pattern3 pattern2 pattern1') + exec "normal" "d?pattern\" + call s:assert.equals(getline('.'), 'pattern4 pattern3 pattern2 1') + normal! . + call s:assert.equals(getline('.'), 'pattern4 pattern3 1') + normal! . + call s:assert.equals(getline('.'), 'pattern4 1') + normal! . + call s:assert.equals(getline('.'), '1') +endfunction + +function! s:suite.stay() + call s:add_line('1pattern 2pattern 3pattern 4pattern') + normal! gg0 + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "dg/\\dpattern\" + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "dg/\\dpattern\\" + call s:assert.equals(s:get_pos_char(), '2') + normal! . + call s:assert.equals(s:get_pos_char(), '3') + normal! . + call s:assert.equals(s:get_pos_char(), '4') +endfunction + +function! s:suite.count_forward() + call s:add_line('1pattern 2pattern 3pattern 4pattern 5pattern') + normal! gg0 + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "2d/\\dpattern\" + call s:assert.equals(s:get_pos_char(), '3') + normal! . + call s:assert.equals(s:get_pos_char(), '5') +endfunction + +function! s:suite.count_backward() + call s:add_line('pattern5 pattern4 pattern3 pattern2 pattern1') + normal! gg$ + call s:assert.equals(getline('.'), 'pattern5 pattern4 pattern3 pattern2 pattern1') + exec "normal" "2d?pattern\" + call s:assert.equals(getline('.'), 'pattern5 pattern4 pattern3 1') + normal! . + call s:assert.equals(getline('.'), 'pattern5 1') +endfunction + +function! s:suite.repetition_forward_change() + call s:add_line('1pattern 2pattern 3pattern 4pattern') + normal! gg0 + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "c/\\dpattern\vim\" + call s:assert.equals(s:get_pos_char(), 'm') + normal! l + call s:assert.equals(s:get_pos_char(), '2') + normal! . + call s:assert.equals(s:get_pos_char(), 'm') + normal! l + call s:assert.equals(s:get_pos_char(), '3') + normal! . + call s:assert.equals(s:get_pos_char(), 'm') + normal! l + call s:assert.equals(s:get_pos_char(), '4') +endfunction + +function! s:suite.repetition_backward_change() + call s:add_line('1pattern 2pattern 3pattern 4pattern') + normal! gg$ + call s:assert.equals(s:get_pos_char(), 'n') + exec "normal" "c?\\dpattern\vim\" + call s:assert.equals(s:get_pos_char(), 'm') + call s:assert.equals(getline('.'), '1pattern 2pattern 3pattern vimn') + normal! . + call s:assert.equals(getline('.'), '1pattern 2pattern vimmn') + normal! . + call s:assert.equals(getline('.'), '1pattern vimmmn') +endfunction + +function! s:suite.repetition_stay_change() + call s:add_line('1pattern 2pattern 3pattern 4pattern') + normal! gg0 + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "cg/\\dpattern\ggg\" + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "cg/\\dpattern\\vim\" + call s:assert.equals(s:get_pos_char(), 'm') + normal! l + call s:assert.equals(s:get_pos_char(), '2') + normal! . + call s:assert.equals(s:get_pos_char(), 'm') + normal! l + call s:assert.equals(s:get_pos_char(), '3') + normal! . + call s:assert.equals(s:get_pos_char(), 'm') + normal! l + call s:assert.equals(s:get_pos_char(), '4') +endfunction diff --git a/bundle/incsearch.vim/test/scroll.vim b/bundle/incsearch.vim/test/scroll.vim new file mode 100644 index 000000000..069ce5041 --- /dev/null +++ b/bundle/incsearch.vim/test/scroll.vim @@ -0,0 +1,91 @@ +let s:suite = themis#suite('scroll') +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(copy(s:line_texts)) + normal! Gddgg0zt +endfunction + +function! s:suite.before() + map / (incsearch-forward) + map ? (incsearch-backward) + map g/ (incsearch-stay) + let h = winheight(0) + let s:line_texts = + \ ['pattern1 pattern2 pattern3'] + \ + range(h * 2) + \ + ['pattern4 pattern5 pattern6'] + call s:reset_buffer() +endfunction + +function! s:suite.before_each() + :1 + normal! zt + set wrapscan& +endfunction + +function! s:suite.after() + unmap / + unmap ? + unmap g/ + :1,$ delete + set wrapscan& +endfunction + +function! s:suite.scroll_f_works() + call s:assert.equals(s:get_pos_char(), 'p') + exec "normal /pattern\\zs\\d\" + normal! gg0 + exec "normal /pattern\\zs\\d\\" + call s:assert.equals(s:get_pos_char(), '4') + normal! gg0 + exec "normal /pattern\\zs\\d\\\\" + call s:assert.equals(s:get_pos_char(), '5') +endfunction + +function! s:suite.scroll_b_works() + normal! G$ + call s:assert.equals(getline('.'), 'pattern4 pattern5 pattern6') + normal! gg + call s:assert.equals(getline('.'), 'pattern1 pattern2 pattern3') + normal! G$ + call s:assert.equals(s:get_pos_char(), '6') + normal! G$zt + call s:assert.equals(s:get_pos_char(), '6') + exec "normal ?pattern\\zs\\d\\" + call s:assert.equals(s:get_pos_char(), '3') +endfunction + +function! s:suite.wrapscan_scroll_reverse__move_cursor() + call s:assert.equals(s:get_pos_char(), 'p') + exec "normal /pattern\\zs\\d\\" + call s:assert.equals(s:get_pos_char(), '6') +endfunction + +function! s:suite.nowrapscan_scroll_reverse_move_cursor_to_the_last_pattern() + set nowrapscan + normal! G0 + call s:assert.equals(s:get_pos_char(), 'p') + exec "normal /pattern\\zs\\d\\" + call s:assert.not_equals(s:get_pos_char(), '3') + call s:assert.equals(s:get_pos_char(), '4') + normal! gg$ + call s:assert.equals(s:get_pos_char(), '3') + exec "normal ?pattern\\zs\\d\\" + call s:assert.not_equals(s:get_pos_char(), '4') + call s:assert.equals(s:get_pos_char(), '2') +endfunction diff --git a/bundle/incsearch.vim/test/test.vimrc b/bundle/incsearch.vim/test/test.vimrc new file mode 100644 index 000000000..4aa4914e4 --- /dev/null +++ b/bundle/incsearch.vim/test/test.vimrc @@ -0,0 +1,11 @@ +" This vimrc is for manual test, is not relavant with themis +" $ vim -N -u test/test.vimrc + +set nocompatible +let s:path = expand(":h:h") +set runtimepath& +let &runtimepath .= ',' . s:path + +map / (incsearch-forward) +map ? (incsearch-backward) +map g/ (incsearch-stay) diff --git a/bundle/incsearch.vim/test/util.vim b/bundle/incsearch.vim/test/util.vim new file mode 100644 index 000000000..23f54eafa --- /dev/null +++ b/bundle/incsearch.vim/test/util.vim @@ -0,0 +1,87 @@ +let s:suite = themis#suite('util') +let s:assert = themis#helper('assert') + +function! s:suite.after_each() + set ignorecase& smartcase& +endfunction + +function! s:suite.parse_pattern() + call s:assert.equals( + \ incsearch#parse_pattern('pattern/e', '/'), ['pattern', 'e']) + call s:assert.equals( + \ incsearch#parse_pattern('{pattern\/pattern}/{offset}', '/'), + \ ['{pattern\/pattern}', '{offset}']) + call s:assert.equals( + \ incsearch#parse_pattern('{pattern}/;/{newpattern} :h //;', '/'), + \ ['{pattern}', ';/{newpattern} :h //;']) + call s:assert.equals( + \ incsearch#parse_pattern('pattern?e', '?'), ['pattern', 'e']) + call s:assert.equals( + \ incsearch#parse_pattern('pattern?e', '/'), ['pattern?e', '']) + call s:assert.equals( + \ incsearch#parse_pattern('{pattern\?pattern}?{offset}', '?'), + \ ['{pattern\?pattern}', '{offset}']) +endfunction + +function! s:suite.detect_case() + set noignorecase nosmartcase + call s:assert.equals(incsearch#detect_case('pattern'), '\C') + call s:assert.equals(incsearch#detect_case('PatterN'), '\C') + set ignorecase nosmartcase + call s:assert.equals(incsearch#detect_case('pattern'), '\c') + call s:assert.equals(incsearch#detect_case('PatterN'), '\c') + set noignorecase smartcase + call s:assert.equals(incsearch#detect_case('pattern'), '\C') + call s:assert.equals(incsearch#detect_case('PatterN'), '\C') + set ignorecase smartcase + call s:assert.equals(incsearch#detect_case('pattern'), '\c') + call s:assert.equals(incsearch#detect_case('PatterN'), '\C') +endfunction + +function! s:suite.detect_case_ignore_uppercase_escaped_letters() + set noignorecase nosmartcase + call s:assert.equals(incsearch#detect_case('\Vpattern'), '\C') + call s:assert.equals(incsearch#detect_case('\VPatterN'), '\C') + set ignorecase nosmartcase + call s:assert.equals(incsearch#detect_case('\Vpattern'), '\c') + call s:assert.equals(incsearch#detect_case('\VPatterN'), '\c') + set noignorecase smartcase + call s:assert.equals(incsearch#detect_case('\Vpattern'), '\C') + call s:assert.equals(incsearch#detect_case('\VPatterN'), '\C') + set ignorecase smartcase + call s:assert.equals(incsearch#detect_case('\Vpattern'), '\c') + call s:assert.equals(incsearch#detect_case('\VPatterN'), '\C') +endfunction + +function! s:suite.detect_case_explicit_flag() + set noignorecase nosmartcase + call s:assert.equals(incsearch#detect_case('\cpattern'), '\c') + call s:assert.equals(incsearch#detect_case('\Cpattern'), '\C') + call s:assert.equals(incsearch#detect_case('\CPatterN'), '\C') + call s:assert.equals(incsearch#detect_case('\cPatterN'), '\c') + set ignorecase nosmartcase + call s:assert.equals(incsearch#detect_case('\cpattern'), '\c') + call s:assert.equals(incsearch#detect_case('\Cpattern'), '\C') + call s:assert.equals(incsearch#detect_case('\CPatterN'), '\C') + call s:assert.equals(incsearch#detect_case('\cPatterN'), '\c') + set noignorecase smartcase + call s:assert.equals(incsearch#detect_case('\cpattern'), '\c') + call s:assert.equals(incsearch#detect_case('\Cpattern'), '\C') + call s:assert.equals(incsearch#detect_case('\CPatterN'), '\C') + call s:assert.equals(incsearch#detect_case('\cPatterN'), '\c') + set ignorecase smartcase + call s:assert.equals(incsearch#detect_case('\cpattern'), '\c') + call s:assert.equals(incsearch#detect_case('\Cpattern'), '\C') + call s:assert.equals(incsearch#detect_case('\CPatterN'), '\C') + call s:assert.equals(incsearch#detect_case('\cPatterN'), '\c') +endfunction + +function! s:suite.detect_case_parcent() + set ignorecase smartcase + call s:assert.equals(incsearch#detect_case('\%Cpattern'), '\c') + call s:assert.equals(incsearch#detect_case('\%Vpattern'), '\c') + call s:assert.equals(incsearch#detect_case('\%Upattern'), '\c') + call s:assert.equals(incsearch#detect_case('\%Apattern'), '\C') + call s:assert.equals(incsearch#detect_case('\%V\%Vpattern'), '\c') + call s:assert.equals(incsearch#detect_case('\V\Vpattern'), '\c') +endfunction diff --git a/bundle/incsearch.vim/test/util/regexp.vimspec b/bundle/incsearch.vim/test/util/regexp.vimspec new file mode 100644 index 000000000..f85a9ebb7 --- /dev/null +++ b/bundle/incsearch.vim/test/util/regexp.vimspec @@ -0,0 +1,161 @@ +Describe util.regexp + Before all + let SL = vital#of('vital').import('Vim.ScriptLocal') + let U = SL.sfuncs('autoload/incsearch/util.vim') + End + + Describe .regexp_join() + It returns joined regular expression from patterns + let ps = ['incsearch', 'vim'] + let r = U.regexp_join(ps) + Assert Equals('\m\%(incsearch\m\|vim\m\)', r) + for p in ps + Assert True(p =~# r) + endfor + End + + It supports regular expressions including various flags + let ps = ['\d\+', '\v(neo)?vim'] + let r = U.regexp_join(ps) + Assert Equals('\m\%(\d\+\m\|\v(neo)?vim\m\)', r) + for p in ['1', '12310', 'vim', 'neovim'] + Assert True(p =~# r) + endfor + End + + It handles unbalanced `[` with \m\v flag + let ps = ['\d\+[', '[vim]'] + let r = U.regexp_join(ps) + Assert Equals('\m\%(\d\+\[\m\|[vim]\m\)', r) + for p in ['1[', '12310[', 'v', 'i', 'm'] + Assert True(p =~# r) + endfor + for p in ['\', '\['] + Assert False(p =~# r) + endfor + End + End + + Describe .escape_unbalanced_left_r() + It case 0 + Assert Equals('\[', U.escape_unbalanced_left_r('[')) + End + It case 1 + Assert Equals('\[', U.escape_unbalanced_left_r('\[')) + End + It case 2 + Assert Equals('\\\[', U.escape_unbalanced_left_r('\\[')) + End + It case 3 + Assert Equals('\\\[', U.escape_unbalanced_left_r('\\\[')) + End + It case 4 + Assert Equals('[]', U.escape_unbalanced_left_r('[]')) + End + It case 5 + Assert Equals('\[]', U.escape_unbalanced_left_r('\[]')) + End + It case 6 + Assert Equals('\\[]', U.escape_unbalanced_left_r('\\[]')) + End + It case 7 + Assert Equals('\\\[]', U.escape_unbalanced_left_r('\\\[]')) + End + It case 8 + Assert Equals('[]\[', U.escape_unbalanced_left_r('[][')) + End + It case 9 + Assert Equals('\[]\[', U.escape_unbalanced_left_r('\[][')) + End + It case 10 + Assert Equals('\\[]\[', U.escape_unbalanced_left_r('\\[][')) + End + It case 11 + Assert Equals('\\\[]\[', U.escape_unbalanced_left_r('\\\[][')) + End + It case 12 + Assert Equals('[]...\[', U.escape_unbalanced_left_r('[]...[')) + End + It case 13 + Assert Equals('\[]...\[', U.escape_unbalanced_left_r('\[]...[')) + End + It case 14 + Assert Equals('\\[]...\[', U.escape_unbalanced_left_r('\\[]...[')) + End + It case 15 + Assert Equals('\\\[]...\[', U.escape_unbalanced_left_r('\\\[]...[')) + End + It case 16 + Assert Equals('\m\[', U.escape_unbalanced_left_r('\m[')) + End + It case 17 + Assert Equals('\m\[', U.escape_unbalanced_left_r('\m\[')) + End + It case 18 + Assert Equals('\m\\\[', U.escape_unbalanced_left_r('\m\\[')) + End + It case 19 + Assert Equals('\m\\\[', U.escape_unbalanced_left_r('\m\\\[')) + End + It case 20 + Assert Equals('\v\[', U.escape_unbalanced_left_r('\v[')) + End + It case 21 + Assert Equals('\v\[', U.escape_unbalanced_left_r('\v\[')) + End + It case 22 + Assert Equals('\v\\\[', U.escape_unbalanced_left_r('\v\\[')) + End + It case 23 + Assert Equals('\v\\\[', U.escape_unbalanced_left_r('\v\\\[')) + End + It case 24 + Assert Equals('\M[', U.escape_unbalanced_left_r('\M[')) + End + It case 25 + Assert Equals('\M[', U.escape_unbalanced_left_r('\M\[')) + End + It case 26 + Assert Equals('\M\\[', U.escape_unbalanced_left_r('\M\\[')) + End + It case 27 + Assert Equals('\M\\[', U.escape_unbalanced_left_r('\M\\\[')) + End + It case 28 + Assert Equals('\V[', U.escape_unbalanced_left_r('\V[')) + End + It case 29 + Assert Equals('\V[', U.escape_unbalanced_left_r('\V\[')) + End + It case 30 + Assert Equals('\V\\[', U.escape_unbalanced_left_r('\V\\[')) + End + It case 31 + Assert Equals('\V\\[', U.escape_unbalanced_left_r('\V\\\[')) + End + It case 32 + Assert Equals('\[\M[\v\[', U.escape_unbalanced_left_r('[\M\[\v[')) + End + It case 33 + Assert Equals('[\M\[\v[]', U.escape_unbalanced_left_r('[\M\[\v[]')) + End + It case 34 + Assert Equals('[[]', U.escape_unbalanced_left_r('[[]')) + End + It case 35 + Assert Equals('[\[]', U.escape_unbalanced_left_r('[\[]')) + End + It case 36 + Assert Equals('\M\[[]', U.escape_unbalanced_left_r('\M\[[]')) + End + It case 37 + let p = '[' . repeat('[', 10000) . ']' + Assert Equals(p, U.escape_unbalanced_left_r(p)) + End + It case 38 + let p = '[' . repeat('\[', 10000) . ']' + Assert Equals(p, U.escape_unbalanced_left_r(p)) + End + End + +End diff --git a/bundle/incsearch.vim/test/vimlint.sh b/bundle/incsearch.vim/test/vimlint.sh new file mode 100644 index 000000000..c65b261c9 --- /dev/null +++ b/bundle/incsearch.vim/test/vimlint.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +BASE_DIR=$HOME/.vim/bundle +sh ${BASE_DIR}/vim-vimlint/bin/vimlint.sh \ + -l ${BASE_DIR}/vim-vimlint \ + -p ${BASE_DIR}/vim-vimlparser \ + -e EVL102.l:_=1 \ + autoload/incsearch.vim +sh ${BASE_DIR}/vim-vimlint/bin/vimlint.sh \ + -l ${BASE_DIR}/vim-vimlint \ + -p ${BASE_DIR}/vim-vimlparser \ + -e EVL102.l:_=1 \ + autoload/incsearch diff --git a/bundle/incsearch.vim/test/visual_behavior.vim b/bundle/incsearch.vim/test/visual_behavior.vim new file mode 100644 index 000000000..49c24ee19 --- /dev/null +++ b/bundle/incsearch.vim/test/visual_behavior.vim @@ -0,0 +1,90 @@ +let s:suite = themis#suite('visual_behaviors') +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(copy(s:line_texts)) + normal! Gddgg0zt +endfunction + +function! s:suite.before() + map / (incsearch-forward) + map ? (incsearch-backward) + map g/ (incsearch-stay) + let s:line_texts = [ + \ '1pattern 2pattern' + \ , '3pattern 4pattern' + \ ] + call s:reset_buffer() +endfunction + +function! s:suite.before_each() + :1 + call setreg(v:register, '') +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" "v/2pattern\" | normal! y + call s:assert.equals(getreg(), "1pattern 2") + normal! gg0 + exec "normal" "V/2pattern\" | normal! y + call s:assert.equals(getreg(), "1pattern 2pattern\n") + normal! gg0 + exec "normal" "\/4pattern\" | normal! y + call s:assert.equals(getreg(), "1pattern 2\n3pattern 4") + normal! gg0 + exec "normal" "v/2pattern/e\" | normal! y + call s:assert.equals(getreg(), "1pattern 2pattern") +endfunction + +function! s:suite.backward() + normal! G$ + exec "normal" "v?3pattern?e\" | normal! y + call s:assert.equals(getreg(), 'n 4pattern') + normal! G$ + exec "normal" "V?3pattern?e\" | normal! y + call s:assert.equals(getreg(), "3pattern 4pattern\n") + normal! G$ + exec "normal" "\?2pattern\" | normal! y + call s:assert.equals(getreg(), "2pattern\n4pattern") +endfunction + +function! s:suite.stay() + call s:assert.equals(getreg(), '') + call s:assert.equals(s:get_pos_char(), '1') + exec "normal" "vg/2pattern\" | normal! y + call s:assert.equals(getreg(), '1') + normal! gg0 + exec "normal" "vg/2pattern\\" | normal! y + call s:assert.equals(getreg(), '1pattern 2') + normal! gg0 + exec "normal" "veg/3pattern\" | normal! y + call s:assert.equals(getreg(), '1pattern') + normal! gg0 + exec "normal" "Vg/2pattern\" | normal! y + call s:assert.equals(getreg(), "1pattern 2pattern\n") + normal! gg0 + exec "normal" "\g/3pattern/e\\" | normal! y + call s:assert.equals(getreg(), "1pattern\n3pattern") +endfunction diff --git a/bundle/incsearch.vim/test/visual_emulation.vim b/bundle/incsearch.vim/test/visual_emulation.vim new file mode 100644 index 000000000..596dedb30 --- /dev/null +++ b/bundle/incsearch.vim/test/visual_emulation.vim @@ -0,0 +1,162 @@ +let s:suite = themis#suite('visual_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 + +function! s:reset_buffer() + normal! ggdG + 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_each() + call s:reset_buffer() +endfunction + +function! s:assert.equal_matches(pattern, ...) + " :h getmatches() + let m = getmatches()[0] + call s:assert.equals(m.pattern, a:pattern) +endfunction + +function! s:assert.equal_view(view) + for key in keys(a:view) + call s:assert.equals(winsaveview()[key], a:view[key]) + endfor +endfunction + +function! s:assert.equal_line(line) + call s:assert.equals(getline('.'), a:line) +endfunction + +function! s:assert.equal_pos_char(char) + call s:assert.equals(s:get_pos_char(), a:char) +endfunction + +function! s:suite.emulate_v() + normal! v3jy + call s:assert.equals(visualmode(), "v") + call incsearch#highlight#emulate_visual_highlight() + call s:assert.equal_matches('\v%1l%1c\_.{-}%4l|%4l\_.*%4l%1c') + call incsearch#highlight#emulate_visual_highlight('v') + call s:assert.equal_matches('\v%1l%1c\_.{-}%4l|%4l\_.*%4l%1c') +endfunction + +function! s:suite.emulate_V() + normal! V3jy + call s:assert.equals(visualmode(), "V") + call incsearch#highlight#emulate_visual_highlight() + call s:assert.equal_matches('\v%1l\_.*%4l') + call incsearch#highlight#emulate_visual_highlight('V') + call s:assert.equal_matches('\v%1l\_.*%4l') +endfunction + +function! s:suite.emulate_ctrl_v() + exec "normal! \2j2ly" + call s:assert.equals(visualmode(), "\") + call incsearch#highlight#emulate_visual_highlight() + call s:assert.equal_matches('\v%1l%1c.*%4c|%2l%1c.*%4c|%3l%1c.*%4c') + call incsearch#highlight#emulate_visual_highlight("\") + call s:assert.equal_matches('\v%1l%1c.*%4c|%2l%1c.*%4c|%3l%1c.*%4c') +endfunction + +function! s:suite.emulate_v_End() + normal! v3j$y + call s:assert.equals(visualmode(), 'v') + call incsearch#highlight#emulate_visual_highlight() + call s:assert.equal_matches('\v%1l%1c\_.{-}%4l|%4l\_.*%4l%11c') + call incsearch#highlight#emulate_visual_highlight('v') + call s:assert.equal_matches('\v%1l%1c\_.{-}%4l|%4l\_.*%4l%11c') +endfunction + +function! s:suite.emulate_V_End() + normal! V3j$y + call s:assert.equals(visualmode(), 'V') + call incsearch#highlight#emulate_visual_highlight() + call s:assert.equal_matches('\v%1l\_.*%4l') + call incsearch#highlight#emulate_visual_highlight('V') + call s:assert.equal_matches('\v%1l\_.*%4l') +endfunction + +function! s:suite.emulate_ctrl_v_End() + exec "normal! \3j$y" + call s:assert.equals(visualmode(), "\") + call incsearch#highlight#emulate_visual_highlight() + call s:assert.equal_matches('\v%1l%1c.*%11c|%2l%1c.*%11c|%3l%1c.*%11c|%4l%1c.*%11c') + call incsearch#highlight#emulate_visual_highlight("\") + call s:assert.equal_matches('\v%1l%1c.*%11c|%2l%1c.*%11c|%3l%1c.*%11c|%4l%1c.*%11c') +endfunction + +function! s:suite.custom_highlight() + normal! v3jy + call s:assert.equals(visualmode(), 'v') + call incsearch#highlight#emulate_visual_highlight() + let visual_hl = incsearch#highlight#capture('Visual') + call s:assert.equals(getmatches()[0].group, '_IncSearchVisual') + let h = incsearch#highlight#capture('_IncSearchVisual') + call s:assert.equals(h.highlight, visual_hl.highlight) + + let error_hl = incsearch#highlight#capture('ErrorMsg') + call incsearch#highlight#emulate_visual_highlight('v', error_hl) + let h = incsearch#highlight#capture('_IncSearchVisual') + call s:assert.equals(h.highlight, error_hl.highlight) +endfunction + +function! s:suite.get_pattern_v() + let r = incsearch#highlight#get_visual_pattern('v', [5,2], [2,4]) + call s:assert.equals(r, '\v%2l%4c\_.{-}%5l|%5l\_.*%5l%2c') +endfunction + +function! s:suite.get_pattern_V() + let r = incsearch#highlight#get_visual_pattern('V', [5,2], [2,4]) + call s:assert.equals(r, '\v%2l\_.*%5l') +endfunction + +function! s:suite.get_pattern_ctrl_v() + let r = incsearch#highlight#get_visual_pattern("\", [5,2], [2,4]) + call s:assert.equals(r, '\v%2l%2c.*%5c|%3l%2c.*%5c|%4l%2c.*%5c|%5l%2c.*%5c') +endfunction + +function! s:suite.over_win_height() + normal! 100ggzz + let r = incsearch#highlight#get_visual_pattern('V', [1,1], [100,100]) + let e = incsearch#highlight#get_visual_pattern('V', [line('w0'),1], [100,100]) + call s:assert.equals(r, e) + normal! ggzt + let r2 = incsearch#highlight#get_visual_pattern('V', [1,1], [100,100]) + let e2 = '\v%1l\_.*%' . line('w$') . 'l' + call s:assert.equals(r2, e2) +endfunction + +function! s:suite.unexpected_mode() + let throwed = 0 + try + let r = incsearch#highlight#get_visual_pattern('a', [1,1], [100,100]) + catch /incsearch.vim:/ + let throwed = 1 + call s:assert.equals(v:exception, 'incsearch.vim: unexpected mode a') + endtry + call s:assert.equals(throwed, 1) +endfunction + +function! s:suite.update_highlight_on_colorscheme() + colorscheme default + let old_hl = incsearch#highlight#get_visual_hlobj() + colorscheme desert + let new_hl = incsearch#highlight#get_visual_hlobj() + call s:assert.not_equals(old_hl, new_hl) +endfunction +