├── LICENSE ├── README.md ├── autoload ├── autoprogramming.vim └── autoprogramming │ └── async.vim └── doc └── auto-programming.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 haya14busa 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 copies 9 | of the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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 IMPLIED, 16 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 17 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 20 | THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-auto-programming 2 | 3 | vim-auto-programming provides statistical whole lines completions for git projects. 4 | It's inspired by [hitode909/atom-auto-programming](https://github.com/hitode909/atom-auto-programming). 5 | 6 | It's like `i_CTRL-X_CTRL-L` and `i_CTRL-X_CTRL-K` but powered by `git grep`. 7 | 8 | ![demo](https://raw.githubusercontent.com/haya14busa/i/41a4dddba9d6bb00654c506cc84455d756e8cd31/vim-auto-programming/anim.gif) 9 | 10 | ![demo_keyword_compl.gif (914×766)](https://raw.githubusercontent.com/haya14busa/i/bd561ea622e581efcce58efd961237b91de22292/vim-auto-programming/demo_keyword_compl.gif) 11 | 12 | ## How To Use 13 | 14 | ```vim 15 | set completefunc=autoprogramming#complete 16 | ``` 17 | 18 | Write some code and run `` or something to invoke `autoprogramming#complete` manually. 19 | You will get candidates of next line of the code. 20 | 21 | For example, when you type `impo`, the code you want to get is `import (`, and you might want to insert next line as `"fmt"`. 22 | 23 | ## Requirements 24 | - Only git projects are supported. 25 | 26 | -------------------------------------------------------------------------------- /autoload/autoprogramming.vim: -------------------------------------------------------------------------------- 1 | "============================================================================= 2 | " FILE: autoload/autoprogramming.vim 3 | " AUTHOR: haya14busa 4 | " License: MIT license 5 | "============================================================================= 6 | scriptencoding utf-8 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | let g:autoprogramming#maxwidth = get(g:, 'autoprogramming#maxwidth', 50) 11 | 12 | function! autoprogramming#complete(findstart, base) abort 13 | if a:findstart 14 | return autoprogramming#find_start_col() 15 | endif 16 | return autoprogramming#completion_items(a:base) 17 | endfunction 18 | 19 | function! autoprogramming#find_start_col() abort 20 | return len(matchstr(getline('.'), '^\s*')) 21 | endfunction 22 | 23 | function! autoprogramming#completion_items(base) abort 24 | let query = s:trim_start(a:base) 25 | if query ==# '' 26 | return s:vertical(s:trim_start(getline(line('.')-1))) 27 | endif 28 | return s:horizontal(query, 0) 29 | endfunction 30 | 31 | function! s:horizontal(query, skip) abort 32 | let shortq = s:shorten(a:query, a:skip) 33 | if shortq ==# '' || (a:skip > 0 && a:query ==# shortq) 34 | return [] 35 | endif 36 | let cmd = ['git', 'grep', '--fixed-string', '-h', '-e', shortq] 37 | let job = autoprogramming#async#new_job(cmd) 38 | call job.start() 39 | call job.await({-> complete_check() || getchar(1)}) 40 | let lines = job.stdout 41 | let counts = {} 42 | let abbrs = {} 43 | let usages = {} 44 | for line in lines 45 | let precompl = '' 46 | for whole_line in [v:false, v:true] 47 | let compl = s:compl(line, shortq, whole_line) 48 | if compl !=# '' && precompl !=# compl 49 | let l = s:trim_start(a:query . compl) 50 | if !has_key(counts, l) 51 | let counts[l] = 0 52 | let abbrs[l] = shortq . compl 53 | let usages[l] = {} 54 | endif 55 | let counts[l] += 1 56 | let usages[l][s:trim_start(line)] = 1 57 | endif 58 | let precompl = compl 59 | endfor 60 | endfor 61 | if empty(counts) 62 | return s:horizontal(a:query, a:skip+1) 63 | endif 64 | return s:summarize(counts, abbrs, usages) 65 | endfunction 66 | 67 | function! s:vertical(query) abort 68 | let cmd = ['git', 'grep', '-A1', '--fixed-string', '-h', '-e', a:query] 69 | let job = autoprogramming#async#new_job(cmd) 70 | call job.start() 71 | call job.await({-> complete_check() || getchar(1)}) 72 | let lines = job.stdout 73 | let counts = {} 74 | while len(lines) > 1 75 | if s:trim_start(remove(lines, 0)) ==# a:query 76 | let l = s:trim_start(remove(lines, 0)) 77 | if !has_key(counts, l) 78 | let counts[l] = 0 79 | endif 80 | let counts[l] += 1 81 | endif 82 | endwhile 83 | return s:summarize(counts, {}, {}) 84 | endfunction 85 | 86 | function! s:summarize(counts, abbrs, usages) abort 87 | let results = [] 88 | for [line, cnt] in sort(items(a:counts), {a, b -> b[1] - a[1]}) 89 | let abbr = get(a:abbrs, line, line)[:g:autoprogramming#maxwidth] 90 | let results += [{ 91 | \ 'word': line, 92 | \ 'abbr': abbr, 93 | \ 'menu': printf('(%d)', cnt), 94 | \ 'info': join(keys(get(a:usages, line, {})), "\n"), 95 | \ }] 96 | endfor 97 | return results 98 | endfunction 99 | 100 | function! s:trim_start(str) abort 101 | return matchstr(a:str,'^\s*\zs.\{-}$') 102 | endfunction 103 | 104 | function! s:shorten(str, i) abort 105 | let str = a:str 106 | let p = '^.\{-1,}\%(\<\|$\)' 107 | for _ in range(a:i) 108 | let str = substitute(str, p, '', '') 109 | endfor 110 | return str 111 | endfunction 112 | 113 | function! s:compl(found, short_query, whole_line) abort 114 | let i = stridx(a:found, a:short_query) 115 | if i > 0 && a:found[i-1] =~# '\k' 116 | return '' 117 | endif 118 | let rest = a:found[i + len(a:short_query):] 119 | if a:whole_line 120 | return rest 121 | endif 122 | return matchstr(rest, '^\s*\(\k\+\|\S\+\)') 123 | endfunction 124 | 125 | if expand('%:p') ==# expand(':p') 126 | setlocal completefunc=autoprogramming#complete 127 | endif 128 | 129 | let &cpo = s:save_cpo 130 | unlet s:save_cpo 131 | " __END__ 132 | " vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker 133 | -------------------------------------------------------------------------------- /autoload/autoprogramming/async.vim: -------------------------------------------------------------------------------- 1 | "============================================================================= 2 | " FILE: autoload/autoprogramming/async.vim 3 | " AUTHOR: haya14busa 4 | " License: MIT license 5 | "============================================================================= 6 | scriptencoding utf-8 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | 11 | let s:job = { 12 | \ 'cmd': [], 13 | \ 'stdout': [], 14 | \ } 15 | 16 | function! autoprogramming#async#new_job(cmd) abort 17 | let job = deepcopy(s:job) 18 | let job.cmd = a:cmd 19 | return job 20 | endfunction 21 | 22 | function! s:job.start() abort 23 | let self.job = job_start(self.cmd, { 24 | \ 'out_cb': self._out_cb, 25 | \ }) 26 | endfunction 27 | 28 | function! s:job.await(...) abort 29 | let l:DoneF = get(a:, 1, {->0}) 30 | while !l:DoneF() && job_status(self.job) ==# "run" 31 | sleep 5ms 32 | endwhile 33 | endfunction 34 | 35 | function! s:job._out_cb(ch, msg) abort 36 | let self.stdout += split(a:msg, "\n") 37 | endfunction 38 | 39 | let &cpo = s:save_cpo 40 | unlet s:save_cpo 41 | " __END__ 42 | " vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker 43 | -------------------------------------------------------------------------------- /doc/auto-programming.txt: -------------------------------------------------------------------------------- 1 | *auto-programming.txt* Statistical complements for git project 2 | 3 | Author : haya14busa 4 | Version : 0.9.0 5 | License : MIT license {{{ 6 | 7 | Copyright (c) 2016 haya14busa 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining 10 | a copy of this software and associated documentation files (the 11 | "Software"), to deal in the Software without restriction, including 12 | without limitation the rights to use, copy, modify, merge, publish, 13 | distribute, sublicense, and/or sell copies of the Software, and to 14 | permit persons to whom the Software is furnished to do so, subject to 15 | the following conditions: 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | 27 | }}} 28 | 29 | ============================================================================== 30 | CONTENTS *auto-programming-contents* 31 | 32 | INTRODUCTION |auto-programming-introduction| 33 | INTERFACE |auto-programming-interface| 34 | FUNCTIONS |auto-programming-functions| 35 | OPTIONS |auto-programming-options| 36 | CHANGELOG |auto-programming-changelog| 37 | 38 | ============================================================================== 39 | INTRODUCTION *auto-programming-introduction* 40 | 41 | *vim-auto-programming* (*auto-programming.vim* ) provide statistical whole 42 | line completions for git project. 43 | It's inspired by https://github.com/hitode909/atom-auto-programming. 44 | 45 | It's like |i_CTRL-X_CTRL-L| and |i_CTRL-X_CTRL-K| but powerd by `git grep`. 46 | 47 | Setup~ 48 | > 49 | set completefunc=autoprogramming#complete 50 | < 51 | Requirements: 52 | - Vim 8.0 or later 53 | - git 54 | 55 | Latest version: 56 | https://github.com/haya14busa/vim-auto-programming 57 | 58 | ============================================================================== 59 | INTERFACE *auto-programming-interface* 60 | ------------------------------------------------------------------------------ 61 | FUNCTIONS *auto-programming-functions* 62 | 63 | autoprogramming#complete *autoprogramming#complete* 64 | Completion function (|complete-functions|) for 'completefunc'. 65 | Complete items includes whole-line oriented completion items like 66 | |compl-whole-line| and keyword or pseudo-omni oriented completion 67 | items collected by `git grep`. The items are sorted by the number of 68 | matched result of grep. It shows whole matched lines in 69 | |preview-window|. It's useful as an usage example of completion items. 70 | > 71 | set completefunc=autoprogramming#complete 72 | < 73 | ============================================================================== 74 | OPTIONS *auto-programming-options* 75 | 76 | g:autoprogramming#maxwidth *g:opengoogletranslate#default_lang* 77 | Max width of abbr length of |complete-items|. Default: 50 78 | 79 | ============================================================================== 80 | CHANGELOG *auto-programming-changelog* 81 | 82 | 0.9.0 2016-11-12 83 | - Init. 84 | 85 | ============================================================================== 86 | vim:tw=78:ts=8:ft=help:norl:noet:fen:fdl=0:fdm=marker: 87 | --------------------------------------------------------------------------------