├── .github ├── TODO.md ├── demo.gif └── demo_win_change.gif ├── .vintrc.yaml ├── LICENSE.txt ├── README.md ├── autoload ├── shiny.vim ├── shiny │ └── window.vim ├── vital.vim └── vital │ ├── _shiny.vim │ ├── _shiny │ ├── Coaster │ │ ├── Highlight.vim │ │ └── Window.vim │ ├── Data │ │ ├── Dict.vim │ │ └── List.vim │ ├── Gift.vim │ ├── Gift │ │ ├── Tabpage.vim │ │ └── Window.vim │ ├── Prelude.vim │ └── Vim │ │ ├── Buffer.vim │ │ └── Guard.vim │ ├── shiny.vim │ └── shiny.vital ├── circle.yml ├── doc └── vim-shiny.txt ├── plugin └── shiny.vim └── reviewdog.yml /.github/TODO.md: -------------------------------------------------------------------------------- 1 | ## TODO 2 | 3 | - paste 4 | - [x] p `(shiny-p)` 5 | - [x] P `(shiny-P)` 6 | - [x] gp `(shiny-gp)` 7 | - [x] gP `(shiny-gP)` 8 | 9 | - undo `*1` 10 | - [ ] u 11 | - [ ] U 12 | 13 | > `*1` : Not highlight when decrease line from prev state. 14 | 15 | - [ ] support legacy vim (for no lambda, no timer) 16 | 17 | - [ ] dot repeat 18 | 19 | - configureable 20 | - [x] highlight group 21 | 22 | - [ ] document 23 | -------------------------------------------------------------------------------- /.github/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaxMEllon/vim-shiny/f5f1c48824e72b5ecba90af05369e5b2b0cabba3/.github/demo.gif -------------------------------------------------------------------------------- /.github/demo_win_change.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaxMEllon/vim-shiny/f5f1c48824e72b5ecba90af05369e5b2b0cabba3/.github/demo_win_change.gif -------------------------------------------------------------------------------- /.vintrc.yaml: -------------------------------------------------------------------------------- 1 | # Config for vint 2 | # https://github.com/Kuniwak/vint 3 | policies: 4 | ProhibitImplicitScopeVariable: 5 | enabled: false 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 MaxMEllon (Kento TSUJI) 2 | MIT License 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | The above copyright notice and this permission notice shall be 11 | included in all copies or substantial portions of the Software. 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 13 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 14 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 16 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 17 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 18 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-shiny 2 | 3 | [![CircleCI](https://img.shields.io/circleci/project/github/MaxMEllon/vim-shiny/master.svg?style=flat-square&label=Circle%20CI)](https://circleci.com/gh/MaxMEllon/vim-shiny) 4 | [![Support Vim 8.0.0039 or above](https://img.shields.io/badge/support-Vim%208.0.0039%20or%20above-yellowgreen.svg?style=flat-square)](github.com/vim/vim/releases/tag/v8.0.0039) 5 | [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE.txt) 6 | [![Doc](https://img.shields.io/badge/doc%20-%3Ah%20vim--shiny-red.svg?style=flat-square)](./doc/vim-shiny.txt) 7 | 8 | A plugin goal is effective highlight, like as [atom-vim-mode-plus](https://github.com/t9md/atom-vim-mode-plus). 9 | 10 | - paste yank 11 | 12 | ![Demo movie](./.github/demo.gif) 13 | > with vim-operator-flashy 14 | 15 | - if enabled `termguicolors` or `gui_running` 16 | 17 | ![Demo movie](https://user-images.githubusercontent.com/9594376/32803036-8fbb49a2-c9c5-11e7-82e7-af5e79cbe925.gif) 18 | 19 | - change window 20 | 21 | ![Demo movie](./.github/demo_win_change.gif) 22 | 23 | ## Inspired 24 | 25 | - [vim-operator-flashy](https://github.com/haya14busa/vim-operator-flashy) 26 | - [atom-vim-mode-plus](https://github.com/t9md/atom-vim-mode-plus) 27 | 28 | Special Thanks! 29 | 30 | ## Usage 31 | 32 | ```vim 33 | nmap p (shiny-p) 34 | nmap P (shiny-P) 35 | nmap gp (shiny-gp) 36 | nmap gP (shiny-gP) 37 | ``` 38 | 39 | if you want to flash when change window 40 | 41 | ```vim 42 | let g:vim_shiny_window_change = 1 43 | ``` 44 | 45 | LICENSE 46 | --- 47 | 48 | MIT 49 | -------------------------------------------------------------------------------- /autoload/shiny.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | let s:save_cpo = &cpo 3 | set cpo&vim 4 | 5 | let s:V = vital#shiny#of() 6 | let s:Highlight = s:V.import('Coaster.Highlight') 7 | let s:vim_shiny_hi_paste = get(g:, 'vim_shiny_hi_paste', 'Shiny') 8 | let s:enable_fade = get(g:, 'vim_shiny_enable_fade_on_gui', 1) 9 | 10 | let s:colors = { 11 | \ 'light': ['#ccffd2', '#b2ffbc', '#9effaa', '#b2ffbc', '#ccffd2'], 12 | \ 'dark': ['#056313', '#088c1c', '#08a31c', '#088c1c', '#056313'], 13 | \} 14 | 15 | function! s:initialize() abort 16 | highlight default Shiny term=bold ctermbg=22 gui=bold guibg=#13354A 17 | endfunction 18 | 19 | call s:initialize() 20 | 21 | function! shiny#p(...) abort range 22 | call s:flash_and_paste('p', a:lastline - a:firstline + 1) 23 | endfunction 24 | 25 | function! shiny#gp(...) abort range 26 | call s:flash_and_paste('gp', a:lastline - a:firstline + 1) 27 | endfunction 28 | 29 | function! shiny#P(...) abort range 30 | call s:flash_and_paste('P', a:lastline - a:firstline + 1) 31 | endfunction 32 | 33 | function! shiny#gP(...) abort range 34 | call s:flash_and_paste('gP', a:lastline - a:firstline + 1) 35 | endfunction 36 | 37 | function! s:generate_matcher_for_visual(start_loc, end_loc) abort 38 | return [ 39 | \printf('\%%%dl\%%%dv\_.*\%%%dl', a:start_loc[0], a:start_loc[1], a:start_loc[0]), 40 | \printf('\%%%dl\_.*\%%%dl', a:start_loc[0] + 1, a:end_loc[0] - 1), 41 | \printf('\%%%dl%\_.*\%%%dl\%%%dv', a:end_loc[0], a:end_loc[0], a:end_loc[1]), 42 | \] 43 | endfunction 44 | 45 | function! s:generate_matcher_for_visual_block(start_loc, end_loc) abort 46 | let s = a:start_loc 47 | let e = a:end_loc 48 | let patterns = [] 49 | let k = 0 50 | for i in range(e[0] - s[0] + 1) 51 | let line = s[0] + i 52 | let p = printf('\%%%dl\%%%dv\_.*\%%%dl\%%%dv', line, s[1], line, e[1] + 1) 53 | let patterns = add(patterns, p) 54 | let k += 1 55 | endfor 56 | return patterns 57 | endfunction 58 | 59 | function! s:generate_patterns(count) abort 60 | let s = getpos("'[")[1:2] 61 | let e = getpos("']")[1:2] 62 | let mode = getregtype(v:register) 63 | let length = len(split(getreg(v:register), "[\n|\r]")) 64 | 65 | if length == 1 && a:count == 1 66 | return s:generate_matcher_for_visual_block(s, e) 67 | endif 68 | 69 | if mode ==# 'V' 70 | return [printf('\%%%dl\_.*\%%%dl', s[0], e[0])] 71 | endif 72 | 73 | if mode ==# 'v' 74 | return s:generate_matcher_for_visual(s, e) 75 | endif 76 | 77 | return s:generate_matcher_for_visual_block(s, e) 78 | endfunction 79 | 80 | function! s:flash_and_paste(target, count) abort 81 | exec 'normal! "' . v:register . a:count . a:target 82 | let patterns = s:generate_patterns(a:count) 83 | call s:flash(patterns, s:vim_shiny_hi_paste) 84 | endfunction 85 | 86 | function! s:_flash(patterns, group) abort 87 | let i = 0 88 | for p in a:patterns 89 | if getchar(1) 90 | break 91 | endif 92 | call s:Highlight.highlight('ShinyFlash' . i, a:group, p, 1) 93 | let i += 1 94 | endfor 95 | redraw 96 | call s:clear(i) 97 | endfunction 98 | 99 | function! s:_flash_fade(patterns, group) abort 100 | let bg = &background ==# 'dark' ? 'dark' : 'light' 101 | let c = s:colors[bg] 102 | let duration = 100 / len(c) 103 | for k in range(5) 104 | if getchar(1) 105 | break 106 | endif 107 | exe 'hi! ' . a:group .' guibg=' . c[k] 108 | let i = 0 109 | for p in a:patterns 110 | call s:Highlight.highlight('ShinyFlash' . i, a:group, p, 1) 111 | let i += 1 112 | endfor 113 | exec 'sleep ' . duration . 'm' 114 | redraw 115 | endfor 116 | call s:clear(i) 117 | endfunction 118 | 119 | function! s:flash(patterns, group) abort 120 | if (has('gui_running') || &termguicolors) && s:enable_fade 121 | call timer_start(0, { -> s:_flash_fade(a:patterns, a:group) }) 122 | else 123 | call timer_start(0, { -> s:_flash(a:patterns, a:group) }) 124 | endif 125 | endfunction 126 | 127 | function! s:clear(num) abort 128 | for i in range(a:num) 129 | call s:Highlight.clear('ShinyFlash' . i) 130 | endfor 131 | endfunction 132 | 133 | let &cpo = s:save_cpo 134 | unlet s:save_cpo 135 | " vim: fdm=marker:et:ts=2:sw=2:sts=2 136 | -------------------------------------------------------------------------------- /autoload/shiny/window.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | let s:save_cpo = &cpo 3 | set cpo&vim 4 | 5 | let s:colorcolumn = &colorcolumn 6 | let s:vim_shiny_hi_window_change = get(g:, 'vim_shiny_hi_window_change', 'WindowChange') 7 | 8 | function! s:initialize() abort 9 | highlight default WindowChange ctermbg=236 guibg=#333333 10 | endfunction 11 | 12 | call s:initialize() 13 | 14 | function! s:restore_hi(hi) abort 15 | exec 'hi! ' . a:hi 16 | endfunction 17 | 18 | function! s:clear() abort 19 | function! s:_clear() closure 20 | let &colorcolumn = s:colorcolumn 21 | highlight! link ColorColumn NONE 22 | endfunction 23 | 24 | let timer = timer_start(300, { -> s:_clear() }) 25 | endfunction 26 | 27 | function! shiny#window#flash() abort 28 | for i in range(1, tabpagewinnr(tabpagenr(), '$')) 29 | let range = '' 30 | if i == winnr() 31 | let l:width = 256 32 | let l:range = join(range(1, l:width), ',') 33 | exec 'highlight! link ColorColumn ' . s:vim_shiny_hi_window_change 34 | call setwinvar(i, '&colorcolumn', range) 35 | call s:clear() 36 | endif 37 | endfor 38 | endfunction 39 | 40 | let &cpo = s:save_cpo 41 | unlet s:save_cpo 42 | " vim: fdm=marker:et:ts=2:sw=2:sts=2 43 | -------------------------------------------------------------------------------- /autoload/vital.vim: -------------------------------------------------------------------------------- 1 | function! vital#of(name) abort 2 | let files = globpath(&runtimepath, 'autoload/vital/' . a:name . '.vital', 1) 3 | let file = split(files, "\n") 4 | if empty(file) 5 | throw 'vital: version file not found: ' . a:name 6 | endif 7 | let ver = readfile(file[0], 'b') 8 | if empty(ver) 9 | throw 'vital: invalid version file: ' . a:name 10 | endif 11 | return vital#_{substitute(ver[0], '\W', '', 'g')}#new() 12 | endfunction 13 | -------------------------------------------------------------------------------- /autoload/vital/_shiny.vim: -------------------------------------------------------------------------------- 1 | let s:_plugin_name = expand(':t:r') 2 | 3 | function! vital#{s:_plugin_name}#new() abort 4 | return vital#{s:_plugin_name[1:]}#new() 5 | endfunction 6 | -------------------------------------------------------------------------------- /autoload/vital/_shiny/Coaster/Highlight.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_shiny#Coaster#Highlight#import() abort 6 | 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': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_shiny#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': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | scriptencoding utf-8 17 | let s:save_cpo = &cpo 18 | set cpo&vim 19 | 20 | 21 | function! s:_vital_loaded(V) 22 | let s:V = a:V 23 | let s:Window = a:V.import("Coaster.Window") 24 | let s:Gift = a:V.import("Gift") 25 | call s:_init() 26 | endfunction 27 | 28 | 29 | function! s:_vital_depends() 30 | return [ 31 | \ "Coaster.Window", 32 | \ "Gift", 33 | \ ] 34 | endfunction 35 | 36 | 37 | 38 | let s:base = { 39 | \ "variables" : { 40 | \ "hl_list" : {}, 41 | \ "id_list" : {} 42 | \ } 43 | \} 44 | 45 | 46 | function! s:base.add(name, group, pattern, ...) 47 | call self.delete(a:name) 48 | let priority = get(a:, 1, 10) 49 | let self.variables.hl_list[a:name] = { 50 | \ "group" : a:group, 51 | \ "pattern" : a:pattern, 52 | \ "priority" : priority, 53 | \ "name" : a:name, 54 | \ } 55 | endfunction 56 | 57 | 58 | function! s:base.is_added(name) 59 | return has_key(self.variables.hl_list, a:name) 60 | endfunction 61 | 62 | 63 | function! s:base.hl_list() 64 | return keys(self.variables.hl_list) 65 | endfunction 66 | 67 | 68 | function! s:base.to_list() 69 | return values(self.variables.hl_list) 70 | endfunction 71 | 72 | 73 | function! s:_is_equal(__expr, __hl) 74 | let name = a:__hl.name 75 | let group = a:__hl.group 76 | let pattern = a:__hl.pattern 77 | let priority = a:__hl.priority 78 | return eval(a:__expr) 79 | endfunction 80 | 81 | 82 | function! s:base.to_list_by(expr) 83 | return filter(values(self.variables.hl_list), "s:_is_equal(a:expr, v:val)") 84 | endfunction 85 | 86 | 87 | function! s:base.enable_list(...) 88 | let window = get(a:, 1, s:Gift.uniq_winnr()) 89 | return keys(get(self.variables.id_list, window, {})) 90 | endfunction 91 | 92 | 93 | function! s:base.delete(name) 94 | if !self.is_added(a:name) 95 | return -1 96 | endif 97 | unlet! self.variables.hl_list[a:name] 98 | endfunction 99 | 100 | 101 | function! s:base.delete_by(expr) 102 | return map(self.to_list_by(a:expr), "self.delete(v:val.name)") 103 | endfunction 104 | 105 | 106 | function! s:base.delete_all() 107 | for name in self.hl_list() 108 | call self.delete(name) 109 | endfor 110 | endfunction 111 | 112 | 113 | function! s:base.get_hl_id(name, ...) 114 | let window = get(a:, 1, s:Gift.uniq_winnr()) 115 | return get(get(self.variables.id_list, window, {}), a:name, "") 116 | endfunction 117 | 118 | 119 | function! s:base.is_enabled(name, ...) 120 | let window = get(a:, 1, s:Gift.uniq_winnr()) 121 | return self.get_hl_id(a:name, window) != "" 122 | endfunction 123 | 124 | 125 | function! s:base.enable(name) 126 | let hl = get(self.variables.hl_list, a:name, {}) 127 | if empty(hl) 128 | return -1 129 | endif 130 | if self.is_enabled(a:name) 131 | call self.disable(a:name) 132 | endif 133 | let winnr = s:Gift.uniq_winnr() 134 | if !has_key(self.variables.id_list, winnr) 135 | let self.variables.id_list[winnr] = {} 136 | endif 137 | let self.variables.id_list[winnr][a:name] = matchadd(hl.group, hl.pattern, hl.priority) 138 | endfunction 139 | 140 | 141 | function! s:base.enable_all() 142 | for name in self.hl_list() 143 | call self.enable(name) 144 | endfor 145 | endfunction 146 | 147 | 148 | function! s:base.disable(name) 149 | if !self.is_enabled(a:name) 150 | return -1 151 | endif 152 | let id = -1 153 | silent! let id = matchdelete(self.get_hl_id(a:name)) 154 | if id == -1 155 | return -1 156 | endif 157 | let winnr = get(a:, 1, s:Gift.uniq_winnr()) 158 | unlet! self.variables.id_list[winnr][a:name] 159 | endfunction 160 | 161 | 162 | function! s:base.disable_all() 163 | for name in self.enable_list() 164 | call self.disable(name) 165 | endfor 166 | endfunction 167 | 168 | 169 | function! s:base.update(name) 170 | call self.disable(a:name) 171 | call self.enable(a:name) 172 | endfunction 173 | 174 | 175 | function! s:base.update_all() 176 | call self.disable_all() 177 | call self.enable_all() 178 | endfunction 179 | 180 | 181 | function! s:base.highlight(name, group, pattern, ...) 182 | let priority = get(a:, 1, 10) 183 | call self.add(a:name, a:group, a:pattern, priority) 184 | call self.enable(a:name) 185 | endfunction 186 | 187 | 188 | function! s:base.clear(name) 189 | call self.disable(a:name) 190 | call self.delete(a:name) 191 | endfunction 192 | 193 | 194 | function! s:base.clear_all() 195 | call self.disable_all() 196 | call self.delete_all() 197 | endfunction 198 | 199 | 200 | function! s:base.as_windo() 201 | return self.windo 202 | endfunction 203 | 204 | 205 | function! s:make() 206 | let result = deepcopy(s:base) 207 | let result.windo = s:Window.as_windo(result) 208 | return result 209 | endfunction 210 | 211 | 212 | let s:global = deepcopy(s:base) 213 | let s:funcs = keys(filter(copy(s:global), "type(v:val) == type(function('tr'))")) 214 | 215 | for s:name in s:funcs 216 | execute 217 | \ "function! s:" . s:name . "(...) \n" 218 | \ "return call(s:global." . s:name . ", a:000, s:global) \n" 219 | \ "endfunction" 220 | endfor 221 | unlet s:name 222 | 223 | 224 | function! s:_init() 225 | let s:global.windo = s:Window.as_windo(s:global) 226 | endfunction 227 | 228 | " function! s:matchadd(...) 229 | " return { 230 | " \ "id" : call("matchadd", a:000), 231 | " \ "bufnr" : bufnr("%"), 232 | " \ } 233 | " endfunction 234 | " 235 | " 236 | " function! s:matchdelete(id) 237 | " if empty(a:id) 238 | " return -1 239 | " endif 240 | " return s:Buffer.execute(a:id.bufnr, "call matchdelete(" . a:id.id . ")") 241 | " endfunction 242 | 243 | 244 | let &cpo = s:save_cpo 245 | unlet s:save_cpo 246 | -------------------------------------------------------------------------------- /autoload/vital/_shiny/Coaster/Window.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_shiny#Coaster#Window#import() abort 6 | return map({'as_windo': '', '_vital_depends': '', 'windo': '', '_vital_loaded': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_shiny#Coaster#Window#import() abort', printf("return map({'as_windo': '', '_vital_depends': '', 'windo': '', '_vital_loaded': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | scriptencoding utf-8 17 | let s:save_cpo = &cpo 18 | set cpo&vim 19 | 20 | 21 | function! s:_vital_loaded(V) 22 | let s:V = a:V 23 | let s:Buffer = a:V.import("Vim.Buffer") 24 | endfunction 25 | 26 | 27 | function! s:_vital_depends() 28 | return [ 29 | \ "Vim.Buffer", 30 | \ ] 31 | endfunction 32 | 33 | 34 | function! s:windo(func, args, ...) 35 | let dict = get(a:, 1, {}) 36 | if len(tabpagebuflist()) <= 1 || s:Buffer.is_cmdwin() 37 | return call(a:func, a:args, dict) 38 | endif 39 | let pre_winnr = winnr() 40 | 41 | noautocmd windo call call(a:func, a:args, dict) 42 | 43 | if pre_winnr == winnr() 44 | return 45 | endif 46 | execute pre_winnr . "wincmd w" 47 | endfunction 48 | 49 | 50 | function! s:as_windo(base) 51 | let windo = {} 52 | let windo.obj = a:base 53 | for [key, Value] in items(a:base) 54 | if type(function("tr")) == type(Value) 55 | execute 56 | \ "function! windo.". key. "(...)\n" 57 | \ " return s:windo(self.obj." . key . ", a:000, self.obj)\n" 58 | \ "endfunction" 59 | endif 60 | unlet Value 61 | endfor 62 | return windo 63 | endfunction 64 | 65 | 66 | 67 | let &cpo = s:save_cpo 68 | unlet s:save_cpo 69 | -------------------------------------------------------------------------------- /autoload/vital/_shiny/Data/Dict.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_shiny#Data#Dict#import() abort 6 | return map({'pick': '', 'clear': '', 'max_by': '', 'foldl': '', 'swap': '', 'omit': '', 'min_by': '', 'foldr': '', 'make_index': '', 'make': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_shiny#Data#Dict#import() abort', printf("return map({'pick': '', 'clear': '', 'max_by': '', 'foldl': '', 'swap': '', 'omit': '', 'min_by': '', 'foldr': '', 'make_index': '', 'make': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | " Utilities for dictionary. 17 | 18 | let s:save_cpo = &cpo 19 | set cpo&vim 20 | 21 | " Makes a dict from keys and values 22 | function! s:make(keys, values, ...) abort 23 | let dict = {} 24 | let fill = a:0 ? a:1 : 0 25 | for i in range(len(a:keys)) 26 | let key = type(a:keys[i]) == type('') ? a:keys[i] : string(a:keys[i]) 27 | if key ==# '' 28 | throw "vital: Data.Dict: Can't use an empty string for key." 29 | endif 30 | let dict[key] = get(a:values, i, fill) 31 | endfor 32 | return dict 33 | endfunction 34 | 35 | " Swaps keys and values 36 | function! s:swap(dict) abort 37 | return s:make(values(a:dict), keys(a:dict)) 38 | endfunction 39 | 40 | " Makes a index dict from a list 41 | function! s:make_index(list, ...) abort 42 | let value = a:0 ? a:1 : 1 43 | return s:make(a:list, [], value) 44 | endfunction 45 | 46 | function! s:pick(dict, keys) abort 47 | let new_dict = {} 48 | for key in a:keys 49 | if has_key(a:dict, key) 50 | let new_dict[key] = a:dict[key] 51 | endif 52 | endfor 53 | return new_dict 54 | endfunction 55 | 56 | function! s:omit(dict, keys) abort 57 | let new_dict = copy(a:dict) 58 | for key in a:keys 59 | if has_key(a:dict, key) 60 | call remove(new_dict, key) 61 | endif 62 | endfor 63 | return new_dict 64 | endfunction 65 | 66 | function! s:clear(dict) abort 67 | for key in keys(a:dict) 68 | call remove(a:dict, key) 69 | endfor 70 | return a:dict 71 | endfunction 72 | 73 | function! s:_max_by(dict, expr) abort 74 | let dict = s:swap(map(copy(a:dict), a:expr)) 75 | let key = dict[max(keys(dict))] 76 | return [key, a:dict[key]] 77 | endfunction 78 | 79 | function! s:max_by(dict, expr) abort 80 | if empty(a:dict) 81 | throw 'vital: Data.Dict: Empty dictionary' 82 | endif 83 | return s:_max_by(a:dict, a:expr) 84 | endfunction 85 | 86 | function! s:min_by(dict, expr) abort 87 | if empty(a:dict) 88 | throw 'vital: Data.Dict: Empty dictionary' 89 | endif 90 | return s:_max_by(a:dict, '-(' . a:expr . ')') 91 | endfunction 92 | 93 | function! s:_foldl(f, init, xs) abort 94 | let memo = a:init 95 | for [k, v] in a:xs 96 | let expr = substitute(a:f, 'v:key', string(k), 'g') 97 | let expr = substitute(expr, 'v:val', string(v), 'g') 98 | let expr = substitute(expr, 'v:memo', string(memo), 'g') 99 | unlet memo 100 | let memo = eval(expr) 101 | endfor 102 | return memo 103 | endfunction 104 | 105 | function! s:foldl(f, init, dict) abort 106 | return s:_foldl(a:f, a:init, items(a:dict)) 107 | endfunction 108 | 109 | function! s:foldr(f, init, dict) abort 110 | return s:_foldl(a:f, a:init, reverse(items(a:dict))) 111 | endfunction 112 | 113 | let &cpo = s:save_cpo 114 | unlet s:save_cpo 115 | 116 | " vim:set et ts=2 sts=2 sw=2 tw=0: 117 | -------------------------------------------------------------------------------- /autoload/vital/_shiny/Data/List.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_shiny#Data#List#import() abort 6 | 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': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_shiny#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': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | " Utilities for list. 17 | 18 | let s:save_cpo = &cpo 19 | set cpo&vim 20 | 21 | function! s:pop(list) abort 22 | return remove(a:list, -1) 23 | endfunction 24 | 25 | function! s:push(list, val) abort 26 | call add(a:list, a:val) 27 | return a:list 28 | endfunction 29 | 30 | function! s:shift(list) abort 31 | return remove(a:list, 0) 32 | endfunction 33 | 34 | function! s:unshift(list, val) abort 35 | return insert(a:list, a:val) 36 | endfunction 37 | 38 | function! s:cons(x, xs) abort 39 | return [a:x] + a:xs 40 | endfunction 41 | 42 | function! s:conj(xs, x) abort 43 | return a:xs + [a:x] 44 | endfunction 45 | 46 | " Removes duplicates from a list. 47 | function! s:uniq(list) abort 48 | return s:uniq_by(a:list, 'v:val') 49 | endfunction 50 | 51 | " Removes duplicates from a list. 52 | function! s:uniq_by(list, f) abort 53 | let list = map(copy(a:list), printf('[v:val, %s]', a:f)) 54 | let i = 0 55 | let seen = {} 56 | while i < len(list) 57 | let key = string(list[i][1]) 58 | if has_key(seen, key) 59 | call remove(list, i) 60 | else 61 | let seen[key] = 1 62 | let i += 1 63 | endif 64 | endwhile 65 | return map(list, 'v:val[0]') 66 | endfunction 67 | 68 | function! s:clear(list) abort 69 | if !empty(a:list) 70 | unlet! a:list[0 : len(a:list) - 1] 71 | endif 72 | return a:list 73 | endfunction 74 | 75 | " Concatenates a list of lists. 76 | " XXX: Should we verify the input? 77 | function! s:concat(list) abort 78 | let memo = [] 79 | for Value in a:list 80 | let memo += Value 81 | endfor 82 | return memo 83 | endfunction 84 | 85 | " Take each elements from lists to a new list. 86 | function! s:flatten(list, ...) abort 87 | let limit = a:0 > 0 ? a:1 : -1 88 | let memo = [] 89 | if limit == 0 90 | return a:list 91 | endif 92 | let limit -= 1 93 | for Value in a:list 94 | let memo += 95 | \ type(Value) == type([]) ? 96 | \ s:flatten(Value, limit) : 97 | \ [Value] 98 | unlet! Value 99 | endfor 100 | return memo 101 | endfunction 102 | 103 | " Sorts a list with expression to compare each two values. 104 | " a:a and a:b can be used in {expr}. 105 | function! s:sort(list, expr) abort 106 | if type(a:expr) == type(function('function')) 107 | return sort(a:list, a:expr) 108 | endif 109 | let s:expr = a:expr 110 | return sort(a:list, 's:_compare') 111 | endfunction 112 | 113 | function! s:_compare(a, b) abort 114 | return eval(s:expr) 115 | endfunction 116 | 117 | " Sorts a list using a set of keys generated by mapping the values in the list 118 | " through the given expr. 119 | " v:val is used in {expr} 120 | function! s:sort_by(list, expr) abort 121 | let pairs = map(a:list, printf('[v:val, %s]', a:expr)) 122 | return map(s:sort(pairs, 123 | \ 'a:a[1] ==# a:b[1] ? 0 : a:a[1] ># a:b[1] ? 1 : -1'), 'v:val[0]') 124 | endfunction 125 | 126 | " Returns a maximum value in {list} through given {expr}. 127 | " Returns 0 if {list} is empty. 128 | " v:val is used in {expr} 129 | function! s:max_by(list, expr) abort 130 | if empty(a:list) 131 | return 0 132 | endif 133 | let list = map(copy(a:list), a:expr) 134 | return a:list[index(list, max(list))] 135 | endfunction 136 | 137 | " Returns a minimum value in {list} through given {expr}. 138 | " Returns 0 if {list} is empty. 139 | " v:val is used in {expr} 140 | " FIXME: -0x80000000 == 0x80000000 141 | function! s:min_by(list, expr) abort 142 | return s:max_by(a:list, '-(' . a:expr . ')') 143 | endfunction 144 | 145 | " Returns List of character sequence between [a:from, a:to] 146 | " e.g.: s:char_range('a', 'c') returns ['a', 'b', 'c'] 147 | function! s:char_range(from, to) abort 148 | return map( 149 | \ range(char2nr(a:from), char2nr(a:to)), 150 | \ 'nr2char(v:val)' 151 | \) 152 | endfunction 153 | 154 | " Returns true if a:list has a:value. 155 | " Returns false otherwise. 156 | function! s:has(list, value) abort 157 | return index(a:list, a:value) isnot -1 158 | endfunction 159 | 160 | " Returns true if a:list[a:index] exists. 161 | " Returns false otherwise. 162 | " NOTE: Returns false when a:index is negative number. 163 | function! s:has_index(list, index) abort 164 | " Return true when negative index? 165 | " let index = a:index >= 0 ? a:index : len(a:list) + a:index 166 | return 0 <= a:index && a:index < len(a:list) 167 | endfunction 168 | 169 | " similar to Haskell's Data.List.span 170 | function! s:span(f, xs) abort 171 | let border = len(a:xs) 172 | for i in range(len(a:xs)) 173 | if !eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g')) 174 | let border = i 175 | break 176 | endif 177 | endfor 178 | return border == 0 ? [[], copy(a:xs)] : [a:xs[: border - 1], a:xs[border :]] 179 | endfunction 180 | 181 | " similar to Haskell's Data.List.break 182 | function! s:break(f, xs) abort 183 | return s:span(printf('!(%s)', a:f), a:xs) 184 | endfunction 185 | 186 | " similar to Haskell's Data.List.takeWhile 187 | function! s:take_while(f, xs) abort 188 | return s:span(a:f, a:xs)[0] 189 | endfunction 190 | 191 | " similar to Haskell's Data.List.dropWhile 192 | function! s:drop_while(f, xs) abort 193 | return s:span(a:f, a:xs)[1] 194 | endfunction 195 | 196 | " similar to Haskell's Data.List.partition 197 | function! s:partition(f, xs) abort 198 | return [filter(copy(a:xs), a:f), filter(copy(a:xs), '!(' . a:f . ')')] 199 | endfunction 200 | 201 | " similar to Haskell's Prelude.all 202 | function! s:all(f, xs) abort 203 | return !s:any(printf('!(%s)', a:f), a:xs) 204 | endfunction 205 | 206 | " similar to Haskell's Prelude.any 207 | function! s:any(f, xs) abort 208 | return !empty(filter(map(copy(a:xs), a:f), 'v:val')) 209 | endfunction 210 | 211 | " similar to Haskell's Prelude.and 212 | function! s:and(xs) abort 213 | return s:all('v:val', a:xs) 214 | endfunction 215 | 216 | " similar to Haskell's Prelude.or 217 | function! s:or(xs) abort 218 | return s:any('v:val', a:xs) 219 | endfunction 220 | 221 | function! s:map_accum(expr, xs, init) abort 222 | let memo = [] 223 | let init = a:init 224 | for x in a:xs 225 | let expr = substitute(a:expr, 'v:memo', init, 'g') 226 | let expr = substitute(expr, 'v:val', x, 'g') 227 | let [tmp, init] = eval(expr) 228 | call add(memo, tmp) 229 | endfor 230 | return memo 231 | endfunction 232 | 233 | " similar to Haskell's Prelude.foldl 234 | function! s:foldl(f, init, xs) abort 235 | let memo = a:init 236 | for x in a:xs 237 | let expr = substitute(a:f, 'v:val', string(x), 'g') 238 | let expr = substitute(expr, 'v:memo', string(memo), 'g') 239 | unlet memo 240 | let memo = eval(expr) 241 | endfor 242 | return memo 243 | endfunction 244 | 245 | " similar to Haskell's Prelude.foldl1 246 | function! s:foldl1(f, xs) abort 247 | if len(a:xs) == 0 248 | throw 'vital: Data.List: foldl1' 249 | endif 250 | return s:foldl(a:f, a:xs[0], a:xs[1:]) 251 | endfunction 252 | 253 | " similar to Haskell's Prelude.foldr 254 | function! s:foldr(f, init, xs) abort 255 | return s:foldl(a:f, a:init, reverse(copy(a:xs))) 256 | endfunction 257 | 258 | " similar to Haskell's Prelude.fold11 259 | function! s:foldr1(f, xs) abort 260 | if len(a:xs) == 0 261 | throw 'vital: Data.List: foldr1' 262 | endif 263 | return s:foldr(a:f, a:xs[-1], a:xs[0:-2]) 264 | endfunction 265 | 266 | " similar to python's zip() 267 | function! s:zip(...) abort 268 | return map(range(min(map(copy(a:000), 'len(v:val)'))), "map(copy(a:000), 'v:val['.v:val.']')") 269 | endfunction 270 | 271 | " similar to zip(), but goes until the longer one. 272 | function! s:zip_fill(xs, ys, filler) abort 273 | if empty(a:xs) && empty(a:ys) 274 | return [] 275 | elseif empty(a:ys) 276 | return s:cons([a:xs[0], a:filler], s:zip_fill(a:xs[1 :], [], a:filler)) 277 | elseif empty(a:xs) 278 | return s:cons([a:filler, a:ys[0]], s:zip_fill([], a:ys[1 :], a:filler)) 279 | else 280 | return s:cons([a:xs[0], a:ys[0]], s:zip_fill(a:xs[1 :], a:ys[1: ], a:filler)) 281 | endif 282 | endfunction 283 | 284 | " Inspired by Ruby's with_index method. 285 | function! s:with_index(list, ...) abort 286 | let base = a:0 > 0 ? a:1 : 0 287 | return map(copy(a:list), '[v:val, v:key + base]') 288 | endfunction 289 | 290 | " similar to Ruby's detect or Haskell's find. 291 | function! s:find(list, default, f) abort 292 | let l:Call = type(a:f) is type(function('function')) 293 | \ ? function('call') 294 | \ : function('s:_call_string_expr') 295 | 296 | for x in a:list 297 | if l:Call(a:f, [x]) 298 | return x 299 | endif 300 | endfor 301 | return a:default 302 | endfunction 303 | 304 | function! s:_call_string_expr(expr, args) abort 305 | return map([a:args[0]], a:expr)[0] 306 | endfunction 307 | 308 | " Returns the index of the first element which satisfies the given expr. 309 | function! s:find_index(xs, f, ...) abort 310 | let len = len(a:xs) 311 | let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : 0 312 | let default = a:0 > 1 ? a:2 : -1 313 | if start >=# len || start < 0 314 | return default 315 | endif 316 | for i in range(start, len - 1) 317 | if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g')) 318 | return i 319 | endif 320 | endfor 321 | return default 322 | endfunction 323 | 324 | " Returns the index of the last element which satisfies the given expr. 325 | function! s:find_last_index(xs, f, ...) abort 326 | let len = len(a:xs) 327 | let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : len - 1 328 | let default = a:0 > 1 ? a:2 : -1 329 | if start >=# len || start < 0 330 | return default 331 | endif 332 | for i in range(start, 0, -1) 333 | if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g')) 334 | return i 335 | endif 336 | endfor 337 | return default 338 | endfunction 339 | 340 | " Similar to find_index but returns the list of indices satisfying the given expr. 341 | function! s:find_indices(xs, f, ...) abort 342 | let len = len(a:xs) 343 | let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : 0 344 | let result = [] 345 | if start >=# len || start < 0 346 | return result 347 | endif 348 | for i in range(start, len - 1) 349 | if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g')) 350 | call add(result, i) 351 | endif 352 | endfor 353 | return result 354 | endfunction 355 | 356 | " Return non-zero if a:list1 and a:list2 have any common item(s). 357 | " Return zero otherwise. 358 | function! s:has_common_items(list1, list2) abort 359 | return !empty(filter(copy(a:list1), 'index(a:list2, v:val) isnot -1')) 360 | endfunction 361 | 362 | function! s:intersect(list1, list2) abort 363 | let items = [] 364 | " for funcref 365 | for X in a:list1 366 | if index(a:list2, X) != -1 && index(items, X) == -1 367 | let items += [X] 368 | endif 369 | endfor 370 | return items 371 | endfunction 372 | 373 | " similar to Ruby's group_by. 374 | function! s:group_by(xs, f) abort 375 | let result = {} 376 | let list = map(copy(a:xs), printf('[v:val, %s]', a:f)) 377 | for x in list 378 | let Val = x[0] 379 | let key = type(x[1]) !=# type('') ? string(x[1]) : x[1] 380 | if has_key(result, key) 381 | call add(result[key], Val) 382 | else 383 | let result[key] = [Val] 384 | endif 385 | unlet Val 386 | endfor 387 | return result 388 | endfunction 389 | 390 | function! s:_default_compare(a, b) abort 391 | return a:a <# a:b ? -1 : a:a ># a:b ? 1 : 0 392 | endfunction 393 | 394 | function! s:binary_search(list, value, ...) abort 395 | let Predicate = a:0 >= 1 ? a:1 : 's:_default_compare' 396 | let dic = a:0 >= 2 ? a:2 : {} 397 | let start = 0 398 | let end = len(a:list) - 1 399 | 400 | while 1 401 | if start > end 402 | return -1 403 | endif 404 | 405 | let middle = (start + end) / 2 406 | 407 | let compared = call(Predicate, [a:value, a:list[middle]], dic) 408 | 409 | if compared < 0 410 | let end = middle - 1 411 | elseif compared > 0 412 | let start = middle + 1 413 | else 414 | return middle 415 | endif 416 | endwhile 417 | endfunction 418 | 419 | function! s:product(lists) abort 420 | let result = [[]] 421 | for pool in a:lists 422 | let tmp = [] 423 | for x in result 424 | let tmp += map(copy(pool), 'x + [v:val]') 425 | endfor 426 | let result = tmp 427 | endfor 428 | return result 429 | endfunction 430 | 431 | function! s:permutations(list, ...) abort 432 | if a:0 > 1 433 | throw 'vital: Data.List: too many arguments' 434 | endif 435 | let r = a:0 == 1 ? a:1 : len(a:list) 436 | if r > len(a:list) 437 | return [] 438 | elseif r < 0 439 | throw 'vital: Data.List: {r} must be non-negative integer' 440 | endif 441 | let n = len(a:list) 442 | let result = [] 443 | for indices in s:product(map(range(r), 'range(n)')) 444 | if len(s:uniq(indices)) == r 445 | call add(result, map(indices, 'a:list[v:val]')) 446 | endif 447 | endfor 448 | return result 449 | endfunction 450 | 451 | function! s:combinations(list, r) abort 452 | if a:r > len(a:list) 453 | return [] 454 | elseif a:r < 0 455 | throw 'vital: Data.List: {r} must be non-negative integer' 456 | endif 457 | let n = len(a:list) 458 | let result = [] 459 | for indices in s:permutations(range(n), a:r) 460 | if s:sort(copy(indices), 'a:a - a:b') == indices 461 | call add(result, map(indices, 'a:list[v:val]')) 462 | endif 463 | endfor 464 | return result 465 | endfunction 466 | 467 | let &cpo = s:save_cpo 468 | unlet s:save_cpo 469 | 470 | " vim:set et ts=2 sts=2 sw=2 tw=0: 471 | -------------------------------------------------------------------------------- /autoload/vital/_shiny/Gift.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_shiny#Gift#import() abort 6 | 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': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_shiny#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': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | scriptencoding utf-8 17 | let s:save_cpo = &cpo 18 | set cpo&vim 19 | 20 | 21 | function! s:_vital_loaded(V) 22 | let s:V = a:V 23 | let s:Window = s:V.import("Gift.Window") 24 | let s:Tabpage = s:V.import("Gift.Tabpage") 25 | endfunction 26 | 27 | 28 | function! s:_vital_depends() 29 | return [ 30 | \ "Gift.Window", 31 | \ "Gift.Tabpage", 32 | \ ] 33 | endfunction 34 | 35 | 36 | function! s:to_fullpath(filename) 37 | let name = substitute(fnamemodify(a:filename, ":p"), '\', '/', "g") 38 | if filereadable(name) 39 | return name 40 | else 41 | return a:filename 42 | endif 43 | endfunction 44 | 45 | 46 | function! s:flatten(list) 47 | return eval(join(a:list, "+")) 48 | endfunction 49 | 50 | 51 | function! s:bufnr(expr) 52 | return type(a:expr) == type([]) 53 | \ ? s:bufnr(s:uniq_winnr(a:expr[1], a:expr[0])) 54 | \ : s:Window.bufnr(a:expr) 55 | endfunction 56 | 57 | 58 | function! s:openable_bufnr_list() 59 | return map(s:tabpagewinnr_list(), "s:bufnr([v:val[0], v:val[1]])") 60 | endfunction 61 | 62 | 63 | function! s:tabpagewinnr(...) 64 | return a:0 == 0 ? s:tabpagewinnr(s:uniq_winnr()) 65 | \ : s:Window.tabpagewinnr(a:1) 66 | endfunction 67 | 68 | 69 | function! s:tabpagewinnr_list() 70 | return s:Window.tabpagewinnr_list() 71 | " return s:flatten(map(range(1, tabpagenr("$")), "map(range(1, tabpagewinnr(v:val, '$')), '['.v:val.', v:val]')")) 72 | endfunction 73 | 74 | 75 | 76 | function! s:uniq_winnr(...) 77 | return call(s:Window.uniq_nr, a:000, s:Window) 78 | endfunction 79 | 80 | 81 | function! s:winnr(uniqnr) 82 | let [tabnr, winnr] = s:Window.tabpagewinnr(a:uniqnr) 83 | return winnr 84 | endfunction 85 | 86 | 87 | function! s:uniq_winnr_list(...) 88 | return map(s:tabpagewinnr_list(), "s:uniq_winnr(v:val[1], v:val[0])") 89 | endfunction 90 | 91 | 92 | 93 | function! s:find(expr) 94 | let gift_find_result = [] 95 | for [tabnr, winnr] in s:tabpagewinnr_list() 96 | let bufnr = s:bufnr([tabnr, winnr]) 97 | if eval(a:expr) 98 | call add(gift_find_result, [tabnr, winnr]) 99 | endif 100 | endfor 101 | return gift_find_result 102 | endfunction 103 | 104 | 105 | function! s:find_by(expr) 106 | if type(a:expr) == type(function("tr")) 107 | return filter(s:tabpagewinnr_list(), "a:expr(s:bufnr([v:val[0], v:val[1]]), v:val[0], v:val[1])") 108 | else 109 | return s:find(a:expr) 110 | endif 111 | endfunction 112 | 113 | 114 | function! s:jump_window(expr) 115 | return type(a:expr) == type([]) 116 | \ ? s:jump_window(s:uniq_winnr(a:expr[1], a:expr[0])) 117 | \ : s:Window.jump(a:expr) 118 | endfunction 119 | 120 | 121 | function! s:set_current_window(expr) 122 | return s:jump_window(a:expr) 123 | endfunction 124 | 125 | 126 | function! s:close_window(expr, ...) 127 | let close_cmd = get(a:, 1, "close") 128 | return type(a:expr) == type([]) 129 | \ ? s:close_window(s:uniq_winnr(a:expr[1], a:expr[0]), close_cmd) 130 | \ : s:Window.close(a:expr, close_cmd) 131 | endfunction 132 | 133 | 134 | function! s:close_window_by(expr, ...) 135 | let close_cmd = get(a:, 1, "close") 136 | return map(map(s:find(a:expr), "s:uniq_winnr(v:val[1], v:val[0])"), 's:close_window(v:val, close_cmd)') 137 | endfunction 138 | 139 | 140 | function! s:execute(expr, execute) 141 | return type(a:expr) == type([]) 142 | \ ? s:execute(s:uniq_winnr(a:expr[1], a:expr[0]), a:execute) 143 | \ : s:Window.execute(a:expr, a:execute) 144 | endfunction 145 | 146 | 147 | function! s:getwinvar(uniq_winnr, varname, ...) 148 | let def = get(a:, 1, "") 149 | return s:Window.getvar(a:uniq_winnr, a:varname, def) 150 | endfunction 151 | 152 | 153 | function! s:setwinvar(uniq_winnr, varname, val) 154 | return s:Window.setvar(a:uniq_winnr, a:varname, a:val) 155 | endfunction 156 | 157 | 158 | function! s:uniq_tabpagenr(...) 159 | return call(s:Tabpage.uniq_nr, a:000, s:Tabpage) 160 | endfunction 161 | 162 | 163 | 164 | let &cpo = s:save_cpo 165 | unlet s:save_cpo 166 | -------------------------------------------------------------------------------- /autoload/vital/_shiny/Gift/Tabpage.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_shiny#Gift#Tabpage#import() abort 6 | return map({'uniq_nr': '', 'make_uniq_nr': '', 'numbering': '', 'set_prefix': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_shiny#Gift#Tabpage#import() abort', printf("return map({'uniq_nr': '', 'make_uniq_nr': '', 'numbering': '', 'set_prefix': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | scriptencoding utf-8 17 | let s:save_cpo = &cpo 18 | set cpo&vim 19 | 20 | 21 | let s:prefix = expand(":p:h:h:t") 22 | function! s:set_prefix(prefix) 23 | let s:prefix = a:prefix 24 | endfunction 25 | 26 | 27 | let s:uniq_counter = 0 28 | function! s:make_uniq_nr() 29 | let s:uniq_counter += 1 30 | return s:uniq_counter 31 | endfunction 32 | 33 | 34 | function! s:numbering(...) 35 | let tabnr = get(a:, 1, tabpagenr()) 36 | let uniq_nr = s:make_uniq_nr() 37 | call settabvar(tabnr, s:prefix . "_gift_uniq_tabpagenr", uniq_nr) 38 | return uniq_nr 39 | endfunction 40 | 41 | 42 | function! s:uniq_nr(...) 43 | let tabnr = get(a:, 1, tabpagenr()) 44 | let uniq_nr = get(gettabvar(tabnr, ""), s:prefix . "_gift_uniq_tabpagenr", -1) 45 | if uniq_nr == -1 46 | let uniq_nr = s:numbering(tabnr) 47 | endif 48 | return uniq_nr 49 | endfunction 50 | 51 | 52 | let &cpo = s:save_cpo 53 | unlet s:save_cpo 54 | -------------------------------------------------------------------------------- /autoload/vital/_shiny/Gift/Window.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_shiny#Gift#Window#import() abort 6 | 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': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_shiny#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': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | scriptencoding utf-8 17 | let s:save_cpo = &cpo 18 | set cpo&vim 19 | 20 | 21 | function! s:_vital_loaded(V) 22 | let s:V = a:V 23 | let s:Tabpage = s:V.import("Gift.Tabpage") 24 | endfunction 25 | 26 | 27 | function! s:_vital_depends() 28 | return [ 29 | \ "Gift.Tabpage", 30 | \ ] 31 | endfunction 32 | 33 | 34 | let s:prefix = expand(":p:h:h:t") 35 | function! s:set_prefix(prefix) 36 | let s:prefix = a:prefix 37 | endfunction 38 | 39 | function! s:flatten(list) 40 | return eval(join(a:list, "+")) 41 | endfunction 42 | 43 | 44 | function! s:tabpagewinnr_list() 45 | return s:flatten(map(range(1, tabpagenr("$")), "map(range(1, tabpagewinnr(v:val, '$')), '['.v:val.', v:val]')")) 46 | endfunction 47 | 48 | 49 | if !exists("s:uniq_counter") 50 | let s:uniq_counter = 0 51 | endif 52 | function! s:make_uniq_nr() 53 | let s:uniq_counter += 1 54 | return s:uniq_counter 55 | endfunction 56 | 57 | 58 | function! s:numbering(...) 59 | let winnr = get(a:, 1, winnr()) 60 | let tabnr = get(a:, 2, tabpagenr()) 61 | let uniq_nr = s:make_uniq_nr() 62 | call settabwinvar(tabnr, winnr, s:prefix . "_gift_uniq_winnr", uniq_nr) 63 | return uniq_nr 64 | endfunction 65 | 66 | 67 | function! s:uniq_nr(...) 68 | let winnr = get(a:, 1, winnr()) 69 | let tabnr = get(a:, 2, tabpagenr()) 70 | let uniq_nr = get(gettabwinvar(tabnr, winnr, ""), s:prefix . "_gift_uniq_winnr", -1) 71 | if uniq_nr == -1 72 | let uniq_nr = s:numbering(winnr, tabnr) 73 | endif 74 | return uniq_nr 75 | endfunction 76 | 77 | 78 | function! s:exists(nr) 79 | let [tabnr, winnr] = s:tabpagewinnr(a:nr) 80 | return tabnr != 0 && winnr != 0 81 | endfunction 82 | 83 | 84 | function! s:tabpagewinnr(nr) 85 | if a:nr == 0 86 | return s:tabpagewinnr(s:uniq_nr()) 87 | endif 88 | let tabwinnrs = s:tabpagewinnr_list() 89 | for [tabnr, winnr] in tabwinnrs 90 | if s:uniq_nr(winnr, tabnr) == a:nr 91 | return [tabnr, winnr] 92 | endif 93 | endfor 94 | return [0, 0] 95 | endfunction 96 | 97 | 98 | function! s:getvar(nr, varname, ...) 99 | let def = get(a:, 1, "") 100 | let [tabnr, winnr] = s:tabpagewinnr(a:nr) 101 | return get(gettabwinvar(tabnr, winnr, ""), a:varname, def) 102 | endfunction 103 | 104 | 105 | function! s:setvar(nr, varname, val) 106 | let [tabnr, winnr] = s:tabpagewinnr(a:nr) 107 | if tabnr == 0 || winnr == 0 108 | return 109 | endif 110 | return settabwinvar(tabnr, winnr, a:varname, a:val) 111 | endfunction 112 | 113 | 114 | function! s:bufnr(nr) 115 | let [tabnr, winnr] = s:tabpagewinnr(a:nr) 116 | return winnr >= 1 ? get(tabpagebuflist(tabnr), winnr-1, -1) : -1 117 | endfunction 118 | 119 | 120 | 121 | function! s:jump(nr) 122 | let [tabnr, winnr] = s:tabpagewinnr(a:nr) 123 | if tabnr == 0 || winnr == 0 124 | return -1 125 | endif 126 | 127 | execute "tabnext" tabnr 128 | execute winnr . "wincmd w" 129 | endfunction 130 | 131 | 132 | function! s:close(nr, close_cmd) 133 | call s:execute(a:nr, a:close_cmd) 134 | " let current = gift#uniq_winnr() 135 | " let result = s:jump(a:nr) 136 | " if result == -1 137 | " return -1 138 | " endif 139 | " execute a:close_cmd 140 | " return s:jump(current) 141 | endfunction 142 | 143 | 144 | function! s:execute(nr, expr) 145 | let current = s:uniq_nr() 146 | let result = s:jump(a:nr) 147 | if result == -1 148 | return -1 149 | endif 150 | execute a:expr 151 | return s:jump(current) 152 | endfunction 153 | 154 | 155 | 156 | 157 | 158 | let &cpo = s:save_cpo 159 | unlet s:save_cpo 160 | -------------------------------------------------------------------------------- /autoload/vital/_shiny/Prelude.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_shiny#Prelude#import() abort 6 | 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': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_shiny#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': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | let s:save_cpo = &cpo 17 | set cpo&vim 18 | 19 | if v:version > 703 || 20 | \ (v:version == 703 && has('patch465')) 21 | function! s:glob(expr) abort 22 | return glob(a:expr, 1, 1) 23 | endfunction 24 | else 25 | function! s:glob(expr) abort 26 | return split(glob(a:expr, 1), '\n') 27 | endfunction 28 | endif 29 | 30 | if v:version > 704 || 31 | \ (v:version == 704 && has('patch279')) 32 | function! s:globpath(path, expr) abort 33 | return globpath(a:path, a:expr, 1, 1) 34 | endfunction 35 | else 36 | function! s:globpath(path, expr) abort 37 | return split(globpath(a:path, a:expr, 1), '\n') 38 | endfunction 39 | endif 40 | 41 | " Wrapper functions for type(). 42 | " NOTE: __TYPE_FLOAT = -1 when -float. 43 | " this doesn't match to anything. 44 | if has('patch-7.4.2071') 45 | let [ 46 | \ s:__TYPE_NUMBER, 47 | \ s:__TYPE_STRING, 48 | \ s:__TYPE_FUNCREF, 49 | \ s:__TYPE_LIST, 50 | \ s:__TYPE_DICT, 51 | \ s:__TYPE_FLOAT] = [ 52 | \ v:t_number, 53 | \ v:t_string, 54 | \ v:t_func, 55 | \ v:t_list, 56 | \ v:t_dict, 57 | \ v:t_float] 58 | else 59 | let [ 60 | \ s:__TYPE_NUMBER, 61 | \ s:__TYPE_STRING, 62 | \ s:__TYPE_FUNCREF, 63 | \ s:__TYPE_LIST, 64 | \ s:__TYPE_DICT, 65 | \ s:__TYPE_FLOAT] = [ 66 | \ type(3), 67 | \ type(''), 68 | \ type(function('tr')), 69 | \ type([]), 70 | \ type({}), 71 | \ has('float') ? type(str2float('0')) : -1] 72 | endif 73 | 74 | " Number or Float 75 | function! s:is_numeric(Value) abort 76 | let _ = type(a:Value) 77 | return _ ==# s:__TYPE_NUMBER 78 | \ || _ ==# s:__TYPE_FLOAT 79 | endfunction 80 | 81 | " Number 82 | function! s:is_number(Value) abort 83 | return type(a:Value) ==# s:__TYPE_NUMBER 84 | endfunction 85 | 86 | " String 87 | function! s:is_string(Value) abort 88 | return type(a:Value) ==# s:__TYPE_STRING 89 | endfunction 90 | 91 | " Funcref 92 | function! s:is_funcref(Value) abort 93 | return type(a:Value) ==# s:__TYPE_FUNCREF 94 | endfunction 95 | 96 | " List 97 | function! s:is_list(Value) abort 98 | return type(a:Value) ==# s:__TYPE_LIST 99 | endfunction 100 | 101 | " Dictionary 102 | function! s:is_dict(Value) abort 103 | return type(a:Value) ==# s:__TYPE_DICT 104 | endfunction 105 | 106 | " Float 107 | function! s:is_float(Value) abort 108 | return type(a:Value) ==# s:__TYPE_FLOAT 109 | endfunction 110 | 111 | 112 | function! s:truncate_skipping(str, max, footer_width, separator) abort 113 | call s:_warn_deprecated('truncate_skipping', 'Data.String.truncate_skipping') 114 | 115 | let width = s:wcswidth(a:str) 116 | if width <= a:max 117 | let ret = a:str 118 | else 119 | let header_width = a:max - s:wcswidth(a:separator) - a:footer_width 120 | let ret = s:strwidthpart(a:str, header_width) . a:separator 121 | \ . s:strwidthpart_reverse(a:str, a:footer_width) 122 | endif 123 | 124 | return s:truncate(ret, a:max) 125 | endfunction 126 | 127 | function! s:truncate(str, width) abort 128 | " Original function is from mattn. 129 | " http://github.com/mattn/googlereader-vim/tree/master 130 | 131 | call s:_warn_deprecated('truncate', 'Data.String.truncate') 132 | 133 | if a:str =~# '^[\x00-\x7f]*$' 134 | return len(a:str) < a:width ? 135 | \ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width) 136 | endif 137 | 138 | let ret = a:str 139 | let width = s:wcswidth(a:str) 140 | if width > a:width 141 | let ret = s:strwidthpart(ret, a:width) 142 | let width = s:wcswidth(ret) 143 | endif 144 | 145 | if width < a:width 146 | let ret .= repeat(' ', a:width - width) 147 | endif 148 | 149 | return ret 150 | endfunction 151 | 152 | function! s:strwidthpart(str, width) abort 153 | call s:_warn_deprecated('strwidthpart', 'Data.String.strwidthpart') 154 | 155 | if a:width <= 0 156 | return '' 157 | endif 158 | let ret = a:str 159 | let width = s:wcswidth(a:str) 160 | while width > a:width 161 | let char = matchstr(ret, '.$') 162 | let ret = ret[: -1 - len(char)] 163 | let width -= s:wcswidth(char) 164 | endwhile 165 | 166 | return ret 167 | endfunction 168 | function! s:strwidthpart_reverse(str, width) abort 169 | call s:_warn_deprecated('strwidthpart_reverse', 'Data.String.strwidthpart_reverse') 170 | 171 | if a:width <= 0 172 | return '' 173 | endif 174 | let ret = a:str 175 | let width = s:wcswidth(a:str) 176 | while width > a:width 177 | let char = matchstr(ret, '^.') 178 | let ret = ret[len(char) :] 179 | let width -= s:wcswidth(char) 180 | endwhile 181 | 182 | return ret 183 | endfunction 184 | 185 | if v:version >= 703 186 | " Use builtin function. 187 | function! s:wcswidth(str) abort 188 | call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth') 189 | return strwidth(a:str) 190 | endfunction 191 | else 192 | function! s:wcswidth(str) abort 193 | call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth') 194 | 195 | if a:str =~# '^[\x00-\x7f]*$' 196 | return strlen(a:str) 197 | end 198 | 199 | let mx_first = '^\(.\)' 200 | let str = a:str 201 | let width = 0 202 | while 1 203 | let ucs = char2nr(substitute(str, mx_first, '\1', '')) 204 | if ucs == 0 205 | break 206 | endif 207 | let width += s:_wcwidth(ucs) 208 | let str = substitute(str, mx_first, '', '') 209 | endwhile 210 | return width 211 | endfunction 212 | 213 | " UTF-8 only. 214 | function! s:_wcwidth(ucs) abort 215 | let ucs = a:ucs 216 | if (ucs >= 0x1100 217 | \ && (ucs <= 0x115f 218 | \ || ucs == 0x2329 219 | \ || ucs == 0x232a 220 | \ || (ucs >= 0x2e80 && ucs <= 0xa4cf 221 | \ && ucs != 0x303f) 222 | \ || (ucs >= 0xac00 && ucs <= 0xd7a3) 223 | \ || (ucs >= 0xf900 && ucs <= 0xfaff) 224 | \ || (ucs >= 0xfe30 && ucs <= 0xfe6f) 225 | \ || (ucs >= 0xff00 && ucs <= 0xff60) 226 | \ || (ucs >= 0xffe0 && ucs <= 0xffe6) 227 | \ || (ucs >= 0x20000 && ucs <= 0x2fffd) 228 | \ || (ucs >= 0x30000 && ucs <= 0x3fffd) 229 | \ )) 230 | return 2 231 | endif 232 | return 1 233 | endfunction 234 | endif 235 | 236 | let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95') 237 | let s:is_cygwin = has('win32unix') 238 | let s:is_mac = !s:is_windows && !s:is_cygwin 239 | \ && (has('mac') || has('macunix') || has('gui_macvim') || 240 | \ (!isdirectory('/proc') && executable('sw_vers'))) 241 | let s:is_unix = has('unix') 242 | 243 | function! s:is_windows() abort 244 | return s:is_windows 245 | endfunction 246 | 247 | function! s:is_cygwin() abort 248 | return s:is_cygwin 249 | endfunction 250 | 251 | function! s:is_mac() abort 252 | return s:is_mac 253 | endfunction 254 | 255 | function! s:is_unix() abort 256 | return s:is_unix 257 | endfunction 258 | 259 | function! s:_warn_deprecated(name, alternative) abort 260 | try 261 | echohl Error 262 | echomsg 'Prelude.' . a:name . ' is deprecated! Please use ' . a:alternative . ' instead.' 263 | finally 264 | echohl None 265 | endtry 266 | endfunction 267 | 268 | function! s:smart_execute_command(action, word) abort 269 | execute a:action . ' ' . (a:word ==# '' ? '' : '`=a:word`') 270 | endfunction 271 | 272 | function! s:escape_file_searching(buffer_name) abort 273 | return escape(a:buffer_name, '*[]?{}, ') 274 | endfunction 275 | 276 | function! s:escape_pattern(str) abort 277 | call s:_warn_deprecated( 278 | \ 'escape_pattern', 279 | \ 'Data.String.escape_pattern', 280 | \) 281 | return escape(a:str, '~"\.^$[]*') 282 | endfunction 283 | 284 | function! s:getchar(...) abort 285 | let c = call('getchar', a:000) 286 | return type(c) == type(0) ? nr2char(c) : c 287 | endfunction 288 | 289 | function! s:getchar_safe(...) abort 290 | let c = s:input_helper('getchar', a:000) 291 | return type(c) == type('') ? c : nr2char(c) 292 | endfunction 293 | 294 | function! s:input_safe(...) abort 295 | return s:input_helper('input', a:000) 296 | endfunction 297 | 298 | function! s:input_helper(funcname, args) abort 299 | let success = 0 300 | if inputsave() !=# success 301 | throw 'vital: Prelude: inputsave() failed' 302 | endif 303 | try 304 | return call(a:funcname, a:args) 305 | finally 306 | if inputrestore() !=# success 307 | throw 'vital: Prelude: inputrestore() failed' 308 | endif 309 | endtry 310 | endfunction 311 | 312 | function! s:set_default(var, val) abort 313 | if !exists(a:var) || type({a:var}) != type(a:val) 314 | let {a:var} = a:val 315 | endif 316 | endfunction 317 | 318 | function! s:substitute_path_separator(path) abort 319 | return s:is_windows ? substitute(a:path, '\\', '/', 'g') : a:path 320 | endfunction 321 | 322 | function! s:path2directory(path) abort 323 | return s:substitute_path_separator(isdirectory(a:path) ? a:path : fnamemodify(a:path, ':p:h')) 324 | endfunction 325 | 326 | function! s:_path2project_directory_git(path) abort 327 | let parent = a:path 328 | 329 | while 1 330 | let path = parent . '/.git' 331 | if isdirectory(path) || filereadable(path) 332 | return parent 333 | endif 334 | let next = fnamemodify(parent, ':h') 335 | if next == parent 336 | return '' 337 | endif 338 | let parent = next 339 | endwhile 340 | endfunction 341 | 342 | function! s:_path2project_directory_svn(path) abort 343 | let search_directory = a:path 344 | let directory = '' 345 | 346 | let find_directory = s:escape_file_searching(search_directory) 347 | let d = finddir('.svn', find_directory . ';') 348 | if d ==# '' 349 | return '' 350 | endif 351 | 352 | let directory = fnamemodify(d, ':p:h:h') 353 | 354 | " Search parent directories. 355 | let parent_directory = s:path2directory( 356 | \ fnamemodify(directory, ':h')) 357 | 358 | if parent_directory !=# '' 359 | let d = finddir('.svn', parent_directory . ';') 360 | if d !=# '' 361 | let directory = s:_path2project_directory_svn(parent_directory) 362 | endif 363 | endif 364 | return directory 365 | endfunction 366 | 367 | function! s:_path2project_directory_others(vcs, path) abort 368 | let vcs = a:vcs 369 | let search_directory = a:path 370 | 371 | let find_directory = s:escape_file_searching(search_directory) 372 | let d = finddir(vcs, find_directory . ';') 373 | if d ==# '' 374 | return '' 375 | endif 376 | return fnamemodify(d, ':p:h:h') 377 | endfunction 378 | 379 | function! s:path2project_directory(path, ...) abort 380 | let is_allow_empty = get(a:000, 0, 0) 381 | let search_directory = s:path2directory(a:path) 382 | let directory = '' 383 | 384 | " Search VCS directory. 385 | for vcs in ['.git', '.bzr', '.hg', '.svn'] 386 | if vcs ==# '.git' 387 | let directory = s:_path2project_directory_git(search_directory) 388 | elseif vcs ==# '.svn' 389 | let directory = s:_path2project_directory_svn(search_directory) 390 | else 391 | let directory = s:_path2project_directory_others(vcs, search_directory) 392 | endif 393 | if directory !=# '' 394 | break 395 | endif 396 | endfor 397 | 398 | " Search project file. 399 | if directory ==# '' 400 | for d in ['build.xml', 'prj.el', '.project', 'pom.xml', 'package.json', 401 | \ 'Makefile', 'configure', 'Rakefile', 'NAnt.build', 402 | \ 'P4CONFIG', 'tags', 'gtags'] 403 | let d = findfile(d, s:escape_file_searching(search_directory) . ';') 404 | if d !=# '' 405 | let directory = fnamemodify(d, ':p:h') 406 | break 407 | endif 408 | endfor 409 | endif 410 | 411 | if directory ==# '' 412 | " Search /src/ directory. 413 | let base = s:substitute_path_separator(search_directory) 414 | if base =~# '/src/' 415 | let directory = base[: strridx(base, '/src/') + 3] 416 | endif 417 | endif 418 | 419 | if directory ==# '' && !is_allow_empty 420 | " Use original path. 421 | let directory = search_directory 422 | endif 423 | 424 | return s:substitute_path_separator(directory) 425 | endfunction 426 | 427 | let &cpo = s:save_cpo 428 | unlet s:save_cpo 429 | 430 | " vim:set et ts=2 sts=2 sw=2 tw=0: 431 | -------------------------------------------------------------------------------- /autoload/vital/_shiny/Vim/Buffer.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_shiny#Vim#Buffer#import() abort 6 | return map({'parse_cmdarg': '', '_vital_depends': '', 'read_content': '', 'get_selected_text': '', 'is_cmdwin': '', 'edit_content': '', 'open': '', 'get_last_selected': '', '_vital_loaded': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_shiny#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': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | let s:save_cpo = &cpo 17 | set cpo&vim 18 | 19 | let s:t_funcref = type(function('tr')) 20 | let s:t_string = type('') 21 | let s:t_number = type(0) 22 | 23 | function! s:_vital_loaded(V) abort 24 | let s:V = a:V 25 | let s:Guard = s:V.import('Vim.Guard') 26 | endfunction 27 | 28 | function! s:_vital_depends() abort 29 | return ['Vim.Guard'] 30 | endfunction 31 | 32 | if exists('*getcmdwintype') 33 | function! s:is_cmdwin() abort 34 | return getcmdwintype() !=# '' 35 | endfunction 36 | else 37 | function! s:is_cmdwin() abort 38 | return bufname('%') ==# '[Command Line]' 39 | endfunction 40 | endif 41 | 42 | function! s:open(buffer, ...) abort 43 | if a:0 == 1 && (type(a:1) == s:t_string || type(a:1) == s:t_funcref) 44 | " For backward compatibility 45 | let options = {'opener': a:1} 46 | else 47 | let options = get(a:000, 0, {}) 48 | endif 49 | let options = extend({ 50 | \ 'mods': '', 51 | \ 'cmdarg': '', 52 | \ 'opener': empty(a:buffer) ? 'enew' : 'edit', 53 | \}, options 54 | \) 55 | 56 | let guard = s:Guard.store(['&wildignore']) 57 | try 58 | let &wildignore = '' 59 | if type(options.opener) == s:t_funcref 60 | let loaded = !bufloaded(a:buffer) 61 | call options.opener(a:buffer) 62 | elseif a:buffer is 0 || a:buffer is# '' 63 | let loaded = 1 64 | silent execute options.mods options.opener 65 | enew 66 | else 67 | let loaded = !bufloaded(a:buffer) 68 | if type(a:buffer) == s:t_string 69 | execute options.mods options.opener options.cmdarg '`=a:buffer`' 70 | elseif type(a:buffer) == s:t_number 71 | silent execute options.mods options.opener 72 | execute a:buffer 'buffer' 73 | else 74 | throw 'vital: Vim.Buffer: Unknown {buffer} type.' 75 | endif 76 | endif 77 | finally 78 | call guard.restore() 79 | endtry 80 | return loaded 81 | endfunction 82 | 83 | function! s:get_selected_text(...) abort 84 | echohl WarningMsg 85 | echom "vital: Vim.Buffer: Warning: s:get_selected_text() is deprecated. Use 's:get_last_selected()'." 86 | echohl None 87 | return call('s:get_last_selected', a:000) 88 | endfunction 89 | 90 | " Get the last selected text in visual mode 91 | " without using |gv| to avoid |textlock|. 92 | " NOTE: 93 | " * This function uses |gv| only when using |CTRL-V| 94 | " because |gv| is the only way to get selected text 95 | " when using $ . 96 | " Please see #192 for the details. 97 | " * If you don't care about |textlock|, 98 | " you can use simple version of this function. 99 | " https://github.com/vim-jp/vital.vim/commit/39aae80f3839fdbeebd838ff14d87327a6b889a9 100 | function! s:get_last_selected() abort 101 | if visualmode() ==# "\" 102 | let save = getreg('"', 1) 103 | let save_type = getregtype('"') 104 | try 105 | normal! gv""y 106 | return @" 107 | finally 108 | call setreg('"', save, save_type) 109 | endtry 110 | else 111 | let [begin, end] = [getpos("'<"), getpos("'>")] 112 | let lastchar = matchstr(getline(end[1])[end[2]-1 :], '.') 113 | if begin[1] ==# end[1] 114 | let lines = [getline(begin[1])[begin[2]-1 : end[2]-2]] 115 | else 116 | let lines = [getline(begin[1])[begin[2]-1 :]] 117 | \ + (end[1] - begin[1] <# 2 ? [] : getline(begin[1]+1, end[1]-1)) 118 | \ + [getline(end[1])[: end[2]-2]] 119 | endif 120 | return join(lines, "\n") . lastchar . (visualmode() ==# 'V' ? "\n" : '') 121 | endif 122 | endfunction 123 | 124 | function! s:read_content(content, ...) abort 125 | let options = extend({ 126 | \ 'tempfile': '', 127 | \ 'fileformat': '', 128 | \ 'encoding': '', 129 | \ 'binary': 0, 130 | \ 'nobinary': 0, 131 | \ 'bad': '', 132 | \ 'edit': 0, 133 | \ 'line': '', 134 | \ 'lockmarks': 0, 135 | \}, get(a:000, 0, {})) 136 | let tempfile = empty(options.tempfile) ? tempname() : options.tempfile 137 | let optnames = [ 138 | \ empty(options.fileformat) ? '' : '++ff=' . options.fileformat, 139 | \ empty(options.encoding) ? '' : '++enc=' . options.encoding, 140 | \ empty(options.binary) ? '' : '++bin', 141 | \ empty(options.nobinary) ? '' : '++nobin', 142 | \ empty(options.bad) ? '' : '++bad=' . options.bad, 143 | \ empty(options.edit) ? '' : '++edit', 144 | \] 145 | let optname = join(filter(optnames, '!empty(v:val)')) 146 | try 147 | call writefile(a:content, tempfile) 148 | execute printf('keepalt keepjumps %s%sread %s%s', 149 | \ options.lockmarks ? 'lockmarks ' : '', 150 | \ options.line, 151 | \ empty(optname) ? '' : optname . ' ', 152 | \ fnameescape(tempfile), 153 | \) 154 | finally 155 | call delete(tempfile) 156 | " To remove 'tempfile' from unlisted-buffer #439 157 | silent execute 'bwipeout!' fnameescape(tempfile) 158 | endtry 159 | endfunction 160 | 161 | function! s:edit_content(content, ...) abort 162 | let options = extend({ 163 | \ 'edit': 1, 164 | \ 'lockmarks': 0, 165 | \}, get(a:000, 0, {})) 166 | let guard = s:Guard.store(['&l:modifiable']) 167 | let saved_view = winsaveview() 168 | try 169 | let &l:modifiable=1 170 | silent execute printf( 171 | \ 'keepjumps %s%%delete _', 172 | \ options.lockmarks ? 'lockmarks ' : '', 173 | \) 174 | silent call s:read_content(a:content, options) 175 | silent execute printf( 176 | \ 'keepjumps %s1delete _', 177 | \ options.lockmarks ? 'lockmarks ' : '', 178 | \) 179 | finally 180 | keepjumps call winrestview(saved_view) 181 | call guard.restore() 182 | endtry 183 | setlocal nomodified 184 | endfunction 185 | 186 | function! s:parse_cmdarg(...) abort 187 | let cmdarg = get(a:000, 0, v:cmdarg) 188 | let options = {} 189 | if cmdarg =~# '++enc=' 190 | let options.encoding = matchstr(cmdarg, '++enc=\zs[^ ]\+\ze') 191 | endif 192 | if cmdarg =~# '++ff=' 193 | let options.fileformat = matchstr(cmdarg, '++ff=\zs[^ ]\+\ze') 194 | endif 195 | if cmdarg =~# '++bad=' 196 | let options.bad = matchstr(cmdarg, '++bad=\zs[^ ]\+\ze') 197 | endif 198 | if cmdarg =~# '++bin' 199 | let options.binary = 1 200 | endif 201 | if cmdarg =~# '++nobin' 202 | let options.nobinary = 1 203 | endif 204 | if cmdarg =~# '++edit' 205 | let options.edit = 1 206 | endif 207 | return options 208 | endfunction 209 | 210 | let &cpo = s:save_cpo 211 | unlet s:save_cpo 212 | 213 | " vim:set et ts=2 sts=2 sw=2 tw=0: 214 | -------------------------------------------------------------------------------- /autoload/vital/_shiny/Vim/Guard.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_shiny#Vim#Guard#import() abort 6 | return map({'_vital_depends': '', '_vital_created': '', 'store': '', '_vital_loaded': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_shiny#Vim#Guard#import() abort', printf("return map({'_vital_depends': '', '_vital_created': '', 'store': '', '_vital_loaded': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | let s:save_cpo = &cpo 17 | set cpo&vim 18 | 19 | " Use a Funcref as a special term _UNDEFINED 20 | function! s:_undefined() abort 21 | return 'undefined' 22 | endfunction 23 | let s:_UNDEFINED = function('s:_undefined') 24 | 25 | function! s:_vital_loaded(V) abort 26 | let s:V = a:V 27 | let s:Prelude = s:V.import('Prelude') 28 | let s:List = s:V.import('Data.List') 29 | let s:Dict = s:V.import('Data.Dict') 30 | endfunction 31 | function! s:_vital_depends() abort 32 | return ['Prelude', 'Data.List', 'Data.Dict'] 33 | endfunction 34 | function! s:_vital_created(module) abort 35 | " define constant variables 36 | if !exists('s:const') 37 | let s:const = {} 38 | let s:const.is_local_variable_supported = 39 | \ v:version > 703 || (v:version == 703 && has('patch560')) 40 | " NOTE: 41 | " The third argument is available from 7.4.242 but it had bug and that 42 | " bug was fixed from 7.4.513 43 | let s:const.is_third_argument_of_getreg_supported = has('patch-7.4.513') 44 | lockvar s:const 45 | endif 46 | call extend(a:module, s:const) 47 | endfunction 48 | function! s:_throw(msg) abort 49 | throw printf('vital: Vim.Guard: %s', a:msg) 50 | endfunction 51 | 52 | let s:option = {} 53 | function! s:_new_option(name) abort 54 | if a:name !~# '^&' 55 | call s:_throw(printf( 56 | \'An option name "%s" requires to be started from "&"', a:name 57 | \)) 58 | elseif !exists(a:name) 59 | call s:_throw(printf( 60 | \'An option name "%s" does not exist', a:name 61 | \)) 62 | endif 63 | let option = copy(s:option) 64 | let option.name = a:name 65 | let option.value = eval(a:name) 66 | return option 67 | endfunction 68 | function! s:option.restore() abort 69 | execute printf('let %s = %s', self.name, string(self.value)) 70 | endfunction 71 | 72 | let s:register = {} 73 | function! s:_new_register(name) abort 74 | if len(a:name) != 2 75 | call s:_throw(printf( 76 | \'A register name "%s" requires to be "@" + a single character', a:name 77 | \)) 78 | elseif a:name !~# '^@' 79 | call s:_throw(printf( 80 | \'A register name "%s" requires to be started from "@"', a:name 81 | \)) 82 | elseif a:name =~# '^@[:.%]$' 83 | call s:_throw(printf( 84 | \'A register name "%s" is read only', a:name 85 | \)) 86 | elseif a:name !~# '^@[@0-9a-zA-Z#=*+~_/-]$' 87 | call s:_throw(printf( 88 | \'A register name "%s" does not exist. See ":help let-register"', a:name 89 | \)) 90 | endif 91 | let name = a:name ==# '@@' ? '' : a:name[1] 92 | let register = copy(s:register) 93 | let register.name = name 94 | if s:const.is_third_argument_of_getreg_supported 95 | let register.value = getreg(name, 1, 1) 96 | else 97 | let register.value = getreg(name, 1) 98 | endif 99 | let register.type = getregtype(name) 100 | return register 101 | endfunction 102 | function! s:register.restore() abort 103 | " https://github.com/vim/vim/commit/5a50c2255c447838d08d3b4895a3be3a41cd8eda 104 | if has('patch-7.4.243') || self.name !=# '=' 105 | call setreg(self.name, self.value, self.type) 106 | else 107 | let @= = self.value 108 | endif 109 | endfunction 110 | 111 | let s:environment = {} 112 | function! s:_new_environment(name) abort 113 | if a:name !~# '^\$' 114 | call s:_throw(printf( 115 | \'An environment variable name "%s" requires to be started from "$"', a:name 116 | \)) 117 | elseif !exists(a:name) 118 | call s:_throw(printf( 119 | \'An environment variable name "%s" does not exist. While Vim cannot unlet environment variable, it requires to exist', a:name 120 | \)) 121 | endif 122 | let environment = copy(s:environment) 123 | let environment.name = a:name 124 | let environment.value = eval(a:name) 125 | return environment 126 | endfunction 127 | function! s:environment.restore() abort 128 | execute printf('let %s = %s', self.name, string(self.value)) 129 | endfunction 130 | 131 | let s:variable = {} 132 | function! s:_new_variable(name, ...) abort 133 | if a:0 == 0 134 | let m = matchlist(a:name, '^\([bwtg]:\)\(.*\)$') 135 | if empty(m) 136 | call s:_throw(printf( 137 | \ join([ 138 | \ 'An variable name "%s" requires to start from b:, w:, t:, or g:', 139 | \ 'while no {namespace} is specified', 140 | \ ]), 141 | \ a:name, 142 | \)) 143 | endif 144 | let [prefix, name] = m[1 : 2] 145 | let namespace = eval(prefix) 146 | else 147 | let name = a:name 148 | let namespace = a:1 149 | endif 150 | let variable = copy(s:variable) 151 | let variable.name = name 152 | let variable.value = get(namespace, name, s:_UNDEFINED) 153 | let variable.value = 154 | \ type(variable.value) == type({}) || type(variable.value) == type([]) 155 | \ ? deepcopy(variable.value) 156 | \ : variable.value 157 | let variable._namespace = namespace 158 | return variable 159 | endfunction 160 | function! s:variable.restore() abort 161 | " unlet the variable to prevent variable type mis-match in case 162 | silent! unlet! self._namespace[self.name] 163 | if type(self.value) == type(s:_UNDEFINED) && self.value == s:_UNDEFINED 164 | " do nothing, leave the variable as undefined 165 | else 166 | let self._namespace[self.name] = self.value 167 | endif 168 | endfunction 169 | 170 | let s:instance = {} 171 | function! s:_new_instance(instance, ...) abort 172 | let shallow = get(a:000, 0, 0) 173 | if !s:Prelude.is_list(a:instance) && !s:Prelude.is_dict(a:instance) 174 | call s:_throw(printf( 175 | \'An instance "%s" requires to be List or Dictionary', string(a:instance) 176 | \)) 177 | endif 178 | let instance = copy(s:instance) 179 | let instance.instance = a:instance 180 | let instance.values = shallow ? copy(a:instance) : deepcopy(a:instance) 181 | return instance 182 | endfunction 183 | function! s:instance.restore() abort 184 | if s:Prelude.is_list(self.instance) 185 | call s:List.clear(self.instance) 186 | else 187 | call s:Dict.clear(self.instance) 188 | endif 189 | call extend(self.instance, self.values) 190 | endfunction 191 | 192 | let s:guard = {} 193 | function! s:store(targets) abort 194 | let resources = [] 195 | for meta in a:targets 196 | if s:Prelude.is_list(meta) 197 | if len(meta) == 1 198 | call add(resources, s:_new_instance(meta[0])) 199 | elseif len(meta) == 2 200 | if s:Prelude.is_string(meta[0]) 201 | call add(resources, call('s:_new_variable', meta)) 202 | else 203 | call add(resources, call('s:_new_instance', meta)) 204 | endif 205 | else 206 | call s:_throw('List assignment requires one or two elements') 207 | endif 208 | elseif type(meta) == type('') 209 | if meta =~# '^[bwtgls]:' 210 | " Note: 211 | " To improve an error message, handle l:XXX or s:XXX as well 212 | call add(resources, s:_new_variable(meta)) 213 | elseif meta =~# '^&' 214 | call add(resources, s:_new_option(meta)) 215 | elseif meta =~# '^@' 216 | call add(resources, s:_new_register(meta)) 217 | elseif meta =~# '^\$' 218 | call add(resources, s:_new_environment(meta)) 219 | else 220 | call s:_throw(printf( 221 | \ 'Unknown value "%s" was specified', 222 | \ meta 223 | \)) 224 | endif 225 | endif 226 | unlet meta 227 | endfor 228 | let guard = copy(s:guard) 229 | let guard._resources = resources 230 | return guard 231 | endfunction 232 | function! s:guard.restore() abort 233 | for resource in self._resources 234 | call resource.restore() 235 | endfor 236 | endfunction 237 | 238 | let &cpo = s:save_cpo 239 | unlet! s:save_cpo 240 | " vim:set et ts=2 sts=2 sw=2 tw=0 fdm=marker: 241 | -------------------------------------------------------------------------------- /autoload/vital/shiny.vim: -------------------------------------------------------------------------------- 1 | let s:vital_name = expand(':t:r') 2 | let s:base_dir = expand(':h') 3 | let s:loaded = {} 4 | let s:__latest__ = expand(':h') . '/__latest__' 5 | let s:has_self_modules = isdirectory(s:__latest__) 6 | 7 | " function() wrapper 8 | if v:version > 703 || v:version == 703 && has('patch1170') 9 | function! s:_function(fstr) abort 10 | return function(a:fstr) 11 | endfunction 12 | else 13 | function! s:_SID() abort 14 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 15 | endfunction 16 | let s:_s = '' . s:_SID() . '_' 17 | function! s:_function(fstr) abort 18 | return function(substitute(a:fstr, 's:', s:_s, 'g')) 19 | endfunction 20 | endif 21 | 22 | function! vital#{s:vital_name}#of() abort 23 | return s:new(s:vital_name) 24 | endfunction 25 | 26 | let s:Vital = {} 27 | 28 | function! s:new(vital_name) abort 29 | let base = deepcopy(s:Vital) 30 | let base.vital_name = a:vital_name 31 | return base 32 | endfunction 33 | 34 | function! s:vital_files() abort dict 35 | if !exists('s:vital_files') 36 | let s:vital_files = 37 | \ map(s:_self_vital_files(), 'fnamemodify(v:val, ":p:gs?[\\\\/]?/?")') 38 | endif 39 | return copy(s:vital_files) 40 | endfunction 41 | let s:Vital.vital_files = s:_function('s:vital_files') 42 | 43 | function! s:import(name, ...) abort dict 44 | let target = {} 45 | let functions = [] 46 | for a in a:000 47 | if type(a) == type({}) 48 | let target = a 49 | elseif type(a) == type([]) 50 | let functions = a 51 | endif 52 | unlet a 53 | endfor 54 | let module = self._import(a:name) 55 | if empty(functions) 56 | call extend(target, module, 'keep') 57 | else 58 | for f in functions 59 | if has_key(module, f) && !has_key(target, f) 60 | let target[f] = module[f] 61 | endif 62 | endfor 63 | endif 64 | return target 65 | endfunction 66 | let s:Vital.import = s:_function('s:import') 67 | 68 | function! s:load(...) abort dict 69 | for arg in a:000 70 | let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg] 71 | let target = split(join(as, ''), '\W\+') 72 | let dict = self 73 | let dict_type = type({}) 74 | while !empty(target) 75 | let ns = remove(target, 0) 76 | if !has_key(dict, ns) 77 | let dict[ns] = {} 78 | endif 79 | if type(dict[ns]) == dict_type 80 | let dict = dict[ns] 81 | else 82 | unlet dict 83 | break 84 | endif 85 | endwhile 86 | if exists('dict') 87 | call extend(dict, self._import(name)) 88 | endif 89 | unlet arg 90 | endfor 91 | return self 92 | endfunction 93 | let s:Vital.load = s:_function('s:load') 94 | 95 | function! s:unload() abort dict 96 | let s:loaded = {} 97 | unlet! s:vital_files 98 | endfunction 99 | let s:Vital.unload = s:_function('s:unload') 100 | 101 | function! s:exists(name) abort dict 102 | let b = exists(printf('*vital#_%s#%s#import', self.vital_name, substitute(a:name, '\.', '#', 'g'))) 103 | if b 104 | return b 105 | endif 106 | let name_path = substitute(a:name, '\.', '/', 'g') 107 | let path = printf('%s/_%s/%s.vim', s:base_dir, self.vital_name, name_path) 108 | let b = filereadable(path) 109 | if b 110 | return b 111 | endif 112 | let path = printf('%s/_%s/%s.vim', s:base_dir, '_latest__', name_path) 113 | let b = filereadable(path) 114 | endfunction 115 | let s:Vital.exists = s:_function('s:exists') 116 | 117 | function! s:search(pattern) abort dict 118 | let paths = s:_extract_files(a:pattern, self.vital_files()) 119 | let modules = sort(map(paths, 's:_file2module(v:val)')) 120 | return s:_uniq(modules) 121 | endfunction 122 | let s:Vital.search = s:_function('s:search') 123 | 124 | function! s:_self_vital_files() abort 125 | let base = s:base_dir . '/*/**/*.vim' 126 | return split(glob(base, 1), "\n") 127 | endfunction 128 | 129 | function! s:_extract_files(pattern, files) abort 130 | let tr = {'.': '/', '*': '[^/]*', '**': '.*'} 131 | let target = substitute(a:pattern, '\.\|\*\*\?', '\=tr[submatch(0)]', 'g') 132 | let regexp = printf('autoload/vital/[^/]\+/%s.vim$', target) 133 | return filter(a:files, 'v:val =~# regexp') 134 | endfunction 135 | 136 | function! s:_file2module(file) abort 137 | let filename = fnamemodify(a:file, ':p:gs?[\\/]?/?') 138 | let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$') 139 | return join(split(tail, '[\\/]\+'), '.') 140 | endfunction 141 | 142 | " @param {string} name e.g. Data.List 143 | function! s:_import(name) abort dict 144 | if has_key(s:loaded, a:name) 145 | return copy(s:loaded[a:name]) 146 | endif 147 | let module = self._get_module(a:name) 148 | if has_key(module, '_vital_created') 149 | call module._vital_created(module) 150 | endif 151 | let export_module = filter(copy(module), 'v:key =~# "^\\a"') 152 | " Cache module before calling module.vital_loaded() to avoid cyclic 153 | " dependences but remove the cache if module._vital_loaded() fails. 154 | let s:loaded[a:name] = export_module 155 | if has_key(module, '_vital_loaded') 156 | try 157 | call module._vital_loaded(self) 158 | catch 159 | unlet s:loaded[a:name] 160 | throw 'vital: fail to call ._vital_loaded(): ' . v:exception 161 | endtry 162 | endif 163 | return copy(s:loaded[a:name]) 164 | endfunction 165 | let s:Vital._import = function('s:_import') 166 | 167 | function! s:_get_module(name) abort dict 168 | try 169 | let module = vital#_{self.vital_name}#{substitute(a:name, '\.', '#', 'g')}#import() 170 | catch /E117: Unknown function:/ 171 | if !s:has_self_modules 172 | throw 'vital: revitalizer: module not found: ' . a:name 173 | endif 174 | " Retry with original vital to support loading self modules. 175 | let module = s:orig_vital().import(a:name) 176 | endtry 177 | return module 178 | endfunction 179 | let s:Vital._get_module = function('s:_get_module') 180 | 181 | function! s:orig_vital() abort 182 | if !exists('s:orig_vital') 183 | let s:orig_vital = vital#of(s:vital_name) 184 | endif 185 | return s:orig_vital 186 | endfunction 187 | 188 | if exists('*uniq') 189 | function! s:_uniq(list) abort 190 | return uniq(a:list) 191 | endfunction 192 | else 193 | function! s:_uniq(list) abort 194 | let i = len(a:list) - 1 195 | while 0 < i 196 | if a:list[i] ==# a:list[i - 1] 197 | call remove(a:list, i) 198 | let i -= 2 199 | else 200 | let i -= 1 201 | endif 202 | endwhile 203 | return a:list 204 | endfunction 205 | endif 206 | -------------------------------------------------------------------------------- /autoload/vital/shiny.vital: -------------------------------------------------------------------------------- 1 | shiny 2 | 54c31b97679f2396045e54abb23a1a2706791609 3 | 4 | Coaster.Highlight 5 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | override: 3 | - sudo apt-get install -y build-essential ncurses-dev 4 | - git clone https://github.com/vim/vim --depth 1 --branch v8.0.0039 ~/vim 5 | - cd ~/vim && ./configure --with-features=huge --enable-multibyte && make && sudo make install 6 | - pip install vim-vint 7 | - curl -fSL https://github.com/haya14busa/reviewdog/releases/download/0.9.8/reviewdog_linux_amd64 -o ~/bin/reviewdog && chmod +x ~/bin/reviewdog 8 | 9 | test: 10 | pre: 11 | - vim --version 12 | - vint --version 13 | 14 | override: 15 | - PATH="$HOME/bin:$PATH" reviewdog -ci="circle-ci" -diff="git diff" 16 | -------------------------------------------------------------------------------- /doc/vim-shiny.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaxMEllon/vim-shiny/f5f1c48824e72b5ecba90af05369e5b2b0cabba3/doc/vim-shiny.txt -------------------------------------------------------------------------------- /plugin/shiny.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | if exists('g:vim_shiny_loaded') 3 | finish 4 | endif 5 | 6 | let g:vim_shiny_loaded = 1 7 | 8 | let s:vim_shiny_window_change = get(g:, 'vim_shiny_window_change', 0) 9 | 10 | if s:vim_shiny_window_change 11 | augroup plugin-vim-shiny 12 | autocmd WinEnter * call shiny#window#flash() 13 | augroup END 14 | endif 15 | 16 | nnoremap (shiny-p) :call shiny#p() 17 | nnoremap (shiny-P) :call shiny#P() 18 | nnoremap (shiny-gp) :call shiny#gp() 19 | nnoremap (shiny-gP) :call shiny#gP() 20 | -------------------------------------------------------------------------------- /reviewdog.yml: -------------------------------------------------------------------------------- 1 | runner: 2 | vint: 3 | cmd: vint $(git ls-files | grep -v vital | grep '\.vim') 4 | errorformat: 5 | - "%f:%l:%c: %m" 6 | --------------------------------------------------------------------------------