├── autoload ├── vital │ ├── game_engine.vim.vital │ ├── _897c317 │ │ ├── Data │ │ │ ├── Collection.vim │ │ │ ├── Dict.vim │ │ │ ├── Tree.vim │ │ │ ├── OrderedSet.vim │ │ │ ├── Base64.vim │ │ │ ├── LazyList.vim │ │ │ ├── String.vim │ │ │ └── List.vim │ │ ├── Math.vim │ │ ├── Random │ │ │ └── Xor128.vim │ │ ├── Bitwise.vim │ │ └── Prelude.vim │ └── _897c317.vim ├── vital.vim ├── game_engine │ ├── xxd.vim │ ├── buffer.vim │ └── bmp.vim └── game_engine.vim ├── README.md ├── syntax └── game_engine.vim ├── plugin └── game_engine.vim └── LICENSE /autoload/vital/game_engine.vim.vital: -------------------------------------------------------------------------------- 1 | 897c317 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # vim-game\_engine 3 | 4 | ## [rbtnn/vim-puyo](https://github.com/rbtnn/vim-puyo) 5 | ## [rbtnn/vim-mario](https://github.com/rbtnn/vim-mario) 6 | 7 | 8 | -------------------------------------------------------------------------------- /syntax/game_engine.vim: -------------------------------------------------------------------------------- 1 | 2 | if exists ("b:current_syntax") 3 | finish 4 | endif 5 | 6 | let s:dict = game_engine#syntax() 7 | for s:name in keys(s:dict) 8 | call game_engine#define_syntax(s:name, s:dict[(s:name)]) 9 | endfor 10 | 11 | let b:current_syntax = "game_engine" 12 | 13 | -------------------------------------------------------------------------------- /plugin/game_engine.vim: -------------------------------------------------------------------------------- 1 | 2 | function! s:start_game(f) 3 | try 4 | call game_engine#version() 5 | call function(a:f)() 6 | catch '.*' 7 | call game_engine#exit_game() 8 | echohl Error 9 | echomsg v:exception 10 | echomsg v:throwpoint 11 | echohl None 12 | endtry 13 | endfunction 14 | command! -nargs=1 GameEngineStartGame :call start_game() 15 | 16 | -------------------------------------------------------------------------------- /autoload/vital.vim: -------------------------------------------------------------------------------- 1 | function! vital#of(name) 2 | let files = globpath(&runtimepath, 'autoload/vital/' . a:name . '.vital') 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/_897c317/Data/Collection.vim: -------------------------------------------------------------------------------- 1 | " Utilities both for list and dict. 2 | 3 | let s:save_cpo = &cpo 4 | set cpo&vim 5 | 6 | function! s:get_f(collection, key, otherwise) 7 | " TODO make it work also for list 8 | if has_key(a:collection, a:key) 9 | return a:collection[a:key] 10 | else 11 | return function(a:otherwise)() 12 | endif 13 | endfunction 14 | 15 | let &cpo = s:save_cpo 16 | unlet s:save_cpo 17 | 18 | " vim:set et ts=2 sts=2 sw=2 tw=0: 19 | -------------------------------------------------------------------------------- /autoload/vital/_897c317/Math.vim: -------------------------------------------------------------------------------- 1 | " math utilities. 2 | 3 | let s:save_cpo = &cpo 4 | set cpo&vim 5 | 6 | " TODO Simpler way? 7 | function! s:modulo(m, n) 8 | let d = a:m * a:n < 0 ? 1 : 0 9 | return a:m + (-(a:m + (0 < a:n ? d : -d)) / a:n + d) * a:n 10 | endfunction 11 | 12 | function! s:fib(n) 13 | let [a, b, i] = [0, 1, 0] 14 | while i < a:n 15 | let [a, b, i] = [b, a + b, i + 1] 16 | endwhile 17 | return a 18 | endfunction 19 | 20 | let &cpo = s:save_cpo 21 | unlet s:save_cpo 22 | 23 | " vim:set et ts=2 sts=2 sw=2 tw=0: 24 | -------------------------------------------------------------------------------- /autoload/vital/_897c317/Random/Xor128.vim: -------------------------------------------------------------------------------- 1 | " random number generator using xorshift128 2 | " http://www.jstatsoft.org/v08/i14/paper 3 | 4 | let s:save_cpo = &cpo 5 | set cpo&vim 6 | 7 | 8 | function! s:_vital_loaded(V) 9 | let s:V = a:V 10 | let s:B = s:V.import('Bitwise') 11 | let s:x = 123456789 12 | let s:y = 362436069 13 | let s:z = 521288629 14 | let s:w = 88675123 15 | endfunction 16 | 17 | function! s:srand(...) 18 | if a:0 == 0 19 | let s:x = has('reltime') ? reltime()[1] : localtime() 20 | elseif a:0 == 1 21 | let s:x = a:1 22 | else 23 | throw 'Random.Xor128.srand() too many arguments' 24 | endif 25 | endfunction 26 | 27 | function! s:rand() 28 | let t = s:B.xor(s:x, s:B.lshift(s:x, 11)) 29 | let s:x = s:y 30 | let s:y = s:z 31 | let s:z = s:w 32 | let s:w = s:B.xor(s:B.xor(s:w, s:B.rshift(s:w, 19)), s:B.xor(t, s:B.rshift(t, 8))) 33 | return s:w 34 | endfunction 35 | 36 | 37 | let &cpo = s:save_cpo 38 | unlet s:save_cpo 39 | 40 | " vim:set et ts=2 sts=2 sw=2 tw=0: 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 rbtnn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /autoload/game_engine/xxd.vim: -------------------------------------------------------------------------------- 1 | 2 | function! game_engine#xxd#read(path, ...) abort 3 | let xs = [] 4 | if filereadable(a:path) 5 | let offset = 0 < a:0 ? (0 < str2nr(a:1) ? str2nr(a:1) : 0) : 0 6 | let length = 1 < a:0 ? str2nr(a:2) : getfsize(a:path) 7 | if 0 <= length && length < 4 * 1024 * 1024 8 | let lines = split(system(printf('xxd -s %d -l %d -g 1 "%s"', offset, length, a:path)), "\n") 9 | for line in lines 10 | let xs += split(matchlist(line, '^[0-9a-f]\+: \(\%([0-9a-f]\{2,2} \)*\).*$')[1], ' ') 11 | endfor 12 | else 13 | throw printf('game_engine#xxd#read: Reading bytes should be less than 4MB. (%d bytes) ', length) 14 | endif 15 | endif 16 | return map(xs, 'eval("0x" . v:val)') 17 | endfunction 18 | 19 | function! game_engine#xxd#write(xs, path) abort 20 | let t = tempname() 21 | let lines = [] 22 | let line = '' 23 | for i in range(1, len(a:xs)) 24 | let line .= printf(' %02x', a:xs[i - 1]) 25 | if 0 == i % 16 || i == len(a:xs) 26 | let lines += [printf('%07x:%s ', ((i + 15) / 16 - 1) * 16, line)] 27 | let line = '' 28 | endif 29 | endfor 30 | call writefile(lines, t) 31 | if filereadable(a:path) 32 | call delete(a:path) 33 | endif 34 | call system(printf('xxd -g 1 -r "%s" "%s"', t, a:path)) 35 | if filereadable(t) 36 | call delete(t) 37 | endif 38 | endfunction 39 | 40 | -------------------------------------------------------------------------------- /autoload/game_engine/buffer.vim: -------------------------------------------------------------------------------- 1 | 2 | scriptencoding utf-8 3 | 4 | function! game_engine#buffer#nrlist() 5 | return filter(range(1, bufnr("$")), "bufexists(v:val) && buflisted(v:val)") 6 | endfunction 7 | function! game_engine#buffer#escape(bname) 8 | return '^' . join(map(split(a:bname, '\zs'), '"[".v:val."]"'), '') . '$' 9 | endfunction 10 | function! game_engine#buffer#nr(bname) 11 | return bufnr(game_engine#buffer#escape(a:bname)) 12 | endfunction 13 | function! game_engine#buffer#winnr(bname) 14 | return bufwinnr(game_engine#buffer#escape(a:bname)) 15 | endfunction 16 | function! game_engine#buffer#uniq_open(bname,lines,mode) 17 | let curr_bufname = bufname('%') 18 | 19 | if ! bufexists(a:bname) 20 | execute printf('split %s',a:bname) 21 | setlocal bufhidden=hide buftype=nofile noswapfile nobuflisted 22 | elseif game_engine#buffer#winnr(a:bname) != -1 23 | execute game_engine#buffer#winnr(a:bname) 'wincmd w' 24 | else 25 | execute 'split' 26 | execute 'buffer' game_engine#buffer#nr(a:bname) 27 | endif 28 | 29 | if a:mode is# 'w' 30 | let lnum = 1 31 | for line in a:lines 32 | if line isnot getline(lnum) 33 | call setline(lnum, line) 34 | endif 35 | let lnum += 1 36 | endfor 37 | " silent % delete _ 38 | " silent put=a:lines 39 | " silent 1 delete _ 40 | elseif a:mode is# 'a' 41 | call append('$',a:lines) 42 | endif 43 | 44 | execute bufwinnr(curr_bufname) 'wincmd w' 45 | endfunction 46 | 47 | -------------------------------------------------------------------------------- /autoload/vital/_897c317/Data/Dict.vim: -------------------------------------------------------------------------------- 1 | " Utilities for dictionary. 2 | 3 | let s:save_cpo = &cpo 4 | set cpo&vim 5 | 6 | " Makes a dict from keys and values 7 | function! s:make(keys, values, ...) 8 | let dict = {} 9 | let fill = a:0 ? a:1 : 0 10 | for i in range(len(a:keys)) 11 | let key = type(a:keys[i]) == type('') ? a:keys[i] : string(a:keys[i]) 12 | if key ==# '' 13 | throw "vital: Data.Dict.make(): Can't use an empty string for key." 14 | endif 15 | let dict[key] = get(a:values, i, fill) 16 | endfor 17 | return dict 18 | endfunction 19 | 20 | " Swaps keys and values 21 | function! s:swap(dict) 22 | return s:make(values(a:dict), keys(a:dict)) 23 | endfunction 24 | 25 | " Makes a index dict from a list 26 | function! s:make_index(list, ...) 27 | let value = a:0 ? a:1 : 1 28 | return s:make(a:list, [], value) 29 | endfunction 30 | 31 | function! s:pick(dict, keys) 32 | let new_dict = {} 33 | for key in a:keys 34 | if has_key(a:dict, key) 35 | let new_dict[key] = a:dict[key] 36 | endif 37 | endfor 38 | return new_dict 39 | endfunction 40 | 41 | function! s:omit(dict, keys) 42 | let new_dict = copy(a:dict) 43 | for key in a:keys 44 | if has_key(a:dict, key) 45 | call remove(new_dict, key) 46 | endif 47 | endfor 48 | return new_dict 49 | endfunction 50 | 51 | function! s:clear(dict) 52 | for key in keys(a:dict) 53 | call remove(a:dict, key) 54 | endfor 55 | return a:dict 56 | endfunction 57 | 58 | let &cpo = s:save_cpo 59 | unlet s:save_cpo 60 | 61 | " vim:set et ts=2 sts=2 sw=2 tw=0: 62 | -------------------------------------------------------------------------------- /autoload/vital/_897c317/Data/Tree.vim: -------------------------------------------------------------------------------- 1 | 2 | let s:save_cpo = &cpo 3 | set cpo&vim 4 | 5 | function! s:new(token,...) 6 | if type(a:token) == type({}) && has_key(a:token,'token') && has_key(a:token,'children') 7 | let obj = a:token 8 | else 9 | let obj = { 'token' : a:token , 'children' : a:0 > 0 10 | \ ? ( a:0 == 1 ? (type(a:1) == type([]) ? a:1 : [(a:1)]) 11 | \ : a:000 12 | \ ) 13 | \ : [] } 14 | endif 15 | 16 | function! obj.addchild(...) dict 17 | for node in a:000 18 | let self.children += [copy(node)] 19 | endfor 20 | return self 21 | endfunction 22 | 23 | function! obj.tostring() dict 24 | return { type(self.token) == type('') 25 | \ ? self.token : string(self.token) 26 | \ : map(copy(self.children),'type(v:val) == type({}) ? v:val.tostring() : string(v:val)') } 27 | endfunction 28 | 29 | function! obj.preorder_traversal() dict 30 | let tkns = [] 31 | let tkns += [(self.token)] 32 | for child in self.children 33 | let tkns += s:new(child).preorder_traversal() 34 | unlet child 35 | endfor 36 | return tkns 37 | endfunction 38 | 39 | function! obj.inorder_traversal() dict 40 | let tkns = [] 41 | if ! empty(self.children) 42 | let tkns += s:new(get(self.children,0,'')).inorder_traversal() 43 | endif 44 | let tkns += [(self.token)] 45 | if ! empty(self.children) 46 | let tkns += s:new(get(self.children,1,'')).inorder_traversal() 47 | endif 48 | return tkns 49 | endfunction 50 | 51 | function! obj.postorder_traversal() dict 52 | let tkns = [] 53 | for child in self.children 54 | let tkns += s:new(child).preorder_traversal() 55 | unlet child 56 | endfor 57 | let tkns += [(self.token)] 58 | return tkns 59 | endfunction 60 | 61 | return deepcopy(obj) 62 | endfunction 63 | 64 | let &cpo = s:save_cpo 65 | unlet s:save_cpo 66 | 67 | -------------------------------------------------------------------------------- /autoload/vital/_897c317/Data/OrderedSet.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | 5 | function! s:version() 6 | return '0.0.15' 7 | endfunction 8 | 9 | function! s:new(...) 10 | let obj = deepcopy(s:ordered_set) 11 | if a:0 12 | \ && type(a:1) == type({}) 13 | \ && has_key(a:1, 'Fn_identifier') 14 | let obj.Fn_identifier = a:1.Fn_identifier 15 | endif 16 | return obj 17 | endfunction 18 | 19 | 20 | let s:ordered_set = { 21 | \ '_list': [], 22 | \ '_dict': {}, 23 | \ '_origin_pos': 0, 24 | \ 'Fn_identifier': 'string', 25 | \} 26 | 27 | function! s:ordered_set.prepend(list) 28 | for V in reverse(a:list) 29 | call self.unshift(V) 30 | endfor 31 | endfunction 32 | 33 | function! s:ordered_set.append(list) 34 | for V in a:list 35 | call self.push(V) 36 | endfor 37 | endfunction 38 | 39 | function s:ordered_set.push(elem) 40 | let id = call(self.Fn_identifier, [a:elem]) 41 | if !has_key(self._dict, id) 42 | let self._dict[id] = len(self._list) - self._origin_pos 43 | call add(self._list, a:elem) 44 | return 1 45 | endif 46 | return 0 47 | endfunction 48 | 49 | function! s:ordered_set.unshift(elem) 50 | let id = call(self.Fn_identifier, [a:elem]) 51 | if !has_key(self._dict, id) 52 | let self._origin_pos += 1 53 | let self._dict[id] = -self._origin_pos 54 | call insert(self._list, a:elem) 55 | return 1 56 | endif 57 | return 0 58 | endfunction 59 | 60 | function! s:ordered_set.empty() 61 | return empty(self._list) 62 | endfunction 63 | 64 | function! s:ordered_set.size() 65 | return len(self._list) 66 | endfunction 67 | 68 | function! s:ordered_set.to_list() 69 | return copy(self._list) 70 | endfunction 71 | 72 | function! s:ordered_set.has(elem) 73 | let id = call(self.Fn_identifier, [a:elem]) 74 | return has_key(self._dict, id) 75 | endfunction 76 | 77 | function! s:ordered_set.has_id(id) 78 | return has_key(self._dict, a:id) 79 | endfunction 80 | 81 | function! s:ordered_set.clear() 82 | let self._list = [] 83 | let self._dict = {} 84 | let self._origin_pos = 0 85 | endfunction 86 | 87 | function! s:ordered_set.remove(elem) 88 | let id = call(self.Fn_identifier, [a:elem]) 89 | if has_key(self._dict, id) 90 | let idx = self._origin_pos + self._dict[id] 91 | unlet self._dict[id] 92 | unlet self._list[idx] 93 | if idx < self._origin_pos 94 | for i in range(0, idx - 1) 95 | let id = call(self.Fn_identifier, [self._list[i]]) 96 | let self._dict[id] += 1 97 | endfor 98 | let self._origin_pos -= 1 99 | else 100 | for i in range(idx, len(self._list) - 1) 101 | let id = call(self.Fn_identifier, [self._list[i]]) 102 | let self._dict[id] -= 1 103 | endfor 104 | endif 105 | return 1 106 | endif 107 | return 0 108 | endfunction 109 | 110 | 111 | let &cpo = s:save_cpo 112 | unlet s:save_cpo 113 | 114 | " vim:set et ts=2 sts=2 sw=2 tw=0: 115 | -------------------------------------------------------------------------------- /autoload/vital/_897c317/Data/Base64.vim: -------------------------------------------------------------------------------- 1 | " Utilities for Base64. 2 | 3 | let s:save_cpo = &cpo 4 | set cpo&vim 5 | 6 | function! s:encode(data) 7 | let b64 = s:_b64encode(s:_str2bytes(a:data), s:standard_table, '=') 8 | return join(b64, '') 9 | endfunction 10 | 11 | function! s:encodebin(data) 12 | let b64 = s:_b64encode(s:_binstr2bytes(a:data), s:standard_table, '=') 13 | return join(b64, '') 14 | endfunction 15 | 16 | function! s:decode(data) 17 | let bytes = s:_b64decode(split(a:data, '\zs'), s:standard_table, '=') 18 | return s:_bytes2str(bytes) 19 | endfunction 20 | 21 | let s:standard_table = [ 22 | \ "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P", 23 | \ "Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f", 24 | \ "g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v", 25 | \ "w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"] 26 | 27 | let s:urlsafe_table = [ 28 | \ "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P", 29 | \ "Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f", 30 | \ "g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v", 31 | \ "w","x","y","z","0","1","2","3","4","5","6","7","8","9","-","_"] 32 | 33 | function! s:_b64encode(bytes, table, pad) 34 | let b64 = [] 35 | for i in range(0, len(a:bytes) - 1, 3) 36 | let n = a:bytes[i] * 0x10000 37 | \ + get(a:bytes, i + 1, 0) * 0x100 38 | \ + get(a:bytes, i + 2, 0) 39 | call add(b64, a:table[n / 0x40000]) 40 | call add(b64, a:table[n / 0x1000 % 0x40]) 41 | call add(b64, a:table[n / 0x40 % 0x40]) 42 | call add(b64, a:table[n % 0x40]) 43 | endfor 44 | if len(a:bytes) % 3 == 1 45 | let b64[-1] = a:pad 46 | let b64[-2] = a:pad 47 | endif 48 | if len(a:bytes) % 3 == 2 49 | let b64[-1] = a:pad 50 | endif 51 | return b64 52 | endfunction 53 | 54 | function! s:_b64decode(b64, table, pad) 55 | let a2i = {} 56 | for i in range(len(a:table)) 57 | let a2i[a:table[i]] = i 58 | endfor 59 | let bytes = [] 60 | for i in range(0, len(a:b64) - 1, 4) 61 | let n = a2i[a:b64[i]] * 0x40000 62 | \ + a2i[a:b64[i + 1]] * 0x1000 63 | \ + (a:b64[i + 2] == a:pad ? 0 : a2i[a:b64[i + 2]]) * 0x40 64 | \ + (a:b64[i + 3] == a:pad ? 0 : a2i[a:b64[i + 3]]) 65 | call add(bytes, n / 0x10000) 66 | call add(bytes, n / 0x100 % 0x100) 67 | call add(bytes, n % 0x100) 68 | endfor 69 | if a:b64[-1] == a:pad 70 | unlet a:b64[-1] 71 | endif 72 | if a:b64[-2] == a:pad 73 | unlet a:b64[-1] 74 | endif 75 | return bytes 76 | endfunction 77 | 78 | function! s:_binstr2bytes(str) 79 | return map(range(len(a:str)/2), 'eval("0x".a:str[v:val*2 : v:val*2+1])') 80 | endfunction 81 | 82 | function! s:_str2bytes(str) 83 | return map(range(len(a:str)), 'char2nr(a:str[v:val])') 84 | endfunction 85 | 86 | function! s:_bytes2str(bytes) 87 | return eval('"' . join(map(copy(a:bytes), 'printf(''\x%02x'', v:val)'), '') . '"') 88 | endfunction 89 | 90 | let &cpo = s:save_cpo 91 | unlet s:save_cpo 92 | 93 | " vim:set et ts=2 sts=2 sw=2 tw=0: 94 | -------------------------------------------------------------------------------- /autoload/vital/_897c317.vim: -------------------------------------------------------------------------------- 1 | let s:self_version = expand(':t:r') 2 | 3 | " Note: The extra argument to globpath() was added in Patch 7.2.051. 4 | let s:globpath_third_arg = v:version > 702 || v:version == 702 && has('patch51') 5 | 6 | let s:loaded = {} 7 | 8 | function! s:import(name, ...) 9 | let target = {} 10 | let functions = [] 11 | for a in a:000 12 | if type(a) == type({}) 13 | let target = a 14 | elseif type(a) == type([]) 15 | let functions = a 16 | endif 17 | unlet a 18 | endfor 19 | let module = s:_import(a:name) 20 | if empty(functions) 21 | call extend(target, module, 'keep') 22 | else 23 | for f in functions 24 | if has_key(module, f) && !has_key(target, f) 25 | let target[f] = module[f] 26 | endif 27 | endfor 28 | endif 29 | return target 30 | endfunction 31 | 32 | function! s:load(...) dict 33 | for arg in a:000 34 | let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg] 35 | let target = split(join(as, ''), '\W\+') 36 | let dict = self 37 | while 1 <= len(target) 38 | let ns = remove(target, 0) 39 | if !has_key(dict, ns) 40 | let dict[ns] = {} 41 | endif 42 | if type(dict[ns]) == type({}) 43 | let dict = dict[ns] 44 | else 45 | unlet dict 46 | break 47 | endif 48 | endwhile 49 | 50 | if exists('dict') 51 | call extend(dict, s:_import(name)) 52 | endif 53 | unlet arg 54 | endfor 55 | return self 56 | endfunction 57 | 58 | function! s:unload() 59 | let s:loaded = {} 60 | endfunction 61 | 62 | function! s:_import(name) 63 | if type(a:name) == type(0) 64 | return s:_build_module(a:name) 65 | endif 66 | let path = s:_get_module_path(a:name) 67 | if path ==# '' 68 | throw 'vital: module not found: ' . a:name 69 | endif 70 | let sid = get(s:_scripts(), path, 0) 71 | if !sid 72 | try 73 | execute 'source' fnameescape(path) 74 | catch /^Vim\%((\a\+)\)\?:E484/ 75 | throw 'vital: module not found: ' . a:name 76 | catch /^Vim\%((\a\+)\)\?:E127/ 77 | " Ignore. 78 | endtry 79 | 80 | let sid = s:_scripts()[path] 81 | endif 82 | return s:_build_module(sid) 83 | endfunction 84 | 85 | function! s:_get_module_path(name) 86 | if s:_is_absolute_path(a:name) && filereadable(a:name) 87 | return s:_unify_path(a:name) 88 | endif 89 | if a:name ==# '' 90 | let tailpath = printf('autoload/vital/%s.vim', s:self_version) 91 | elseif a:name =~# '\v^\u\w*%(\.\u\w*)*$' 92 | let target = '/' . substitute(a:name, '\W\+', '/', 'g') 93 | let tailpath = printf('autoload/vital/%s%s.vim', s:self_version, target) 94 | else 95 | throw 'vital: Invalid module name: ' . a:name 96 | endif 97 | 98 | if s:globpath_third_arg 99 | let paths = split(globpath(&runtimepath, tailpath, 1), "\n") 100 | else 101 | let paths = split(globpath(&runtimepath, tailpath), "\n") 102 | endif 103 | call filter(paths, 'filereadable(v:val)') 104 | return s:_unify_path(get(paths, 0, '')) 105 | endfunction 106 | 107 | function! s:_scripts() 108 | let scripts = {} 109 | for line in filter(split(s:_redir('scriptnames'), "\n"), 110 | \ 'stridx(v:val, s:self_version) > 0') 111 | let list = matchlist(line, '^\s*\(\d\+\):\s\+\(.\+\)\s*$') 112 | if !empty(list) 113 | let scripts[s:_unify_path(list[2])] = list[1] - 0 114 | endif 115 | endfor 116 | return scripts 117 | endfunction 118 | 119 | if filereadable(expand(':r') . '.VIM') 120 | function! s:_unify_path(path) 121 | " Note: On windows, vim can't expand path names from 8.3 formats. 122 | " So if getting full path via and $HOME was set as 8.3 format, 123 | " vital load duplicated scripts. Below's :~ avoid this issue. 124 | return tolower(fnamemodify(resolve(fnamemodify( 125 | \ a:path, ':p:gs?[\\/]\+?/?')), ':~')) 126 | endfunction 127 | else 128 | function! s:_unify_path(path) 129 | return resolve(fnamemodify(a:path, ':p:gs?[\\/]\+?/?')) 130 | endfunction 131 | endif 132 | 133 | " Copy from System.Filepath 134 | if has('win16') || has('win32') || has('win64') 135 | function! s:_is_absolute_path(path) 136 | return a:path =~? '^[a-z]:[/\\]' 137 | endfunction 138 | else 139 | function! s:_is_absolute_path(path) 140 | return a:path[0] ==# '/' 141 | endfunction 142 | endif 143 | 144 | function! s:_build_module(sid) 145 | if has_key(s:loaded, a:sid) 146 | return copy(s:loaded[a:sid]) 147 | endif 148 | let prefix = '' . a:sid . '_' 149 | let funcs = s:_redir('function') 150 | let filter_pat = '^\s*function ' . prefix 151 | let map_pat = prefix . '\zs\w\+' 152 | let functions = map(filter(split(funcs, "\n"), 153 | \ 'stridx(v:val, prefix) > 0 && v:val =~# filter_pat'), 154 | \ 'matchstr(v:val, map_pat)') 155 | 156 | let module = {} 157 | for func in functions 158 | let module[func] = function(prefix . func) 159 | endfor 160 | if has_key(module, '_vital_loaded') 161 | let V = vital#{s:self_version}#new() 162 | if has_key(module, '_vital_depends') 163 | call call(V.load, module._vital_depends(), V) 164 | endif 165 | try 166 | call module._vital_loaded(V) 167 | catch 168 | " FIXME: Show an error message for debug. 169 | endtry 170 | endif 171 | if !get(g:, 'vital_debug', 0) 172 | call filter(module, 'v:key =~# "^\\a"') 173 | endif 174 | let s:loaded[a:sid] = module 175 | return copy(module) 176 | endfunction 177 | 178 | function! s:_redir(cmd) 179 | let [save_verbose, save_verbosefile] = [&verbose, &verbosefile] 180 | set verbose=0 verbosefile= 181 | redir => res 182 | silent! execute a:cmd 183 | redir END 184 | let [&verbose, &verbosefile] = [save_verbose, save_verbosefile] 185 | return res 186 | endfunction 187 | 188 | function! vital#{s:self_version}#new() 189 | return s:_import('').load(['Prelude', '']) 190 | endfunction 191 | -------------------------------------------------------------------------------- /autoload/vital/_897c317/Data/LazyList.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | function! s:_vital_loaded(V) 5 | let s:V = a:V 6 | let s:L = s:V.import('Data.List') 7 | endfunction 8 | 9 | function! s:_vital_depends() 10 | return ['Data.List'] 11 | endfunction 12 | 13 | function! s:from_list(list) 14 | return [[], {'list': a:list, 'run': function('s:_f_from_list')}] 15 | endfunction 16 | 17 | function! s:_f_from_list() dict 18 | if len(self.list) == 0 19 | return [[], {}] 20 | else 21 | let [x, xs] = [self.list[0], self.list[1 :]] 22 | return [[x], {'list': xs, 'run': function('s:_f_from_list')}] 23 | endif 24 | endfunction 25 | 26 | function! s:file_readlines(fname) 27 | if !s:V.has_vimproc() 28 | throw 'Data.LazyList.file_readlines() requires vimproc' 29 | endif 30 | return [[], { 31 | \ 'f': vimproc#fopen(a:fname, 'r'), 32 | \ 'run': function('s:_f_file_readlines')}] 33 | endfunction 34 | 35 | " TODO resource management 36 | function! s:_f_file_readlines() dict 37 | if self.f.eof 38 | call self.f.close() 39 | return [[], {}] 40 | else 41 | " caution: this is destructive! 42 | return [[self.f.read_line()], self] 43 | endif 44 | endfunction 45 | 46 | function! s:iterate(init, f) 47 | let thunk = { 48 | \ 'memo': a:init, 'f': a:f, 49 | \ 'run': function('s:_f_iterate')} 50 | return [[], thunk] 51 | endfunction 52 | 53 | function! s:_f_iterate() dict 54 | let next_thunk = { 55 | \ 'memo': eval(substitute(self.f, 'v:val', self.memo, 'g')), 56 | \ 'f': self.f, 57 | \ 'run': self.run} 58 | return [[self.memo], next_thunk] 59 | endfunction 60 | 61 | function! s:zip(xs, ys) 62 | let [xfs, xs] = a:xs 63 | let [yfs, ys] = a:ys 64 | let thunk = { 65 | \ 'xfs': xfs, 'yfs': yfs, 66 | \ 'xs': xs, 'ys': ys, 67 | \ 'run': function('s:_f_zip')} 68 | return [[], thunk] 69 | endfunction 70 | 71 | function! s:_f_zip() dict 72 | let [x, xs] = s:_unapply(self.xfs, self.xs) 73 | let [y, ys] = s:_unapply(self.yfs, self.ys) 74 | if len(x) == 0 || len(y) == 0 75 | return [[], {}] 76 | else 77 | let next_thunk = { 78 | \ 'xfs': self.xfs, 'yfs': self.yfs, 79 | \ 'xs': xs, 'ys': ys, 80 | \ 'run': self.run} 81 | return [[[x[0], y[0]]], next_thunk] 82 | endif 83 | endfunction 84 | 85 | function! s:is_empty(xs) 86 | let [fs, xs] = a:xs 87 | return xs == {} 88 | endfunction 89 | 90 | function! s:_eval(fs, x) 91 | let memo = a:x 92 | for f in a:fs 93 | if len(memo) 94 | " f is like 'v:val < 2 ? [v:val] : []' 95 | let expr = substitute(f, 'v:val', string(memo[0]), 'g') 96 | unlet memo 97 | let memo = eval(expr) 98 | endif 99 | endfor 100 | return memo 101 | endfunction 102 | 103 | function! s:_unapply(fs, xs) 104 | let [x, xs] = a:xs.run() 105 | return [s:_eval(a:fs, x), xs] 106 | endfunction 107 | 108 | function! s:filter(xs, f) 109 | let [fs, xs] = a:xs 110 | let f = printf("%s ? [v:val] : []", a:f) 111 | return [s:L.conj(fs, f), xs] 112 | endfunction 113 | 114 | function! s:map(xs, f) 115 | let [fs, xs] = a:xs 116 | let f = printf('[%s]', a:f) 117 | return [s:L.conj(fs, f), xs] 118 | endfunction 119 | 120 | function! s:take(n, xs) 121 | if a:n == 0 || s:is_empty(a:xs) 122 | return [] 123 | else 124 | let [fs, xs] = a:xs 125 | let [x, xs] = s:_unapply(fs, xs) 126 | if len(x) 127 | return x + s:take(a:n - 1, [fs, xs]) 128 | else 129 | return s:take(a:n, [fs, xs]) 130 | endif 131 | endif 132 | endfunction 133 | 134 | function! s:take_while(xs, f) 135 | if s:is_empty(a:xs) 136 | return [] 137 | else 138 | let [fs, xs] = a:xs 139 | let [x, xs1] = s:_unapply(fs, xs) 140 | if len(x) && eval(substitute(a:f, 'v:val', x[0], 'g')) 141 | return x + s:take_while([fs, xs1], a:f) 142 | else 143 | return [] 144 | endif 145 | endif 146 | endfunction 147 | 148 | function! s:first(xs, default) 149 | let xs = s:take(1, a:xs) 150 | return len(xs) == 0 ? a:default : xs[0] 151 | endfunction 152 | 153 | function! s:rest(xs, default) 154 | if s:is_empty(a:xs) 155 | return a:default 156 | else 157 | let [fs, xs] = a:xs 158 | let [_, xs] = s:_unapply(fs, xs) 159 | return [fs, xs] 160 | endif 161 | endfunction 162 | 163 | function! s:drop(n, xs) 164 | if s:is_empty(a:xs) 165 | return [] 166 | else 167 | let [fs, xs] = a:xs 168 | let memo = xs.memo 169 | for i in range(1,a:n) 170 | let memo = s:_eval([ xs.f ], memo) 171 | endfor 172 | let new_xs = deepcopy(a:xs) 173 | let new_xs[1].memo = memo 174 | return new_xs 175 | endif 176 | endfunction 177 | 178 | 179 | " echo s:L.take(10, s:L.iterate(0, 'v:val + 1') ) 180 | " [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ] 181 | " echo s:L.take(10,s:drop(3,s:L.iterate(0, 'v:val + 1'))) 182 | " [ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ] 183 | 184 | 185 | 186 | "call s:_vital_loaded(g:V) 187 | "let xs = s:file_readlines('/tmp/a.txt') 188 | "let xs = s:map(xs, 'split(v:val, ":")') 189 | "let xs = s:filter(xs, 'v:val[1] < 3') 190 | "echo s:take(3, xs) 191 | 192 | " echo s:from_list([3, 1, 4]) 193 | "let xs = s:from_list([3, 1, 4]) 194 | "let ys = s:from_list(['a', 'b', 'c']) 195 | "echo s:take(3, s:zip(s:map(xs, 'v:val + 1'), ys)) 196 | " echo s:take(2, s:from_list([3, 1, 4])) 197 | " echo s:take(2, s:from_list([3, 1, 4])) == [3, 1] 198 | " 199 | " echo s:take(2, s:filter(s:from_list([3, 1, 4, 0]), 'v:val < 2')) 200 | " echo s:take_while(s:from_list([3, 1, 4, 1]), 'v:val % 2 == 1') 201 | " echo s:take(3, s:iterate(0, 'v:val + 1')) 202 | " echo s:take(3, s:filter(s:iterate(0, 'v:val + 1'), 'v:val % 2 == 0')) 203 | " echo s:take(4, s:file_readlines('/tmp/a.txt')) 204 | " echo s:take(3, s:map(s:iterate(0, 'v:val + 1'), 'v:val * 2')) 205 | " echo s:first(s:from_list([3, 1, 4]), 'nil') 206 | " echo s:first(s:filter(s:from_list([3, 1, 4]), '0'), 'nil') 207 | " echo s:rest(s:from_list([3, 1, 4]), s:from_list([])) 208 | " echo s:first(s:rest(s:from_list([3, 1, 4]), s:from_list([])), 'nil') 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/_897c317/Data/String.vim: -------------------------------------------------------------------------------- 1 | " Utilities for string. 2 | 3 | let s:save_cpo = &cpo 4 | set cpo&vim 5 | 6 | function! s:_vital_loaded(V) 7 | let s:V = a:V 8 | let s:L = s:V.import('Data.List') 9 | endfunction 10 | 11 | function! s:_vital_depends() 12 | return ['Data.List'] 13 | endfunction 14 | 15 | " Substitute a:from => a:to by string. 16 | " To substitute by pattern, use substitute() instead. 17 | function! s:replace(str, from, to) 18 | return s:_replace(a:str, a:from, a:to, 'g') 19 | endfunction 20 | 21 | " Substitute a:from => a:to only once. 22 | " cf. s:replace() 23 | function! s:replace_first(str, from, to) 24 | return s:_replace(a:str, a:from, a:to, '') 25 | endfunction 26 | 27 | " implement of replace() and replace_first() 28 | function! s:_replace(str, from, to, flags) 29 | return substitute(a:str, '\V'.escape(a:from, '\'), escape(a:to, '\'), a:flags) 30 | endfunction 31 | 32 | function! s:scan(str, pattern) 33 | let list = [] 34 | call substitute(a:str, a:pattern, '\=add(list, submatch(0)) == [] ? "" : ""', 'g') 35 | return list 36 | endfunction 37 | 38 | function! s:reverse(str) 39 | return join(reverse(split(a:str, '.\zs')), '') 40 | endfunction 41 | 42 | function! s:common_head(strs) 43 | if empty(a:strs) 44 | return '' 45 | endif 46 | let len = len(a:strs) 47 | if len == 1 48 | return a:strs[0] 49 | endif 50 | let strs = len == 2 ? a:strs : sort(copy(a:strs)) 51 | let pat = substitute(strs[0], '.', '[\0]', 'g') 52 | return pat == '' ? '' : matchstr(strs[-1], '^\%[' . pat . ']') 53 | endfunction 54 | 55 | " Split to two elements of List. ([left, right]) 56 | " e.g.: s:split3('neocomplcache', 'compl') returns ['neo', 'compl', 'cache'] 57 | function! s:split_leftright(expr, pattern) 58 | let [left, _, right] = s:split3(a:expr, a:pattern) 59 | return [left, right] 60 | endfunction 61 | 62 | function! s:split3(expr, pattern) 63 | let ERROR = ['', '', ''] 64 | if a:expr ==# '' || a:pattern ==# '' 65 | return ERROR 66 | endif 67 | let begin = match(a:expr, a:pattern) 68 | if begin is -1 69 | return ERROR 70 | endif 71 | let end = matchend(a:expr, a:pattern) 72 | let left = begin <=# 0 ? '' : a:expr[: begin - 1] 73 | let right = a:expr[end :] 74 | return [left, a:expr[begin : end-1], right] 75 | endfunction 76 | 77 | " Slices into strings determines the number of substrings. 78 | " e.g.: s:nsplit("neo compl cache", 2, '\s') returns ['neo', 'compl cache'] 79 | function! s:nsplit(expr, n, ...) 80 | let pattern = get(a:000, 0, '\s') 81 | let keepempty = get(a:000, 1, 1) 82 | let ret = [] 83 | let expr = a:expr 84 | if a:n <= 1 85 | return [expr] 86 | endif 87 | while 1 88 | let pos = match(expr, pattern) 89 | if pos == -1 90 | if expr !~ pattern || keepempty 91 | call add(ret, expr) 92 | endif 93 | break 94 | elseif pos >= 0 95 | let left = pos > 0 ? expr[:pos-1] : '' 96 | if pos > 0 || keepempty 97 | call add(ret, left) 98 | endif 99 | let ml = len(matchstr(expr, pattern)) 100 | if pos == 0 && ml == 0 101 | let pos = 1 102 | endif 103 | let expr = expr[pos+ml :] 104 | endif 105 | if len(expr) == 0 106 | break 107 | endif 108 | if len(ret) == a:n - 1 109 | call add(ret, expr) 110 | break 111 | endif 112 | endwhile 113 | return ret 114 | endfunction 115 | 116 | " Returns the number of character in a:str. 117 | " NOTE: This returns proper value 118 | " even if a:str contains multibyte character(s). 119 | " s:strchars(str) {{{ 120 | if exists('*strchars') 121 | function! s:strchars(str) 122 | return strchars(a:str) 123 | endfunction 124 | else 125 | function! s:strchars(str) 126 | return strlen(substitute(copy(a:str), '.', 'x', 'g')) 127 | endfunction 128 | endif "}}} 129 | 130 | " Returns the bool of contains any multibyte character in s:str 131 | function! s:contains_multibyte(str) "{{{ 132 | return strlen(a:str) != s:strchars(a:str) 133 | endfunction "}}} 134 | 135 | " Remove last character from a:str. 136 | " NOTE: This returns proper value 137 | " even if a:str contains multibyte character(s). 138 | function! s:chop(str) "{{{ 139 | return substitute(a:str, '.$', '', '') 140 | endfunction "}}} 141 | 142 | " Remove last \r,\n,\r\n from a:str. 143 | function! s:chomp(str) "{{{ 144 | return substitute(a:str, '\%(\r\n\|[\r\n]\)$', '', '') 145 | endfunction "}}} 146 | 147 | " wrap() and its internal functions 148 | " * _split_by_wcswidth_once() 149 | " * _split_by_wcswidth() 150 | " * _concat() 151 | " * wrap() 152 | " 153 | " NOTE _concat() is just a copy of Data.List.concat(). 154 | " FIXME don't repeat yourself 155 | function! s:_split_by_wcswidth_once(body, x) 156 | let fst = s:V.strwidthpart(a:body, a:x) 157 | let snd = s:V.strwidthpart_reverse(a:body, s:V.wcswidth(a:body) - s:V.wcswidth(fst)) 158 | return [fst, snd] 159 | endfunction 160 | 161 | function! s:_split_by_wcswidth(body, x) 162 | let memo = [] 163 | let body = a:body 164 | while s:V.wcswidth(body) > a:x 165 | let [tmp, body] = s:_split_by_wcswidth_once(body, a:x) 166 | call add(memo, tmp) 167 | endwhile 168 | call add(memo, body) 169 | return memo 170 | endfunction 171 | 172 | function! s:trim(str) 173 | return matchstr(a:str,'^\s*\zs.\{-}\ze\s*$') 174 | endfunction 175 | 176 | function! s:wrap(str,...) 177 | let _columns = a:0 > 0 ? a:1 : &columns 178 | return s:L.concat( 179 | \ map(split(a:str, '\r\n\|[\r\n]'), 's:_split_by_wcswidth(v:val, _columns - 1)')) 180 | endfunction 181 | 182 | function! s:nr2byte(nr) 183 | if a:nr < 0x80 184 | return nr2char(a:nr) 185 | elseif a:nr < 0x800 186 | return nr2char(a:nr/64+192).nr2char(a:nr%64+128) 187 | else 188 | return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128) 189 | endif 190 | endfunction 191 | 192 | function! s:nr2enc_char(charcode) 193 | if &encoding == 'utf-8' 194 | return nr2char(a:charcode) 195 | endif 196 | let char = s:nr2byte(a:charcode) 197 | if strlen(char) > 1 198 | let char = strtrans(iconv(char, 'utf-8', &encoding)) 199 | endif 200 | return char 201 | endfunction 202 | 203 | function! s:nr2hex(nr) 204 | let n = a:nr 205 | let r = "" 206 | while n 207 | let r = '0123456789ABCDEF'[n % 16] . r 208 | let n = n / 16 209 | endwhile 210 | return r 211 | endfunction 212 | 213 | " If a ==# b, returns -1. 214 | " If a !=# b, returns first index of diffrent character. 215 | function! s:diffidx(a, b) 216 | return a:a ==# a:b ? -1 : strlen(s:common_head([a:a, a:b])) 217 | endfunction 218 | 219 | function! s:substitute_last(expr, pat, sub) 220 | return substitute(a:expr, printf('.*\zs%s', a:pat), a:sub, '') 221 | endfunction 222 | 223 | function! s:dstring(expr) 224 | let x = substitute(string(a:expr), "^'\\|'$", '', 'g') 225 | let x = substitute(x, "''", "'", 'g') 226 | return printf('"%s"', escape(x, '"')) 227 | endfunction 228 | 229 | let &cpo = s:save_cpo 230 | unlet s:save_cpo 231 | 232 | " vim:set et ts=2 sts=2 sw=2 tw=0: 233 | -------------------------------------------------------------------------------- /autoload/vital/_897c317/Bitwise.vim: -------------------------------------------------------------------------------- 1 | " bitwise operators 2 | " moved from github.com/ynkdir/vim-funlib 3 | 4 | let s:save_cpo = &cpo 5 | set cpo&vim 6 | 7 | " compare as unsigned int 8 | function! s:compare(a, b) 9 | if (a:a >= 0 && a:b >= 0) || (a:a < 0 && a:b < 0) 10 | return a:a < a:b ? -1 : a:a > a:b ? 1 : 0 11 | else 12 | return a:a < 0 ? 1 : -1 13 | endif 14 | endfunction 15 | 16 | function! s:lshift(a, n) 17 | return a:a * s:pow2[s:and(a:n, 0x1F)] 18 | endfunction 19 | 20 | function! s:rshift(a, n) 21 | let n = s:and(a:n, 0x1F) 22 | return n == 0 ? a:a : 23 | \ a:a < 0 ? (a:a - 0x80000000) / s:pow2[n] + 0x40000000 / s:pow2[n - 1] 24 | \ : a:a / s:pow2[n] 25 | endfunction 26 | 27 | let s:pow2 = [ 28 | \ 0x1, 0x2, 0x4, 0x8, 29 | \ 0x10, 0x20, 0x40, 0x80, 30 | \ 0x100, 0x200, 0x400, 0x800, 31 | \ 0x1000, 0x2000, 0x4000, 0x8000, 32 | \ 0x10000, 0x20000, 0x40000, 0x80000, 33 | \ 0x100000, 0x200000, 0x400000, 0x800000, 34 | \ 0x1000000, 0x2000000, 0x4000000, 0x8000000, 35 | \ 0x10000000, 0x20000000, 0x40000000, 0x80000000, 36 | \ ] 37 | 38 | if exists('*and') 39 | function! s:_vital_loaded(V) dict 40 | for op in ['and', 'or', 'xor', 'invert'] 41 | let self[op] = function(op) 42 | let s:[op] = self[op] 43 | endfor 44 | endfunction 45 | finish 46 | endif 47 | 48 | 49 | function! s:invert(a) 50 | return -a:a - 1 51 | endfunction 52 | 53 | function! s:and(a, b) 54 | let a = a:a < 0 ? a:a - 0x80000000 : a:a 55 | let b = a:b < 0 ? a:b - 0x80000000 : a:b 56 | let r = 0 57 | let n = 1 58 | while a && b 59 | let r += s:and[a % 0x10][b % 0x10] * n 60 | let a = a / 0x10 61 | let b = b / 0x10 62 | let n = n * 0x10 63 | endwhile 64 | if (a:a < 0) && (a:b < 0) 65 | let r += 0x80000000 66 | endif 67 | return r 68 | endfunction 69 | 70 | function! s:or(a, b) 71 | let a = a:a < 0 ? a:a - 0x80000000 : a:a 72 | let b = a:b < 0 ? a:b - 0x80000000 : a:b 73 | let r = 0 74 | let n = 1 75 | while a || b 76 | let r += s:or[a % 0x10][b % 0x10] * n 77 | let a = a / 0x10 78 | let b = b / 0x10 79 | let n = n * 0x10 80 | endwhile 81 | if (a:a < 0) || (a:b < 0) 82 | let r += 0x80000000 83 | endif 84 | return r 85 | endfunction 86 | 87 | function! s:xor(a, b) 88 | let a = a:a < 0 ? a:a - 0x80000000 : a:a 89 | let b = a:b < 0 ? a:b - 0x80000000 : a:b 90 | let r = 0 91 | let n = 1 92 | while a || b 93 | let r += s:xor[a % 0x10][b % 0x10] * n 94 | let a = a / 0x10 95 | let b = b / 0x10 96 | let n = n * 0x10 97 | endwhile 98 | if (a:a < 0) != (a:b < 0) 99 | let r += 0x80000000 100 | endif 101 | return r 102 | endfunction 103 | 104 | let s:and = [ 105 | \ [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0], 106 | \ [0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1], 107 | \ [0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2], 108 | \ [0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3], 109 | \ [0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4], 110 | \ [0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5, 0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5], 111 | \ [0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6, 0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6], 112 | \ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7], 113 | \ [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8], 114 | \ [0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x8, 0x9, 0x8, 0x9, 0x8, 0x9, 0x8, 0x9], 115 | \ [0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x8, 0x8, 0xA, 0xA, 0x8, 0x8, 0xA, 0xA], 116 | \ [0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xA, 0xB, 0x8, 0x9, 0xA, 0xB], 117 | \ [0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0xC, 0xC, 0xC, 0xC], 118 | \ [0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5, 0x8, 0x9, 0x8, 0x9, 0xC, 0xD, 0xC, 0xD], 119 | \ [0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6, 0x8, 0x8, 0xA, 0xA, 0xC, 0xC, 0xE, 0xE], 120 | \ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF] 121 | \ ] 122 | 123 | let s:or = [ 124 | \ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF], 125 | \ [0x1, 0x1, 0x3, 0x3, 0x5, 0x5, 0x7, 0x7, 0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF], 126 | \ [0x2, 0x3, 0x2, 0x3, 0x6, 0x7, 0x6, 0x7, 0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF], 127 | \ [0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF], 128 | \ [0x4, 0x5, 0x6, 0x7, 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF], 129 | \ [0x5, 0x5, 0x7, 0x7, 0x5, 0x5, 0x7, 0x7, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF], 130 | \ [0x6, 0x7, 0x6, 0x7, 0x6, 0x7, 0x6, 0x7, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF], 131 | \ [0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF], 132 | \ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF], 133 | \ [0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF, 0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF], 134 | \ [0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF, 0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF], 135 | \ [0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF, 0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF], 136 | \ [0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF], 137 | \ [0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF], 138 | \ [0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF], 139 | \ [0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF] 140 | \ ] 141 | 142 | let s:xor = [ 143 | \ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF], 144 | \ [0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE], 145 | \ [0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD], 146 | \ [0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC], 147 | \ [0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB], 148 | \ [0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA], 149 | \ [0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9], 150 | \ [0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8], 151 | \ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7], 152 | \ [0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6], 153 | \ [0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5], 154 | \ [0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4], 155 | \ [0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3], 156 | \ [0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2], 157 | \ [0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1], 158 | \ [0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0] 159 | \ ] 160 | 161 | let &cpo = s:save_cpo 162 | unlet s:save_cpo 163 | 164 | " vim:set et ts=2 sts=2 sw=2 tw=0: 165 | -------------------------------------------------------------------------------- /autoload/game_engine/bmp.vim: -------------------------------------------------------------------------------- 1 | 2 | " http://www.kk.iij4u.or.jp/~kondo/bmp/ 3 | 4 | let s:os2_bitmap = 12 5 | let s:windows_bitmap = 40 6 | 7 | let s:size = 4 8 | 9 | let s:file_header_size = [ 10 | \ ['type', 2], 11 | \ ['size', 4], 12 | \ ['reserved1', 2], 13 | \ ['reserved2', 2], 14 | \ ['off_bits', 4], 15 | \ ] 16 | 17 | let s:info_header_size = { 18 | \ 'os2' : [ 19 | \ ['size', s:size], 20 | \ ['width', 2], 21 | \ ['height', 2], 22 | \ ['planes', 2], 23 | \ ['bit_count', 2], 24 | \ ], 25 | \ 'windows' : [ 26 | \ ['size', s:size], 27 | \ ['width', 4], 28 | \ ['height', 4], 29 | \ ['planes', 2], 30 | \ ['bit_count', 2], 31 | \ ['copmression', 4], 32 | \ ['size_image', 4], 33 | \ ['x_pix_per_meter', 4], 34 | \ ['y_pix_per_meter', 4], 35 | \ ['clr_used', 4], 36 | \ ['cir_important', 4], 37 | \ ], 38 | \ } 39 | 40 | function! s:bitmap_format_name(size) abort 41 | if a:size is s:os2_bitmap 42 | return 'os2' 43 | endif 44 | if a:size is s:windows_bitmap 45 | return 'windows' 46 | endif 47 | endfunction 48 | 49 | function! s:get_off_bits(size) abort 50 | let off_bits = 0 51 | for pair in s:file_header_size 52 | let off_bits += pair[1] 53 | endfor 54 | let bitmap_format_name = s:bitmap_format_name(a:size) 55 | for pair in s:info_header_size[bitmap_format_name] 56 | let off_bits += pair[1] 57 | endfor 58 | return off_bits 59 | endfunction 60 | 61 | function! s:slice(xs, offset, length) abort 62 | return [ a:xs[(a:offset):(a:offset + a:length - 1)], a:offset + a:length ] 63 | endfunction 64 | 65 | function! s:to_hex(xs) abort 66 | return map(deepcopy(a:xs), 'printf("%02X", v:val)') 67 | endfunction 68 | 69 | function! s:to_integer(xs) abort 70 | return str2nr(join(map(reverse(deepcopy(a:xs)), 'printf("%02X", v:val)'), ''), 16) 71 | endfunction 72 | 73 | function! s:integer_to_bytes(n, bytes) abort 74 | if a:bytes is 0 75 | return [] 76 | else 77 | return reverse(map(split(printf("%0" . (a:bytes * 2) . "X", a:n), '..\zs'), 'str2nr(v:val, 16)')) 78 | endif 79 | endfunction 80 | 81 | function! s:to_string(xs) abort 82 | return join(map(deepcopy(a:xs), 'nr2char(v:val)'), '') 83 | endfunction 84 | 85 | function! s:string_to_bytes(str) abort 86 | return map(split(a:str, '\zs'), 'char2nr(v:val)') 87 | endfunction 88 | 89 | function! s:file_header(xs) abort 90 | let dict = {} 91 | 92 | let offset = 0 93 | for pair in s:file_header_size 94 | let [value, offset] = s:slice(a:xs, offset, pair[1]) 95 | let dict[pair[0]] = function(pair[0] is 'type' ? 's:to_string' : 's:to_integer')(value) 96 | endfor 97 | 98 | return [dict, offset] 99 | endfunction 100 | 101 | function! s:info_header(xs, offset) abort 102 | let [size, offset] = s:slice(a:xs, a:offset, s:size) 103 | let dict = { 'size' : s:to_integer(size) } 104 | 105 | let bitmap_format_name = s:bitmap_format_name(dict.size) 106 | 107 | for pair in s:info_header_size[bitmap_format_name] 108 | if pair[0] isnot 'size' 109 | let [value, offset] = s:slice(a:xs, offset, pair[1]) 110 | let dict[pair[0]] = s:to_integer(value) 111 | endif 112 | endfor 113 | 114 | return [dict, offset] 115 | endfunction 116 | 117 | function! s:bit24_imagedata(xs, offset, info_header) abort 118 | let line_width = a:info_header.width * a:info_header.bit_count / 8 119 | let padding_size = (line_width % 4 is 0) ? 0 : (4 - line_width % 4) 120 | let offset = a:offset 121 | let data = [] 122 | for h in range(1, a:info_header.height) 123 | let line_data = [] 124 | for w in range(1, a:info_header.width) 125 | let [blue, offset] = s:slice(a:xs, offset, 1) 126 | let [green, offset] = s:slice(a:xs, offset, 1) 127 | let [red, offset] = s:slice(a:xs, offset, 1) 128 | let line_data += [blue + green + red] 129 | endfor 130 | let [_, offset] = s:slice(a:xs, offset, padding_size) 131 | let data += [line_data] 132 | endfor 133 | return [data, offset] 134 | endfunction 135 | 136 | function! s:bit32_imagedata(xs, offset, info_header) abort 137 | let offset = a:offset 138 | let data = [] 139 | for h in range(1, a:info_header.height) 140 | let line_data = [] 141 | for w in range(1, a:info_header.width) 142 | let [blue, offset] = s:slice(a:xs, offset, 1) 143 | let [green, offset] = s:slice(a:xs, offset, 1) 144 | let [red, offset] = s:slice(a:xs, offset, 1) 145 | let [reserved, offset] = s:slice(a:xs, offset, 1) 146 | let line_data += [blue + green + red + reserved] 147 | endfor 148 | let data += [line_data] 149 | endfor 150 | return [data, offset] 151 | endfunction 152 | 153 | function! game_engine#bmp#read(path, ...) abort 154 | let dict = {} 155 | let headeronly = 0 < a:0 ? a:1 : 0 156 | let xs = call('game_engine#xxd#read', [a:path, 0] + (headeronly ? [100]: [])) 157 | let [file_header, offset] = s:file_header(xs) 158 | if file_header.type is 'BM' 159 | let [info_header, offset] = s:info_header(xs, offset) 160 | if !headeronly 161 | if info_header.bit_count is 24 162 | let [data, offset] = s:bit24_imagedata(xs, offset, info_header) 163 | let dict['data'] = data 164 | elseif info_header.bit_count is 32 165 | let [data, offset] = s:bit32_imagedata(xs, offset, info_header) 166 | let dict['data'] = data 167 | else 168 | echomsg printf('Do not suport %d bit bitmap', info_header.bit_count) 169 | endif 170 | endif 171 | let dict['file_header'] = file_header 172 | let dict['info_header'] = info_header 173 | else 174 | echomsg 'Not BMP File Format' 175 | endif 176 | return dict 177 | endfunction 178 | 179 | function! game_engine#bmp#write(data, path) abort 180 | let bit_count = 32 181 | let bitmap_format = s:windows_bitmap 182 | " let bitmap_format = s:os2_bitmap 183 | let bitmap_format_name = s:bitmap_format_name(bitmap_format) 184 | let width = len(get(a:data, 0, [])) 185 | let height = len(a:data) 186 | let line_width = width * bit_count / 8 187 | let padding_size = (line_width % 4 is 0) ? 0 : (4 - line_width % 4) 188 | let off_bits = s:get_off_bits(bitmap_format) 189 | let size = off_bits + height * (line_width + padding_size) 190 | 191 | let xs = [] 192 | 193 | " file header 194 | let vs = [0x4d42, size, 0, 0, off_bits,] 195 | for i in range(0, len(vs) - 1) 196 | let xs += s:integer_to_bytes(vs[i], s:file_header_size[i][1]) 197 | endfor 198 | 199 | " info header 200 | if bitmap_format is s:os2_bitmap 201 | let vs = [bitmap_format, width, height, 1, bit_count,] 202 | endif 203 | if bitmap_format is s:windows_bitmap 204 | let vs = [bitmap_format, width, height, 1, bit_count, 0, (size - off_bits), 0, 0, 0, 0,] 205 | endif 206 | for i in range(0, len(vs) - 1) 207 | let xs += s:integer_to_bytes(vs[i], s:info_header_size[bitmap_format_name][i][1]) 208 | endfor 209 | 210 | " data 211 | let data = [] 212 | for h in range(0, height - 1) 213 | for w in range(0, width - 1) 214 | if bit_count is 24 || bit_count is 32 215 | " Blue 216 | let data += s:integer_to_bytes(a:data[h][w][0], 1) 217 | " Green 218 | let data += s:integer_to_bytes(a:data[h][w][1], 1) 219 | " Red 220 | let data += s:integer_to_bytes(a:data[h][w][2], 1) 221 | endif 222 | if bit_count is 32 223 | " Reserved 224 | let data += s:integer_to_bytes(0, 1) 225 | endif 226 | endfor 227 | if bit_count is 24 228 | let data += s:integer_to_bytes(0x00, padding_size) 229 | endif 230 | endfor 231 | let xs += data 232 | 233 | call game_engine#xxd#write(xs, a:path) 234 | endfunction 235 | 236 | -------------------------------------------------------------------------------- /autoload/game_engine.vim: -------------------------------------------------------------------------------- 1 | 2 | scriptencoding utf-8 3 | 4 | let s:V = vital#of('game_engine.vim') 5 | let s:List = s:V.import('Data.List') 6 | let s:Random = s:V.import('Random.Xor128') 7 | let s:game_engine = { 8 | \ 'save_data' : {}, 9 | \ } 10 | call s:Random.srand() 11 | 12 | function! game_engine#version() 13 | if v:version < 704 || !executable('xxd') 14 | throw '[game_engine.vim] game_engine.vim requires version 7.4 or higher and to execute xxd.' 15 | endif 16 | return '0.0' 17 | endfunction 18 | function! game_engine#auto_funcref() 19 | try 20 | call b:session._.auto_funcref() 21 | call feedkeys(mode() is# 'i' ? "\\" : "g\", 'n') 22 | catch '.*' 23 | endtry 24 | endfunction 25 | 26 | function! game_engine#start_game(game_title, auto_funcref) 27 | call game_engine#version() 28 | 29 | tabnew 30 | call game_engine#buffer#uniq_open(a:game_title, [], "w") 31 | execute printf("%dwincmd w", game_engine#buffer#winnr(a:game_title)) 32 | setlocal filetype=game_engine 33 | only 34 | 35 | let b:session = s:get_session(a:game_title, a:auto_funcref) 36 | 37 | if s:is_windows() 38 | setlocal guifont=Consolas:h2:cSHIFTJIS 39 | elseif s:is_mac() 40 | setlocal guifont=Menlo\ Regular:h5 41 | elseif s:is_unix() 42 | setlocal guifont=Monospace\ 2 43 | else 44 | endif 45 | let &l:spell = 0 46 | let &l:list = 0 47 | let &l:hlsearch = 0 48 | 49 | augroup GameEngine 50 | autocmd! 51 | autocmd CursorHold,CursorHoldI * call game_engine#auto_funcref() 52 | augroup END 53 | 54 | if has('gui_running') 55 | let &columns = 9999 56 | let &lines = 999 57 | endif 58 | endfunction 59 | function! game_engine#exit_game() 60 | if &filetype is# "game_engine" 61 | augroup GameEngine 62 | autocmd! 63 | augroup END 64 | 65 | let &maxfuncdepth = b:session._.backup.maxfuncdepth 66 | let &guifont = b:session._.backup.guifont 67 | let &updatetime = b:session._.backup.updatetime 68 | let &titlestring = b:session._.backup.titlestring 69 | let &spell = b:session._.backup.spell 70 | let &list = b:session._.backup.list 71 | if has('gui_running') 72 | let &columns = b:session._.backup.columns 73 | let &lines = b:session._.backup.lines 74 | endif 75 | bdelete! 76 | endif 77 | endfunction 78 | function! game_engine#save_game(game_title, key) 79 | if &filetype is# "game_engine" 80 | if b:session._.game_title is a:game_title 81 | if !has_key(s:game_engine.save_data, a:game_title) 82 | let s:game_engine.save_data[(a:game_title)] = {} 83 | endif 84 | let s:game_engine.save_data[(a:game_title)][(a:key)] = deepcopy(b:session) 85 | endif 86 | endif 87 | endfunction 88 | function! game_engine#load_game(game_title, key) 89 | if &filetype is# "game_engine" 90 | if b:session._.game_title is a:game_title 91 | if !has_key(s:game_engine.save_data, a:game_title) 92 | let s:game_engine.save_data[(a:game_title)] = {} 93 | endif 94 | let b:session = deepcopy(get(s:game_engine.save_data[(a:game_title)], a:key, {})) 95 | endif 96 | endif 97 | endfunction 98 | 99 | function! game_engine#rand(n) 100 | return abs(s:Random.rand()) % a:n 101 | endfunction 102 | 103 | " echo game_engine#scale2d([ 104 | " \[1,2], 105 | " \[3,4]], 106 | " \ { 107 | " \ '1' : [[1,1,1], 108 | " \ [1,1,1], 109 | " \ [1,1,1]], 110 | " \ '2' : [[4,4,4], 111 | " \ [4,4,4], 112 | " \ [4,4,4]], 113 | " \ '4' : [[16,16,16], 114 | " \ [16,16,16], 115 | " \ [16,16,16]], 116 | " \ }, [[0,0,0], 117 | " \ [0,0,0], 118 | " \ [0,0,0]]) 119 | function! game_engine#scale2d(data, scale_dict, default) 120 | let lines = [] 121 | for row in a:data 122 | let scaled_row = map(deepcopy(row), 123 | \ 's:List.zip(get(a:scale_dict, v:val, a:default))') 124 | for lnum in range(0, len(scaled_row[0]) - 1) 125 | let line = [] 126 | for idx in range(0, len(scaled_row) - 1) 127 | let line += scaled_row[idx][lnum][0] 128 | endfor 129 | let lines += [line] 130 | endfor 131 | endfor 132 | return lines 133 | endfunction 134 | 135 | function! game_engine#syntax(...) 136 | let syntax_dict = {} 137 | 138 | let syntax_dict['_ff0000'] = { 'gui' : '#ff0000', 'cterm' : 'Red' } 139 | let syntax_dict['_00ff00'] = { 'gui' : '#00ff00', 'cterm' : 'Green' } 140 | let syntax_dict['_0000ff'] = { 'gui' : '#0000ff', 'cterm' : 'Blue' } 141 | let syntax_dict['_ffff00'] = { 'gui' : '#ffff00', 'cterm' : 'Yellow' } 142 | let syntax_dict['_8B008B'] = { 'gui' : '#8B008B', 'cterm' : 'DarkMagenta' } 143 | let syntax_dict['_965042'] = { 'gui' : '#965042', 'cterm' : 'DarkRed' } 144 | let syntax_dict['_ffffff'] = { 'gui' : '#ffffff', 'cterm' : 'White' } 145 | let syntax_dict['_000000'] = { 'gui' : '#000000', 'cterm' : 'Black' } 146 | let syntax_dict['_333333'] = { 'gui' : '#333333', 'cterm' : 'Gray' } 147 | let syntax_dict['_ff00ff'] = { 'gui' : '#ff00ff', 'cterm' : 'Magenta' } 148 | for key in keys(deepcopy(syntax_dict)) 149 | let syntax_dict[syntax_dict[key].cterm] = deepcopy(syntax_dict[key]) 150 | endfor 151 | 152 | for arg_dict in a:000 153 | let key = tr(arg_dict.gui, '#', '_') 154 | if !has_key(syntax_dict, key) 155 | let syntax_dict[key] = arg_dict 156 | endif 157 | endfor 158 | 159 | let ts = 160 | \ map(range(0, 9), 'nr2char(0x30 + v:val)') 161 | \ + map(range(1, 26), 'nr2char(0x40 + v:val)') 162 | \ + map(range(1, 26), 'nr2char(0x60 + v:val)') 163 | let idx = 0 164 | for key in keys(syntax_dict) 165 | let syntax_dict[key].text = '@' . ts[idx] 166 | let idx += 1 167 | endfor 168 | 169 | return syntax_dict 170 | endfunction 171 | function! game_engine#define_syntax(name, dict) 172 | execute printf('highlight! game_engine%sHi guifg=%s guibg=%s ctermfg=%s ctermbg=%s', 173 | \ a:name, 174 | \ a:dict['gui'], a:dict['gui'], 175 | \ a:dict['cterm'], a:dict['cterm'] 176 | \ ) 177 | execute printf('syntax match game_engine%s "%s"', 178 | \ a:name, a:dict['text']) 179 | execute printf('highlight! default link game_engine%s game_engine%sHi', 180 | \ a:name, a:name) 181 | endfunction 182 | 183 | function! s:get_session(game_title, auto_funcref) 184 | let session = {} 185 | let session._ = {} 186 | let session._.List = s:List 187 | 188 | let session._.backup = { 189 | \ 'guifont' : &guifont, 190 | \ 'spell' : &spell, 191 | \ 'updatetime' : &updatetime, 192 | \ 'maxfuncdepth' : &maxfuncdepth, 193 | \ 'titlestring' : &titlestring, 194 | \ 'columns' : &columns, 195 | \ 'lines' : &lines, 196 | \ 'list' : &list, 197 | \ } 198 | 199 | let session._.game_title = a:game_title 200 | let session._.auto_funcref = a:auto_funcref 201 | 202 | function! session.redraw(lines) dict 203 | call game_engine#buffer#uniq_open(self._.game_title, a:lines, "w") 204 | redraw 205 | endfunction 206 | 207 | return session 208 | endfunction 209 | 210 | function! s:is_unix() 211 | return has('unix') && ! has('mac') 212 | endfunction 213 | function! s:is_windows() 214 | return has('win95') || has('win16') || has('win32') || has('win64') 215 | endfunction 216 | function! s:is_cygwin() 217 | return has('win32unix') 218 | endfunction 219 | function! s:is_mac() 220 | return ! s:is_windows() 221 | \ && ! s:is_cygwin() 222 | \ && ( 223 | \ has('mac') 224 | \ || has('macunix') 225 | \ || has('gui_macvim') 226 | \ || ( ! executable('xdg-open') 227 | \ && system('uname') =~? '^darwin' 228 | \ ) 229 | \ ) 230 | endfunction 231 | 232 | -------------------------------------------------------------------------------- /autoload/vital/_897c317/Data/List.vim: -------------------------------------------------------------------------------- 1 | " Utilities for list. 2 | 3 | let s:save_cpo = &cpo 4 | set cpo&vim 5 | 6 | function! s:pop(list) 7 | return remove(a:list, -1) 8 | endfunction 9 | 10 | function! s:push(list, val) 11 | call add(a:list, a:val) 12 | return a:list 13 | endfunction 14 | 15 | function! s:shift(list) 16 | return remove(a:list, 0) 17 | endfunction 18 | 19 | function! s:unshift(list, val) 20 | return insert(a:list, a:val) 21 | endfunction 22 | 23 | function! s:cons(x, xs) 24 | return [a:x] + a:xs 25 | endfunction 26 | 27 | " TODO spec 28 | function! s:conj(xs, x) 29 | return a:xs + [a:x] 30 | endfunction 31 | 32 | " Removes duplicates from a list. 33 | function! s:uniq(list, ...) 34 | let list = a:0 ? map(copy(a:list), printf('[v:val, %s]', a:1)) : copy(a:list) 35 | let i = 0 36 | let seen = {} 37 | while i < len(list) 38 | let key = string(a:0 ? list[i][1] : list[i]) 39 | if has_key(seen, key) 40 | call remove(list, i) 41 | else 42 | let seen[key] = 1 43 | let i += 1 44 | endif 45 | endwhile 46 | return a:0 ? map(list, 'v:val[0]') : list 47 | endfunction 48 | 49 | function! s:clear(list) 50 | if !empty(a:list) 51 | unlet! a:list[0 : len(a:list) - 1] 52 | endif 53 | return a:list 54 | endfunction 55 | 56 | " Concatenates a list of lists. 57 | " XXX: Should we verify the input? 58 | function! s:concat(list) 59 | let list = [] 60 | for Value in a:list 61 | let list += Value 62 | endfor 63 | return list 64 | endfunction 65 | 66 | " Flattens a list. 67 | function! s:flatten(list, ...) 68 | let limit = a:0 > 0 ? a:1 : -1 69 | let list = [] 70 | if limit == 0 71 | return a:list 72 | endif 73 | let limit -= 1 74 | for Value in a:list 75 | if type(Value) == type([]) 76 | let list += s:flatten(Value, limit) 77 | else 78 | call add(list, Value) 79 | endif 80 | unlet! Value 81 | endfor 82 | return list 83 | endfunction 84 | 85 | " Sorts a list with expression to compare each two values. 86 | " a:a and a:b can be used in {expr}. 87 | function! s:sort(list, expr) 88 | if type(a:expr) == type(function('function')) 89 | return sort(a:list, a:expr) 90 | endif 91 | let s:expr = a:expr 92 | return sort(a:list, 's:_compare') 93 | endfunction 94 | 95 | function! s:_compare(a, b) 96 | return eval(s:expr) 97 | endfunction 98 | 99 | " Sorts a list using a set of keys generated by mapping the values in the list 100 | " through the given expr. 101 | " v:val is used in {expr} 102 | function! s:sort_by(list, expr) 103 | let pairs = map(a:list, printf('[v:val, %s]', a:expr)) 104 | return map(s:sort(pairs, 105 | \ 'a:a[1] ==# a:b[1] ? 0 : a:a[1] ># a:b[1] ? 1 : -1'), 'v:val[0]') 106 | endfunction 107 | 108 | function! s:max(list, expr) 109 | echoerr 'Data.List.max() is obsolete. Use its max_by() instead.' 110 | return s:max_by(a:list, a:expr) 111 | endfunction 112 | 113 | " Returns a maximum value in {list} through given {expr}. 114 | " Returns 0 if {list} is empty. 115 | " v:val is used in {expr} 116 | function! s:max_by(list, expr) 117 | if empty(a:list) 118 | return 0 119 | endif 120 | let list = map(copy(a:list), a:expr) 121 | return a:list[index(list, max(list))] 122 | endfunction 123 | 124 | function! s:min(list, expr) 125 | echoerr 'Data.List.min() is obsolete. Use its min_by() instead.' 126 | return s:min_by(a:list, a:expr) 127 | endfunction 128 | 129 | " Returns a minimum value in {list} through given {expr}. 130 | " Returns 0 if {list} is empty. 131 | " v:val is used in {expr} 132 | " FIXME: -0x80000000 == 0x80000000 133 | function! s:min_by(list, expr) 134 | return s:max_by(a:list, '-(' . a:expr . ')') 135 | endfunction 136 | 137 | " Returns List of character sequence between [a:from, a:to] 138 | " e.g.: s:char_range('a', 'c') returns ['a', 'b', 'c'] 139 | function! s:char_range(from, to) 140 | return map( 141 | \ range(char2nr(a:from), char2nr(a:to)), 142 | \ 'nr2char(v:val)' 143 | \) 144 | endfunction 145 | 146 | " Returns true if a:list has a:value. 147 | " Returns false otherwise. 148 | function! s:has(list, value) 149 | return index(a:list, a:value) isnot -1 150 | endfunction 151 | 152 | " Returns true if a:list[a:index] exists. 153 | " Returns false otherwise. 154 | " NOTE: Returns false when a:index is negative number. 155 | function! s:has_index(list, index) 156 | " Return true when negative index? 157 | " let index = a:index >= 0 ? a:index : len(a:list) + a:index 158 | return 0 <= a:index && a:index < len(a:list) 159 | endfunction 160 | 161 | " similar to Haskell's Data.List.span 162 | function! s:span(f, xs) 163 | let border = len(a:xs) 164 | for i in range(len(a:xs)) 165 | if !eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g')) 166 | let border = i 167 | break 168 | endif 169 | endfor 170 | return border == 0 ? [[], copy(a:xs)] : [a:xs[: border - 1], a:xs[border :]] 171 | endfunction 172 | 173 | " similar to Haskell's Data.List.break 174 | function! s:break(f, xs) 175 | return s:span(printf('!(%s)', a:f), a:xs) 176 | endfunction 177 | 178 | " similar to Haskell's Data.List.takeWhile 179 | function! s:take_while(f, xs) 180 | return s:span(a:f, a:xs)[0] 181 | endfunction 182 | 183 | " similar to Haskell's Data.List.partition 184 | function! s:partition(f, xs) 185 | return [filter(copy(a:xs), a:f), filter(copy(a:xs), '!(' . a:f . ')')] 186 | endfunction 187 | 188 | " similar to Haskell's Prelude.all 189 | function! s:all(f, xs) 190 | return !s:any(printf('!(%s)', a:f), a:xs) 191 | endfunction 192 | 193 | " similar to Haskell's Prelude.any 194 | function! s:any(f, xs) 195 | return !empty(filter(map(copy(a:xs), a:f), 'v:val')) 196 | endfunction 197 | 198 | " similar to Haskell's Prelude.and 199 | function! s:and(xs) 200 | return s:all('v:val', a:xs) 201 | endfunction 202 | 203 | " similar to Haskell's Prelude.or 204 | function! s:or(xs) 205 | return s:any('v:val', a:xs) 206 | endfunction 207 | 208 | " similar to Haskell's Prelude.foldl 209 | function! s:foldl(f, init, xs) 210 | let memo = a:init 211 | for x in a:xs 212 | let expr = substitute(a:f, 'v:val', string(x), 'g') 213 | let expr = substitute(expr, 'v:memo', string(memo), 'g') 214 | unlet memo 215 | let memo = eval(expr) 216 | endfor 217 | return memo 218 | endfunction 219 | 220 | " similar to Haskell's Prelude.foldl1 221 | function! s:foldl1(f, xs) 222 | if len(a:xs) == 0 223 | throw 'foldl1' 224 | endif 225 | return s:foldl(a:f, a:xs[0], a:xs[1:]) 226 | endfunction 227 | 228 | " similar to Haskell's Prelude.foldr 229 | function! s:foldr(f, init, xs) 230 | let memo = a:init 231 | for i in reverse(range(0, len(a:xs) - 1)) 232 | let x = a:xs[i] 233 | let expr = substitute(a:f, 'v:val', string(x), 'g') 234 | let expr = substitute(expr, 'v:memo', string(memo), 'g') 235 | unlet memo 236 | let memo = eval(expr) 237 | endfor 238 | return memo 239 | endfunction 240 | 241 | " similar to Haskell's Prelude.fold11 242 | function! s:foldr1(f, xs) 243 | if len(a:xs) == 0 244 | throw 'foldr1' 245 | endif 246 | return s:foldr(a:f, a:xs[-1], a:xs[0:-2]) 247 | endfunction 248 | 249 | " similar to python's zip() 250 | function! s:zip(...) 251 | return map(range(min(map(copy(a:000), 'len(v:val)'))), "map(copy(a:000), 'v:val['.v:val.']')") 252 | endfunction 253 | 254 | " similar to zip(), but goes until the longer one. 255 | function! s:zip_fill(xs, ys, filler) 256 | if empty(a:xs) && empty(a:ys) 257 | return [] 258 | elseif empty(a:ys) 259 | return s:cons([a:xs[0], a:filler], s:zip_fill(a:xs[1 :], [], a:filler)) 260 | elseif empty(a:xs) 261 | return s:cons([a:filler, a:ys[0]], s:zip_fill([], a:ys[1 :], a:filler)) 262 | else 263 | return s:cons([a:xs[0], a:ys[0]], s:zip_fill(a:xs[1 :], a:ys[1: ], a:filler)) 264 | endif 265 | endfunction 266 | 267 | " Inspired by Ruby's with_index method. 268 | function! s:with_index(list, ...) 269 | let base = a:0 > 0 ? a:1 : 0 270 | return s:zip(a:list, range(base, len(a:list)+base-1)) 271 | endfunction 272 | 273 | " similar to Ruby's detect or Haskell's find. 274 | " TODO spec and doc 275 | function! s:find(list, default, f) 276 | for x in a:list 277 | if eval(substitute(a:f, 'v:val', string(x), 'g')) 278 | return x 279 | endif 280 | endfor 281 | return a:default 282 | endfunction 283 | 284 | " Return non-zero if a:list1 and a:list2 have any common item(s). 285 | " Return zero otherwise. 286 | function! s:has_common_items(list1, list2) 287 | return !empty(filter(copy(a:list1), 'index(a:list2, v:val) isnot -1')) 288 | endfunction 289 | 290 | let &cpo = s:save_cpo 291 | unlet s:save_cpo 292 | 293 | " vim:set et ts=2 sts=2 sw=2 tw=0: 294 | -------------------------------------------------------------------------------- /autoload/vital/_897c317/Prelude.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | " glob() wrapper which returns List 5 | " and 'wildignore' does not affect 6 | " this function's return value. 7 | if v:version ># 703 || 8 | \ (v:version is 703 && has('patch465')) 9 | function! s:glob(expr) 10 | return glob(a:expr, 1, 1) 11 | endfunction 12 | else 13 | function! s:glob(expr) 14 | let R = glob(a:expr, 1) 15 | return split(R, '\n') 16 | endfunction 17 | endif 18 | 19 | " globpath() wrapper which returns List 20 | " and 'suffixes' and 'wildignore' does not affect 21 | " this function's return value. 22 | function! s:globpath(path, expr) 23 | let R = globpath(a:path, a:expr, 1) 24 | return split(R, '\n') 25 | endfunction 26 | 27 | " Wrapper functions for type(). 28 | let [ 29 | \ s:__TYPE_NUMBER, 30 | \ s:__TYPE_STRING, 31 | \ s:__TYPE_FUNCREF, 32 | \ s:__TYPE_LIST, 33 | \ s:__TYPE_DICT, 34 | \ s:__TYPE_FLOAT] = [ 35 | \ type(3), 36 | \ type(""), 37 | \ type(function('tr')), 38 | \ type([]), 39 | \ type({}), 40 | \ has('float') ? type(str2float('0')) : -1] 41 | " __TYPE_FLOAT = -1 when -float 42 | " This doesn't match to anything. 43 | 44 | " Number or Float 45 | function! s:is_numeric(Value) 46 | let _ = type(a:Value) 47 | return _ ==# s:__TYPE_NUMBER 48 | \ || _ ==# s:__TYPE_FLOAT 49 | endfunction 50 | 51 | " Number 52 | function! s:is_integer(Value) 53 | echoerr 'Prelude.is_integer() is obsolete. Use its is_number() instead; they are equivalent.' 54 | return s:is_number(a:Value) 55 | endfunction 56 | 57 | function! s:is_number(Value) 58 | return type(a:Value) ==# s:__TYPE_NUMBER 59 | endfunction 60 | 61 | " Float 62 | function! s:is_float(Value) 63 | return type(a:Value) ==# s:__TYPE_FLOAT 64 | endfunction 65 | " String 66 | function! s:is_string(Value) 67 | return type(a:Value) ==# s:__TYPE_STRING 68 | endfunction 69 | " Funcref 70 | function! s:is_funcref(Value) 71 | return type(a:Value) ==# s:__TYPE_FUNCREF 72 | endfunction 73 | " List 74 | function! s:is_list(Value) 75 | return type(a:Value) ==# s:__TYPE_LIST 76 | endfunction 77 | " Dictionary 78 | function! s:is_dict(Value) 79 | return type(a:Value) ==# s:__TYPE_DICT 80 | endfunction 81 | 82 | function! s:truncate_smart(str, max, footer_width, separator) 83 | echoerr 'Prelude.truncate_smart() is obsolete. Use its truncate_skipping() instead; they are equivalent.' 84 | return s:truncate_skipping(a:str, a:max, a:footer_width, a:separator) 85 | endfunction 86 | 87 | function! s:truncate_skipping(str, max, footer_width, separator) 88 | let width = s:wcswidth(a:str) 89 | if width <= a:max 90 | let ret = a:str 91 | else 92 | let header_width = a:max - s:wcswidth(a:separator) - a:footer_width 93 | let ret = s:strwidthpart(a:str, header_width) . a:separator 94 | \ . s:strwidthpart_reverse(a:str, a:footer_width) 95 | endif 96 | 97 | return s:truncate(ret, a:max) 98 | endfunction 99 | 100 | function! s:truncate(str, width) 101 | " Original function is from mattn. 102 | " http://github.com/mattn/googlereader-vim/tree/master 103 | 104 | if a:str =~# '^[\x00-\x7f]*$' 105 | return len(a:str) < a:width ? 106 | \ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width) 107 | endif 108 | 109 | let ret = a:str 110 | let width = s:wcswidth(a:str) 111 | if width > a:width 112 | let ret = s:strwidthpart(ret, a:width) 113 | let width = s:wcswidth(ret) 114 | endif 115 | 116 | if width < a:width 117 | let ret .= repeat(' ', a:width - width) 118 | endif 119 | 120 | return ret 121 | endfunction 122 | 123 | function! s:strwidthpart(str, width) 124 | if a:width <= 0 125 | return '' 126 | endif 127 | let ret = a:str 128 | let width = s:wcswidth(a:str) 129 | while width > a:width 130 | let char = matchstr(ret, '.$') 131 | let ret = ret[: -1 - len(char)] 132 | let width -= s:wcswidth(char) 133 | endwhile 134 | 135 | return ret 136 | endfunction 137 | function! s:strwidthpart_reverse(str, width) 138 | if a:width <= 0 139 | return '' 140 | endif 141 | let ret = a:str 142 | let width = s:wcswidth(a:str) 143 | while width > a:width 144 | let char = matchstr(ret, '^.') 145 | let ret = ret[len(char) :] 146 | let width -= s:wcswidth(char) 147 | endwhile 148 | 149 | return ret 150 | endfunction 151 | 152 | if v:version >= 703 153 | " Use builtin function. 154 | function! s:wcswidth(str) 155 | return strwidth(a:str) 156 | endfunction 157 | else 158 | function! s:wcswidth(str) 159 | if a:str =~# '^[\x00-\x7f]*$' 160 | return strlen(a:str) 161 | end 162 | 163 | let mx_first = '^\(.\)' 164 | let str = a:str 165 | let width = 0 166 | while 1 167 | let ucs = char2nr(substitute(str, mx_first, '\1', '')) 168 | if ucs == 0 169 | break 170 | endif 171 | let width += s:_wcwidth(ucs) 172 | let str = substitute(str, mx_first, '', '') 173 | endwhile 174 | return width 175 | endfunction 176 | 177 | " UTF-8 only. 178 | function! s:_wcwidth(ucs) 179 | let ucs = a:ucs 180 | if (ucs >= 0x1100 181 | \ && (ucs <= 0x115f 182 | \ || ucs == 0x2329 183 | \ || ucs == 0x232a 184 | \ || (ucs >= 0x2e80 && ucs <= 0xa4cf 185 | \ && ucs != 0x303f) 186 | \ || (ucs >= 0xac00 && ucs <= 0xd7a3) 187 | \ || (ucs >= 0xf900 && ucs <= 0xfaff) 188 | \ || (ucs >= 0xfe30 && ucs <= 0xfe6f) 189 | \ || (ucs >= 0xff00 && ucs <= 0xff60) 190 | \ || (ucs >= 0xffe0 && ucs <= 0xffe6) 191 | \ || (ucs >= 0x20000 && ucs <= 0x2fffd) 192 | \ || (ucs >= 0x30000 && ucs <= 0x3fffd) 193 | \ )) 194 | return 2 195 | endif 196 | return 1 197 | endfunction 198 | endif 199 | 200 | let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95') 201 | let s:is_cygwin = has('win32unix') 202 | let s:is_mac = !s:is_windows && !s:is_cygwin 203 | \ && (has('mac') || has('macunix') || has('gui_macvim') || 204 | \ (!isdirectory('/proc') && executable('sw_vers'))) 205 | let s:is_unix = has('unix') 206 | 207 | function! s:is_windows() 208 | return s:is_windows 209 | endfunction 210 | 211 | function! s:is_cygwin() 212 | return s:is_cygwin 213 | endfunction 214 | 215 | function! s:is_mac() 216 | return s:is_mac 217 | endfunction 218 | 219 | function! s:is_unix() 220 | return s:is_unix 221 | endfunction 222 | 223 | function! s:print_error(message) 224 | echohl ErrorMsg 225 | for m in split(a:message, "\n") 226 | echomsg m 227 | endfor 228 | echohl None 229 | endfunction 230 | 231 | function! s:smart_execute_command(action, word) 232 | execute a:action . ' ' . (a:word == '' ? '' : '`=a:word`') 233 | endfunction 234 | 235 | function! s:escape_file_searching(buffer_name) 236 | return escape(a:buffer_name, '*[]?{}, ') 237 | endfunction 238 | 239 | function! s:escape_pattern(str) 240 | return escape(a:str, '~"\.^$[]*') 241 | endfunction 242 | 243 | " iconv() wrapper for safety. 244 | function! s:iconv(expr, from, to) 245 | if a:from == '' || a:to == '' || a:from ==? a:to 246 | return a:expr 247 | endif 248 | let result = iconv(a:expr, a:from, a:to) 249 | return result != '' ? result : a:expr 250 | endfunction 251 | 252 | " Like builtin getchar() but returns string always. 253 | function! s:getchar(...) 254 | let c = call('getchar', a:000) 255 | return type(c) == type(0) ? nr2char(c) : c 256 | endfunction 257 | 258 | " Like builtin getchar() but returns string always. 259 | " and do inputsave()/inputrestore() before/after getchar(). 260 | function! s:getchar_safe(...) 261 | let c = s:input_helper('getchar', a:000) 262 | return type(c) == type("") ? c : nr2char(c) 263 | endfunction 264 | 265 | " Like builtin getchar() but 266 | " do inputsave()/inputrestore() before/after input(). 267 | function! s:input_safe(...) 268 | return s:input_helper('input', a:000) 269 | endfunction 270 | 271 | " Do inputsave()/inputrestore() before/after calling a:funcname. 272 | function! s:input_helper(funcname, args) 273 | let success = 0 274 | if inputsave() !=# success 275 | throw 'inputsave() failed' 276 | endif 277 | try 278 | return call(a:funcname, a:args) 279 | finally 280 | if inputrestore() !=# success 281 | throw 'inputrestore() failed' 282 | endif 283 | endtry 284 | endfunction 285 | 286 | function! s:set_default(var, val) 287 | if !exists(a:var) || type({a:var}) != type(a:val) 288 | let {a:var} = a:val 289 | endif 290 | endfunction 291 | 292 | function! s:set_dictionary_helper(variable, keys, pattern) 293 | for key in split(a:keys, '\s*,\s*') 294 | if !has_key(a:variable, key) 295 | let a:variable[key] = a:pattern 296 | endif 297 | endfor 298 | endfunction 299 | 300 | function! s:substitute_path_separator(path) 301 | return s:is_windows ? substitute(a:path, '\\', '/', 'g') : a:path 302 | endfunction 303 | 304 | function! s:path2directory(path) 305 | return s:substitute_path_separator(isdirectory(a:path) ? a:path : fnamemodify(a:path, ':p:h')) 306 | endfunction 307 | 308 | function! s:_path2project_directory_git(path) 309 | let parent = a:path 310 | 311 | while 1 312 | let path = parent . '/.git' 313 | if isdirectory(path) || filereadable(path) 314 | return parent 315 | endif 316 | let next = fnamemodify(parent, ':h') 317 | if next == parent 318 | return '' 319 | endif 320 | let parent = next 321 | endwhile 322 | endfunction 323 | 324 | function! s:_path2project_directory_svn(path) 325 | let search_directory = a:path 326 | let directory = '' 327 | 328 | let find_directory = s:escape_file_searching(search_directory) 329 | let d = finddir('.svn', find_directory . ';') 330 | if d == '' 331 | return '' 332 | endif 333 | 334 | let directory = fnamemodify(d, ':p:h:h') 335 | 336 | " Search parent directories. 337 | let parent_directory = s:path2directory( 338 | \ fnamemodify(directory, ':h')) 339 | 340 | if parent_directory != '' 341 | let d = finddir('.svn', parent_directory . ';') 342 | if d != '' 343 | let directory = s:_path2project_directory_svn(parent_directory) 344 | endif 345 | endif 346 | return directory 347 | endfunction 348 | 349 | function! s:_path2project_directory_others(vcs, path) 350 | let vcs = a:vcs 351 | let search_directory = a:path 352 | let directory = '' 353 | 354 | let find_directory = s:escape_file_searching(search_directory) 355 | let d = finddir(vcs, find_directory . ';') 356 | if d == '' 357 | return '' 358 | endif 359 | return fnamemodify(d, ':p:h:h') 360 | endfunction 361 | 362 | function! s:path2project_directory(path, ...) 363 | let is_allow_empty = get(a:000, 0, 0) 364 | let search_directory = s:path2directory(a:path) 365 | let directory = '' 366 | 367 | " Search VCS directory. 368 | for vcs in ['.git', '.bzr', '.hg', '.svn'] 369 | if vcs ==# '.git' 370 | let directory = s:_path2project_directory_git(search_directory) 371 | elseif vcs ==# '.svn' 372 | let directory = s:_path2project_directory_svn(search_directory) 373 | else 374 | let directory = s:_path2project_directory_others(vcs, search_directory) 375 | endif 376 | if directory != '' 377 | break 378 | endif 379 | endfor 380 | 381 | " Search project file. 382 | if directory == '' 383 | for d in ['build.xml', 'prj.el', '.project', 'pom.xml', 384 | \ 'Makefile', 'configure', 'Rakefile', 'NAnt.build', 'tags', 'gtags'] 385 | let d = findfile(d, s:escape_file_searching(search_directory) . ';') 386 | if d != '' 387 | let directory = fnamemodify(d, ':p:h') 388 | break 389 | endif 390 | endfor 391 | endif 392 | 393 | if directory == '' 394 | " Search /src/ directory. 395 | let base = s:substitute_path_separator(search_directory) 396 | if base =~# '/src/' 397 | let directory = base[: strridx(base, '/src/') + 3] 398 | endif 399 | endif 400 | 401 | if directory == '' && !is_allow_empty 402 | " Use original path. 403 | let directory = search_directory 404 | endif 405 | 406 | return s:substitute_path_separator(directory) 407 | endfunction 408 | 409 | " Check vimproc. 410 | function! s:has_vimproc() 411 | if !exists('s:exists_vimproc') 412 | try 413 | call vimproc#version() 414 | let s:exists_vimproc = 1 415 | catch 416 | let s:exists_vimproc = 0 417 | endtry 418 | endif 419 | return s:exists_vimproc 420 | endfunction 421 | 422 | function! s:system(str, ...) 423 | let command = a:str 424 | let input = a:0 >= 1 ? a:1 : '' 425 | let command = s:iconv(command, &encoding, 'char') 426 | let input = s:iconv(input, &encoding, 'char') 427 | 428 | if a:0 == 0 429 | let output = s:has_vimproc() ? 430 | \ vimproc#system(command) : system(command) 431 | elseif a:0 == 1 432 | let output = s:has_vimproc() ? 433 | \ vimproc#system(command, input) : system(command, input) 434 | else 435 | " ignores 3rd argument unless you have vimproc. 436 | let output = s:has_vimproc() ? 437 | \ vimproc#system(command, input, a:2) : system(command, input) 438 | endif 439 | 440 | let output = s:iconv(output, 'char', &encoding) 441 | 442 | return output 443 | endfunction 444 | 445 | function! s:get_last_status() 446 | return s:has_vimproc() ? 447 | \ vimproc#get_last_status() : v:shell_error 448 | endfunction 449 | 450 | let &cpo = s:save_cpo 451 | unlet s:save_cpo 452 | 453 | " vim:set et ts=2 sts=2 sw=2 tw=0: 454 | --------------------------------------------------------------------------------