mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-03-15 19:45:46 +08:00
parent
524ae813ad
commit
e9099b6611
@ -86,7 +86,7 @@ function! SpaceVim#layers#lang#vim#plugins() abort
|
|||||||
" https://github.com/maralla/completor.vim/issues/250
|
" https://github.com/maralla/completor.vim/issues/250
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
call add(plugins,['tweekmonster/helpful.vim', {'on_cmd': 'HelpfulVersion'}])
|
call add(plugins, [g:_spacevim_root_dir . 'bundle/helpful.vim', {'merged' : 0, 'on_cmd' : 'HelpfulVersion'}])
|
||||||
return plugins
|
return plugins
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
29
bundle/helpful.vim/.github/workflows/update-tags.yml
vendored
Normal file
29
bundle/helpful.vim/.github/workflows/update-tags.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
name: Update Tags
|
||||||
|
|
||||||
|
on:
|
||||||
|
# Run at midnight every day
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
name: Update Tags
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: update tags
|
||||||
|
run: make update
|
||||||
|
- name: get date
|
||||||
|
id: date
|
||||||
|
run: echo "::set-output name=date::$(date --rfc-3339=seconds)"
|
||||||
|
- name: check for update
|
||||||
|
id: diff
|
||||||
|
run: echo "::set-output name=diff::$(git diff --name-only data/)"
|
||||||
|
- name: push
|
||||||
|
uses: actions-x/commit@v2
|
||||||
|
with:
|
||||||
|
name: Tag Update Bot
|
||||||
|
files: data/tags doc/helpful-version.txt
|
||||||
|
message: Auto-updated tags ${{ steps.date.outputs.date }}
|
||||||
|
if: ${{ steps.diff.outputs.diff != '' }}
|
92
bundle/helpful.vim/.gitignore
vendored
Normal file
92
bundle/helpful.vim/.gitignore
vendored
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/support/src
|
||||||
|
|
||||||
|
### Python ###
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
env/
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*,cover
|
||||||
|
.hypothesis/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
|
||||||
|
# Flask instance folder
|
||||||
|
instance/
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# IPython Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# dotenv
|
||||||
|
.env
|
||||||
|
|
||||||
|
# virtualenv
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
20
bundle/helpful.vim/LICENSE
Normal file
20
bundle/helpful.vim/LICENSE
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
The MIT License
|
||||||
|
Copyright (c) 2016 Tommy Allen
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
13
bundle/helpful.vim/Makefile
Normal file
13
bundle/helpful.vim/Makefile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.PHONY: update auto
|
||||||
|
|
||||||
|
update:
|
||||||
|
cd support && python difftags.py
|
||||||
|
|
||||||
|
auto:
|
||||||
|
-test "master" = "$$(git rev-parse --abbrev-ref HEAD)" \
|
||||||
|
&& python3 support/difftags.py \
|
||||||
|
&& test " M data/tags" = "$$(git status --porcelain | grep 'data/tags')" \
|
||||||
|
&& git add data doc \
|
||||||
|
&& git commit -m "Auto-updated tags $$(date --rfc-3339=seconds)" \
|
||||||
|
&& git push
|
||||||
|
git checkout -- doc/
|
37
bundle/helpful.vim/README.md
Normal file
37
bundle/helpful.vim/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# helpful.vim
|
||||||
|
|
||||||
|
A plugin for plugin developers to get the version of Vim and Neovim that
|
||||||
|
introduced or removed features.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The command `:HelpfulVersion` takes a Vim pattern to search for helptags and
|
||||||
|
display version information.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```vim
|
||||||
|
" Search for a function
|
||||||
|
:HelpfulVersion matchaddpos()
|
||||||
|
|
||||||
|
" Search for keys
|
||||||
|
:HelpfulVersion <.*>
|
||||||
|
|
||||||
|
" Case-insensitive search
|
||||||
|
:HelpfulVersion f11\c
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
- `b:helpful` - If set to `1`, display version information about the text under
|
||||||
|
the cursor on `CursorMoved` in `help` or `vim` filetypes.
|
||||||
|
- `g:helpful` - Same as above but always on. It's also less humorous to read
|
||||||
|
out loud.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
389
bundle/helpful.vim/autoload/helpful.vim
Normal file
389
bundle/helpful.vim/autoload/helpful.vim
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
let s:base = expand('<sfile>:p:h:h')
|
||||||
|
|
||||||
|
" Text around the word that might produce a match, in order of 'usefulness' to
|
||||||
|
" a developer.
|
||||||
|
let s:ornaments = [
|
||||||
|
\ [':', ''],
|
||||||
|
\ ['', '()'],
|
||||||
|
\ [':func-', ''],
|
||||||
|
\ ["'", "'"],
|
||||||
|
\ ['<', '>'],
|
||||||
|
\ ['@', ''],
|
||||||
|
\ ['"', ''],
|
||||||
|
\ ['hl-', ''],
|
||||||
|
\ ['syn-', ''],
|
||||||
|
\ ['[', ']'],
|
||||||
|
\ ['{', '}'],
|
||||||
|
\ ['+', ''],
|
||||||
|
\ ]
|
||||||
|
|
||||||
|
|
||||||
|
function! s:load_data() abort
|
||||||
|
if exists('s:data')
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let s:data = {}
|
||||||
|
for line in readfile(s:base.'/data/tags')
|
||||||
|
let parts = split(line, "\x07")
|
||||||
|
for flavor in parts[1:]
|
||||||
|
let name = matchstr(flavor, '^[^:]\+')
|
||||||
|
let versions = split(matchstr(flavor, ':\zs.*'), ',', 1)
|
||||||
|
if !has_key(s:data, parts[0])
|
||||||
|
let s:data[parts[0]] = {}
|
||||||
|
endif
|
||||||
|
|
||||||
|
let s:data[parts[0]][name] = {
|
||||||
|
\ '+': versions[0],
|
||||||
|
\ '-': versions[1],
|
||||||
|
\ }
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Wrap a pattern with an outer pattern that matches likely helptag characters.
|
||||||
|
function! s:pattern_wrap(pattern, help) abort
|
||||||
|
let pattern = a:pattern
|
||||||
|
if a:help
|
||||||
|
let tagpattern = '\%(\1\@!.\)*'.pattern.'\%(\1\@!.\)*'
|
||||||
|
return '\%(\([|*]\)\zs'.tagpattern.'\ze\1\)\|'
|
||||||
|
\ .'\%(\zs''[^'']*'.pattern.'[^'']*''\ze\)\|'
|
||||||
|
\ .'\%(\zs\%(:\%(\w\|[-_]\)\)\?<[^<>]*'.pattern.'[^<>]*>\ze\)\|'
|
||||||
|
\ .'\%(\zs\[[^\[\]]*'.pattern.'[^\[\]]*\]\ze\)\|'
|
||||||
|
\ .'\%(\zs{[^{}]*'.pattern.'[^{}]*}\ze\)\|'
|
||||||
|
\ .'\zs\%(\k\|[_-]\)*'.pattern.'\%(\k\|[_-]\)*\ze('
|
||||||
|
endif
|
||||||
|
let word_atom = '\%(\w\|[&:_@#{}/\+-]\)*'
|
||||||
|
return word_atom.pattern.word_atom
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Get the word under the cursor.
|
||||||
|
" <cword> and <cWORD> aren't reliable for helpful.vim
|
||||||
|
function! s:cword() abort
|
||||||
|
let pattern = s:pattern_wrap('\%'.col('.').'c', &filetype == 'help')
|
||||||
|
let word = matchstr(getline('.'), pattern)
|
||||||
|
|
||||||
|
if &filetype == 'help'
|
||||||
|
return word
|
||||||
|
endif
|
||||||
|
|
||||||
|
if word =~# '^!'
|
||||||
|
let word = word[1:]
|
||||||
|
endif
|
||||||
|
|
||||||
|
if empty(word)
|
||||||
|
return ''
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Force a match on <Key> tags, but make an exception for :map-<whatever>
|
||||||
|
if word !~# '^:' && word =~# '<.*>'
|
||||||
|
let word = matchstr(word, '<[^>]\+>')
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Find some clues about the text under the cursor.
|
||||||
|
if word =~# '^&l:'
|
||||||
|
let word = "'".word[3:]."'"
|
||||||
|
elseif word =~# '^&'
|
||||||
|
let word = "'".word[1:]."'"
|
||||||
|
elseif word =~# '^end.'
|
||||||
|
let word = word[3:]
|
||||||
|
endif
|
||||||
|
|
||||||
|
return word
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Find the best match for a helptag. Oranments are put around the the tag if
|
||||||
|
" there's no first match. If there is no match, return an empty string.
|
||||||
|
function! s:match_word(word) abort
|
||||||
|
call s:load_data()
|
||||||
|
|
||||||
|
if has_key(s:data, a:word)
|
||||||
|
return a:word
|
||||||
|
endif
|
||||||
|
|
||||||
|
for [t1, t2] in s:ornaments
|
||||||
|
if has_key(s:data, t1.a:word.t2)
|
||||||
|
return t1.a:word.t2
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
return ''
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:helptag_version(word, ...) abort
|
||||||
|
let word = a:word
|
||||||
|
|
||||||
|
if !exists('b:_helpful_word') || b:_helpful_word[0] != word
|
||||||
|
let word = s:match_word(word)
|
||||||
|
if empty(word)
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let info = s:data[word]
|
||||||
|
let b:_helpful_word = [a:word, word, info]
|
||||||
|
else
|
||||||
|
let word = b:_helpful_word[1]
|
||||||
|
let info = b:_helpful_word[2]
|
||||||
|
endif
|
||||||
|
|
||||||
|
let keys = has('nvim') ? ['neovim', 'vim'] : ['vim', 'neovim']
|
||||||
|
|
||||||
|
if !a:0
|
||||||
|
redraw
|
||||||
|
endif
|
||||||
|
|
||||||
|
echohl Special
|
||||||
|
echo printf('%*S', a:0 ? a:1 : 0, word)
|
||||||
|
echohl None
|
||||||
|
|
||||||
|
for k in keys
|
||||||
|
if !has_key(info, k) || (empty(info[k]['+']) && empty(info[k]['-']))
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
|
||||||
|
echon ' | '
|
||||||
|
echon k.': '
|
||||||
|
|
||||||
|
if !empty(info[k]['+'])
|
||||||
|
echohl DiffAdd
|
||||||
|
echon '+'.info[k]['+']
|
||||||
|
echohl None
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !empty(info[k]['-'])
|
||||||
|
if !empty(info[k]['+'])
|
||||||
|
echon ', '
|
||||||
|
endif
|
||||||
|
echohl DiffDelete
|
||||||
|
echon '-'.info[k]['-']
|
||||||
|
echohl None
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Find a helptag using a word under the cursor
|
||||||
|
function! helpful#cursor_word() abort
|
||||||
|
if mode() ==? 'v'
|
||||||
|
" Need to save the original visual marks? Visual marks aren't updated
|
||||||
|
" until visual mode is left.
|
||||||
|
let view = winsaveview()
|
||||||
|
let v1 = getpos("'<")
|
||||||
|
let v2 = getpos("'>")
|
||||||
|
|
||||||
|
execute "normal! \<esc>gv"
|
||||||
|
|
||||||
|
let p1 = getpos("'<")[1:2]
|
||||||
|
let p2 = getpos("'>")[1:2]
|
||||||
|
|
||||||
|
call winrestview(view)
|
||||||
|
call setpos("'<", v1)
|
||||||
|
call setpos("'>", v2)
|
||||||
|
|
||||||
|
if p1[0] != p2[0]
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
let word = getline(p1[0])[p1[1]-1:p2[1]-1]
|
||||||
|
else
|
||||||
|
let word = s:cword()
|
||||||
|
endif
|
||||||
|
|
||||||
|
if empty(word)
|
||||||
|
echo ''
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:helptag_version(word)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Normalize Vim's goofy old versions so they can be compared with the other
|
||||||
|
" versions.
|
||||||
|
"
|
||||||
|
" Where M = major, m = minor, R = rev, A = alpha
|
||||||
|
" MmRRRRA
|
||||||
|
"
|
||||||
|
" Vim:
|
||||||
|
" 7.4.300 = 7403000
|
||||||
|
" 7.2.1234 = 7212340
|
||||||
|
" 7.1a = 7100001
|
||||||
|
"
|
||||||
|
" Neovim:
|
||||||
|
" 0.1.3 = 100030
|
||||||
|
" 1.0.1 = 1000010
|
||||||
|
" 2.5.22 = 2500220
|
||||||
|
function! s:parse_version(version) abort
|
||||||
|
let vparts = split(matchstr(a:version, '\d.*'), '\.')
|
||||||
|
if empty(vparts)
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
let major = str2nr(vparts[0])
|
||||||
|
let minor = 0
|
||||||
|
let alpha = 0
|
||||||
|
let rev = 0
|
||||||
|
|
||||||
|
if vparts[1] =~ '\D'
|
||||||
|
let minor = str2nr(matchstr(vparts[1], '\d'))
|
||||||
|
let alpha = char2nr(tolower(matchstr(vparts[1], '\D'))) - 96
|
||||||
|
elseif len(vparts) == 2 && vparts[1] =~# '\d\{4}'
|
||||||
|
let minor = 0
|
||||||
|
let rev = str2nr(vparts[1])
|
||||||
|
else
|
||||||
|
let minor = str2nr(vparts[1])
|
||||||
|
endif
|
||||||
|
|
||||||
|
if len(vparts) > 2
|
||||||
|
let rev = str2nr(vparts[2])
|
||||||
|
endif
|
||||||
|
|
||||||
|
return major * 1000000 +
|
||||||
|
\ minor * 100000 +
|
||||||
|
\ rev * 10 +
|
||||||
|
\ alpha
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Reverses the result of s:parse_version()
|
||||||
|
function! s:unparse_version(version) abort
|
||||||
|
if !a:version || a:version == 99999999
|
||||||
|
return '???'
|
||||||
|
endif
|
||||||
|
|
||||||
|
let v = a:version
|
||||||
|
let major = a:version / 1000000
|
||||||
|
let v -= major * 1000000
|
||||||
|
let minor = v / 100000
|
||||||
|
let v -= minor * 100000
|
||||||
|
let rev = v / 10
|
||||||
|
let v -= rev * 10
|
||||||
|
|
||||||
|
if v
|
||||||
|
return printf('v%d.%d%s', major, minor, nr2char(v + 96))
|
||||||
|
elseif major == 7 && minor == 0
|
||||||
|
return printf('v%d.0%03d', major, rev)
|
||||||
|
endif
|
||||||
|
|
||||||
|
return printf('v%d.%d.%0*d', major, minor, major >= 7 ? 3 : 0, rev)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:_lookup_sort(a, b) abort
|
||||||
|
if a:a[1] < a:b[1]
|
||||||
|
return -1
|
||||||
|
elseif a:a[1] > a:b[1]
|
||||||
|
return 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
let al = strlen(a:a[0])
|
||||||
|
let bl = strlen(a:b[0])
|
||||||
|
|
||||||
|
if al < bl
|
||||||
|
return -1
|
||||||
|
elseif al > bl
|
||||||
|
return 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
return 0
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Find helptag using a pattern and print the results.
|
||||||
|
function! helpful#lookup(pattern) abort
|
||||||
|
call s:load_data()
|
||||||
|
let tags = []
|
||||||
|
let width = 0
|
||||||
|
|
||||||
|
for tag in keys(s:data)
|
||||||
|
let m = match(tag, a:pattern)
|
||||||
|
if m != -1
|
||||||
|
call add(tags, [tag, m])
|
||||||
|
let width = max([width, strlen(tag)])
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
let s:search_pattern = a:pattern
|
||||||
|
for [tag, _] in sort(tags, 's:_lookup_sort')
|
||||||
|
call s:helptag_version(tag, width)
|
||||||
|
endfor
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:min_pair(x, y) abort
|
||||||
|
return a:x[0] < a:y[0] ? a:x : a:y
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:max_pair(x, y) abort
|
||||||
|
return a:x[0] > a:y[0] ? a:x : a:y
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Find functions in the buffer and print min and max versions that are
|
||||||
|
" required. Only a proof of concept, there is no plan for it to be smarter.
|
||||||
|
function! helpful#buffer_version() abort
|
||||||
|
call s:load_data()
|
||||||
|
|
||||||
|
let view = winsaveview()
|
||||||
|
let s = @/
|
||||||
|
let b = getreg('b')
|
||||||
|
let bt = getregtype('b')
|
||||||
|
normal! qbq
|
||||||
|
silent g/\k\+(/normal! gn"By
|
||||||
|
let @/ = s
|
||||||
|
call histdel('search', -1)
|
||||||
|
|
||||||
|
let funcs = map(split(getreg('b'), '('), 'v:val."()"')
|
||||||
|
call setreg('b', b, bt)
|
||||||
|
call winrestview(view)
|
||||||
|
|
||||||
|
let neovim_min = [0, '']
|
||||||
|
let neovim_max = [99999999, '']
|
||||||
|
let vim_min = [0, '']
|
||||||
|
let vim_max = [99999999, '']
|
||||||
|
|
||||||
|
for f in funcs
|
||||||
|
if has_key(s:data, f)
|
||||||
|
let vinfo = s:data[f]
|
||||||
|
|
||||||
|
if has_key(vinfo, 'neovim')
|
||||||
|
let neovim_max = s:min_pair(neovim_max,
|
||||||
|
\ [s:parse_version(vinfo['neovim']['-']), f])
|
||||||
|
let neovim_min = s:max_pair(neovim_min,
|
||||||
|
\ [s:parse_version(vinfo['neovim']['+']), f])
|
||||||
|
endif
|
||||||
|
|
||||||
|
if has_key(vinfo, 'vim')
|
||||||
|
let vim_max = s:min_pair(vim_max,
|
||||||
|
\ [s:parse_version(vinfo['vim']['-']), f])
|
||||||
|
let vim_min = s:max_pair(vim_min,
|
||||||
|
\ [s:parse_version(vinfo['vim']['+']), f])
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
echo printf('Neovim: %s (%s) - %s (%s)',
|
||||||
|
\ s:unparse_version(neovim_min[0]), neovim_min[1],
|
||||||
|
\ s:unparse_version(neovim_max[0]), neovim_max[1])
|
||||||
|
echo printf('Vim: %s (%s) - %s (%s)',
|
||||||
|
\ s:unparse_version(vim_min[0]), vim_min[1],
|
||||||
|
\ s:unparse_version(vim_max[0]), vim_max[1])
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:enabled() abort
|
||||||
|
return get(b:, 'helpful', get(g:, 'helpful', 0))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! helpful#setup() abort
|
||||||
|
augroup helpful
|
||||||
|
autocmd! * <buffer>
|
||||||
|
autocmd CursorMoved <buffer> if s:enabled() | call helpful#cursor_word() | endif
|
||||||
|
augroup END
|
||||||
|
endfunction
|
58712
bundle/helpful.vim/doc/helpful-version.txt
Normal file
58712
bundle/helpful.vim/doc/helpful-version.txt
Normal file
File diff suppressed because it is too large
Load Diff
5
bundle/helpful.vim/plugin/helpful.vim
Normal file
5
bundle/helpful.vim/plugin/helpful.vim
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
augroup help_versions
|
||||||
|
autocmd! FileType vim,help call helpful#setup()
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
command! -nargs=+ -complete=help HelpfulVersion call helpful#lookup(<q-args>)
|
9429
bundle/helpful.vim/plugin/tags.txt
Normal file
9429
bundle/helpful.vim/plugin/tags.txt
Normal file
File diff suppressed because it is too large
Load Diff
4
bundle/helpful.vim/support/README.md
Normal file
4
bundle/helpful.vim/support/README.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Attention!
|
||||||
|
|
||||||
|
You do not need to run `difftags.py` yourself. It is a utility for keeping
|
||||||
|
this repo up to date.
|
200
bundle/helpful.vim/support/difftags.py
Normal file
200
bundle/helpful.vim/support/difftags.py
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from datetime import date, datetime
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
base = os.path.dirname(__file__)
|
||||||
|
src = os.path.abspath(os.path.join(base, 'src'))
|
||||||
|
repos = {
|
||||||
|
'neovim': 'https://github.com/neovim/neovim.git',
|
||||||
|
'vim': 'https://github.com/vim/vim.git',
|
||||||
|
}
|
||||||
|
|
||||||
|
neovim_repo = os.path.join(src, 'neovim')
|
||||||
|
vim_repo = os.path.join(src, 'vim')
|
||||||
|
|
||||||
|
_tag_re = re.compile(br'\s\*([^*\s]+)\*\s')
|
||||||
|
|
||||||
|
if not os.path.isdir(src):
|
||||||
|
os.makedirs(os.path.join(src))
|
||||||
|
|
||||||
|
|
||||||
|
def command(cmd, print_stdout=False, print_stderr=True, cwd=None):
|
||||||
|
"""Run a git command and return the stdout as lines.
|
||||||
|
|
||||||
|
The stdout is returned as bytes in case a diff breaks up unicode bytes.
|
||||||
|
"""
|
||||||
|
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE, cwd=cwd)
|
||||||
|
stdout, stderr = p.communicate()
|
||||||
|
|
||||||
|
if print_stdout and stdout:
|
||||||
|
print(stdout.decode('utf8'))
|
||||||
|
|
||||||
|
if print_stderr and stderr:
|
||||||
|
print(cmd, stderr.decode('utf8'), file=sys.stderr)
|
||||||
|
|
||||||
|
return list(filter(None, stdout.split(b'\n')))
|
||||||
|
|
||||||
|
|
||||||
|
def get_latest(repo):
|
||||||
|
path = os.path.join(src, repo)
|
||||||
|
if os.path.exists(path):
|
||||||
|
return command(['git', 'fetch', '-q', '--tags', repos.get(repo),
|
||||||
|
'master:master'], True, cwd=path)
|
||||||
|
else:
|
||||||
|
return command(['git', 'clone', '-q', '--bare', '--single-branch',
|
||||||
|
repos.get(repo), path], True)
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_hunk(lines):
|
||||||
|
"""Normalize a hunk to give ample whitespace between tag delimiters.
|
||||||
|
|
||||||
|
Also cleans out garbage whitespace
|
||||||
|
"""
|
||||||
|
out = b' '
|
||||||
|
for line in lines:
|
||||||
|
out += re.sub(br'\s', b' ', line[1:]).replace(b'* *', b'* *') + b' '
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def doc_diff(path, a, b):
|
||||||
|
"""Parse diff lines to get tags
|
||||||
|
|
||||||
|
A counter is used to keep track of the additions and deletions.
|
||||||
|
"""
|
||||||
|
tags = defaultdict(int)
|
||||||
|
if not a or not b:
|
||||||
|
cmd = ['git', 'show', '-U0', '--oneline', a or b, '--',
|
||||||
|
'runtime/doc/*.txt']
|
||||||
|
else:
|
||||||
|
cmd = ['git', 'diff', '-U0', a, b, '--', 'runtime/doc/*.txt']
|
||||||
|
stdout = command(cmd, cwd=path)
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
while i < len(stdout):
|
||||||
|
line = stdout[i]
|
||||||
|
i += 1
|
||||||
|
if line[:2] != b'@@':
|
||||||
|
continue
|
||||||
|
|
||||||
|
delta = line.split()
|
||||||
|
deleted = 1
|
||||||
|
added = 1
|
||||||
|
if b',' in delta[1]:
|
||||||
|
deleted = int(delta[1].split(b',')[-1])
|
||||||
|
if b',' in delta[2]:
|
||||||
|
added = int(delta[2].split(b',')[-1])
|
||||||
|
|
||||||
|
if deleted > 0:
|
||||||
|
for t in _tag_re.findall(normalize_hunk(stdout[i:i+deleted])):
|
||||||
|
tags[t] -= 1
|
||||||
|
i += deleted
|
||||||
|
|
||||||
|
if added > 0:
|
||||||
|
for t in _tag_re.findall(normalize_hunk(stdout[i:i+added])):
|
||||||
|
tags[t] += 1
|
||||||
|
i += added
|
||||||
|
|
||||||
|
return tags
|
||||||
|
|
||||||
|
|
||||||
|
def repo_tags(path):
|
||||||
|
"""Get tags that can be diff'd."""
|
||||||
|
stdout = command(['git', 'log', '--pretty=oneline'], cwd=path)
|
||||||
|
first = stdout[-1].decode('utf8').split()[0]
|
||||||
|
last = stdout[0].decode('utf8').split()[0]
|
||||||
|
|
||||||
|
cmd = ['git', 'for-each-ref',
|
||||||
|
"--format=%(*committerdate:raw)%(committerdate:raw) %(refname) %(objectname)",
|
||||||
|
'refs/tags']
|
||||||
|
|
||||||
|
tags = [('alpha', first, None)]
|
||||||
|
stdout = command(cmd, print_stderr=False, cwd=path)
|
||||||
|
for line in sorted(stdout, key=lambda x: x.split()[0]):
|
||||||
|
parts = line.decode('utf8').split()
|
||||||
|
timestamp, tz = parts[:2]
|
||||||
|
tag_date = date.fromtimestamp(int(timestamp))
|
||||||
|
tag, ref = parts[-2:]
|
||||||
|
tag = tag.split('/')[-1]
|
||||||
|
if tag.startswith('untagged-'):
|
||||||
|
continue
|
||||||
|
tags.append((tag, ref, tag_date))
|
||||||
|
tags.append(('dev', last, None))
|
||||||
|
tags.append(('dev', 'HEAD', None))
|
||||||
|
|
||||||
|
return tags
|
||||||
|
|
||||||
|
|
||||||
|
def collect(repo):
|
||||||
|
"""Collects the helptag differences between versions."""
|
||||||
|
path = os.path.join(src, repo)
|
||||||
|
|
||||||
|
tags = repo_tags(path)
|
||||||
|
versions = defaultdict(lambda: {'added': [], 'removed': []})
|
||||||
|
|
||||||
|
for i in range(len(tags) - 1):
|
||||||
|
helptags = doc_diff(path, tags[i][1], tags[i+1][1])
|
||||||
|
version = versions[tags[i+1][0]]
|
||||||
|
for k, v in helptags.items():
|
||||||
|
if v < 0:
|
||||||
|
version['removed'].append(k)
|
||||||
|
elif v > 0:
|
||||||
|
version['added'].append(k)
|
||||||
|
|
||||||
|
return [(info, versions[info[0]]) for info in tags]
|
||||||
|
|
||||||
|
|
||||||
|
def generate():
|
||||||
|
"""Generate the data file for the plugin.
|
||||||
|
|
||||||
|
All byte strings from here.
|
||||||
|
"""
|
||||||
|
get_latest('neovim')
|
||||||
|
get_latest('vim')
|
||||||
|
|
||||||
|
tags = defaultdict(lambda: defaultdict(lambda: defaultdict(bytes)))
|
||||||
|
|
||||||
|
for target in (b'neovim', b'vim'):
|
||||||
|
for (version, ref, tag_date), deltas in collect(target.decode('ascii')):
|
||||||
|
for change, items in deltas.items():
|
||||||
|
for item in items:
|
||||||
|
tags[item][target][change] = version.encode('ascii')
|
||||||
|
|
||||||
|
with open(os.path.join(base, '..', 'data', 'tags'), 'wb') as fp:
|
||||||
|
with open(os.path.join(base, '..', 'doc',
|
||||||
|
'helpful-version.txt'), 'wb') as hfp:
|
||||||
|
|
||||||
|
hfp.write(b'*helpful-version.txt* Generated: ' +
|
||||||
|
str(datetime.utcnow().replace(microsecond=0))
|
||||||
|
.encode('utf8') + b' UTC')
|
||||||
|
hfp.write(b'\n\n')
|
||||||
|
hfp.write(b'A listing of helptags with the versions they became '
|
||||||
|
b'available or were removed.\n\n')
|
||||||
|
|
||||||
|
for helptag, targets in sorted(tags.items(), key=lambda x: x[0]):
|
||||||
|
# Not creating new tags since it adds too much noise to help
|
||||||
|
# completion.
|
||||||
|
hfp.write(b'\n|' + helptag + b'|\n\n')
|
||||||
|
|
||||||
|
target_versions = []
|
||||||
|
for target, versions in sorted(targets.items(), key=lambda x: x[0]):
|
||||||
|
hfp.write(b' ' + target.title().rjust(8) + b': ')
|
||||||
|
if versions['added']:
|
||||||
|
hfp.write(b'+' + versions['added'] + b' ')
|
||||||
|
if versions['removed']:
|
||||||
|
hfp.write(b'-' + versions['removed'] + b' ')
|
||||||
|
hfp.write(b'\n')
|
||||||
|
|
||||||
|
target_versions.append(target + b':' +
|
||||||
|
versions['added'] + b',' +
|
||||||
|
versions['removed'])
|
||||||
|
fp.write(b'\x07'.join([helptag] + target_versions))
|
||||||
|
fp.write(b'\n')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
generate()
|
Loading…
x
Reference in New Issue
Block a user