mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-23 07:20:04 +08:00
Add bundle dir (#3542)
This commit is contained in:
parent
06c7cc740a
commit
aebee1b28b
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@ doc/tags-cn
|
||||
wiki/.git
|
||||
*.class
|
||||
.floo
|
||||
*.pyc
|
||||
.flooignore
|
||||
*.netrwhist
|
||||
*-rplugin~
|
||||
|
@ -149,6 +149,7 @@ For more features, please read [SpaceVim's Blog](https://spacevim.org/blog/)
|
||||
├─ docs/ website(cn/en)
|
||||
├─ wiki/ wiki(cn/en)
|
||||
├─ bin/ executable
|
||||
├─ bundle/ forked repos
|
||||
└─ test/ tests
|
||||
```
|
||||
|
||||
|
@ -70,6 +70,7 @@ function! SpaceVim#autocmds#init() abort
|
||||
augroup END
|
||||
endfunction
|
||||
|
||||
let g:_spacevim_cursorline_flag = -1
|
||||
function! s:enable_cursorline() abort
|
||||
if g:_spacevim_cursorline_flag == -1
|
||||
setl cursorline
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
function! SpaceVim#layers#autocomplete#plugins() abort
|
||||
let plugins = [
|
||||
\ ['honza/vim-snippets', { 'on_event' : 'InsertEnter', 'loadconf_before' : 1}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-snippets', { 'on_event' : 'InsertEnter', 'loadconf_before' : 1}],
|
||||
\ ['Shougo/neco-syntax', { 'on_event' : 'InsertEnter'}],
|
||||
\ ['Shougo/context_filetype.vim', { 'on_event' : 'InsertEnter'}],
|
||||
\ ['Shougo/neoinclude.vim', { 'on_event' : 'InsertEnter'}],
|
||||
|
@ -18,7 +18,7 @@ function! SpaceVim#layers#checkers#plugins() abort
|
||||
let plugins = []
|
||||
|
||||
if g:spacevim_enable_neomake && g:spacevim_enable_ale == 0
|
||||
call add(plugins, ['neomake/neomake', {'merged' : 0, 'loadconf' : 1 , 'loadconf_before' : 1}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/neomake', {'merged' : 0, 'loadconf' : 1 , 'loadconf_before' : 1}])
|
||||
elseif g:spacevim_enable_ale
|
||||
call add(plugins, ['dense-analysis/ale', {'merged' : 0, 'loadconf_before' : 1}])
|
||||
else
|
||||
|
@ -11,40 +11,40 @@ let s:SYS = SpaceVim#api#import('system')
|
||||
function! SpaceVim#layers#core#plugins() abort
|
||||
let plugins = []
|
||||
if g:spacevim_filemanager ==# 'nerdtree'
|
||||
call add(plugins, ['scrooloose/nerdtree', { 'merged' : 0,
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/nerdtree', { 'merged' : 0,
|
||||
\ 'loadconf' : 1}])
|
||||
elseif g:spacevim_filemanager ==# 'vimfiler'
|
||||
call add(plugins, ['Shougo/vimfiler.vim',{
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/vimfiler.vim',{
|
||||
\ 'merged' : 0,
|
||||
\ 'loadconf' : 1 ,
|
||||
\ 'loadconf_before' : 1,
|
||||
\ 'on_cmd' : ['VimFiler', 'VimFilerBufferDir']
|
||||
\ }])
|
||||
call add(plugins, ['Shougo/unite.vim',{
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/unite.vim',{
|
||||
\ 'merged' : 0,
|
||||
\ 'loadconf' : 1
|
||||
\ }])
|
||||
call add(plugins, ['Shougo/vimproc.vim', {'build' : [(executable('gmake') ? 'gmake' : 'make')]}])
|
||||
elseif g:spacevim_filemanager ==# 'defx'
|
||||
call add(plugins, ['Shougo/defx.nvim',{'merged' : 0, 'loadconf' : 1 , 'loadconf_before' : 1}])
|
||||
call add(plugins, ['kristijanhusak/defx-git',{'merged' : 0, 'loadconf' : 1}])
|
||||
call add(plugins, ['kristijanhusak/defx-icons',{'merged' : 0}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/defx.nvim',{'merged' : 0, 'loadconf' : 1 , 'loadconf_before' : 1}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/defx-git',{'merged' : 0, 'loadconf' : 1}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/defx-icons',{'merged' : 0}])
|
||||
endif
|
||||
|
||||
if !g:spacevim_vimcompatible
|
||||
call add(plugins, ['rhysd/clever-f.vim', {'merged' : 0}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/clever-f.vim', {'merged' : 0}])
|
||||
endif
|
||||
call add(plugins, ['scrooloose/nerdcommenter', { 'loadconf' : 1, 'merged' : 0}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/nerdcommenter', { 'loadconf' : 1, 'merged' : 0}])
|
||||
|
||||
if exists('*matchaddpos')
|
||||
call add(plugins, ['andymass/vim-matchup', {'merged' : 0}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/vim-matchup', {'merged' : 0}])
|
||||
endif
|
||||
call add(plugins, ['gruvbox-community/gruvbox', {'loadconf' : 1, 'merged' : 0}])
|
||||
call add(plugins, ['tyru/open-browser.vim', {
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/gruvbox', {'loadconf' : 1, 'merged' : 0}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/open-browser.vim', {
|
||||
\ 'merged' : 0,
|
||||
\ 'loadconf' : 1,
|
||||
\}])
|
||||
call add(plugins, ['mhinz/vim-grepper' , { 'on_cmd' : 'Grepper',
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/vim-grepper' , { 'on_cmd' : 'Grepper',
|
||||
\ 'loadconf' : 1} ])
|
||||
return plugins
|
||||
endfunction
|
||||
|
@ -15,28 +15,28 @@ let s:VIM = SpaceVim#api#import('vim')
|
||||
|
||||
function! SpaceVim#layers#edit#plugins() abort
|
||||
let plugins = [
|
||||
\ ['tpope/vim-surround'],
|
||||
\ ['tpope/vim-repeat'],
|
||||
\ ['junegunn/vim-emoji'],
|
||||
\ ['terryma/vim-expand-region', { 'loadconf' : 1}],
|
||||
\ ['kana/vim-textobj-user'],
|
||||
\ ['kana/vim-textobj-indent'],
|
||||
\ ['kana/vim-textobj-line'],
|
||||
\ ['dhruvasagar/vim-table-mode'],
|
||||
\ ['kana/vim-textobj-entire'],
|
||||
\ ['gcmt/wildfire.vim',{'on_map' : '<Plug>(wildfire-'}],
|
||||
\ ['easymotion/vim-easymotion'],
|
||||
\ ['haya14busa/vim-easyoperator-line'],
|
||||
\ ['editorconfig/editorconfig-vim', { 'merged' : 0, 'if' : has('python') || has('python3')}],
|
||||
\ ['osyo-manga/vim-jplus', { 'on_map' : '<Plug>(jplus' }],
|
||||
\ ['godlygeek/tabular', { 'merged' : 0}],
|
||||
\ ['ntpeters/vim-better-whitespace', { 'on_cmd' : ['StripWhitespace', 'ToggleWhitespace', 'DisableWhitespace', 'EnableWhitespace']}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-surround'],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-repeat'],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-emoji'],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-expand-region', { 'loadconf' : 1}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-textobj-user'],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-textobj-indent'],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-textobj-line'],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-table-mode'],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-textobj-entire'],
|
||||
\ [g:_spacevim_root_dir . 'bundle/wildfire.vim',{'on_map' : '<Plug>(wildfire-'}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-easymotion'],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-easyoperator-line'],
|
||||
\ [g:_spacevim_root_dir . 'bundle/editorconfig-vim', { 'merged' : 0, 'if' : has('python') || has('python3')}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/evim-jplus', { 'on_map' : '<Plug>(jplus' }],
|
||||
\ [g:_spacevim_root_dir . 'bundle/tabular', { 'merged' : 0}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-better-whitespace', { 'on_cmd' : ['StripWhitespace', 'ToggleWhitespace', 'DisableWhitespace', 'EnableWhitespace']}],
|
||||
\ ]
|
||||
if executable('fcitx')
|
||||
call add(plugins,['lilydjwg/fcitx.vim', { 'on_event' : 'InsertEnter'}])
|
||||
call add(plugins,[g:_spacevim_root_dir . 'bundle/fcitx.vim', { 'on_event' : 'InsertEnter'}])
|
||||
endif
|
||||
if g:spacevim_enable_bepo_layout
|
||||
call add(plugins,['michamos/vim-bepo', { 'merged' : 0}])
|
||||
call add(plugins,[g:_spacevim_root_dir . 'bundle/vim-bepo', { 'merged' : 0}])
|
||||
endif
|
||||
return plugins
|
||||
endfunction
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
function! SpaceVim#layers#format#plugins() abort
|
||||
return [
|
||||
\ ['neoformat/neoformat', {'merged' : 0, 'loadconf' : 1 , 'loadconf_before' : 1}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/neoformat', {'merged' : 0, 'loadconf' : 1 , 'loadconf_before' : 1}],
|
||||
\ ]
|
||||
endfunction
|
||||
|
||||
|
@ -9,17 +9,17 @@
|
||||
scriptencoding utf-8
|
||||
function! SpaceVim#layers#ui#plugins() abort
|
||||
let plugins = [
|
||||
\ ['Yggdroot/indentLine', {'merged' : 0}],
|
||||
\ ['wsdjeg/tagbar', {'loadconf' : 1, 'merged' : 0}],
|
||||
\ ['tenfyzhong/tagbar-makefile.vim', {'merged': 0}],
|
||||
\ ['tenfyzhong/tagbar-proto.vim', {'merged': 0}],
|
||||
\ ['t9md/vim-choosewin', {'merged' : 0}],
|
||||
\ ['mhinz/vim-startify', {'loadconf' : 1, 'merged' : 0}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/indentLine', {'merged' : 0}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/tagbar', {'loadconf' : 1, 'merged' : 0}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/tagbar-makefile.vim', {'merged': 0}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/tagbar-proto.vim', {'merged': 0}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-choosewin', {'merged' : 0}],
|
||||
\ [g:_spacevim_root_dir . 'bundle/vim-startify', {'loadconf' : 1, 'merged' : 0}],
|
||||
\ ]
|
||||
if !SpaceVim#layers#isLoaded('core#statusline')
|
||||
call add(plugins, ['vim-airline/vim-airline', { 'merged' : 0,
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/vim-airline', { 'merged' : 0,
|
||||
\ 'loadconf' : 1}])
|
||||
call add(plugins, ['vim-airline/vim-airline-themes', { 'merged' : 0}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/vim-airline-themes', { 'merged' : 0}])
|
||||
endif
|
||||
|
||||
return plugins
|
||||
@ -259,7 +259,6 @@ function! s:toggle_win_fringe() abort
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let g:_spacevim_cursorline_flag = -1
|
||||
function! s:toggle_cursorline() abort
|
||||
setl cursorline!
|
||||
let g:_spacevim_cursorline_flag = g:_spacevim_cursorline_flag * -1
|
||||
|
@ -140,28 +140,8 @@ function! s:install_manager() abort
|
||||
\ . fnameescape(g:spacevim_plugin_bundle_dir)
|
||||
\ . 'neobundle.vim'
|
||||
elseif g:spacevim_plugin_manager ==# 'dein'
|
||||
"auto install dein
|
||||
if filereadable(expand(g:spacevim_plugin_bundle_dir)
|
||||
\ . join(['repos', 'github.com',
|
||||
\ 'Shougo', 'dein.vim', 'README.md'],
|
||||
\ s:Fsep))
|
||||
let g:_spacevim_dein_installed = 1
|
||||
else
|
||||
if executable('git')
|
||||
exec '!git clone https://github.com/Shougo/dein.vim "'
|
||||
\ . expand(g:spacevim_plugin_bundle_dir)
|
||||
\ . join(['repos', 'github.com',
|
||||
\ 'Shougo', 'dein.vim"'], s:Fsep)
|
||||
let g:_spacevim_dein_installed = 1
|
||||
else
|
||||
echohl WarningMsg
|
||||
echom 'You need install git!'
|
||||
echohl None
|
||||
endif
|
||||
endif
|
||||
exec 'set runtimepath+='. fnameescape(g:spacevim_plugin_bundle_dir)
|
||||
\ . join(['repos', 'github.com', 'Shougo',
|
||||
\ 'dein.vim'], s:Fsep)
|
||||
let g:_spacevim_dein_installed = 1
|
||||
exec 'set runtimepath+=' . g:_spacevim_root_dir . 'bundle/dein.vim/'
|
||||
elseif g:spacevim_plugin_manager ==# 'vim-plug'
|
||||
"auto install vim-plug
|
||||
if filereadable(expand(g:spacevim_data_dir.'/vim-plug/autoload/plug.vim'))
|
||||
@ -184,9 +164,8 @@ function! s:install_manager() abort
|
||||
endif
|
||||
endf
|
||||
|
||||
if get(g:,'spacevim_enable_plugins', 1)
|
||||
call s:install_manager()
|
||||
endif
|
||||
call s:install_manager()
|
||||
|
||||
|
||||
function! SpaceVim#plugins#begin(path) abort
|
||||
let g:unite_source_menu_menus.AddedPlugins =
|
||||
|
@ -417,28 +417,32 @@ endfunction
|
||||
function! s:pull(repo) abort
|
||||
let s:pct += 1
|
||||
let s:ui_buf[a:repo.name] = s:pct
|
||||
let argv = ['git', 'pull', '--progress']
|
||||
if s:JOB.vim_job || s:JOB.nvim_job
|
||||
let jobid = s:JOB.start(argv,{
|
||||
\ 'on_stderr' : function('s:on_install_stdout'),
|
||||
\ 'cwd' : a:repo.path,
|
||||
\ 'on_exit' : function('s:on_pull_exit')
|
||||
\ })
|
||||
if jobid != 0
|
||||
let s:pulling_repos[jobid] = a:repo
|
||||
if !get(a:repo, 'local', 0)
|
||||
let argv = ['git', 'pull', '--progress']
|
||||
if s:JOB.vim_job || s:JOB.nvim_job
|
||||
let jobid = s:JOB.start(argv,{
|
||||
\ 'on_stderr' : function('s:on_install_stdout'),
|
||||
\ 'cwd' : a:repo.path,
|
||||
\ 'on_exit' : function('s:on_pull_exit')
|
||||
\ })
|
||||
if jobid != 0
|
||||
let s:pulling_repos[jobid] = a:repo
|
||||
call s:msg_on_start(a:repo.name)
|
||||
endif
|
||||
else
|
||||
let s:jobpid += 1
|
||||
let s:pulling_repos[s:jobpid] = a:repo
|
||||
call s:msg_on_start(a:repo.name)
|
||||
redraw!
|
||||
call s:JOB.start(argv,{
|
||||
\ 'on_stderr' : function('s:on_install_stdout'),
|
||||
\ 'cwd' : a:repo.path,
|
||||
\ 'on_exit' : function('s:on_pull_exit')
|
||||
\ })
|
||||
|
||||
endif
|
||||
else
|
||||
let s:jobpid += 1
|
||||
let s:pulling_repos[s:jobpid] = a:repo
|
||||
call s:msg_on_start(a:repo.name)
|
||||
redraw!
|
||||
call s:JOB.start(argv,{
|
||||
\ 'on_stderr' : function('s:on_install_stdout'),
|
||||
\ 'cwd' : a:repo.path,
|
||||
\ 'on_exit' : function('s:on_pull_exit')
|
||||
\ })
|
||||
|
||||
call s:msg_on_local(a:repo.name)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
@ -525,6 +529,9 @@ if has('nvim')
|
||||
function! s:msg_on_start(name) abort
|
||||
call s:set_buf_line(s:plugin_manager_buffer, s:ui_buf[a:name] + 3, '+ ' . a:name . ': Updating...')
|
||||
endfunction
|
||||
function! s:msg_on_local(name) abort
|
||||
call s:set_buf_line(s:plugin_manager_buffer, s:ui_buf[a:name] + 3, '- ' . a:name . ': Skip local')
|
||||
endfunction
|
||||
function! s:msg_on_install_start(name) abort
|
||||
call s:set_buf_line(s:plugin_manager_buffer, s:ui_buf[a:name] + 3, '+ ' . a:name . ': Installing...')
|
||||
endfunction
|
||||
@ -532,6 +539,9 @@ elseif s:VIM_CO.has('python')
|
||||
function! s:msg_on_start(name) abort
|
||||
call s:append_buf_line(s:plugin_manager_buffer, s:ui_buf[a:name] + 3, '+ ' . a:name . ': Updating...')
|
||||
endfunction
|
||||
function! s:msg_on_local(name) abort
|
||||
call s:append_buf_line(s:plugin_manager_buffer, s:ui_buf[a:name] + 3, '- ' . a:name . ': Skip local')
|
||||
endfunction
|
||||
function! s:msg_on_install_start(name) abort
|
||||
call s:append_buf_line(s:plugin_manager_buffer, s:ui_buf[a:name] + 3, '+ ' . a:name . ': Installing...')
|
||||
endfunction
|
||||
@ -539,6 +549,9 @@ else
|
||||
function! s:msg_on_start(name) abort
|
||||
call s:set_buf_line(s:plugin_manager_buffer, s:ui_buf[a:name] + 3, '+ ' . a:name . ': Updating...')
|
||||
endfunction
|
||||
function! s:msg_on_local(name) abort
|
||||
call s:set_buf_line(s:plugin_manager_buffer, s:ui_buf[a:name] + 3, '- ' . a:name . ': Skip local')
|
||||
endfunction
|
||||
function! s:msg_on_install_start(name) abort
|
||||
call s:set_buf_line(s:plugin_manager_buffer, s:ui_buf[a:name] + 3, '+ ' . a:name . ': Installing...')
|
||||
endfunction
|
||||
|
11
bundle/README.md
Normal file
11
bundle/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
## Forked repos
|
||||
|
||||
### checkers layer
|
||||
|
||||
- neomake
|
||||
- vim-snippets
|
||||
- neco-syntax
|
||||
- context_filetype.vim
|
||||
- neoinclude.vim
|
||||
- neosnippet-snippets
|
||||
- neopairs.vim
|
8
bundle/clever-f.vim/.codecov.yml
Normal file
8
bundle/clever-f.vim/.codecov.yml
Normal file
@ -0,0 +1,8 @@
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: 0%
|
||||
patch:
|
||||
default:
|
||||
target: 0%
|
66
bundle/clever-f.vim/.github/workflows/ci.yml
vendored
Normal file
66
bundle/clever-f.vim/.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
name: CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
unit-tests:
|
||||
name: Unit tests
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
neovim: [false, true]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Checkout themis.vim
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: thinca/vim-themis
|
||||
path: vim-themis
|
||||
- name: Install Vim or Neovim
|
||||
uses: rhysd/action-setup-vim@v1
|
||||
id: vim
|
||||
with:
|
||||
neovim: ${{ matrix.neovim }}
|
||||
- name: Run unit tests
|
||||
env:
|
||||
THEMIS_VIM: ${{ steps.vim.outputs.executable }}
|
||||
PROFILE_LOG: profile.txt
|
||||
run: |
|
||||
cd ./test
|
||||
echo $THEMIS_VIM
|
||||
../vim-themis/bin/themis .
|
||||
# covimerage seems not maintained for Windows. Skip taking code coverage on Windows
|
||||
- name: Install Python
|
||||
if: matrix.os != 'windows-latest'
|
||||
uses: actions/setup-python@v1
|
||||
- name: Install covimerage
|
||||
if: matrix.os != 'windows-latest'
|
||||
run: |
|
||||
pip install covimerage
|
||||
covimerage --version
|
||||
- name: Run covimerage
|
||||
if: matrix.os != 'windows-latest'
|
||||
run: |
|
||||
cd ./test
|
||||
covimerage write_coverage profile.txt
|
||||
- name: Take coverage
|
||||
if: matrix.os != 'windows-latest'
|
||||
run: |
|
||||
cd ./test
|
||||
coverage report
|
||||
coverage xml
|
||||
- name: Upload coverage to codecov
|
||||
if: matrix.os != 'windows-latest'
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
file: ./test/coverage.xml
|
||||
|
||||
vint:
|
||||
name: Run vint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v1
|
||||
- run: pip install vim-vint
|
||||
- run: vint --warning --verbose --enable-neovim ./autoload ./plugin
|
4
bundle/clever-f.vim/.gitignore
vendored
Normal file
4
bundle/clever-f.vim/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/doc/tags
|
||||
/test/profile.txt
|
||||
/test/htmlcov
|
||||
/test/.coverage_covimerage
|
158
bundle/clever-f.vim/README.md
Normal file
158
bundle/clever-f.vim/README.md
Normal file
@ -0,0 +1,158 @@
|
||||
clever-[f][].vim
|
||||
================
|
||||
[![Build Status][]][CI]
|
||||
[![Coverage Status][]][Codecov]
|
||||
|
||||
clever-f.vim extends `f`, `F`, `t` and `T` mappings for more convenience. Instead of `;`, `f` is available
|
||||
to repeat after you type `f{char}` or `F{char}`. `F` after `f{char}` and `F{char}` is also available
|
||||
to undo a jump. `t{char}` and `T{char}` are ditto. This extension makes a repeat easier and makes you
|
||||
forget the existence of `;`. You can use `;` for other key mapping. In addition, this extension provides
|
||||
many convenient features like target character highlighting, smart case matching and so on.
|
||||
|
||||
If you want to reset the searching character without moving cursor, map `<Plug>(clever-f-reset)` to your
|
||||
favorite key.
|
||||
|
||||
Lastly, you can customize the behavior of the mappings and features.
|
||||
|
||||
### [Try Online Demo][] using [vim.js][]
|
||||
|
||||
|
||||
## USAGE
|
||||
|
||||
![Screen shot](https://raw.githubusercontent.com/rhysd/screenshots/master/clever-f.vim/cleverf_main.gif)
|
||||
|
||||
I'll show some examples of usage. `_` is the place of cursor, `->` is a move of cursor, alphabets above
|
||||
`->` is input by keyboard. Note that this is a part of clever-f.vim's features.
|
||||
|
||||
### __`f`__
|
||||
|
||||
input: fh f f e fo f
|
||||
move : _---------->_------>_---------->_->_---------------->_->_
|
||||
input: F F
|
||||
move : _<-----------------------------_<-_
|
||||
text : hoge huga hoo hugu ponyo
|
||||
|
||||
![f screencast](https://raw.githubusercontent.com/rhysd/screenshots/master/clever-f.vim/cleverf_1.gif)
|
||||
|
||||
|
||||
### __`F`__
|
||||
|
||||
input: f Fh b f Fo
|
||||
move : _<----------_<------_<-_<-----------------------------_<-_
|
||||
input: F F F
|
||||
move : _---------->_------>_----------->_
|
||||
text : hoge huga huyo hugu ponyo
|
||||
|
||||
![F screencast](https://raw.githubusercontent.com/rhysd/screenshots/master/clever-f.vim/cleverf_2.gif)
|
||||
|
||||
|
||||
### __`t`__
|
||||
|
||||
input: th t t e to t
|
||||
move : _--------->_------>_---------->_-->_--------------->_->_
|
||||
input: T T
|
||||
move : _<-----------------------------__
|
||||
text : hoge huga hoo hugu ponyo
|
||||
|
||||
![t screencast](https://raw.githubusercontent.com/rhysd/screenshots/master/clever-f.vim/cleverf_3.gif)
|
||||
|
||||
|
||||
## CUSTOMIZE
|
||||
|
||||
### Search a character only in current line
|
||||
|
||||
`g:clever_f_across_no_line` controls to search a character across multi lines or not. Please set it
|
||||
to `1` in your vimrc to search a character only in current line.
|
||||
|
||||
### Ignore case
|
||||
|
||||
`g:clever_f_ignore_case` controls whether or not searches are case-insensitive. If you want searches
|
||||
to be case-insensitive, set it to `1` in your vimrc.
|
||||
|
||||
### Smart case
|
||||
|
||||
`g:clever_f_smart_case` controls whether searches are smart case or not. If you type a lower case character, the case will be ignored however if you type an upper case character it will only search for upper case characters. Please set it to `1` in your vimrc to enable searching by smart case.
|
||||
|
||||
### Target character highlighting in current line
|
||||
|
||||
clever-f.vim highlights the target character you input in current line. The highlight is cleared
|
||||
automatically when the search ends. If you want to change the highlight group, set your favorite highlight
|
||||
group to `g:clever_f_mark_char_color`.
|
||||
|
||||
Below is an example using `ta` in description of clever-f.vim.
|
||||
|
||||
![highlight example](https://raw.githubusercontent.com/rhysd/screenshots/master/clever-f.vim/cleverf_4.gif)
|
||||
|
||||
Here, `ta` searches `a` forward then matches the character before `a` and `Ta` searches `a` backward
|
||||
then matches the character after `a`. You can see the highlighted target is dynamically changed following
|
||||
the cursor's direction.
|
||||
|
||||
### Timeout
|
||||
|
||||
You can specify the timeout for `f`, `F`, `t` and `T` mappings. If the interval of these mappings
|
||||
is greater than the one you specified, clever-f.vim resets its state to make you input a new character.
|
||||
This feature is disabled by default. If you want to use this feature, set `g:clever_f_timeout_ms`
|
||||
to proper value.
|
||||
|
||||
### Repeat last input
|
||||
|
||||
`<CR>` is easy to type but usually it isn't input as the target character of search. So by default,
|
||||
when you input `<CR>` as `{char}`, the previous input is used instead of `<CR>`. For example, when
|
||||
you previously input `fa` and then input `f<CR>`, `a` will be used as input instead of `<CR>`.
|
||||
You can specify characters to use previous input by setting `g:clever_f_repeat_last_char_inputs`.
|
||||
Adding `<Tab>` may be handy.
|
||||
|
||||
### Migemo support
|
||||
|
||||
In Japanese environment, it is convenient that `fa` matches `あ` in some cases. Originally, this
|
||||
feature is provided by [migemo](http://0xcc.net/migemo/). clever-f can search multibyte Japanese
|
||||
character with `f`, 'F', 't' and 'T' key mappings. A cmigemo package is **NOT** required because clever-f
|
||||
includes regex patterns generated by migemo. Set `clever_f_use_migemo` to `1` to get migemo support.
|
||||
|
||||
### Fix a direction of search
|
||||
|
||||
If you always want to search forward with `f` and always want to search backward with `F`,
|
||||
set `g:clever_f_fix_key_direction` to `1`.
|
||||
|
||||
input: F Fh b F Fo
|
||||
move : _<----------_<------_<-_<-----------------------------_<-_
|
||||
input: f f f
|
||||
move : _---------->_------>_----------->_
|
||||
text : hoge huga huyo hugu ponyo
|
||||
|
||||
### Show prompt
|
||||
|
||||
If you want to show a prompt when you input a character for clever-f, set `g:clever_f_show_prompt`
|
||||
to `1`. The prompt is disposed after a character is input.
|
||||
|
||||
### Match all symbols with one char
|
||||
|
||||
Many symbol (`{`, `(`, `"`, and so on) keys are hard to press. If you want to match `;` key to all symbols,
|
||||
you can use `g:clever_f_chars_match_any_signs`. If you set it to `';'`, `f;` matches all symbols.
|
||||
|
||||
input: f; f f f f f f
|
||||
move : _-->_--->_--------->_>_>_------------>_>_
|
||||
text : hoge.huga( autoloads: %w{ aaa bbb ccc } )
|
||||
|
||||
### Keeping the functionality of `;` and `,` via mappings
|
||||
|
||||
If you are used to using `;` and `,` for forward and backward searching, but still want these to work
|
||||
the same way with clever-f, you can simply remap `;`and `,` to use this plugin:
|
||||
|
||||
```
|
||||
map ; <Plug>(clever-f-repeat-forward)
|
||||
map , <Plug>(clever-f-repeat-back)
|
||||
```
|
||||
|
||||
## LICENSE
|
||||
|
||||
Distributed under MIT License. See `doc/clever_f.txt`
|
||||
|
||||
|
||||
[f]: https://github.com/vim/vim/blob/0d76683e094c6cac2e879601aff3acf1163cbe0b/runtime/doc/motion.txt#L254-L262
|
||||
[Build Status]: https://github.com/rhysd/clever-f.vim/workflows/CI/badge.svg?branch=master&event=push
|
||||
[CI]: https://github.com/rhysd/clever-f.vim/actions?query=workflow%3ACI+branch%3Amaster
|
||||
[Coverage Status]: https://codecov.io/gh/rhysd/clever-f.vim/branch/master/graph/badge.svg
|
||||
[Codecov]: https://codecov.io/gh/rhysd/clever-f.vim
|
||||
[Try Online Demo]: http://rhysd.github.io/clever-f.vim/
|
||||
[vim.js]: https://github.com/coolwanglu/vim.js/
|
488
bundle/clever-f.vim/autoload/clever_f.vim
Normal file
488
bundle/clever-f.vim/autoload/clever_f.vim
Normal file
@ -0,0 +1,488 @@
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
" constants
|
||||
let s:ON_NVIM = has('nvim')
|
||||
|
||||
" configurations
|
||||
let g:clever_f_across_no_line = get(g:, 'clever_f_across_no_line', 0)
|
||||
let g:clever_f_ignore_case = get(g:, 'clever_f_ignore_case', 0)
|
||||
let g:clever_f_use_migemo = get(g:, 'clever_f_use_migemo', 0)
|
||||
let g:clever_f_fix_key_direction = get(g:, 'clever_f_fix_key_direction', 0)
|
||||
let g:clever_f_show_prompt = get(g:, 'clever_f_show_prompt', 0)
|
||||
let g:clever_f_smart_case = get(g:, 'clever_f_smart_case', 0)
|
||||
let g:clever_f_chars_match_any_signs = get(g:, 'clever_f_chars_match_any_signs', '')
|
||||
let g:clever_f_mark_cursor = get(g:, 'clever_f_mark_cursor', 1)
|
||||
let g:clever_f_hide_cursor_on_cmdline = get(g:, 'clever_f_hide_cursor_on_cmdline', 1)
|
||||
let g:clever_f_timeout_ms = get(g:, 'clever_f_timeout_ms', 0)
|
||||
let g:clever_f_mark_char = get(g:, 'clever_f_mark_char', 1)
|
||||
let g:clever_f_repeat_last_char_inputs = get(g:, 'clever_f_repeat_last_char_inputs', ["\<CR>"])
|
||||
let g:clever_f_mark_direct = get(g:, 'clever_f_mark_direct', 0)
|
||||
|
||||
" below variable must be set before loading this script
|
||||
let g:clever_f_clean_labels_eagerly = get(g:, 'clever_f_clean_labels_eagerly', 1)
|
||||
|
||||
" highlight labels
|
||||
augroup plugin-clever-f-highlight
|
||||
autocmd!
|
||||
autocmd ColorScheme * highlight default CleverFDefaultLabel ctermfg=red ctermbg=NONE cterm=bold,underline guifg=red guibg=NONE gui=bold,underline
|
||||
augroup END
|
||||
highlight default CleverFDefaultLabel ctermfg=red ctermbg=NONE cterm=bold,underline guifg=red guibg=NONE gui=bold,underline
|
||||
|
||||
" Priority of highlight customization is:
|
||||
" High: When g:clever_f_*_color
|
||||
" Middle: :highlight in a colorscheme
|
||||
" Low: Default highlights
|
||||
" When the variable is defined, it should be linked with :hi! since :hi does
|
||||
" not overwrite existing highlight group. (#50)
|
||||
if g:clever_f_mark_cursor
|
||||
if exists('g:clever_f_mark_cursor_color')
|
||||
execute 'highlight! link CleverFCursor' g:clever_f_mark_cursor_color
|
||||
else
|
||||
highlight link CleverFCursor Cursor
|
||||
endif
|
||||
endif
|
||||
if g:clever_f_mark_char
|
||||
if exists('g:clever_f_mark_char_color')
|
||||
execute 'highlight! link CleverFChar' g:clever_f_mark_char_color
|
||||
else
|
||||
highlight link CleverFChar CleverFDefaultLabel
|
||||
endif
|
||||
endif
|
||||
if g:clever_f_mark_direct
|
||||
if exists('g:clever_f_mark_direct_color')
|
||||
execute 'highlight! link CleverFDirect' g:clever_f_mark_direct_color
|
||||
else
|
||||
highlight link CleverFDirect CleverFDefaultLabel
|
||||
endif
|
||||
endif
|
||||
|
||||
if g:clever_f_clean_labels_eagerly
|
||||
augroup plugin-clever-f-permanent-finalizer
|
||||
autocmd!
|
||||
autocmd WinEnter,WinLeave,CmdWinLeave * if g:clever_f_mark_char | call s:remove_highlight() | endif
|
||||
augroup END
|
||||
endif
|
||||
augroup plugin-clever-f-finalizer
|
||||
autocmd!
|
||||
augroup END
|
||||
|
||||
" initialize the internal state
|
||||
let s:last_mode = ''
|
||||
let s:previous_map = {}
|
||||
let s:previous_pos = {}
|
||||
let s:first_move = {}
|
||||
let s:migemo_dicts = {}
|
||||
let s:previous_char_num = {}
|
||||
let s:timestamp = [0, 0]
|
||||
|
||||
" keys are mode string returned from mode()
|
||||
function! clever_f#reset() abort
|
||||
let s:previous_map = {}
|
||||
let s:previous_pos = {}
|
||||
let s:first_move = {}
|
||||
let s:migemo_dicts = {}
|
||||
|
||||
" Note:
|
||||
" [0, 0] may be invalid because the representation of return value of reltime() depends on implementation.
|
||||
let s:timestamp = [0, 0]
|
||||
|
||||
call s:remove_highlight()
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
" hidden API for debug
|
||||
function! clever_f#_reset_all() abort
|
||||
call clever_f#reset()
|
||||
let s:last_mode = ''
|
||||
let s:previous_char_num = {}
|
||||
autocmd! plugin-clever-f-finalizer
|
||||
unlet! s:moved_forward
|
||||
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:remove_highlight() abort
|
||||
for h in filter(getmatches(), 'v:val.group ==# "CleverFChar"')
|
||||
call matchdelete(h.id)
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:is_timedout() abort
|
||||
let cur = reltime()
|
||||
let rel = reltimestr(reltime(s:timestamp, cur))
|
||||
let elapsed_ms = float2nr(str2float(rel) * 1000.0)
|
||||
let s:timestamp = cur
|
||||
return elapsed_ms > g:clever_f_timeout_ms
|
||||
endfunction
|
||||
|
||||
" highlight characters to which the cursor can be moved directly
|
||||
function! s:mark_direct(forward, count) abort
|
||||
let line = getline('.')
|
||||
let [_, l, c, _] = getpos('.')
|
||||
|
||||
if (a:forward && c == len(line)) || (!a:forward && c == 1)
|
||||
" there is no matching characters
|
||||
return []
|
||||
endif
|
||||
|
||||
if g:clever_f_ignore_case
|
||||
let line = tolower(line)
|
||||
endif
|
||||
|
||||
let char_count = {}
|
||||
let matches = []
|
||||
let indices = a:forward ? range(c, len(line) - 1, 1) : range(c - 2, 0, -1)
|
||||
for i in indices
|
||||
let ch = line[i]
|
||||
" only matches to ASCII
|
||||
if ch !~# '^[\x00-\x7F]$' | continue | endif
|
||||
let ch_lower = tolower(ch)
|
||||
|
||||
let char_count[ch] = get(char_count, ch, 0) + 1
|
||||
if g:clever_f_smart_case && ch =~# '\u'
|
||||
" uppercase characters are doubly counted
|
||||
let char_count[ch_lower] = get(char_count, ch_lower, 0) + 1
|
||||
endif
|
||||
|
||||
if char_count[ch] == a:count ||
|
||||
\ (g:clever_f_smart_case && char_count[ch_lower] == a:count)
|
||||
" NOTE: should not use `matchaddpos(group, [...position])`,
|
||||
" because the maximum number of position is 8
|
||||
let m = matchaddpos('CleverFDirect', [[l, i + 1]])
|
||||
call add(matches, m)
|
||||
endif
|
||||
endfor
|
||||
return matches
|
||||
endfunction
|
||||
|
||||
" introduce public function for test
|
||||
function! clever_f#_mark_direct(forward, count) abort
|
||||
return s:mark_direct(a:forward, a:count)
|
||||
endfunction
|
||||
|
||||
function! s:mark_char_in_current_line(map, char) abort
|
||||
let regex = '\%' . line('.') . 'l' . s:generate_pattern(a:map, a:char)
|
||||
call matchadd('CleverFChar', regex , 999)
|
||||
endfunction
|
||||
|
||||
" Note:
|
||||
" \x80\xfd` seems to be sent by a terminal.
|
||||
" Below is a workaround for the sequence.
|
||||
function! s:getchar() abort
|
||||
while 1
|
||||
let cn = getchar()
|
||||
if type(cn) != type('') || cn !=# "\x80\xfd`"
|
||||
return cn
|
||||
endif
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! s:include_multibyte_char(str) abort
|
||||
return strlen(a:str) != clever_f#compat#strchars(a:str)
|
||||
endfunction
|
||||
|
||||
function! clever_f#find_with(map) abort
|
||||
if a:map !~# '^[fFtT]$'
|
||||
throw "Error: Invalid mapping '" . a:map . "'"
|
||||
endif
|
||||
|
||||
if &foldopen =~# '\<\%(all\|hor\)\>'
|
||||
while foldclosed(line('.')) >= 0
|
||||
foldopen
|
||||
endwhile
|
||||
endif
|
||||
|
||||
let current_pos = getpos('.')[1 : 2]
|
||||
|
||||
let mode = s:mode()
|
||||
if current_pos != get(s:previous_pos, mode, [0, 0])
|
||||
let back = 0
|
||||
if g:clever_f_mark_cursor
|
||||
let cursor_marker = matchadd('CleverFCursor', '\%#', 999)
|
||||
redraw
|
||||
endif
|
||||
" block-NONE does not work on Neovim
|
||||
if g:clever_f_hide_cursor_on_cmdline && !s:ON_NVIM
|
||||
let guicursor_save = &guicursor
|
||||
set guicursor=n-o:block-NONE
|
||||
let t_ve_save = &t_ve
|
||||
set t_ve=
|
||||
endif
|
||||
try
|
||||
if g:clever_f_mark_direct
|
||||
let direct_markers = s:mark_direct(a:map =~# '\l', v:count1)
|
||||
redraw
|
||||
endif
|
||||
if g:clever_f_show_prompt | echon 'clever-f: ' | endif
|
||||
let s:previous_map[mode] = a:map
|
||||
let s:first_move[mode] = 1
|
||||
let cn = s:getchar()
|
||||
if cn == char2nr("\<Esc>")
|
||||
return "\<Esc>"
|
||||
endif
|
||||
if index(map(deepcopy(g:clever_f_repeat_last_char_inputs), 'char2nr(v:val)'), cn) == -1
|
||||
let s:previous_char_num[mode] = cn
|
||||
else
|
||||
if has_key(s:previous_char_num, s:last_mode)
|
||||
let s:previous_char_num[mode] = s:previous_char_num[s:last_mode]
|
||||
else
|
||||
echohl ErrorMsg | echo 'Previous input not found.' | echohl None
|
||||
return ''
|
||||
endif
|
||||
endif
|
||||
let s:last_mode = mode
|
||||
|
||||
if g:clever_f_timeout_ms > 0
|
||||
let s:timestamp = reltime()
|
||||
endif
|
||||
|
||||
if g:clever_f_mark_char
|
||||
call s:remove_highlight()
|
||||
if mode ==# 'n' || mode ==? 'v' || mode ==# "\<C-v>" ||
|
||||
\ mode ==# 'ce' || mode ==? 's' || mode ==# "\<C-s>"
|
||||
augroup plugin-clever-f-finalizer
|
||||
autocmd CursorMoved <buffer> call s:maybe_finalize()
|
||||
autocmd InsertEnter <buffer> call s:finalize()
|
||||
augroup END
|
||||
call s:mark_char_in_current_line(s:previous_map[mode], s:previous_char_num[mode])
|
||||
endif
|
||||
endif
|
||||
|
||||
if g:clever_f_show_prompt | redraw! | endif
|
||||
finally
|
||||
if g:clever_f_mark_cursor | call matchdelete(cursor_marker) | endif
|
||||
if g:clever_f_mark_direct
|
||||
for m in direct_markers
|
||||
call matchdelete(m)
|
||||
endfor
|
||||
endif
|
||||
if g:clever_f_hide_cursor_on_cmdline && !s:ON_NVIM
|
||||
" Set default value at first then restore (#49)
|
||||
" For example, when the value is a:blinkon0, it does not affect cursor shape so cursor
|
||||
" shape continues to disappear.
|
||||
set guicursor&
|
||||
|
||||
if &guicursor !=# guicursor_save
|
||||
let &guicursor = guicursor_save
|
||||
endif
|
||||
let &t_ve = t_ve_save
|
||||
endif
|
||||
endtry
|
||||
else
|
||||
" when repeated
|
||||
let back = a:map =~# '\u'
|
||||
if g:clever_f_fix_key_direction
|
||||
let back = s:previous_map[mode] =~# '\u' ? !back : back
|
||||
endif
|
||||
|
||||
" reset and retry if timed out
|
||||
if g:clever_f_timeout_ms > 0 && s:is_timedout()
|
||||
call clever_f#reset()
|
||||
return clever_f#find_with(a:map)
|
||||
endif
|
||||
endif
|
||||
|
||||
return clever_f#repeat(back)
|
||||
endfunction
|
||||
|
||||
function! clever_f#repeat(back) abort
|
||||
let mode = s:mode()
|
||||
let pmap = get(s:previous_map, mode, '')
|
||||
let prev_char_num = get(s:previous_char_num, mode, 0)
|
||||
|
||||
if pmap ==# ''
|
||||
return ''
|
||||
endif
|
||||
|
||||
" ignore special characters like \<Left>
|
||||
if type(prev_char_num) == type('') && char2nr(prev_char_num) == 128
|
||||
return ''
|
||||
endif
|
||||
|
||||
if a:back
|
||||
let pmap = s:swapcase(pmap)
|
||||
endif
|
||||
|
||||
if mode[0] ==? 'v' || mode[0] ==# "\<C-v>"
|
||||
let cmd = s:move_cmd_for_visualmode(pmap, prev_char_num)
|
||||
else
|
||||
let inclusive = mode ==# 'no' && pmap =~# '\l'
|
||||
let cmd = printf("%s:\<C-u>call clever_f#find(%s, %s)\<CR>",
|
||||
\ inclusive ? 'v' : '',
|
||||
\ string(pmap), prev_char_num)
|
||||
endif
|
||||
|
||||
return cmd
|
||||
endfunction
|
||||
|
||||
" absolutely moved forward?
|
||||
function! s:moves_forward(p, n) abort
|
||||
if a:p[0] != a:n[0]
|
||||
return a:p[0] < a:n[0]
|
||||
endif
|
||||
|
||||
if a:p[1] != a:n[1]
|
||||
return a:p[1] < a:n[1]
|
||||
endif
|
||||
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! clever_f#find(map, char_num) abort
|
||||
let before_pos = getpos('.')[1 : 2]
|
||||
let next_pos = s:next_pos(a:map, a:char_num, v:count1)
|
||||
if next_pos == [0, 0]
|
||||
return
|
||||
endif
|
||||
|
||||
let moves_forward = s:moves_forward(before_pos, next_pos)
|
||||
|
||||
" update highlight when cursor moves across lines
|
||||
let mode = s:mode()
|
||||
if g:clever_f_mark_char
|
||||
if next_pos[0] != before_pos[0]
|
||||
\ || (a:map ==? 't' && !s:first_move[mode] && clever_f#compat#xor(s:moved_forward, moves_forward))
|
||||
call s:remove_highlight()
|
||||
call s:mark_char_in_current_line(a:map, a:char_num)
|
||||
endif
|
||||
endif
|
||||
|
||||
let s:moved_forward = moves_forward
|
||||
let s:previous_pos[mode] = next_pos
|
||||
let s:first_move[mode] = 0
|
||||
endfunction
|
||||
|
||||
function! s:finalize() abort
|
||||
autocmd! plugin-clever-f-finalizer
|
||||
call s:remove_highlight()
|
||||
let s:previous_pos = {}
|
||||
let s:moved_forward = 0
|
||||
endfunction
|
||||
|
||||
function! s:maybe_finalize() abort
|
||||
let pp = get(s:previous_pos, s:last_mode, [0, 0])
|
||||
if getpos('.')[1 : 2] != pp
|
||||
call s:finalize()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:move_cmd_for_visualmode(map, char_num) abort
|
||||
let next_pos = s:next_pos(a:map, a:char_num, v:count1)
|
||||
if next_pos == [0, 0]
|
||||
return ''
|
||||
endif
|
||||
|
||||
let m = s:mode()
|
||||
call setpos("''", [0] + next_pos + [0])
|
||||
let s:previous_pos[m] = next_pos
|
||||
let s:first_move[m] = 0
|
||||
|
||||
return '``'
|
||||
endfunction
|
||||
|
||||
function! s:search(pat, flag) abort
|
||||
if g:clever_f_across_no_line
|
||||
return search(a:pat, a:flag, line('.'))
|
||||
else
|
||||
return search(a:pat, a:flag)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:should_use_migemo(char) abort
|
||||
if !g:clever_f_use_migemo || a:char !~# '^\a$'
|
||||
return 0
|
||||
endif
|
||||
|
||||
if !g:clever_f_across_no_line
|
||||
return 1
|
||||
endif
|
||||
|
||||
return s:include_multibyte_char(getline('.'))
|
||||
endfunction
|
||||
|
||||
function! s:load_migemo_dict() abort
|
||||
let enc = &l:encoding
|
||||
if enc ==# 'utf-8'
|
||||
return clever_f#migemo#utf8#load_dict()
|
||||
elseif enc ==# 'cp932'
|
||||
return clever_f#migemo#cp932#load_dict()
|
||||
elseif enc ==# 'euc-jp'
|
||||
return clever_f#migemo#eucjp#load_dict()
|
||||
else
|
||||
let g:clever_f_use_migemo = 0
|
||||
throw 'Error: ' . enc . ' is not supported. Migemo is disabled.'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:generate_pattern(map, char_num) abort
|
||||
let char = type(a:char_num) == type(0) ? nr2char(a:char_num) : a:char_num
|
||||
let regex = char
|
||||
|
||||
let should_use_migemo = s:should_use_migemo(char)
|
||||
if should_use_migemo
|
||||
if !has_key(s:migemo_dicts, &l:encoding)
|
||||
let s:migemo_dicts[&l:encoding] = s:load_migemo_dict()
|
||||
endif
|
||||
let regex = s:migemo_dicts[&l:encoding][regex] . '\&\%(' . char . '\|\A\)'
|
||||
elseif stridx(g:clever_f_chars_match_any_signs, char) != -1
|
||||
let regex = '\[!"#$%&''()=~|\-^\\@`[\]{};:+*<>,.?_/]'
|
||||
elseif char ==# '\'
|
||||
let regex = '\\'
|
||||
endif
|
||||
|
||||
let is_exclusive_visual = &selection ==# 'exclusive' && s:mode()[0] ==? 'v'
|
||||
if a:map ==# 't' && !is_exclusive_visual
|
||||
let regex = '\_.\ze\%(' . regex . '\)'
|
||||
elseif is_exclusive_visual && a:map ==# 'f'
|
||||
let regex = '\%(' . regex . '\)\zs\_.'
|
||||
elseif a:map ==# 'T'
|
||||
let regex = '\%(' . regex . '\)\@<=\_.'
|
||||
endif
|
||||
|
||||
if !should_use_migemo
|
||||
let regex = '\V'.regex
|
||||
endif
|
||||
|
||||
return ((g:clever_f_smart_case && char =~# '\l') || g:clever_f_ignore_case ? '\c' : '\C') . regex
|
||||
endfunction
|
||||
|
||||
function! s:next_pos(map, char_num, count) abort
|
||||
let mode = s:mode()
|
||||
let search_flag = a:map =~# '\l' ? 'W' : 'bW'
|
||||
let cnt = a:count
|
||||
let pattern = s:generate_pattern(a:map, a:char_num)
|
||||
|
||||
if a:map ==? 't' && get(s:first_move, mode, 1)
|
||||
if !s:search(pattern, search_flag . 'c')
|
||||
return [0, 0]
|
||||
endif
|
||||
let cnt -= 1
|
||||
endif
|
||||
|
||||
while 0 < cnt
|
||||
if !s:search(pattern, search_flag)
|
||||
return [0, 0]
|
||||
endif
|
||||
let cnt -= 1
|
||||
endwhile
|
||||
|
||||
return getpos('.')[1 : 2]
|
||||
endfunction
|
||||
|
||||
function! s:swapcase(char) abort
|
||||
return a:char =~# '\u' ? tolower(a:char) : toupper(a:char)
|
||||
endfunction
|
||||
|
||||
" Drop forced visual mode character ('nov' -> 'no')
|
||||
function! s:mode() abort
|
||||
let mode = mode(1)
|
||||
if mode =~# '^no'
|
||||
let mode = mode[0 : 1]
|
||||
endif
|
||||
return mode
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
19
bundle/clever-f.vim/autoload/clever_f/compat.vim
Normal file
19
bundle/clever-f.vim/autoload/clever_f/compat.vim
Normal file
@ -0,0 +1,19 @@
|
||||
if exists('*strchars')
|
||||
function! clever_f#compat#strchars(str) abort
|
||||
return strchars(a:str)
|
||||
endfunction
|
||||
else
|
||||
function! clever_f#compat#strchars(str) abort
|
||||
return strlen(substitute(a:str, '.', 'x', 'g'))
|
||||
endfunction
|
||||
endif
|
||||
|
||||
if exists('*xor')
|
||||
function! clever_f#compat#xor(a, b) abort
|
||||
return xor(a:a, a:b)
|
||||
endfunction
|
||||
else
|
||||
function! clever_f#compat#xor(a, b) abort
|
||||
return a:a && !a:b || !a:a && a:b
|
||||
endfunction
|
||||
endif
|
57
bundle/clever-f.vim/autoload/clever_f/migemo/cp932.vim
Normal file
57
bundle/clever-f.vim/autoload/clever_f/migemo/cp932.vim
Normal file
File diff suppressed because one or more lines are too long
57
bundle/clever-f.vim/autoload/clever_f/migemo/eucjp.vim
Normal file
57
bundle/clever-f.vim/autoload/clever_f/migemo/eucjp.vim
Normal file
File diff suppressed because one or more lines are too long
57
bundle/clever-f.vim/autoload/clever_f/migemo/utf8.vim
Normal file
57
bundle/clever-f.vim/autoload/clever_f/migemo/utf8.vim
Normal file
File diff suppressed because one or more lines are too long
274
bundle/clever-f.vim/doc/clever_f.txt
Normal file
274
bundle/clever-f.vim/doc/clever_f.txt
Normal file
@ -0,0 +1,274 @@
|
||||
*clever-f.txt* Make |f|, |F|, |t| and |T| cleverer.
|
||||
|
||||
Author : rhysd <lin90162@yahoo.co.jp>
|
||||
Version : 1.5
|
||||
|
||||
CONTENTS *clever-f.vim-contents*
|
||||
|
||||
Introduction |clever-f.vim-introduction|
|
||||
Usage |clever-f.vim-usage|
|
||||
Mappings |clever-f.vim-mappings|
|
||||
Variables |clever-f.vim-variables|
|
||||
Special Thanks |clever-f.vim-special-thanks|
|
||||
Repository Page |clever-f.vim-repository-page|
|
||||
License |clever-f.vim-license|
|
||||
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *clever-f.vim-introduction*
|
||||
|
||||
*clever-f.vim* or *clever-f* extends |f|, |F|, |t| and |T| key mappings for more
|
||||
convenience.
|
||||
Instead of |;|, |f| is available to repeat after you type |f|{char} or |F|{char}. |F|
|
||||
after |f|{char} and |F|{char} is also available to undo a jump. |t|{char} and
|
||||
|T|{char} are ditto. This extension makes a repeat easier and makes you forget
|
||||
the existence of |;|. You can use |;| for other key mapping.
|
||||
In addition, many handy features (target highlighting, smartcase matching, and
|
||||
so on) are provided and you can customize behavior of the mappings.
|
||||
Please check |clever-f.vim-variables|.
|
||||
|
||||
|
||||
==============================================================================
|
||||
USAGE *clever-f.vim-usage*
|
||||
|
||||
I'll show an example of usage. _ is the place of cursor, -> is a move of
|
||||
cursor, alphabets above -> is input by keyboard.
|
||||
|
||||
>
|
||||
input: fh f f e fo f
|
||||
move : _---------->_------>_---------->_->_---------------->_->_
|
||||
input: F F
|
||||
move : _<-----------------------------_<-_
|
||||
text : hoge huga hoo hugu ponyo
|
||||
<
|
||||
|
||||
>
|
||||
input: f Fh b f Fo
|
||||
move : _<----------_<------_<-_<-----------------------------_<-_
|
||||
input: F F F
|
||||
move : _---------->_------>_----------->_
|
||||
text : hoge huga huyo hugu ponyo
|
||||
<
|
||||
|
||||
>
|
||||
input: th t t e to t
|
||||
move : _--------->_------>_---------->_-->_--------------->_->_
|
||||
input: T T
|
||||
move : _<-----------------------------__
|
||||
text : hoge huga hoo hugu ponyo
|
||||
<
|
||||
|
||||
==============================================================================
|
||||
MAPPINGS *clever-f.vim-mappings*
|
||||
*g:clever_f_not_overwrites_standard_mappings*
|
||||
|
||||
If you don't set |g:clever_f_not_overwrites_standard_mappings|, |clever-f|
|
||||
replaces |f|, |F|, |t|, and |T| with |<Plug>(clever-f-f)|, |<Plug>(clever-f-F)|,
|
||||
|<Plug>(clever-f-t)| and |<Plug>(clever-f-T)| as default mappings.
|
||||
|
||||
<Plug>(clever-f-f) *<Plug>(clever-f-f)*
|
||||
<Plug>(clever-f-F) *<Plug>(clever-f-F)*
|
||||
<Plug>(clever-f-t) *<Plug>(clever-f-t)*
|
||||
<Plug>(clever-f-T) *<Plug>(clever-f-T)*
|
||||
<Plug>(clever-f-reset) *<Plug>(clever-f-reset)*
|
||||
<Plug>(clever-f-repeat-forward) *<Plug>(clever-f-repeat-forward)*
|
||||
<Plug>(clever-f-repeat-back) *<Plug>(clever-f-repeat-back)*
|
||||
|
||||
|
||||
==============================================================================
|
||||
VARIABLES *clever-f.vim-variables*
|
||||
|
||||
g:clever_f_across_no_line *g:clever_f_across_no_line*
|
||||
|
||||
If the value is equivalent to 1, |clever-f| mappings search target
|
||||
character only in the cursor line. The default value is 0.
|
||||
|
||||
g:clever_f_ignore_case *g:clever_f_ignore_case*
|
||||
|
||||
If the value is equivalent to 1, it makes |clever-f| mappings' search case-
|
||||
insensitive. For example, if you input "fa", it matches both "a" and "A".
|
||||
The default value is 0.
|
||||
|
||||
g:clever_f_smart_case *g:clever_f_smart_case*
|
||||
|
||||
If the value is equivalent to 1, it makes |clever-f| mappings' search
|
||||
smart case. For example, if you input "fa", it matches both "a" and "A",
|
||||
but if you input "fA", it matches only "A".
|
||||
The default value is 0.
|
||||
|
||||
g:clever_f_use_migemo *g:clever_f_use_migemo*
|
||||
|
||||
If the value is equivalent to 1, migemo support is enabled. This feature
|
||||
is useful in Japanese environment. |clever-f| can match multibyte Japanese
|
||||
character with a alphabet input. For example, "fa" can search "あ".
|
||||
This feature doesn't require |cmigemo| because |clever-f| includes regex
|
||||
patterns generated by cmigemo.
|
||||
Please see http://0xcc.net/migemo/ if you want to know more about migemo.
|
||||
The default value of this variable is 0.
|
||||
>
|
||||
input: fm f f
|
||||
move : _---->_---->_----------------------------------------->_
|
||||
input: F F F
|
||||
move : _<----_<----_<-----------------------------------------_
|
||||
text : ビム!ビム!ビムゥぅうわぁああん!!! あぁあっあっー!ビムゥ!!
|
||||
<
|
||||
g:clever_f_fix_key_direction *g:clever_f_fix_key_direction*
|
||||
|
||||
If the value is equivalent to 1, the directions of keys are fixed. For
|
||||
example, |F| is backward search and repeating of |F| after |F| makes the
|
||||
same direction search. Below is the behavior. Please compare examples of
|
||||
|clever-f.vim-usage|.
|
||||
The default value is 0.
|
||||
>
|
||||
input: F Fh b F Fo
|
||||
move : _<----------_<------_<-_<-----------------------------_<-_
|
||||
input: f f f
|
||||
move : _---------->_------>_----------->_
|
||||
text : hoge huga huyo hugu ponyo
|
||||
<
|
||||
g:clever_f_show_prompt *g:clever_f_show_prompt*
|
||||
|
||||
If the value is equivalent to 1, a prompt is shown when a character is
|
||||
input to search. The prompt is disposed after the input.
|
||||
The default value is 0.
|
||||
|
||||
g:clever_f_chars_match_any_signs *g:clever_f_chars_match_any_signs*
|
||||
|
||||
The value must be string. If this variable is not empty, characters in the
|
||||
value matches any signs. For example, when the value is ";:", f; and f:
|
||||
matches all signs. You can jump signs whose keys are hard to press.
|
||||
The default value is "".
|
||||
>
|
||||
input: f; f f f f f f
|
||||
move : _-->_--->_--------->_>_>_------------>_>_
|
||||
text : hoge.huga( autoloads: %w{ aaa bbb ccc } )
|
||||
<
|
||||
g:clever_f_mark_cursor *g:clever_f_mark_cursor*
|
||||
|
||||
If the value is equivalent to 1, current cursor position will be
|
||||
highlighted when waiting for {char}. This way you won't lose your focus
|
||||
from the place your cursor was.
|
||||
The default value is 1.
|
||||
|
||||
g:clever_f_mark_cursor_color *g:clever_f_mark_cursor_color*
|
||||
|
||||
Only used when |g:clever_f_mark_cursor| is enabled. Change highlight group
|
||||
used to mark cursor position.
|
||||
The default value is "Cursor".
|
||||
|
||||
Note:
|
||||
|g:clever_f_mark_cursor_color| must be set before |clever-f| is loaded.
|
||||
(e.g. in your |vimrc|)
|
||||
|
||||
g:clever_f_hide_cursor_on_cmdline *g:clever_f_hide_cursor_on_cmdline*
|
||||
|
||||
If the value is equivalent to 1, a cursor is hidden on inputting {char}.
|
||||
This feature prevents cursor from moving to command line.
|
||||
The default value is 1.
|
||||
|
||||
g:clever_f_timeout_ms *g:clever_f_timeout_ms*
|
||||
|
||||
If the value is greater than 0, |clever-f| check the interval of previous
|
||||
search and next search. If the interval is longer than the value,
|
||||
|clever-f| resets its state to make you input a character. The unit of the
|
||||
value is millisecond.
|
||||
The default value is 0 (it means no timeout).
|
||||
|
||||
g:clever_f_mark_char *g:clever_f_mark_char*
|
||||
|
||||
If the value is equivalent to 1, the characters in line which you input
|
||||
in |f|, |F|, |t| and |T| are highlighted until the search ends. The
|
||||
highlighted characters means candidates the cursor can move to by |f|, |F|, |t|
|
||||
and |T|. Highlighting is enabled in normal and visual mode.
|
||||
The default value is 1.
|
||||
|
||||
g:clever_f_mark_char_color *g:clever_f_mark_char_color*
|
||||
|
||||
If |g:clever_f_mark_char| is enabled, |clever-f| highlights the target
|
||||
characters using the highlight group which |g:clever_f_mark_char_color|
|
||||
specifies. If you want to change the highlight group |clever-f| uses, set
|
||||
your favorite highlight group to this variable.
|
||||
The default value is "CleverFDefaultLabel", which makes characters red and
|
||||
bold. If you want to make an original label highlight, define your own
|
||||
highlight group.(See |:highlight|)
|
||||
|
||||
Note:
|
||||
|g:clever_f_mark_char_color| must be set before |clever-f| is loaded.
|
||||
(e.g. in your |vimrc|)
|
||||
|
||||
g:clever_f_repeat_last_char_inputs *g:clever_f_repeat_last_char_inputs*
|
||||
|
||||
This is a list of string value. If one of the elements are input,
|
||||
|clever-f| use the previous input instead of the input.
|
||||
The default value is ["\<CR>"]. It means that previous input is used when
|
||||
you input <CR>. For example, when you previously input "fa" and then
|
||||
input "f<CR>", "a" will be used instead of "<CR>".
|
||||
If you want to add <Tab> to the element, please write below in your vimrc.
|
||||
>
|
||||
let g:clever_f_repeat_last_char_inputs = ["\<CR>", "\<Tab>"]
|
||||
<
|
||||
g:clever_f_mark_direct *g:clever_f_mark_direct*
|
||||
|
||||
If the value is equivalent to 1, characters to which the cursor can be
|
||||
moved directly are highlighted until you input a character. Highlighting
|
||||
is enabled in normal and visual mode.
|
||||
The default value is 0.
|
||||
|
||||
g:clever_f_mark_direct_color *g:clever_f_mark_direct_color*
|
||||
|
||||
If |g:clever_f_mark_direct| is enabled, |clever-f| highlights characters
|
||||
using the highlight group which |g:clever_f_mark_direct_color| specifies.
|
||||
If you want to change the highlight group |clever-f| uses, set
|
||||
your favorite highlight group to this variable.
|
||||
The default value is "CleverFDefaultLabel", which makes characters red and
|
||||
bold. If you want to make an original label highlight, define your own
|
||||
highlight group.(See |:highlight|)
|
||||
|
||||
Note:
|
||||
|g:clever_f_mark_direct_color| must be set before |clever-f| is loaded.
|
||||
(e.g. in your |vimrc|)
|
||||
|
||||
|
||||
==============================================================================
|
||||
SPECIAL THANKS *clever-f.vim-special-thanks*
|
||||
|
||||
|<Plug>(clever-f-t)|, |<Plug>(clever-f-T)|, repeatability with |.|,
|
||||
availability of |[count]| are the works by @thinca. Thanks!
|
||||
(http://d.hatena.ne.jp/thinca/20130227/1361891993)
|
||||
|
||||
|
||||
==============================================================================
|
||||
REPOSITORY PAGE *clever-f.vim-repository-page*
|
||||
|
||||
The latest version of |clever-f| is available at
|
||||
https://github.com/rhysd/clever-f.vim
|
||||
|
||||
|
||||
==============================================================================
|
||||
LICENSE *clever-f.vim-license*
|
||||
|
||||
|clever-f.vim| is distributed under MIT license.
|
||||
|
||||
Copyright (c) 2013 rhysd
|
||||
|
||||
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.
|
||||
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:colorcolumn=78:ts=8:ft=help:norl:et:fen:fdl=0:
|
28
bundle/clever-f.vim/plugin/clever-f.vim
Normal file
28
bundle/clever-f.vim/plugin/clever-f.vim
Normal file
@ -0,0 +1,28 @@
|
||||
if exists('g:loaded_clever_f') && g:loaded_clever_f
|
||||
finish
|
||||
endif
|
||||
|
||||
noremap <silent><expr><Plug>(clever-f-f) clever_f#find_with('f')
|
||||
noremap <silent><expr><Plug>(clever-f-F) clever_f#find_with('F')
|
||||
noremap <silent><expr><Plug>(clever-f-t) clever_f#find_with('t')
|
||||
noremap <silent><expr><Plug>(clever-f-T) clever_f#find_with('T')
|
||||
noremap <silent><expr><Plug>(clever-f-reset) clever_f#reset()
|
||||
noremap <silent><expr><Plug>(clever-f-repeat-forward) clever_f#repeat(0)
|
||||
noremap <silent><expr><Plug>(clever-f-repeat-back) clever_f#repeat(1)
|
||||
|
||||
if ! exists('g:clever_f_not_overwrites_standard_mappings')
|
||||
nmap f <Plug>(clever-f-f)
|
||||
xmap f <Plug>(clever-f-f)
|
||||
omap f <Plug>(clever-f-f)
|
||||
nmap F <Plug>(clever-f-F)
|
||||
xmap F <Plug>(clever-f-F)
|
||||
omap F <Plug>(clever-f-F)
|
||||
nmap t <Plug>(clever-f-t)
|
||||
xmap t <Plug>(clever-f-t)
|
||||
omap t <Plug>(clever-f-t)
|
||||
nmap T <Plug>(clever-f-T)
|
||||
xmap T <Plug>(clever-f-T)
|
||||
omap T <Plug>(clever-f-T)
|
||||
endif
|
||||
|
||||
let g:loaded_clever_f = 1
|
3
bundle/clever-f.vim/test/.coveragerc
Normal file
3
bundle/clever-f.vim/test/.coveragerc
Normal file
@ -0,0 +1,3 @@
|
||||
[run]
|
||||
plugins = covimerage
|
||||
data_file = .coverage_covimerage
|
15
bundle/clever-f.vim/test/.themisrc
Normal file
15
bundle/clever-f.vim/test/.themisrc
Normal file
@ -0,0 +1,15 @@
|
||||
let g:repo_root = fnamemodify(expand('<sfile>'), ':h:h')
|
||||
|
||||
call themis#option('exclude', g:repo_root . '/test/README.md')
|
||||
call themis#option('exclude', g:repo_root . '/test/.coveragerc')
|
||||
call themis#option('exclude', g:repo_root . '/test/Guardfile')
|
||||
call themis#helper('command').with(themis#helper('assert'))
|
||||
|
||||
if $PROFILE_LOG !=# ''
|
||||
execute 'profile' 'start' $PROFILE_LOG
|
||||
execute 'profile!' 'file' g:repo_root . '/autoload/clever_f.vim'
|
||||
execute 'profile!' 'file' g:repo_root . '/autoload/clever_f/helper.vim'
|
||||
execute 'profile!' 'file' g:repo_root . '/plugin/*'
|
||||
endif
|
||||
|
||||
call themis#option('runtimepath', expand(g:repo_root))
|
38
bundle/clever-f.vim/test/README.md
Normal file
38
bundle/clever-f.vim/test/README.md
Normal file
@ -0,0 +1,38 @@
|
||||
## How to execute tests
|
||||
|
||||
It requires [vim-themis](https://github.com/thinca/vim-themis). You need to install it in advance.
|
||||
|
||||
For example, following clones it locally in clever-f.vim repository.
|
||||
|
||||
```console
|
||||
$ cd /path/to/clever-f.vim/test
|
||||
$ git clone https://github.com/thinca/vim-themis
|
||||
$ ./vim-themis/bin/themis .
|
||||
```
|
||||
|
||||
## How to measure code coverage
|
||||
|
||||
It requires [covimerage](https://github.com/Vimjas/covimerage).
|
||||
|
||||
```console
|
||||
$ pip install covimerage
|
||||
$ cd /path/to/clever-f.vim/test
|
||||
|
||||
# Run tests with profiling
|
||||
$ PROFILE_LOG=profile.txt ./vim-themis/bin/themis .
|
||||
|
||||
# Create a coverage file using profile results
|
||||
$ covimerage write_coverage profile.txt
|
||||
|
||||
# See the coverage results in console output
|
||||
$ coverage report
|
||||
|
||||
# See the coverage results in test/htmlcov/index.html
|
||||
$ coverage html
|
||||
```
|
||||
|
||||
## CI
|
||||
|
||||
CI is run in both Linux and macOS using Travis CI: https://travis-ci.org/rhysd/clever-f.vim
|
||||
|
||||
Coverage is tracked with codecov.io: https://codecov.io/gh/rhysd/clever-f.vim
|
1297
bundle/clever-f.vim/test/test.vimspec
Normal file
1297
bundle/clever-f.vim/test/test.vimspec
Normal file
File diff suppressed because it is too large
Load Diff
21
bundle/context_filetype.vim/LICENSE
Normal file
21
bundle/context_filetype.vim/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
License: MIT license
|
||||
AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
|
||||
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.
|
679
bundle/context_filetype.vim/autoload/context_filetype.vim
Normal file
679
bundle/context_filetype.vim/autoload/context_filetype.vim
Normal file
@ -0,0 +1,679 @@
|
||||
"=============================================================================
|
||||
" FILE: context_filetype.vim
|
||||
" AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
" License: MIT license
|
||||
"=============================================================================
|
||||
|
||||
scriptencoding utf-8
|
||||
|
||||
let g:context_filetype#filetypes = get(g:,
|
||||
\ 'context_filetype#filetypes', {})
|
||||
|
||||
let g:context_filetype#ignore_composite_filetypes = get(g:,
|
||||
\ 'context_filetype#ignore_composite_filetypes', {})
|
||||
|
||||
let g:context_filetype#same_filetypes = get(g:,
|
||||
\ 'context_filetype#same_filetypes', {})
|
||||
|
||||
let g:context_filetype#search_offset = get(g:,
|
||||
\ 'context_filetype#search_offset', 200)
|
||||
|
||||
function! context_filetype#version() abort
|
||||
return str2nr(printf('%02d%02d', 1, 0))
|
||||
endfunction
|
||||
|
||||
|
||||
function! context_filetype#get(...) abort
|
||||
let base_filetype = get(a:, 1, &filetype)
|
||||
let filetypes = context_filetype#filetypes()
|
||||
let context = s:get_nest(base_filetype, filetypes)
|
||||
if context.range == s:null_range && !has_key(context, 'synname')
|
||||
let context.filetype = base_filetype
|
||||
endif
|
||||
return context
|
||||
endfunction
|
||||
|
||||
|
||||
function! context_filetype#get_filetype(...) abort
|
||||
let base_filetype = get(a:, 1, &filetype)
|
||||
return context_filetype#get(base_filetype).filetype
|
||||
endfunction
|
||||
|
||||
function! context_filetype#get_filetypes(...) abort
|
||||
let filetype = call('context_filetype#get_filetype', a:000)
|
||||
|
||||
let filetypes = [filetype]
|
||||
if filetype =~ '\.'
|
||||
if has_key(g:context_filetype#ignore_composite_filetypes, filetype)
|
||||
let filetypes =
|
||||
\ [g:context_filetype#ignore_composite_filetypes[filetype]]
|
||||
else
|
||||
" Set composite filetype.
|
||||
let filetypes += split(filetype, '\.')
|
||||
endif
|
||||
endif
|
||||
|
||||
for ft in copy(filetypes)
|
||||
let filetypes += s:get_same_filetypes(ft)
|
||||
endfor
|
||||
|
||||
if len(filetypes) > 1
|
||||
let filetypes = s:uniq(filetypes)
|
||||
endif
|
||||
|
||||
return filetypes
|
||||
endfunction
|
||||
|
||||
function! context_filetype#get_same_filetypes(...) abort
|
||||
let filetype = call('context_filetype#get_filetype', a:000)
|
||||
|
||||
let filetypes = []
|
||||
for ft in context_filetype#get_filetypes(filetype)
|
||||
let filetypes += s:get_same_filetypes(ft)
|
||||
endfor
|
||||
|
||||
if len(filetypes) > 1
|
||||
let filetypes = s:uniq(filetypes)
|
||||
endif
|
||||
|
||||
return filetypes
|
||||
endfunction
|
||||
|
||||
|
||||
function! context_filetype#get_range(...) abort
|
||||
let base_filetype = get(a:, 1, &filetype)
|
||||
return context_filetype#get(base_filetype).range
|
||||
endfunction
|
||||
|
||||
|
||||
function! context_filetype#default_filetypes() abort
|
||||
return deepcopy(s:default_filetypes)
|
||||
endfunction
|
||||
|
||||
function! context_filetype#filetypes() abort
|
||||
if exists('b:context_filetype_filetypes')
|
||||
return deepcopy(b:context_filetype_filetypes)
|
||||
endif
|
||||
return extend(deepcopy(s:default_filetypes), deepcopy(g:context_filetype#filetypes))
|
||||
endfunction
|
||||
|
||||
|
||||
" s:default_filetypes
|
||||
let s:default_filetypes = {
|
||||
\ 'c': [
|
||||
\ {
|
||||
\ 'start': '_*asm_*\s\+\h\w*',
|
||||
\ 'end': '$', 'filetype': 'masm',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': '_*asm_*\s*\%(\n\s*\)\?{',
|
||||
\ 'end': '}', 'filetype': 'masm',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': '_*asm_*\s*\%(_*volatile_*\s*\)\?(',
|
||||
\ 'end': ');', 'filetype': 'gas',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'cpp': [
|
||||
\ {
|
||||
\ 'start': '_*asm_*\s\+\h\w*',
|
||||
\ 'end': '$', 'filetype': 'masm',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': '_*asm_*\s*\%(\n\s*\)\?{',
|
||||
\ 'end': '}', 'filetype': 'masm',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': '_*asm_*\s*\%(_*volatile_*\s*\)\?(',
|
||||
\ 'end': ');', 'filetype': 'gas',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'd': [
|
||||
\ {
|
||||
\ 'start': 'asm\s*\%(\n\s*\)\?{',
|
||||
\ 'end': '}', 'filetype': 'masm',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'eruby': [
|
||||
\ {
|
||||
\ 'start': '<%[=#]\?',
|
||||
\ 'end': '%>', 'filetype': 'ruby',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'help': [
|
||||
\ {
|
||||
\ 'start': '^>\|\s>$',
|
||||
\ 'end': '^<\|^\S\|^$', 'filetype': 'vim',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'html': [
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<script\%( [^>]*\)\? type="text/javascript"\%( [^>]*\)\?>',
|
||||
\ 'end': '</script>', 'filetype': 'javascript',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<script\%( [^>]*\)\? type="text/coffeescript"\%( [^>]*\)\?>',
|
||||
\ 'end': '</script>', 'filetype': 'coffee',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<script\%( [^>]*\)\?>',
|
||||
\ 'end': '</script>', 'filetype': 'javascript',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<style\%( [^>]*\)\?>',
|
||||
\ 'end': '</style>', 'filetype': 'css',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<[^>]\+ style=\([''"]\)',
|
||||
\ 'end': '\1', 'filetype': 'css',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'vue': [
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<template\%( [^>]*\)\? \%(lang="\%(\(\h\w*\)\)"\)\%( [^>]*\)\?>',
|
||||
\ 'end': '</template>', 'filetype': '\1',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<template\%( [^>]*\)\?>',
|
||||
\ 'end': '</template>', 'filetype': 'html',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<script\%( [^>]*\)\? \%(ts\|lang="\%(ts\|typescript\)"\)\%( [^>]*\)\?>',
|
||||
\ 'end': '</script>', 'filetype': 'typescript',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<script\%( [^>]*\)\? \%(lang="\%(\(\h\w*\)\)"\)\%( [^>]*\)\?>',
|
||||
\ 'end': '</script>', 'filetype': '\1',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<script\%( [^>]*\)\?>',
|
||||
\ 'end': '</script>', 'filetype': 'javascript',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<style\%( [^>]*\)\? \%(lang="\%(\(\h\w*\)\)"\)\%( [^>]*\)\?>',
|
||||
\ 'end': '</style>', 'filetype': '\1',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<style\%( [^>]*\)\?>',
|
||||
\ 'end': '</style>', 'filetype': 'css',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<\(\h\w*\)>',
|
||||
\ 'end': '</\1>', 'filetype': 'vue-\1',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<\(\h\w*\) \%(lang="\%(\(\h\w*\)\)"\)\%( [^>]*\)\?>',
|
||||
\ 'end': '</\1>', 'filetype': '\2',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'int-nyaos': [
|
||||
\ {
|
||||
\ 'start': '\<lua_e\s\+\(["'']\)',
|
||||
\ 'end': '\1\@<!\1\1\@!', 'filetype': 'lua',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'lua': [
|
||||
\ {
|
||||
\ 'start': 'vim.command\s*(\([''"]\)',
|
||||
\ 'end': '\\\@<!\1', 'filetype': 'vim',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': 'vim.eval\s*(\([''"]\)',
|
||||
\ 'end': '\\\@<!\1', 'filetype': 'vim',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'nyaos': [
|
||||
\ {
|
||||
\ 'start': '\<lua_e\s\+\(["'']\)',
|
||||
\ 'end': '\1\@<!\1\1\@!', 'filetype': 'lua',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'perl6': [
|
||||
\ {
|
||||
\ 'start': 'Q:PIR\s*{',
|
||||
\ 'end': '}', 'filetype': 'pir',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'python': [
|
||||
\ {
|
||||
\ 'start': 'vim.command\s*(\([''"]\)',
|
||||
\ 'end': '\\\@<!\1', 'filetype': 'vim',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': 'vim.eval\s*(\([''"]\)',
|
||||
\ 'end': '\\\@<!\1', 'filetype': 'vim',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': 'vim.call\s*(\([''"]\)',
|
||||
\ 'end': '\\\@<!\1', 'filetype': 'vim',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'vim': [
|
||||
\ {
|
||||
\ 'start': '^\s*pe\%[rl\] <<\s*\(\h\w*\)',
|
||||
\ 'end': '^\1', 'filetype': 'perl',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': '^\s*py\%[thon\]3\? <<\s*\(\h\w*\)',
|
||||
\ 'end': '^\1', 'filetype': 'python',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': '^\s*rub\%[y\] <<\s*\(\h\w*\)',
|
||||
\ 'end': '^\1', 'filetype': 'ruby',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': '^\s*lua <<\s*\(\h\w*\)',
|
||||
\ 'end': '^\1', 'filetype': 'lua',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': '^\s*lua ',
|
||||
\ 'end': '\n\|\s\+|', 'filetype': 'lua',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'vimperator': [
|
||||
\ {
|
||||
\ 'start': '^\s*\%(javascript\|js\)\s\+<<\s*\(\h\w*\)',
|
||||
\ 'end': '^\1', 'filetype': 'javascript',
|
||||
\ }
|
||||
\ ],
|
||||
\ 'vimshell': [
|
||||
\ {
|
||||
\ 'start': 'vexe \([''"]\)',
|
||||
\ 'end': '\\\@<!\1', 'filetype': 'vim',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': ' :\w*',
|
||||
\ 'end': '\n', 'filetype': 'vim',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': ' vexe\s\+',
|
||||
\ 'end': '\n', 'filetype': 'vim',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'xhtml': [
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<script\%( [^>]*\)\? type="text/javascript"\%( [^>]*\)\?>',
|
||||
\ 'end': '</script>', 'filetype': 'javascript',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start':
|
||||
\ '<script\%( [^>]*\)\? type="text/coffeescript"\%( [^>]*\)\?>',
|
||||
\ 'end': '</script>', 'filetype': 'coffee',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': '<style\%( [^>]*\)\? type="text/css"\%( [^>]*\)\?>',
|
||||
\ 'end': '</style>', 'filetype': 'css',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'markdown': [
|
||||
\ {
|
||||
\ 'start' : '^\s*```\s*\(\h\w*\)',
|
||||
\ 'end' : '^\s*```$', 'filetype' : '\1',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'haml': [
|
||||
\ {
|
||||
\ 'start' : '^\s*-',
|
||||
\ 'end' : '$', 'filetype' : 'ruby',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start' : '^\s*\w*=',
|
||||
\ 'end' : '$', 'filetype' : 'ruby',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start' : '^:javascript$',
|
||||
\ 'end' : '^\S', 'filetype' : 'javascript',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start' : '^:css$',
|
||||
\ 'end' : '^\S', 'filetype' : 'css',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'jade': [
|
||||
\ {
|
||||
\ 'start' : '^\(\s*\)script\.\s*$',
|
||||
\ 'end' : '^\%(\1\s\|\s*$\)\@!',
|
||||
\ 'filetype' : 'javascript',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start' : '^\(\s*\):coffeescript\s*$',
|
||||
\ 'end' : '^\%(\1\s\|\s*$\)\@!',
|
||||
\ 'filetype' : 'coffee',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start' : '^\(\s*\):\(\h\w*\)\s*$',
|
||||
\ 'end' : '^\%(\1\s\|\s*$\)\@!',
|
||||
\ 'filetype' : '\2',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'toml': [
|
||||
\ {
|
||||
\ 'start': '\<hook_\%('.
|
||||
\ 'add\|source\|post_source\|post_update'.
|
||||
\ '\)\s*=\s*\('."'''".'\|"""\)',
|
||||
\ 'end': '\1', 'filetype': 'vim',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'go': [
|
||||
\ {
|
||||
\ 'start': '^\s*\%(//\s*\)\?#\s*include\s\+',
|
||||
\ 'end': '$', 'filetype': 'c',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'asciidoc': [
|
||||
\ {
|
||||
\ 'start' : '^\[source\%(%[^,]*\)\?,\(\h\w*\)\(,.*\)\?\]\s*\n----\s*\n',
|
||||
\ 'end' : '^----\s*$', 'filetype' : '\1',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start' : '^\[source\%(%[^,]*\)\?,\(\h\w*\)\(,.*\)\?\]\s*\n',
|
||||
\ 'end' : '^$', 'filetype' : '\1',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'review': [
|
||||
\ {
|
||||
\ 'start': '^//list\[[^]]\+\]\[[^]]\+\]\[\([^]]\+\)\]{',
|
||||
\ 'end': '^//}', 'filetype' : '\1',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'javascript': [
|
||||
\ {
|
||||
\ 'synname_pattern': '^jsx',
|
||||
\ 'filetype' : 'jsx',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': '^\s*{/\*',
|
||||
\ 'end': '\*/}', 'filetype' : 'jsx',
|
||||
\ },
|
||||
\ ],
|
||||
\ 'typescript': [
|
||||
\ {
|
||||
\ 'synname_pattern': '^jsx',
|
||||
\ 'filetype' : 'tsx',
|
||||
\ },
|
||||
\ {
|
||||
\ 'start': '^\s*{/\*',
|
||||
\ 'end': '\*/}', 'filetype' : 'tsx',
|
||||
\ },
|
||||
\ ],
|
||||
\}
|
||||
|
||||
|
||||
" s:default_same_filetypes {{{
|
||||
let s:default_same_filetypes = {
|
||||
\ 'cpp': 'c',
|
||||
\ 'erb': 'ruby,html,xhtml',
|
||||
\ 'html': 'xhtml',
|
||||
\ 'xml': 'xhtml',
|
||||
\ 'xhtml': 'html,xml',
|
||||
\ 'htmldjango': 'html',
|
||||
\ 'css': 'scss',
|
||||
\ 'scss': 'css',
|
||||
\ 'stylus': 'css',
|
||||
\ 'less': 'css',
|
||||
\ 'tex': 'bib,plaintex',
|
||||
\ 'plaintex': 'bib,tex',
|
||||
\ 'lingr-say': 'lingr-messages,lingr-members',
|
||||
\ 'J6uil_say': 'J6uil',
|
||||
\ 'vimconsole': 'vim',
|
||||
\
|
||||
\ 'int-irb': 'ruby',
|
||||
\ 'int-ghci': 'haskell',
|
||||
\ 'int-hugs': 'haskell',
|
||||
\ 'int-python': 'python',
|
||||
\ 'int-python3': 'python',
|
||||
\ 'int-ipython': 'python',
|
||||
\ 'int-ipython3': 'python',
|
||||
\ 'int-gosh': 'scheme',
|
||||
\ 'int-clisp': 'lisp',
|
||||
\ 'int-erl': 'erlang',
|
||||
\ 'int-zsh': 'zsh',
|
||||
\ 'int-bash': 'bash',
|
||||
\ 'int-sh': 'sh',
|
||||
\ 'int-cmdproxy': 'dosbatch',
|
||||
\ 'int-powershell': 'powershell',
|
||||
\ 'int-perlsh': 'perl',
|
||||
\ 'int-perl6': 'perl6',
|
||||
\ 'int-ocaml': 'ocaml',
|
||||
\ 'int-clj': 'clojure',
|
||||
\ 'int-lein': 'clojure',
|
||||
\ 'int-sml': 'sml',
|
||||
\ 'int-smlsharp': 'sml',
|
||||
\ 'int-js': 'javascript',
|
||||
\ 'int-kjs': 'javascript',
|
||||
\ 'int-rhino': 'javascript',
|
||||
\ 'int-coffee': 'coffee',
|
||||
\ 'int-gdb': 'gdb',
|
||||
\ 'int-scala': 'scala',
|
||||
\ 'int-nyaos': 'nyaos',
|
||||
\ 'int-php': 'php',
|
||||
\}
|
||||
|
||||
|
||||
function! s:get_same_filetypes(filetype) abort
|
||||
let same_filetypes = extend(copy(s:default_same_filetypes),
|
||||
\ g:context_filetype#same_filetypes)
|
||||
return split(get(same_filetypes, a:filetype,
|
||||
\ get(same_filetypes, '_', '')), ',')
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:stopline_forward() abort
|
||||
let stopline_forward = line('.') + g:context_filetype#search_offset
|
||||
return (stopline_forward > line('$')) ? line('$') : stopline_forward
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:stopline_back() abort
|
||||
let stopline_back = line('.') - g:context_filetype#search_offset
|
||||
return (stopline_back <= 1) ? 1 : stopline_back
|
||||
endfunction
|
||||
|
||||
|
||||
" a <= b
|
||||
function! s:pos_less_equal(a, b) abort
|
||||
return a:a[0] == a:b[0] ? a:a[1] <= a:b[1] : a:a[0] <= a:b[0]
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:is_in(start, end, pos) abort
|
||||
" start <= pos && pos <= end
|
||||
return s:pos_less_equal(a:start, a:pos) && s:pos_less_equal(a:pos, a:end)
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:file_range() abort
|
||||
return [[1, 1], [line('$'), len(getline('$'))+1]]
|
||||
endfunction
|
||||
|
||||
function! s:replace_submatch(pattern, match_list) abort
|
||||
return substitute(a:pattern, '\\\@>\(\d\)',
|
||||
\ {m -> a:match_list[m[1]]}, 'g')
|
||||
endfunction
|
||||
|
||||
function! s:replace_submatch_pattern(pattern, match_list) abort
|
||||
let pattern = ''
|
||||
let backref_end_prev = 0
|
||||
let backref_start = match(a:pattern, '\\\@>\d')
|
||||
let backref_end = backref_start + 2
|
||||
let magic = '\m'
|
||||
let magic_start = match(a:pattern, '\\\@>[vmMV]')
|
||||
while 0 <= backref_start
|
||||
while 0 <= magic_start && magic_start <= backref_end
|
||||
let magic = a:pattern[magic_start : magic_start + 1]
|
||||
let magic_start = match(a:pattern, '\\\@>[vmMV]', magic_start + 2)
|
||||
if magic_start == backref_end
|
||||
let backref_end += 2
|
||||
endif
|
||||
endwhile
|
||||
if backref_start != 0
|
||||
let pattern .= a:pattern[backref_end_prev : backref_start - 1]
|
||||
endif
|
||||
let pattern .= '\V'
|
||||
\ . escape(a:match_list[a:pattern[backref_start + 1]], '\')
|
||||
\ . magic
|
||||
let backref_end_prev = backref_end
|
||||
let backref_start = match(a:pattern, '\\\@>\d', backref_end_prev)
|
||||
let backref_end = backref_start + 2
|
||||
endwhile
|
||||
return pattern . a:pattern[backref_end_prev : -1]
|
||||
endfunction
|
||||
|
||||
|
||||
let s:null_pos = [0, 0]
|
||||
let s:null_range = [[0, 0], [0, 0]]
|
||||
|
||||
|
||||
function! s:search_range(start_pattern, end_pattern) abort
|
||||
let stopline_forward = s:stopline_forward()
|
||||
let stopline_back = s:stopline_back()
|
||||
|
||||
let cur_text =
|
||||
\ (mode() ==# 'i' ? (col('.')-1) : col('.')) >= len(getline('.')) ?
|
||||
\ getline('.') :
|
||||
\ matchstr(getline('.'),
|
||||
\ '^.*\%' . (mode() ==# 'i' ? col('.') : col('.') - 1)
|
||||
\ . 'c' . (mode() ==# 'i' ? '' : '.'))
|
||||
let curline_pattern = a:start_pattern . '\ze.\{-}$'
|
||||
if cur_text =~# curline_pattern
|
||||
let start = [line('.'), matchend(cur_text, curline_pattern)]
|
||||
else
|
||||
let start = searchpos(a:start_pattern, 'bnceW', stopline_back)
|
||||
endif
|
||||
if start == s:null_pos
|
||||
return s:null_range
|
||||
endif
|
||||
let start[1] += 1
|
||||
|
||||
let end_pattern = a:end_pattern
|
||||
if end_pattern =~# '\\\@>\d'
|
||||
let lines = getline(start[0], line('.'))
|
||||
let match_list = matchlist(join(lines, "\n"), a:start_pattern)
|
||||
let end_pattern = s:replace_submatch_pattern(end_pattern, match_list)
|
||||
endif
|
||||
|
||||
let end_forward = searchpos(end_pattern, 'ncW', stopline_forward)
|
||||
if end_forward == s:null_pos
|
||||
let end_forward = [line('$'), len(getline('$'))+1]
|
||||
endi
|
||||
|
||||
let end_backward = searchpos(end_pattern, 'bnW', stopline_back)
|
||||
if s:pos_less_equal(start, end_backward)
|
||||
return s:null_range
|
||||
endif
|
||||
let end_forward[1] -= 1
|
||||
|
||||
if mode() !=# 'i' && start[1] >= strdisplaywidth(getline(start[0]))
|
||||
let start[0] += 1
|
||||
let start[1] = 1
|
||||
endif
|
||||
|
||||
if end_forward[1] <= 1
|
||||
let end_forward[0] -= 1
|
||||
let len = len(getline(end_forward[0]))
|
||||
let len = len ? len : 1
|
||||
let end_forward[1] = len
|
||||
endif
|
||||
|
||||
return [start, end_forward]
|
||||
endfunction
|
||||
|
||||
|
||||
let s:null_context = {
|
||||
\ 'filetype' : '',
|
||||
\ 'range' : s:null_range,
|
||||
\}
|
||||
|
||||
|
||||
function! s:get_context(filetype, context_filetypes, search_range) abort
|
||||
let base_filetype = empty(a:filetype) ? 'nothing' : a:filetype
|
||||
let context_filetypes = get(a:context_filetypes, base_filetype, [])
|
||||
if empty(context_filetypes)
|
||||
return s:null_context
|
||||
endif
|
||||
|
||||
let pos = [line('.'), col('.')]
|
||||
|
||||
for context in context_filetypes
|
||||
if has_key(context, 'synname_pattern')
|
||||
for id in synstack(line('.'), col('.'))
|
||||
let synname = synIDattr(id, 'name')
|
||||
if synname =~# context.synname_pattern
|
||||
return {'filetype' : context.filetype, 'range': s:null_range, 'synname': synname}
|
||||
endif
|
||||
endfor
|
||||
continue
|
||||
endif
|
||||
|
||||
let range = s:search_range(context.start, context.end)
|
||||
|
||||
" Set cursor position
|
||||
let start = range[0]
|
||||
let end = [range[1][0], (mode() ==# 'i') ? range[1][1]+1 : range[1][1]]
|
||||
|
||||
" start <= pos && pos <= end
|
||||
" search_range[0] <= start && start <= search_range[1]
|
||||
" search_range[0] <= end && end <= search_range[1]
|
||||
if range != s:null_range
|
||||
\ && s:is_in(start, end, pos)
|
||||
\ && s:is_in(a:search_range[0], a:search_range[1], range[0])
|
||||
\ && s:is_in(a:search_range[0], a:search_range[1], range[1])
|
||||
let context_filetype = context.filetype
|
||||
if context.filetype =~# '\\\@>\d'
|
||||
let stopline_back = s:stopline_back()
|
||||
let lines = getline(
|
||||
\ searchpos(context.start, 'nbW', stopline_back)[0],
|
||||
\ line('.')
|
||||
\ )
|
||||
let match_list = matchlist(join(lines, "\n"), context.start)
|
||||
let context_filetype = s:replace_submatch(context.filetype, match_list)
|
||||
endif
|
||||
return {'filetype' : context_filetype, 'range' : range}
|
||||
endif
|
||||
endfor
|
||||
|
||||
return s:null_context
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:get_nest_impl(filetype, context_filetypes, prev_context) abort
|
||||
let context = s:get_context(a:filetype,
|
||||
\ a:context_filetypes, a:prev_context.range)
|
||||
if context.range != s:null_range && context.filetype !=# a:filetype
|
||||
return s:get_nest_impl(context.filetype, a:context_filetypes, context)
|
||||
else
|
||||
return a:prev_context
|
||||
endif
|
||||
endfunction
|
||||
|
||||
|
||||
function! s:get_nest(filetype, context_filetypes) abort
|
||||
let context = s:get_context(a:filetype, a:context_filetypes, s:file_range())
|
||||
return s:get_nest_impl(context.filetype, a:context_filetypes, context)
|
||||
endfunction
|
||||
|
||||
function! s:uniq(list) abort
|
||||
let dict = {}
|
||||
for item in a:list
|
||||
if item != '' && !has_key(dict, item)
|
||||
let dict[item] = item
|
||||
endif
|
||||
endfor
|
||||
|
||||
return values(dict)
|
||||
endfunction
|
232
bundle/context_filetype.vim/doc/context_filetype.jax
Normal file
232
bundle/context_filetype.vim/doc/context_filetype.jax
Normal file
@ -0,0 +1,232 @@
|
||||
*context_filetype.txt* Vim script の context filetype ライブラリ
|
||||
|
||||
Version: 1.0
|
||||
Author : Shougo <Shougo.Matsu at gmail.com>
|
||||
License: MIT license
|
||||
|
||||
CONTENTS *context_filetype-contents*
|
||||
|
||||
概要 |context_filetype-introduction|
|
||||
インターフェース |context_filetype-interface|
|
||||
変数 |context_filetype-variables|
|
||||
関数 |context_filetype-functions|
|
||||
変更履歴 |context_filetype-changelog|
|
||||
|
||||
==============================================================================
|
||||
概要 *context_filetype-introduction*
|
||||
|
||||
*context_filetype* はカーソル位置を基準とした、文脈から特定の filetype を判定す
|
||||
る為の Vim script ライブラリです。
|
||||
コード中に他の言語を埋め込むような言語で利用する事が出来ます。
|
||||
|
||||
また、このプラグインは他のプラグインから使用する事を想定して作られています。
|
||||
|
||||
|
||||
==============================================================================
|
||||
サポート *context_filetype-support*
|
||||
|
||||
各 filetype で対応しているコンテキストの一覧です。
|
||||
|
||||
- "c"
|
||||
masm
|
||||
gas
|
||||
|
||||
- "cpp"
|
||||
masm
|
||||
gas
|
||||
|
||||
- "d"
|
||||
masm
|
||||
|
||||
- "eruby"
|
||||
ruby
|
||||
|
||||
- "help"
|
||||
vim
|
||||
|
||||
- "html"
|
||||
javascript
|
||||
coffee
|
||||
css
|
||||
|
||||
- "int-nyaos"
|
||||
lua
|
||||
|
||||
- "lua"
|
||||
vim
|
||||
|
||||
- "nyaos"
|
||||
lua
|
||||
|
||||
- "perl16"
|
||||
pir
|
||||
|
||||
- "python"
|
||||
vim
|
||||
|
||||
- "vim"
|
||||
python
|
||||
ruby
|
||||
lua
|
||||
|
||||
- "vimshell"
|
||||
vim
|
||||
|
||||
- "xhtml"
|
||||
javascript
|
||||
coffee
|
||||
css
|
||||
|
||||
- "markdown"
|
||||
|
||||
- "haml"
|
||||
ruby
|
||||
javascript
|
||||
css
|
||||
|
||||
|
||||
==============================================================================
|
||||
インターフェース *context_filetype-interface*
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
変数 *context_filetype-variables*
|
||||
|
||||
g:context_filetype#filetypes *g:context_filetype#filetypes*
|
||||
各 filetype を判定する為の辞書です。
|
||||
各 filetype に対してリストで設定する事ができます。
|
||||
|
||||
"start" : コンテキストの開始パターン
|
||||
"end" : コンテキストの終了パターン
|
||||
"filetype" : 判定を行う filetype
|
||||
"end" または "filetype" に \1 が設定されている場
|
||||
合は "start" にマッチした値になります。
|
||||
>
|
||||
" Examples:
|
||||
let g:context_filetype#filetypes = {
|
||||
\ 'perl6' : [
|
||||
\ {
|
||||
\ 'start' : 'Q:PIR\s*{',
|
||||
\ 'end' : '}',
|
||||
\ 'filetype' : 'pir',
|
||||
\ }
|
||||
\ ],
|
||||
\ 'vim' : [
|
||||
\ {
|
||||
\ 'start' : '^\s*python <<\s*\(\h\w*\)',
|
||||
\ 'end' : '^\1',
|
||||
\ 'filetype' : 'python',
|
||||
\ }
|
||||
\ ],
|
||||
\ 'markdown': [
|
||||
\ {
|
||||
\ 'start' : '^\s*```\s*\(\h\w*\)',
|
||||
\ 'end' : '^\s*```$',
|
||||
\ 'filetype' : '\1',
|
||||
\ },
|
||||
\ ],
|
||||
\}
|
||||
<
|
||||
b:context_filetype_filetypes *b:context_filetype_filetypes*
|
||||
バッファ変数版の |g:context_filetype#filetypes| です。
|
||||
これが設定されている場合、|g:context_filetype#filetypes| は無
|
||||
視されます。
|
||||
|
||||
|
||||
*g:context_filetype#same_filetypes*
|
||||
g:context_filetype#same_filetypes
|
||||
各 same filetype を判定する為の辞書です。
|
||||
各 filetype に対してカンマ区切りの文字列で設定する事ができま
|
||||
す。
|
||||
>
|
||||
if !exists('g:context_filetype#same_filetypes')
|
||||
let g:context_filetype#same_filetypes = {}
|
||||
endif
|
||||
" In c buffers, completes from cpp and d buffers.
|
||||
let g:context_filetype#same_filetypes.c = 'cpp,d'
|
||||
" In cpp buffers, completes from c buffers.
|
||||
let g:context_filetype#same_filetypes.cpp = 'c'
|
||||
" In gitconfig buffers, completes from all buffers.
|
||||
let g:context_filetype#same_filetypes.gitconfig = '_'
|
||||
" In default, completes from all buffers.
|
||||
let g:context_filetype#same_filetypes._ = '_'
|
||||
<
|
||||
|
||||
*g:context_filetype#ignore_composite_filetypes*
|
||||
g:context_filetype#ignore_composite_filetypes
|
||||
複合 filetype を他の filetype に変換する為の辞書です。
|
||||
>
|
||||
" Examples:
|
||||
let g:context_filetype#ignore_composite_filetypes = {
|
||||
\ 'ruby.spec' : 'ruby'
|
||||
\ }
|
||||
<
|
||||
*g:context_filetype#search_offset*
|
||||
g:context_filetype#search_offset
|
||||
コンテキストを判定する時にカーソル位置からこの変数に設定され
|
||||
ている行数の範囲のみを対象として判定を行います。
|
||||
バッファの行数が多くて動作が重く感じる場合はこの値を小さくし
|
||||
て試してみて下さい。
|
||||
Default: >
|
||||
" カーソル位置から前後 200 行の範囲で判定を行う
|
||||
let g:context_filetype#search_offset = 200
|
||||
<
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
関数 *context_filetype-functions*
|
||||
|
||||
context_filetype#version() *context_filetype#version()*
|
||||
バージョン情報を返す。
|
||||
Note: このライブラリがインストールされているかどうかの判定を
|
||||
使用する場合に利用することもできます。
|
||||
Example: >
|
||||
let has_context_filetype = 0
|
||||
silent! let has_context_filetype = context_filetype#version()
|
||||
if has_context_filetype
|
||||
" context_filetype.vim が使用出来る場合の処理
|
||||
else
|
||||
" context_filetype.vim が使用出来ない場合の処理
|
||||
endif
|
||||
<
|
||||
|
||||
*context_filetype#default_filetypes()*
|
||||
context_filetype#default_filetypes()
|
||||
デフォルトで設定されている |g:context_filetype#filetypes| の値
|
||||
を返す。
|
||||
|
||||
context_filetype#get([{filetype}]) *context_filetype#get()*
|
||||
カーソル位置のコンテキスト情報を下記のようなフォーマットで返
|
||||
す。
|
||||
>
|
||||
{
|
||||
"filetype" : "vim",
|
||||
"range" : [[3, 2], [10, 2]]
|
||||
}
|
||||
<
|
||||
コンテキストの判定には {filetype} が使用され、{filetype} が渡
|
||||
されなければ 'filetype' の値が使用される。
|
||||
|
||||
context_filetype#get_filetype([{filetype}]) *context_filetype#get_filetype()*
|
||||
カーソル位置のコンテキストの filetype を返す。
|
||||
コンテキストの判定には {filetype} が使用され、{filetype} が渡
|
||||
されなければ 'filetype' の値が使用される。
|
||||
コンテキストが見つからなかった場合は {filetype} が返される。
|
||||
|
||||
*context_filetype#get_filetypes()*
|
||||
context_filetype#get_filetypes([{filetype}])
|
||||
カーソル位置のコンテキストの filetype をリスト形式で返す。
|
||||
この filetype には複合 filetype と same filetype が含まれる。
|
||||
コンテキストの判定には {filetype} が使用され、{filetype} が渡
|
||||
されなければ 'filetype' の値が使用される。
|
||||
|
||||
context_filetype#get_range([{filetype}]) *context_filetype#get_range()*
|
||||
カーソル位置のコンテキストの範囲を [[{start}], [{end}]] で返す。
|
||||
>
|
||||
[[3, 1], [4, 2]]
|
||||
<
|
||||
コンテキストの判定には {filetype} が使用され、{filetype} が渡
|
||||
されなければ 'filetype' の値が使用される。
|
||||
コンテキストが見つからなかった場合は [[0,0], [0,0]] が返される。
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:ft=help:norl:noet:fen:noet:
|
140
bundle/context_filetype.vim/doc/context_filetype.txt
Normal file
140
bundle/context_filetype.vim/doc/context_filetype.txt
Normal file
@ -0,0 +1,140 @@
|
||||
*context_filetype.txt* Context filetype library for Vim script
|
||||
|
||||
Version: 1.0
|
||||
Author : Shougo <Shougo.Matsu at gmail.com>
|
||||
License: MIT license
|
||||
|
||||
CONTENTS *context_filetype-contents*
|
||||
|
||||
Introduction |context_filetype-introduction|
|
||||
Interface |context_filetype-interface|
|
||||
Variables |context_filetype-variables|
|
||||
Functions |context_filetype-functions|
|
||||
Changelog |context_filetype-changelog|
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *context_filetype-introduction*
|
||||
|
||||
*context_filetype* provides functions to find fenced code blocks and their
|
||||
filetype.
|
||||
For example Javascript blocks inside of HTML.
|
||||
The fenced code is detected by predefined regular expressions.
|
||||
|
||||
==============================================================================
|
||||
INTERFACE *context_filetype-interface*
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
VARIABLES *context_filetype-variables*
|
||||
|
||||
g:context_filetype#filetypes *g:context_filetype#filetypes*
|
||||
It is a dictionary to define context filetypes.
|
||||
The item is a list of dictionaries.
|
||||
|
||||
The keys and values are below.
|
||||
"filetype" : includes filetype name.
|
||||
"start" : filetype start pattern.
|
||||
"end" : filetype end pattern.
|
||||
|
||||
The patterns in "start" and "end" are always interpreted as if
|
||||
'magic' is set, ignoring the actual value of the 'magic'
|
||||
option.
|
||||
You can use "\0" through "\9" to refer to "start"'s match and
|
||||
sub-matches in "end" and "filetype".
|
||||
>
|
||||
" Examples:
|
||||
if !exists('g:context_filetype#filetypes')
|
||||
let g:context_filetype#filetypes = {}
|
||||
endif
|
||||
let g:context_filetype#filetypes.perl6 =
|
||||
\ [{'filetype' : 'pir', 'start' : 'Q:PIR\s*{', 'end' : '}'}]
|
||||
let g:context_filetype#filetypes.vim =
|
||||
\ [{'filetype' : 'python',
|
||||
\ 'start' : '^\s*python <<\s*\(\h\w*\)', 'end' : '^\1'}]
|
||||
<
|
||||
Because it is complicated, refer to s:initialize() in
|
||||
autoload/context_filetype.vim for the initial value.
|
||||
|
||||
b:context_filetype_filetypes *b:context_filetype_filetypes*
|
||||
It is the buffer variable version of
|
||||
|g:context_filetype#filetypes|.
|
||||
If you set it, |g:context_filetype#filetypes| is ignored.
|
||||
|
||||
*g:context_filetype#same_filetypes*
|
||||
g:context_filetype#same_filetypes
|
||||
It is a dictionary to connect file type mutually. It is
|
||||
effective at time to let you refer to "c" and "cpp" mutually.
|
||||
The value are comma-separated filetypes.
|
||||
If the value contains "_", context_filetype completes from all
|
||||
buffers. If the key is "_", the value will be used for
|
||||
default same filetypes.
|
||||
>
|
||||
if !exists('g:context_filetype#same_filetypes')
|
||||
let g:context_filetype#same_filetypes = {}
|
||||
endif
|
||||
" In c buffers, completes from cpp and d buffers.
|
||||
let g:context_filetype#same_filetypes.c = 'cpp,d'
|
||||
" In cpp buffers, completes from c buffers.
|
||||
let g:context_filetype#same_filetypes.cpp = 'c'
|
||||
" In gitconfig buffers, completes from all buffers.
|
||||
let g:context_filetype#same_filetypes.gitconfig = '_'
|
||||
" In default, completes from all buffers.
|
||||
let g:context_filetype#same_filetypes._ = '_'
|
||||
<
|
||||
Because it is complicated, refer to s:initialize() in
|
||||
autoload/context_filetype.vim for the initial value.
|
||||
|
||||
*g:context_filetype#ignore_composite_filetypes*
|
||||
g:context_filetype#ignore_composite_filetypes
|
||||
It is a dictionary to ignore composite file type.
|
||||
The dictionary's key is composite filetype and value is
|
||||
filetype.
|
||||
>
|
||||
" Examples:
|
||||
let g:context_filetype#ignore_composite_filetypes = {
|
||||
\ 'ruby.spec' : 'ruby'
|
||||
\ }
|
||||
<
|
||||
If you open filetype like "ruby.spec", completion is
|
||||
intended for "ruby" and "spec".
|
||||
But if you only want to complete "ruby" filetype,
|
||||
you can set this variable to ignore "spec".
|
||||
|
||||
Default value is {}.
|
||||
|
||||
*g:context_filetype#search_offset*
|
||||
g:context_filetype#search_offset
|
||||
It is the pattern search offset from current line.
|
||||
|
||||
Default value is 200.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
FUNCTIONS *context_filetype-functions*
|
||||
|
||||
context_filetype#version() *context_filetype#version()*
|
||||
Get version of context filetype library.
|
||||
Note: It is useful for library installation check.
|
||||
|
||||
context_filetype#get([{filetype}]) *context_filetype#get()*
|
||||
Get completion filetype from {filetype}.
|
||||
If you omit {filetype}, 'filetype' will be used.
|
||||
|
||||
*context_filetype#get_filetypes()*
|
||||
context_filetype#get_filetypes([{filetype}])
|
||||
Get completion filetypes from {filetype}.
|
||||
They contains same filetypes and composite filetypes.
|
||||
If you omit {filetype}, 'filetype' will be used.
|
||||
|
||||
*context_filetype#default_filetypes()*
|
||||
context_filetype#default_filetypes()
|
||||
Get the dictionary of all default filetypes.
|
||||
|
||||
*context_filetype#filetypes()*
|
||||
context_filetype#filetypes()
|
||||
Get the dictionary of all filetypes with
|
||||
* |b:context_filetype_filetypes| (if defined)
|
||||
* Or merged dictionary
|
||||
* |context_filetype#default_filetypes()|
|
||||
* |g:context_filetype#filetypes|
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:ft=help:norl:noet:fen:noet:
|
33
bundle/context_filetype.vim/test/test.vim
Normal file
33
bundle/context_filetype.vim/test/test.vim
Normal file
@ -0,0 +1,33 @@
|
||||
" 使い方
|
||||
" このファイルを :source する
|
||||
" test_files に保存されているファイルを開き、:ContextFiletypeTest
|
||||
" マッチしない filetype があれば quickfix へと出力される
|
||||
|
||||
" テストファイルの作り方
|
||||
" コンテキストが書かれたコード記述する
|
||||
" context_filetype#get() が返してほしい位置で filetype を `filetype` で記述する
|
||||
|
||||
|
||||
function! s:checker(filename)
|
||||
try
|
||||
let pos = getpos(".")
|
||||
let filetype_pattern = '`\w\+`'
|
||||
let result = ""
|
||||
|
||||
normal! gg0
|
||||
while search(filetype_pattern, 'W')
|
||||
if context_filetype#get_filetype() !=# expand('<cword>')
|
||||
let result .= printf("%s:%d: bad context filetype\n", a:filename, line('.'))
|
||||
endif
|
||||
endwhile
|
||||
|
||||
cgetexpr result
|
||||
cwindo
|
||||
finally
|
||||
call setpos(".", pos)
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
command! ContextFiletypeTest call s:checker(expand("%:p"))
|
||||
|
||||
|
57
bundle/context_filetype.vim/test/test_files/test.html
Normal file
57
bundle/context_filetype.vim/test/test_files/test.html
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
|
||||
<script type="text/javascript">`javascript`
|
||||
|
||||
`javascript`
|
||||
|
||||
`javascript`
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script>`javascript`
|
||||
|
||||
`javascript`
|
||||
|
||||
`javascript`
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script charset="utf-8">`javascript`
|
||||
|
||||
`javascript`
|
||||
|
||||
`javascript`
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/template">`html`
|
||||
|
||||
`html`
|
||||
|
||||
`html`
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/coffeescript">`coffee`
|
||||
|
||||
`coffee`
|
||||
|
||||
`coffee`
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style type="text/css">`css`
|
||||
|
||||
`css`
|
||||
|
||||
`css`
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
78
bundle/context_filetype.vim/test/test_files/test.md
Normal file
78
bundle/context_filetype.vim/test/test_files/test.md
Normal file
@ -0,0 +1,78 @@
|
||||
|
||||
|
||||
`markdown`
|
||||
|
||||
|
||||
```cpp
|
||||
|
||||
`cpp`
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
```hoge
|
||||
|
||||
`hoge`
|
||||
|
||||
```
|
||||
|
||||
|
||||
```vim
|
||||
|
||||
`vim`
|
||||
|
||||
python << EOF
|
||||
|
||||
`python`
|
||||
|
||||
vim.eval("`vim`")
|
||||
|
||||
EOF `vim`
|
||||
|
||||
|
||||
ruby << EOF
|
||||
|
||||
`ruby`
|
||||
|
||||
EOF
|
||||
|
||||
|
||||
```
|
||||
|
||||
```vim
|
||||
|
||||
ruby << EOF
|
||||
|
||||
`ruby`
|
||||
|
||||
EOF
|
||||
|
||||
```
|
||||
|
||||
```javascript
|
||||
|
||||
<script type="text/javascript">`javascript`
|
||||
|
||||
`javascript`
|
||||
|
||||
`javascript`
|
||||
|
||||
|
||||
`javascript`</script>
|
||||
|
||||
|
||||
```
|
||||
|
||||
```cpp
|
||||
|
||||
`cpp`
|
||||
|
||||
```
|
||||
|
||||
```text
|
||||
`text`本日は晴天なり`text`
|
||||
```
|
||||
|
||||
`markdown`
|
||||
|
13
bundle/context_filetype.vim/test/test_files/test.ny
Normal file
13
bundle/context_filetype.vim/test/test_files/test.ny
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
`nyaos`
|
||||
|
||||
lua_e "
|
||||
`lua`
|
||||
" `nyaos`
|
||||
|
||||
lua_e "`lua`" `nyaos`
|
||||
|
||||
lua_e "
|
||||
print(""`lua`"")
|
||||
" `nyaos`
|
||||
|
46
bundle/context_filetype.vim/test/test_files/test.vim
Normal file
46
bundle/context_filetype.vim/test/test_files/test.vim
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
`vim`
|
||||
|
||||
python << EOF
|
||||
|
||||
`python`
|
||||
|
||||
vim.eval("`vim`")
|
||||
|
||||
EOF `vim`
|
||||
|
||||
|
||||
ruby << EOF
|
||||
|
||||
`ruby`
|
||||
|
||||
EOF
|
||||
|
||||
|
||||
lua << EOF
|
||||
|
||||
`lua`
|
||||
|
||||
EOF
|
||||
|
||||
`vim`
|
||||
|
||||
|
||||
lua << hoge
|
||||
|
||||
`lua`
|
||||
|
||||
hoge
|
||||
|
||||
lua << hoge
|
||||
|
||||
lua l = vim.eval('`vim`')
|
||||
|
||||
EOF
|
||||
|
||||
|
||||
ruby << EOF
|
||||
|
||||
`ruby`
|
||||
|
||||
|
21
bundle/defx-git/LICENSE
Normal file
21
bundle/defx-git/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Kristijan Husak
|
||||
|
||||
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.
|
109
bundle/defx-git/README.md
Normal file
109
bundle/defx-git/README.md
Normal file
@ -0,0 +1,109 @@
|
||||
# defx-git
|
||||
|
||||
Git status implementation for [defx.nvim](http://github.com/Shougo/defx.nvim).
|
||||
|
||||
## Usage
|
||||
|
||||
Just append `git` to your columns when starting defx:
|
||||
|
||||
```viml
|
||||
:Defx -columns=git:mark:filename:type
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### Indicators
|
||||
|
||||
Which indicators (icons) to use for each status. These are the defaults:
|
||||
|
||||
```viml
|
||||
call defx#custom#column('git', 'indicators', {
|
||||
\ 'Modified' : '✹',
|
||||
\ 'Staged' : '✚',
|
||||
\ 'Untracked' : '✭',
|
||||
\ 'Renamed' : '➜',
|
||||
\ 'Unmerged' : '═',
|
||||
\ 'Ignored' : '☒',
|
||||
\ 'Deleted' : '✖',
|
||||
\ 'Unknown' : '?'
|
||||
\ })
|
||||
```
|
||||
|
||||
### Column Length
|
||||
|
||||
How many space should git column take. Default is `1` (Defx adds a single space between columns):
|
||||
|
||||
```viml
|
||||
call defx#custom#column('git', 'column_length', 1)
|
||||
```
|
||||
|
||||
Missing characters to match this length are populated with spaces, which means
|
||||
`✹` becomes `✹ `, etc.
|
||||
|
||||
Note: Make sure indicators are not longer than the column_length
|
||||
|
||||
### Show ignored
|
||||
|
||||
This flag determines if ignored files should be marked with indicator. Default is `false`:
|
||||
|
||||
```viml
|
||||
call defx#custom#column('git', 'show_ignored', 0)
|
||||
```
|
||||
|
||||
### Raw Mode
|
||||
|
||||
Show git status in raw mode (Same as first two chars of `git status --porcelain` command). Default is `0`:
|
||||
|
||||
```viml
|
||||
call defx#custom#column('git', 'raw_mode', 0)
|
||||
```
|
||||
|
||||
### Max Indicator Width
|
||||
|
||||
The number of characters to pad the git column. If not specified, the default
|
||||
will be the width of the longest indicator character.
|
||||
|
||||
```viml
|
||||
call defx#custom#column('git', 'max_indicator_width', 2)
|
||||
```
|
||||
|
||||
## Highlighting
|
||||
|
||||
Each indicator type can be overridden with the custom highlight. These are the defaults:
|
||||
|
||||
```viml
|
||||
hi Defx_git_Untracked guibg=NONE guifg=NONE ctermbg=NONE ctermfg=NONE
|
||||
hi Defx_git_Ignored guibg=NONE guifg=NONE ctermbg=NONE ctermfg=NONE
|
||||
hi Defx_git_Unknown guibg=NONE guifg=NONE ctermbg=NONE ctermfg=NONE
|
||||
hi Defx_git_Renamed ctermfg=214 guifg=#fabd2f
|
||||
hi Defx_git_Modified ctermfg=214 guifg=#fabd2f
|
||||
hi Defx_git_Unmerged ctermfg=167 guifg=#fb4934
|
||||
hi Defx_git_Deleted ctermfg=167 guifg=#fb4934
|
||||
hi Defx_git_Staged ctermfg=142 guifg=#b8bb26
|
||||
```
|
||||
|
||||
To use for example red for untracked files, add this **after** your colorscheme setup:
|
||||
|
||||
```viml
|
||||
colorscheme gruvbox
|
||||
hi Defx_git_Untracked guifg=#FF0000
|
||||
```
|
||||
|
||||
## Mappings
|
||||
|
||||
There are 5 mappings:
|
||||
|
||||
* `<Plug>(defx-git-next)` - Goes to the next file that has a git status
|
||||
* `<Plug>(defx-git-prev)` - Goes to the previous file that has a git status
|
||||
* `<Plug>(defx-git-stage)` - Stages the file/directory under cursor
|
||||
* `<Plug>(defx-git-reset)` - Unstages the file/directory under cursor
|
||||
* `<Plug>(defx-git-discard)` - Discards all changes to file/directory under cursor
|
||||
|
||||
If these are not manually mapped by the user, defaults are:
|
||||
```viml
|
||||
nnoremap <buffer><silent> [c <Plug>(defx-git-prev)
|
||||
nnoremap <buffer><silent> ]c <Plug>(defx-git-next)
|
||||
nnoremap <buffer><silent> ]a <Plug>(defx-git-stage)
|
||||
nnoremap <buffer><silent> ]r <Plug>(defx-git-reset)
|
||||
nnoremap <buffer><silent> ]d <Plug>(defx-git-discard)
|
||||
```
|
83
bundle/defx-git/ftplugin/defx.vim
Normal file
83
bundle/defx-git/ftplugin/defx.vim
Normal file
@ -0,0 +1,83 @@
|
||||
if exists('*defx#redraw')
|
||||
augroup defx_git
|
||||
autocmd!
|
||||
autocmd BufWritePost * call defx#redraw()
|
||||
augroup END
|
||||
endif
|
||||
|
||||
scriptencoding utf-8
|
||||
if exists('b:defx_git_loaded')
|
||||
finish
|
||||
endif
|
||||
|
||||
let b:defx_git_loaded = 1
|
||||
|
||||
function! s:search(dir) abort
|
||||
let l:icons = get(g:, 'defx_git_indicators', {})
|
||||
let l:icons_pattern = join(values(l:icons), '\|')
|
||||
|
||||
if !empty(l:icons_pattern)
|
||||
let l:direction = a:dir > 0 ? 'w' : 'bw'
|
||||
return search(printf('\(%s\)', l:icons_pattern), l:direction)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:git_cmd(cmd) abort
|
||||
let l:actions = {
|
||||
\ 'stage': '!git add',
|
||||
\ 'reset': '!git reset',
|
||||
\ 'discard': '!git checkout --'
|
||||
\ }
|
||||
let l:candidate = defx#get_candidate()
|
||||
let l:path = get(l:candidate, 'action__path')
|
||||
let l:word = get(l:candidate, 'word')
|
||||
let l:is_dir = get(l:candidate, 'is_directory')
|
||||
if empty(l:path)
|
||||
return
|
||||
endif
|
||||
|
||||
let l:cmd = l:actions[a:cmd].' '.l:path
|
||||
if a:cmd !=? 'discard'
|
||||
call execute(l:cmd)
|
||||
return defx#call_action('redraw')
|
||||
endif
|
||||
|
||||
let l:choice = confirm('Are you sure you want to discard all changes to '.l:word.'? ', "&Yes\n&No")
|
||||
if l:choice !=? 1
|
||||
return
|
||||
endif
|
||||
let l:status = system('git status --porcelain '.l:path)
|
||||
" File must be unstaged before discarding
|
||||
if !empty(l:status[0])
|
||||
call execute(l:actions['reset'].' '.l:path)
|
||||
endif
|
||||
|
||||
call execute(l:cmd)
|
||||
return defx#call_action('redraw')
|
||||
endfunction
|
||||
|
||||
nnoremap <buffer><silent><Plug>(defx-git-next) :<C-u>call <sid>search(1)<CR>
|
||||
nnoremap <buffer><silent><Plug>(defx-git-prev) :<C-u>call <sid>search(-1)<CR>
|
||||
nnoremap <buffer><silent><Plug>(defx-git-stage) :<C-u>call <sid>git_cmd('stage')<CR>
|
||||
nnoremap <buffer><silent><Plug>(defx-git-reset) :<C-u>call <sid>git_cmd('reset')<CR>
|
||||
nnoremap <buffer><silent><Plug>(defx-git-discard) :<C-u>call <sid>git_cmd('discard')<CR>
|
||||
|
||||
if !hasmapto('<Plug>(defx-git-prev)') && maparg('[c', 'n') ==? ''
|
||||
silent! nmap <buffer><unique><silent> [c <Plug>(defx-git-prev)
|
||||
endif
|
||||
|
||||
if !hasmapto('<Plug>(defx-git-next)') && maparg(']c', 'n') ==? ''
|
||||
silent! nmap <buffer><unique><silent> ]c <Plug>(defx-git-next)
|
||||
endif
|
||||
|
||||
if !hasmapto('<Plug>(defx-git-stage)') && maparg(']a', 'n') ==? ''
|
||||
silent! nmap <buffer><unique><silent> ]a <Plug>(defx-git-stage)
|
||||
endif
|
||||
|
||||
if !hasmapto('<Plug>(defx-git-reset)') && maparg(']r', 'n') ==? ''
|
||||
silent! nmap <buffer><unique><silent> ]r <Plug>(defx-git-reset)
|
||||
endif
|
||||
|
||||
if !hasmapto('<Plug>(defx-git-discard)') && maparg(']d', 'n') ==? ''
|
||||
silent! nmap <buffer><unique><silent> ]d <Plug>(defx-git-discard)
|
||||
endif
|
225
bundle/defx-git/rplugin/python3/defx/column/git.py
Normal file
225
bundle/defx-git/rplugin/python3/defx/column/git.py
Normal file
@ -0,0 +1,225 @@
|
||||
# ============================================================================
|
||||
# FILE: git.py
|
||||
# AUTHOR: Kristijan Husak <husakkristijan at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import typing
|
||||
import subprocess
|
||||
from defx.base.column import Base
|
||||
from defx.context import Context
|
||||
from defx.view import View
|
||||
from neovim import Nvim
|
||||
from functools import cmp_to_key
|
||||
from pathlib import PurePath
|
||||
|
||||
|
||||
class Column(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'git'
|
||||
self.vars = {
|
||||
'indicators': {
|
||||
'Modified': '✹',
|
||||
'Staged': '✚',
|
||||
'Untracked': '✭',
|
||||
'Renamed': '➜',
|
||||
'Unmerged': '═',
|
||||
'Ignored': '☒',
|
||||
'Deleted': '✖',
|
||||
'Unknown': '?'
|
||||
},
|
||||
'column_length': 1,
|
||||
'show_ignored': False,
|
||||
'raw_mode': False,
|
||||
'max_indicator_width': None
|
||||
}
|
||||
|
||||
custom_opts = ['indicators', 'column_length', 'show_ignored',
|
||||
'raw_mode', 'max_indicator_width']
|
||||
|
||||
for opt in custom_opts:
|
||||
if 'defx_git#' + opt in self.vim.vars:
|
||||
self.vars[opt] = self.vim.vars['defx_git#' + opt]
|
||||
|
||||
self.cache: typing.List[str] = []
|
||||
self.git_root = ''
|
||||
self.colors = {
|
||||
'Modified': {
|
||||
'color': 'guifg=#fabd2f ctermfg=214',
|
||||
'match': ' M'
|
||||
},
|
||||
'Staged': {
|
||||
'color': 'guifg=#b8bb26 ctermfg=142',
|
||||
'match': '\(M\|A\|C\).'
|
||||
},
|
||||
'Renamed': {
|
||||
'color': 'guifg=#fabd2f ctermfg=214',
|
||||
'match': 'R.'
|
||||
},
|
||||
'Unmerged': {
|
||||
'color': 'guifg=#fb4934 ctermfg=167',
|
||||
'match': '\(UU\|AA\|DD\)'
|
||||
},
|
||||
'Deleted': {
|
||||
'color': 'guifg=#fb4934 ctermfg=167',
|
||||
'match': ' D'
|
||||
},
|
||||
'Untracked': {
|
||||
'color': 'guifg=NONE guibg=NONE ctermfg=NONE ctermbg=NONE',
|
||||
'match': '??'
|
||||
},
|
||||
'Ignored': {
|
||||
'color': 'guifg=NONE guibg=NONE ctermfg=NONE ctermbg=NONE',
|
||||
'match': '!!'
|
||||
},
|
||||
'Unknown': {
|
||||
'color': 'guifg=NONE guibg=NONE ctermfg=NONE ctermbg=NONE',
|
||||
'match': 'X '
|
||||
}
|
||||
}
|
||||
min_column_length = 2 if self.vars['raw_mode'] else 1
|
||||
self.column_length = max(min_column_length, self.vars['column_length'])
|
||||
|
||||
def on_init(self, view: View, context: Context) -> None:
|
||||
# Set vim global variable for search mappings matching indicators
|
||||
self.vim.vars['defx_git_indicators'] = self.vars['indicators']
|
||||
|
||||
if not self.vars.get('max_indicator_width'):
|
||||
# Find longest indicator
|
||||
self.vars['max_indicator_width'] = len(
|
||||
max(self.vars['indicators'].values(), key=len))
|
||||
|
||||
def get(self, context: Context, candidate: dict) -> str:
|
||||
default = self.format('').ljust(
|
||||
self.column_length + self.vars['max_indicator_width'] - 1)
|
||||
if candidate.get('is_root', False):
|
||||
self.cache_status(candidate['action__path'])
|
||||
return default
|
||||
|
||||
if not self.cache:
|
||||
return default
|
||||
|
||||
entry = self.find_in_cache(candidate)
|
||||
|
||||
if not entry:
|
||||
return default
|
||||
|
||||
return self.get_indicator(entry)
|
||||
|
||||
def get_indicator(self, entry: str) -> str:
|
||||
if self.vars['raw_mode']:
|
||||
return self.format(entry[:2])
|
||||
|
||||
state = self.get_indicator_name(entry[0], entry[1])
|
||||
return self.format(
|
||||
self.vars['indicators'][state]
|
||||
)
|
||||
|
||||
def length(self, context: Context) -> int:
|
||||
return self.column_length
|
||||
|
||||
def syntaxes(self) -> typing.List[str]:
|
||||
return [
|
||||
self.syntax_name + '_' + name for name in self.vars['indicators']]
|
||||
|
||||
def highlight_commands(self) -> typing.List[str]:
|
||||
commands: typing.List[str] = []
|
||||
for name, icon in self.vars['indicators'].items():
|
||||
if self.vars['raw_mode']:
|
||||
commands.append((
|
||||
'syntax match {0}_{1} /{2}/ contained containedin={0}'
|
||||
).format(self.syntax_name, name, self.colors[name]['match']))
|
||||
else:
|
||||
commands.append((
|
||||
'syntax match {0}_{1} /[{2}]/ contained containedin={0}'
|
||||
).format(self.syntax_name, name, icon))
|
||||
|
||||
commands.append('highlight default {0}_{1} {2}'.format(
|
||||
self.syntax_name, name, self.colors[name]['color']
|
||||
))
|
||||
return commands
|
||||
|
||||
def find_in_cache(self, candidate: dict) -> str:
|
||||
action_path = PurePath(candidate['action__path']).as_posix()
|
||||
path = str(action_path).replace(f'{self.git_root}/', '')
|
||||
path += '/' if candidate['is_directory'] else ''
|
||||
for item in self.cache:
|
||||
item_path = item[3:]
|
||||
if item[0] == 'R':
|
||||
item_path = item_path.split(' -> ')[1]
|
||||
|
||||
if item_path.startswith(path):
|
||||
return item
|
||||
|
||||
return ''
|
||||
|
||||
def cache_status(self, path: str) -> None:
|
||||
self.cache = []
|
||||
|
||||
if not self.git_root or not str(path).startswith(self.git_root):
|
||||
self.git_root = PurePath(self.run_cmd(
|
||||
['git', 'rev-parse', '--show-toplevel'], path
|
||||
)).as_posix()
|
||||
|
||||
if not self.git_root:
|
||||
return None
|
||||
|
||||
cmd = ['git', 'status', '--porcelain', '-u']
|
||||
if self.vars['show_ignored']:
|
||||
cmd += ['--ignored']
|
||||
|
||||
status = self.run_cmd(cmd, self.git_root)
|
||||
results = [line for line in status.split('\n') if line != '']
|
||||
self.cache = sorted(results, key=cmp_to_key(self.sort))
|
||||
|
||||
def sort(self, a, b) -> int:
|
||||
if a[0] == 'U' or a[1] == 'U':
|
||||
return -1
|
||||
|
||||
if (a[0] == 'M' or a[1] == 'M') and not (b[0] == 'U' or b[1] == 'U'):
|
||||
return -1
|
||||
|
||||
if ((a[0] == '?' and a[1] == '?') and not
|
||||
(b[0] in ['M', 'U'] or b[1] in ['M', 'U'])):
|
||||
return -1
|
||||
|
||||
return 1
|
||||
|
||||
def format(self, column: str) -> str:
|
||||
return format(column, f'<{self.column_length}')
|
||||
|
||||
def get_indicator_name(self, us: str, them: str) -> str:
|
||||
if us == '?' and them == '?':
|
||||
return 'Untracked'
|
||||
elif us == ' ' and them == 'M':
|
||||
return 'Modified'
|
||||
elif us in ['M', 'A', 'C']:
|
||||
return 'Staged'
|
||||
elif us == 'R':
|
||||
return 'Renamed'
|
||||
elif us == '!':
|
||||
return 'Ignored'
|
||||
elif (us == 'U' or them == 'U' or us == 'A' and them == 'A'
|
||||
or us == 'D' and them == 'D'):
|
||||
return 'Unmerged'
|
||||
elif them == 'D':
|
||||
return 'Deleted'
|
||||
else:
|
||||
return 'Unknown'
|
||||
|
||||
def run_cmd(self, cmd: typing.List[str], cwd=None) -> str:
|
||||
try:
|
||||
p = subprocess.run(cmd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL, cwd=cwd)
|
||||
except:
|
||||
return ''
|
||||
|
||||
decoded = p.stdout.decode('utf-8')
|
||||
|
||||
if not decoded:
|
||||
return ''
|
||||
|
||||
return decoded.strip('\n')
|
21
bundle/defx-icons/LICENSE
Normal file
21
bundle/defx-icons/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 Kristijan Husak
|
||||
|
||||
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.
|
84
bundle/defx-icons/README.md
Normal file
84
bundle/defx-icons/README.md
Normal file
@ -0,0 +1,84 @@
|
||||
# Defx icons
|
||||
|
||||
Custom implementation of [vim-devicons](https://github.com/ryanoasis/vim-devicons) for [defx.nvim](https://github.com/Shougo/defx.nvim).
|
||||
|
||||
![screenshot from 2018-11-22 23-39-41](https://user-images.githubusercontent.com/1782860/48923552-eeed0b80-eeaf-11e8-98e8-8f4e7ec85194.png)
|
||||
|
||||
## Usage
|
||||
```vimL
|
||||
:Defx -columns=icons:indent:filename:type
|
||||
```
|
||||
This column is a replacement for mark column. It will properly highlight selected files.
|
||||
|
||||
## Configuration
|
||||
This is the default configuration:
|
||||
|
||||
```vimL
|
||||
let g:defx_icons_enable_syntax_highlight = 1
|
||||
let g:defx_icons_column_length = 2
|
||||
let g:defx_icons_directory_icon = ''
|
||||
let g:defx_icons_mark_icon = '*'
|
||||
let g:defx_icons_copy_icon = ''
|
||||
let g:defx_icons_move_icon = ''
|
||||
let g:defx_icons_parent_icon = ''
|
||||
let g:defx_icons_default_icon = ''
|
||||
let g:defx_icons_directory_symlink_icon = ''
|
||||
" Options below are applicable only when using "tree" feature
|
||||
let g:defx_icons_root_opened_tree_icon = ''
|
||||
let g:defx_icons_nested_opened_tree_icon = ''
|
||||
let g:defx_icons_nested_closed_tree_icon = ''
|
||||
```
|
||||
|
||||
Note: Syntax highlighting can cause some performance issues in defx window. Just disable it with the `let g:defx_icons_enable_syntax_highlight = 0`
|
||||
|
||||
|
||||
## Override colors
|
||||
|
||||
If you want to override some of the colors, you can do it this way:
|
||||
|
||||
For gui:
|
||||
|
||||
```vimL
|
||||
let g:defx_icons_gui_colors = {
|
||||
\ 'red': 'FFFFFF'
|
||||
\ }
|
||||
```
|
||||
|
||||
For term:
|
||||
|
||||
```vimL
|
||||
let g:defx_icons_term_colors = {
|
||||
\ 'red': 2
|
||||
\ }
|
||||
```
|
||||
|
||||
For directory icons these highlight groups are defined:
|
||||
|
||||
```vimL
|
||||
hi default link DefxIconsMarkIcon Statement
|
||||
hi default link DefxIconsCopyIcon WarningMsg
|
||||
hi default link DefxIconsMoveIcon ErrorMsg
|
||||
hi default link DefxIconsDirectory Directory
|
||||
hi default link DefxIconsParentDirectory Directory
|
||||
hi default link DefxIconsSymlinkDirectory Directory
|
||||
hi default link DefxIconsOpenedTreeIcon Directory
|
||||
hi default link DefxIconsNestedTreeIcon Directory
|
||||
hi default link DefxIconsClosedTreeIcon Directory
|
||||
```
|
||||
|
||||
For example, to change color of the directory icon when it's opened in tree to red color, you would do something like this:
|
||||
|
||||
```vimL
|
||||
hi DefxIconsOpenedTreeIcon guifg=#FF0000
|
||||
```
|
||||
|
||||
Or link it to something else that you want:
|
||||
|
||||
```vimL
|
||||
hi link DefxIconsOpenedTreeIcon Error
|
||||
```
|
||||
|
||||
## Thanks to
|
||||
|
||||
* [vim-devicons](https://github.com/ryanoasis/vim-devicons) for icons
|
||||
* [vim-nerdtree-syntax-highlight](https://github.com/tiagofumo/vim-nerdtree-syntax-highlight) for colors
|
229
bundle/defx-icons/plugin/defx_icons.vim
Normal file
229
bundle/defx-icons/plugin/defx_icons.vim
Normal file
@ -0,0 +1,229 @@
|
||||
scriptencoding utf-8
|
||||
if exists('g:loaded_defx_icons')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_defx_icons = 1
|
||||
|
||||
let s:enable_syntax_highlight = get(g:, 'defx_icons_enable_syntax_highlight', 1)
|
||||
let s:column_length = get(g:, 'defx_icons_column_length', 1)
|
||||
let s:parent_icon = get(g:, 'defx_icons_parent_icon', '')
|
||||
let s:directory_icon = get(g:, 'defx_icons_directory_icon', '')
|
||||
let s:mark_icon = get(g: , 'defx_icons_mark_icon', '*')
|
||||
let s:default_icon = get(g:, 'defx_icons_default_icon', '')
|
||||
let s:directory_symlink_icon = get(g:, 'defx_icons_directory_symlink_icon', '')
|
||||
let s:root_opened_tree_icon = get(g:, 'defx_icons_root_opened_tree_icon', '')
|
||||
let s:nested_closed_tree_icon = get(g: ,'defx_icons_nested_closed_tree_icon', '')
|
||||
let s:nested_opened_tree_icon = get(g: ,'defx_icons_nested_opened_tree_icon', '')
|
||||
let s:copy_icon = get(g:, 'defx_icons_copy_icon', '')
|
||||
let s:move_icon = get(g:, 'defx_icons_move_icon', '')
|
||||
let s:default_color = synIDattr(hlID('Normal'), 'fg')
|
||||
|
||||
let s:gui_colors = extend({
|
||||
\ 'brown': '905532',
|
||||
\ 'aqua': '3AFFDB',
|
||||
\ 'blue': '689FB6',
|
||||
\ 'darkBlue': '44788E',
|
||||
\ 'purple': '834F79',
|
||||
\ 'lightPurple': '834F79',
|
||||
\ 'red': 'AE403F',
|
||||
\ 'beige': 'F5C06F',
|
||||
\ 'yellow': 'F09F17',
|
||||
\ 'orange': 'D4843E',
|
||||
\ 'darkOrange': 'F16529',
|
||||
\ 'pink': 'CB6F6F',
|
||||
\ 'salmon': 'EE6E73',
|
||||
\ 'green': '8FAA54',
|
||||
\ 'lightGreen': '31B53E',
|
||||
\ 'default': s:default_color,
|
||||
\ }, get(g:, 'defx_icons_gui_colors', {}))
|
||||
|
||||
let s:term_colors = extend({
|
||||
\ 'brown' : 130,
|
||||
\ 'aqua' : 66,
|
||||
\ 'blue' : 67,
|
||||
\ 'darkBlue' : 57,
|
||||
\ 'purple' : 60,
|
||||
\ 'lightPurple' : 103,
|
||||
\ 'red' : 131,
|
||||
\ 'beige' : 137,
|
||||
\ 'yellow' : 229,
|
||||
\ 'orange' : 208,
|
||||
\ 'darkOrange' : 166,
|
||||
\ 'pink' : 205,
|
||||
\ 'salmon' : 209,
|
||||
\ 'green' : 65,
|
||||
\ 'lightGreen' : 108,
|
||||
\ 'default' : 231,
|
||||
\ }, get(g: ,'defx_icons_term_colors', {}))
|
||||
|
||||
let s:extensions = extend({
|
||||
\ 'styl': {'icon': '', 'color': s:gui_colors.green, 'term_color': s:term_colors.green},
|
||||
\ 'sass': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'scss': {'icon': '', 'color': s:gui_colors.pink, 'term_color': s:term_colors.pink},
|
||||
\ 'htm': {'icon': '', 'color': s:gui_colors.darkOrange, 'term_color': s:term_colors.darkOrange},
|
||||
\ 'html': {'icon': '', 'color': s:gui_colors.darkOrange, 'term_color': s:term_colors.darkOrange},
|
||||
\ 'slim': {'icon': '', 'color': s:gui_colors.orange, 'term_color': s:term_colors.orange},
|
||||
\ 'ejs': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'css': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'less': {'icon': '', 'color': s:gui_colors.darkBlue, 'term_color': s:term_colors.darkBlue},
|
||||
\ 'md': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'markdown': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'rmd': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'json': {'icon': '', 'color': s:gui_colors.beige, 'term_color': s:term_colors.beige},
|
||||
\ 'js': {'icon': '', 'color': s:gui_colors.beige, 'term_color': s:term_colors.beige},
|
||||
\ 'mjs': {'icon': '', 'color': s:gui_colors.beige, 'term_color': s:term_colors.beige},
|
||||
\ 'jsx': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'rb': {'icon': '', 'color': s:gui_colors.red, 'term_color': s:term_colors.red},
|
||||
\ 'php': {'icon': '', 'color': s:gui_colors.purple, 'term_color': s:term_colors.purple},
|
||||
\ 'py': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'pyc': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'pyo': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'pyd': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'coffee': {'icon': '', 'color': s:gui_colors.brown, 'term_color': s:term_colors.brown},
|
||||
\ 'mustache': {'icon': '', 'color': s:gui_colors.orange, 'term_color': s:term_colors.orange},
|
||||
\ 'hbs': {'icon': '', 'color': s:gui_colors.orange, 'term_color': s:term_colors.orange},
|
||||
\ 'conf': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'ini': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'yml': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'yaml': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'bat': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'toml': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'jpg': {'icon': '', 'color': s:gui_colors.aqua, 'term_color': s:term_colors.aqua},
|
||||
\ 'jpeg': {'icon': '', 'color': s:gui_colors.aqua, 'term_color': s:term_colors.aqua},
|
||||
\ 'bmp': {'icon': '', 'color': s:gui_colors.aqua, 'term_color': s:term_colors.aqua},
|
||||
\ 'png': {'icon': '', 'color': s:gui_colors.aqua, 'term_color': s:term_colors.aqua},
|
||||
\ 'gif': {'icon': '', 'color': s:gui_colors.aqua, 'term_color': s:term_colors.aqua},
|
||||
\ 'ico': {'icon': '', 'color': s:gui_colors.aqua, 'term_color': s:term_colors.aqua},
|
||||
\ 'twig': {'icon': '', 'color': s:gui_colors.green, 'term_color': s:term_colors.green},
|
||||
\ 'cpp': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'cxx': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'cc': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'cp': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'c': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'h': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'hpp': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'hxx': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'hs': {'icon': '', 'color': s:gui_colors.beige, 'term_color': s:term_colors.beige},
|
||||
\ 'lhs': {'icon': '', 'color': s:gui_colors.beige, 'term_color': s:term_colors.beige},
|
||||
\ 'lua': {'icon': '', 'color': s:gui_colors.purple, 'term_color': s:term_colors.purple},
|
||||
\ 'java': {'icon': '', 'color': s:gui_colors.purple, 'term_color': s:term_colors.purple},
|
||||
\ 'sh': {'icon': '', 'color': s:gui_colors.lightPurple, 'term_color': s:term_colors.lightPurple},
|
||||
\ 'fish': {'icon': '', 'color': s:gui_colors.green, 'term_color': s:term_colors.green},
|
||||
\ 'bash': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'zsh': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'ksh': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'csh': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'awk': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'ps1': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'ml': {'icon': 'λ', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'mli': {'icon': 'λ', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'diff': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'db': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'sql': {'icon': '', 'color': s:gui_colors.darkBlue, 'term_color': s:term_colors.darkBlue},
|
||||
\ 'dump': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'clj': {'icon': '', 'color': s:gui_colors.green, 'term_color': s:term_colors.green},
|
||||
\ 'cljc': {'icon': '', 'color': s:gui_colors.green, 'term_color': s:term_colors.green},
|
||||
\ 'cljs': {'icon': '', 'color': s:gui_colors.green, 'term_color': s:term_colors.green},
|
||||
\ 'edn': {'icon': '', 'color': s:gui_colors.green, 'term_color': s:term_colors.green},
|
||||
\ 'scala': {'icon': '', 'color': s:gui_colors.red, 'term_color': s:term_colors.red},
|
||||
\ 'go': {'icon': '', 'color': s:gui_colors.beige, 'term_color': s:term_colors.beige},
|
||||
\ 'dart': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'xul': {'icon': '', 'color': s:gui_colors.darkOrange, 'term_color': s:term_colors.darkOrange},
|
||||
\ 'sln': {'icon': '', 'color': s:gui_colors.purple, 'term_color': s:term_colors.purple},
|
||||
\ 'suo': {'icon': '', 'color': s:gui_colors.purple, 'term_color': s:term_colors.purple},
|
||||
\ 'pl': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'pm': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 't': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'rss': {'icon': '', 'color': s:gui_colors.darkOrange, 'term_color': s:term_colors.darkOrange},
|
||||
\ 'fsscript': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'fsx': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'fs': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'fsi': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'rs': {'icon': '', 'color': s:gui_colors.darkOrange, 'term_color': s:term_colors.darkOrange},
|
||||
\ 'rlib': {'icon': '', 'color': s:gui_colors.darkOrange, 'term_color': s:term_colors.darkOrange},
|
||||
\ 'd': {'icon': '', 'color': s:gui_colors.red, 'term_color': s:term_colors.red},
|
||||
\ 'erl': {'icon': '', 'color': s:gui_colors.lightPurple, 'term_color': s:term_colors.lightPurple},
|
||||
\ 'ex': {'icon': '', 'color': s:gui_colors.lightPurple, 'term_color': s:term_colors.lightPurple},
|
||||
\ 'exs': {'icon': '', 'color': s:gui_colors.lightPurple, 'term_color': s:term_colors.lightPurple},
|
||||
\ 'eex': {'icon': '', 'color': s:gui_colors.lightPurple, 'term_color': s:term_colors.lightPurple},
|
||||
\ 'hrl': {'icon': '', 'color': s:gui_colors.pink, 'term_color': s:term_colors.pink},
|
||||
\ 'vim': {'icon': '', 'color': s:gui_colors.green, 'term_color': s:term_colors.green},
|
||||
\ 'ai': {'icon': '', 'color': s:gui_colors.darkOrange, 'term_color': s:term_colors.darkOrange},
|
||||
\ 'psd': {'icon': '', 'color': s:gui_colors.darkBlue, 'term_color': s:term_colors.darkBlue},
|
||||
\ 'psb': {'icon': '', 'color': s:gui_colors.darkBlue, 'term_color': s:term_colors.darkBlue},
|
||||
\ 'ts': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'tsx': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'jl': {'icon': '', 'color': s:gui_colors.purple, 'term_color': s:term_colors.purple},
|
||||
\ 'pp': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'vue': {'icon': '﵂', 'color': s:gui_colors.green, 'term_color': s:term_colors.green},
|
||||
\ }, get(g:, 'defx_icons_extensions', {}))
|
||||
|
||||
let s:exact_matches = extend({
|
||||
\ 'gruntfile.coffee': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'gruntfile.js': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'gruntfile.ls': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'gulpfile.coffee': {'icon': '', 'color': s:gui_colors.pink, 'term_color': s:term_colors.pink},
|
||||
\ 'gulpfile.js': {'icon': '', 'color': s:gui_colors.pink, 'term_color': s:term_colors.pink},
|
||||
\ 'gulpfile.ls': {'icon': '', 'color': s:gui_colors.pink, 'term_color': s:term_colors.pink},
|
||||
\ 'dropbox': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ '.ds_store': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ '.gitconfig': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ '.gitignore': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ '.bashrc': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ '.zshrc': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ '.vimrc': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ '.gvimrc': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ '_vimrc': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ '_gvimrc': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ '.bashprofile': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'favicon.ico': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ 'license': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'node_modules': {'icon': '', 'color': s:gui_colors.green, 'term_color': s:term_colors.green},
|
||||
\ 'react.jsx': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'procfile': {'icon': '', 'color': s:gui_colors.purple, 'term_color': s:term_colors.purple},
|
||||
\ 'dockerfile': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ 'docker-compose.yml': {'icon': '', 'color': s:gui_colors.yellow, 'term_color': s:term_colors.yellow},
|
||||
\ }, get(g:, 'defx_icons_exact_matches', {}))
|
||||
|
||||
let s:pattern_matches = extend({
|
||||
\ '.*jquery.*\.js$': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ '.*angular.*\.js$': {'icon': '', 'color': s:gui_colors.red, 'term_color': s:term_colors.red},
|
||||
\ '.*backbone.*\.js$': {'icon': '', 'color': s:gui_colors.darkBlue, 'term_color': s:term_colors.darkBlue},
|
||||
\ '.*require.*\.js$': {'icon': '', 'color': s:gui_colors.blue, 'term_color': s:term_colors.blue},
|
||||
\ '.*materialize.*\.js$': {'icon': '', 'color': s:gui_colors.salmon, 'term_color': s:term_colors.salmon},
|
||||
\ '.*materialize.*\.css$': {'icon': '', 'color': s:gui_colors.salmon, 'term_color': s:term_colors.salmon},
|
||||
\ '.*mootools.*\.js$': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ '.*vimrc.*': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ 'Vagrantfile$': {'icon': '', 'color': s:gui_colors.default, 'term_color': s:term_colors.default},
|
||||
\ }, get(g:, 'defx_icon_pattern_matches', {}))
|
||||
|
||||
hi default link DefxIconsMarkIcon Statement
|
||||
hi default link DefxIconsCopyIcon WarningMsg
|
||||
hi default link DefxIconsMoveIcon ErrorMsg
|
||||
hi default link DefxIconsDirectory Directory
|
||||
hi default link DefxIconsParentDirectory Directory
|
||||
hi default link DefxIconsSymlinkDirectory Directory
|
||||
hi default link DefxIconsOpenedTreeIcon Directory
|
||||
hi default link DefxIconsNestedTreeIcon Directory
|
||||
hi default link DefxIconsClosedTreeIcon Directory
|
||||
|
||||
function! defx_icons#get() abort
|
||||
return {
|
||||
\ 'extensions': s:extensions,
|
||||
\ 'exact_matches': s:exact_matches,
|
||||
\ 'exact_dir_matches': get(g:, 'defx_icon_exact_dir_matches', {}),
|
||||
\ 'pattern_matches': s:pattern_matches,
|
||||
\ 'enable_syntax_highlight': s:enable_syntax_highlight,
|
||||
\ 'column_length': s:column_length,
|
||||
\ 'parent_icon': s:parent_icon,
|
||||
\ 'directory_icon': s:directory_icon,
|
||||
\ 'directory_symlink_icon': s:directory_symlink_icon,
|
||||
\ 'mark_icon': s:mark_icon,
|
||||
\ 'default_icon': s:default_icon,
|
||||
\ 'root_opened_tree_icon': s:root_opened_tree_icon,
|
||||
\ 'nested_closed_tree_icon': s:nested_closed_tree_icon,
|
||||
\ 'nested_opened_tree_icon': s:nested_opened_tree_icon,
|
||||
\ 'copy_icon': s:copy_icon,
|
||||
\ 'move_icon': s:move_icon,
|
||||
\ }
|
||||
endfunction
|
137
bundle/defx-icons/rplugin/python3/defx/column/icons.py
Normal file
137
bundle/defx-icons/rplugin/python3/defx/column/icons.py
Normal file
@ -0,0 +1,137 @@
|
||||
# ============================================================================
|
||||
# FILE: icons.py
|
||||
# AUTHOR: Kristijan Husak <husakkristijan at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import re
|
||||
import typing
|
||||
from pathlib import Path
|
||||
from defx.base.column import Base
|
||||
from defx.context import Context
|
||||
from defx.clipboard import ClipboardAction
|
||||
from defx.view import View
|
||||
from neovim import Nvim
|
||||
|
||||
|
||||
class Column(Base):
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
self.vim = vim
|
||||
self.name = 'icons'
|
||||
self.opts = self.vim.call('defx_icons#get')
|
||||
|
||||
def on_init(self, view: View, context: Context) -> None:
|
||||
self._context = context
|
||||
self._view = view
|
||||
|
||||
def on_redraw(self, view: View, context: Context) -> None:
|
||||
self._context = context
|
||||
self._view = view
|
||||
|
||||
def get(self, context: Context, candidate: dict) -> str:
|
||||
path: Path = candidate['action__path']
|
||||
filename = path.name
|
||||
if 'mark' not in context.columns and candidate['is_selected']:
|
||||
return self.icon(self.opts['mark_icon'])
|
||||
|
||||
if self._view and self._view._clipboard.candidates:
|
||||
for clipboard_candidate in self._view._clipboard.candidates:
|
||||
if str(clipboard_candidate['action__path']) == str(path):
|
||||
return self.clipboard_icon()
|
||||
|
||||
if candidate.get('is_root', False):
|
||||
return self.icon(self.opts['parent_icon'])
|
||||
|
||||
if candidate['is_directory']:
|
||||
if filename in self.opts['exact_dir_matches']:
|
||||
return self.icon(self.opts['exact_dir_matches'][filename]['icon'])
|
||||
|
||||
if candidate.get('level', 0) > 0:
|
||||
if candidate.get('is_opened_tree'):
|
||||
return self.icon(self.opts['nested_opened_tree_icon'])
|
||||
return self.icon(self.opts['nested_closed_tree_icon'])
|
||||
|
||||
if candidate.get('is_opened_tree', False):
|
||||
return self.icon(self.opts['root_opened_tree_icon'])
|
||||
|
||||
if path.is_symlink():
|
||||
return self.icon(self.opts['directory_symlink_icon'])
|
||||
|
||||
return self.icon(self.opts['directory_icon'])
|
||||
|
||||
filename = filename.lower()
|
||||
ext = path.suffix[1:].lower()
|
||||
|
||||
for pattern, pattern_data in self.opts['pattern_matches'].items():
|
||||
if re.search(pattern, filename) is not None:
|
||||
return self.icon(pattern_data['icon'])
|
||||
|
||||
if filename in self.opts['exact_matches']:
|
||||
return self.icon(self.opts['exact_matches'][filename]['icon'])
|
||||
|
||||
if ext in self.opts['extensions']:
|
||||
return self.icon(self.opts['extensions'][ext]['icon'])
|
||||
|
||||
return self.icon(self.opts['default_icon'])
|
||||
|
||||
def length(self, context: Context) -> int:
|
||||
return self.opts['column_length']
|
||||
|
||||
def icon(self, icon: str) -> str:
|
||||
return format(icon, f'<{self.opts["column_length"]}')
|
||||
|
||||
def clipboard_icon(self) -> str:
|
||||
if self._view._clipboard.action == ClipboardAction.COPY:
|
||||
return self.opts['copy_icon']
|
||||
if self._view._clipboard.action == ClipboardAction.MOVE:
|
||||
return self.opts['move_icon']
|
||||
return ''
|
||||
|
||||
def syn_item(self, name, opt_name, hi_group_name) -> typing.List[str]:
|
||||
commands: typing.List[str] = []
|
||||
commands.append(f'silent! syntax clear {self.syntax_name}_{name}')
|
||||
commands.append((
|
||||
'syntax match {0}_{1} /[{2}]/ contained containedin={0}'
|
||||
).format(self.syntax_name, name, self.opts[opt_name]))
|
||||
commands.append('highlight default link {0}_{1} {2}'.format(
|
||||
self.syntax_name, name, hi_group_name
|
||||
))
|
||||
return commands
|
||||
|
||||
def syn_list(self, opt) -> typing.List[str]:
|
||||
commands: typing.List[str] = []
|
||||
for name, opts in self.opts[opt].items():
|
||||
text = re.sub('[^A-Za-z]', '', name)
|
||||
commands.append(f'silent! syntax clear {self.syntax_name}_{text}')
|
||||
commands.append((
|
||||
'syntax match {0}_{1} /[{2}]/ contained containedin={0}'
|
||||
).format(self.syntax_name, text, opts['icon']))
|
||||
commands.append('highlight default {0}_{1} guifg=#{2} ctermfg={3}'.format(
|
||||
self.syntax_name, text, opts['color'], opts.get('term_color',
|
||||
'NONE')))
|
||||
return commands
|
||||
|
||||
def highlight_commands(self) -> typing.List[str]:
|
||||
commands: typing.List[str] = []
|
||||
|
||||
if not self.opts['enable_syntax_highlight']:
|
||||
return commands
|
||||
|
||||
commands += self.syn_item('icon_mark', 'mark_icon', 'DefxIconsMarkIcon')
|
||||
commands += self.syn_item('icon_copy', 'copy_icon', 'DefxIconsCopyIcon')
|
||||
commands += self.syn_item('icon_move', 'move_icon', 'DefxIconsMoveIcon')
|
||||
|
||||
commands += self.syn_item('directory', 'directory_icon', 'DefxIconsDirectory')
|
||||
commands += self.syn_item('parent_directory', 'parent_icon', 'DefxIconsParentDirectory')
|
||||
commands += self.syn_item('symlink_directory', 'directory_symlink_icon', 'DefxIconsSymlinkDirectory')
|
||||
commands += self.syn_item('root_opened_tree_icon', 'root_opened_tree_icon', 'DefxIconsOpenedTreeIcon')
|
||||
commands += self.syn_item('nested_opened_tree_icon', 'nested_opened_tree_icon', 'DefxIconsNestedTreeIcon')
|
||||
commands += self.syn_item('nested_closed_tree_icon', 'nested_closed_tree_icon', 'DefxIconsClosedTreeIcon')
|
||||
|
||||
commands += self.syn_list('pattern_matches')
|
||||
commands += self.syn_list('exact_matches')
|
||||
commands += self.syn_list('exact_dir_matches')
|
||||
commands += self.syn_list('extensions')
|
||||
|
||||
return commands
|
46
bundle/defx.nvim/.github/ISSUE_TEMPLATE.md
vendored
Normal file
46
bundle/defx.nvim/.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
**Warning: I will close the issue without the minimal init.vim and the reproduction instructions.**
|
||||
|
||||
# Problems summary
|
||||
|
||||
|
||||
## Expected
|
||||
|
||||
|
||||
## Environment Information
|
||||
|
||||
* defx version(SHA1):
|
||||
|
||||
* OS:
|
||||
|
||||
* neovim/Vim version:
|
||||
|
||||
* `:checkhealth` or `:CheckHealth` result(neovim only):
|
||||
|
||||
## Provide a minimal init.vim/vimrc with less than 50 lines (Required!)
|
||||
|
||||
```vim
|
||||
" Your minimal init.vim/vimrc
|
||||
set runtimepath+=~/path/to/defx.nvim/
|
||||
```
|
||||
|
||||
|
||||
## The reproduce ways from neovim/Vim starting (Required!)
|
||||
|
||||
1. foo
|
||||
2. bar
|
||||
3. baz
|
||||
|
||||
|
||||
## Generate a logfile if appropriate
|
||||
|
||||
1. export NVIM_PYTHON_LOG_FILE=/tmp/log
|
||||
2. export NVIM_PYTHON_LOG_LEVEL=DEBUG
|
||||
3. nvim -u minimal.vimrc
|
||||
4. some works
|
||||
5. cat /tmp/log_{PID}
|
||||
|
||||
|
||||
## Screen shot (if possible)
|
||||
|
||||
|
||||
## Upload the log file
|
6
bundle/defx.nvim/.gitignore
vendored
Normal file
6
bundle/defx.nvim/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*.py[cod]
|
||||
doc/tags
|
||||
vim-themis
|
||||
.cache
|
||||
.mypy_cache/
|
||||
.pytest_cache/
|
14
bundle/defx.nvim/.travis.yml
Normal file
14
bundle/defx.nvim/.travis.yml
Normal file
@ -0,0 +1,14 @@
|
||||
dist: xenial
|
||||
|
||||
language: python
|
||||
|
||||
python:
|
||||
- 3.6
|
||||
- 3.7
|
||||
|
||||
install:
|
||||
- eval "$(curl -Ss https://raw.githubusercontent.com/neovim/bot-ci/master/scripts/travis-setup.sh) nightly-x64"
|
||||
- make install
|
||||
|
||||
script:
|
||||
- make --keep-going test lint
|
21
bundle/defx.nvim/LICENSE
Normal file
21
bundle/defx.nvim/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
License: MIT license
|
||||
AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
|
||||
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.
|
31
bundle/defx.nvim/Makefile
Normal file
31
bundle/defx.nvim/Makefile
Normal file
@ -0,0 +1,31 @@
|
||||
PATH := ./vim-themis/bin:$(PATH)
|
||||
export THEMIS_VIM := nvim
|
||||
export THEMIS_ARGS := -e -s --headless
|
||||
export THEMIS_HOME := ./vim-themis
|
||||
|
||||
|
||||
install: vim-themis
|
||||
pip install --upgrade -r test/requirements.txt
|
||||
|
||||
install-user: vim-themis
|
||||
pip install --user --upgrade -r test/requirements.txt
|
||||
|
||||
lint:
|
||||
vint --version
|
||||
vint plugin
|
||||
vint autoload
|
||||
flake8 --version
|
||||
flake8 rplugin
|
||||
mypy --version
|
||||
mypy --ignore-missing-imports --follow-imports=skip --strict rplugin/python3/defx
|
||||
|
||||
test:
|
||||
# themis --version
|
||||
# themis test/autoload/*
|
||||
pytest --version
|
||||
pytest
|
||||
|
||||
vim-themis:
|
||||
git clone https://github.com/thinca/vim-themis vim-themis
|
||||
|
||||
.PHONY: install lint test
|
117
bundle/defx.nvim/README.md
Normal file
117
bundle/defx.nvim/README.md
Normal file
@ -0,0 +1,117 @@
|
||||
## About
|
||||
|
||||
[![Join the chat at https://gitter.im/Shougo/defx.nvim](https://badges.gitter.im/Shougo/defx.nvim.svg)](https://gitter.im/Shougo/defx.nvim?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Defx is a dark powered plugin for Neovim/Vim to browse files.
|
||||
It replaces the deprecated vimfiler plugin.
|
||||
|
||||
|
||||
## Concept
|
||||
|
||||
* Doesn't depend on denite.nvim
|
||||
|
||||
* Vim8/neovim compatible(nvim-yarp is needed for Vim8)
|
||||
|
||||
* Implemented by Python3
|
||||
|
||||
* No double filer feature
|
||||
|
||||
* Column feature
|
||||
|
||||
* Source feature like denite.nvim
|
||||
|
||||
* Options
|
||||
|
||||
* Highlight is defined by column
|
||||
|
||||
* Few commands (:Defx command only?)
|
||||
|
||||
* Extended rename
|
||||
|
||||
* Mark
|
||||
|
||||
* Windows supporters are needed
|
||||
|
||||
* Maximum features dislike other file managers
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
**Note:** defx requires Neovim 0.3.0+ or Vim8.1+ with Python3.6.1+. See
|
||||
[requirements](#requirements) if you aren't sure whether you have this.
|
||||
|
||||
For vim-plug
|
||||
|
||||
```viml
|
||||
if has('nvim')
|
||||
Plug 'Shougo/defx.nvim', { 'do': ':UpdateRemotePlugins' }
|
||||
else
|
||||
Plug 'Shougo/defx.nvim'
|
||||
Plug 'roxma/nvim-yarp'
|
||||
Plug 'roxma/vim-hug-neovim-rpc'
|
||||
endif
|
||||
```
|
||||
|
||||
For dein.vim
|
||||
|
||||
```viml
|
||||
call dein#add('Shougo/defx.nvim')
|
||||
if !has('nvim')
|
||||
call dein#add('roxma/nvim-yarp')
|
||||
call dein#add('roxma/vim-hug-neovim-rpc')
|
||||
endif
|
||||
```
|
||||
|
||||
For manual installation(not recommended)
|
||||
|
||||
1. Extract the files and put them in your Neovim or .vim directory
|
||||
(usually `$XDG_CONFIG_HOME/nvim/`).
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
defx requires Python3.6.1+ and Neovim(0.3.0+) or Vim8.1+ with if\_python3. If
|
||||
`:echo has("python3")` returns `1`, then you have python 3 support; otherwise,
|
||||
see below.
|
||||
|
||||
You can enable Python3 interface with pip:
|
||||
|
||||
pip3 install --user pynvim
|
||||
|
||||
Please install nvim-yarp plugin for Vim8.
|
||||
https://github.com/roxma/nvim-yarp
|
||||
|
||||
Please install vim-hug-neovim-rpc plugin for Vim8.
|
||||
https://github.com/roxma/vim-hug-neovim-rpc
|
||||
|
||||
|
||||
## Note: Python3 must be enabled before updating remote plugins
|
||||
If Defx was installed prior to Python support being added to Neovim,
|
||||
`:UpdateRemotePlugins` should be executed manually.
|
||||
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
```vim
|
||||
" Todo
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Screenshots
|
||||
|
||||
![multi root feature](https://user-images.githubusercontent.com/41495/45696476-ac9d0a80-bb9e-11e8-9ee2-120ac7d0f045.png)
|
||||
![Defx -split=vertical](https://user-images.githubusercontent.com/2835826/45823772-7190f900-bcbc-11e8-9727-3dda3ce4c07c.png)
|
||||
![Defx -new](https://user-images.githubusercontent.com/3047695/45927914-7f07e680-bf3b-11e8-9b36-755e1eec2a8f.png)
|
||||
![Defx + neovim-qt](https://user-images.githubusercontent.com/1314340/48659914-0b4a0c00-ea9c-11e8-9953-2f2d5ca7f24a.png)
|
||||
![custom icon](https://user-images.githubusercontent.com/10108377/59982828-ac93d480-9620-11e9-8c10-51909cfeaf94.png)
|
||||
![custom icon2](https://user-images.githubusercontent.com/3021667/55260000-95ba2d80-523d-11e9-877c-756a080a9a28.png)
|
||||
![custom icon3](https://user-images.githubusercontent.com/10397021/57774111-3f04a680-774c-11e9-852a-53c394f672ef.png)
|
||||
![custom icon4](https://user-images.githubusercontent.com/12205650/58801907-d9346d80-85d9-11e9-8a2d-de4635aa1eba.png)
|
||||
![custom icon5](https://user-images.githubusercontent.com/11615211/82411894-381e1b80-9aa5-11ea-9552-fd9847fe25e3.png)
|
||||
![Defx on kitty](https://user-images.githubusercontent.com/8403993/51080184-d29e6b80-16b5-11e9-802b-7c2f56705e2e.png)
|
||||
![Defx in SpaceVim](https://user-images.githubusercontent.com/13142418/54086225-85233f80-4382-11e9-8091-7f387319b90a.png)
|
||||
![Variable column](https://user-images.githubusercontent.com/19503791/56090130-58f26580-5ed0-11e9-8b66-e684cb11b0d1.png)
|
||||
![Denite action call](https://user-images.githubusercontent.com/41671631/56280845-a6bfd580-613d-11e9-857a-d81f2633eeab.png)
|
||||
![Defx floating window](https://user-images.githubusercontent.com/24732170/59892964-1c823f00-9416-11e9-8369-2e21910e168c.png)
|
||||
![Horizon colorscheme](https://user-images.githubusercontent.com/324519/63241202-a4fb4100-c207-11e9-9060-c3c04608ea7b.png)
|
83
bundle/defx.nvim/autoload/defx.vim
Normal file
83
bundle/defx.nvim/autoload/defx.vim
Normal file
@ -0,0 +1,83 @@
|
||||
"=============================================================================
|
||||
" FILE: defx.vim
|
||||
" AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
" License: MIT license
|
||||
"=============================================================================
|
||||
|
||||
function! defx#initialize() abort
|
||||
return defx#init#_initialize()
|
||||
endfunction
|
||||
|
||||
function! defx#start(paths, user_context) abort
|
||||
call defx#initialize()
|
||||
let context = defx#init#_context(a:user_context)
|
||||
let paths = a:paths
|
||||
let paths = map(paths, "fnamemodify(v:val, ':p')")
|
||||
call defx#util#rpcrequest('_defx_start', [paths, context], v:false)
|
||||
if context['search'] !=# ''
|
||||
call defx#call_action('search', [context['search']])
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! defx#do_action(action, ...) abort
|
||||
if &l:filetype !=# 'defx'
|
||||
return ''
|
||||
endif
|
||||
|
||||
let args = defx#util#convert2list(get(a:000, 0, []))
|
||||
return printf(":\<C-u>call defx#call_action(%s, %s)\<CR>",
|
||||
\ string(a:action), string(args))
|
||||
endfunction
|
||||
function! defx#async_action(action, ...) abort
|
||||
if &l:filetype !=# 'defx'
|
||||
return ''
|
||||
endif
|
||||
|
||||
let args = defx#util#convert2list(get(a:000, 0, []))
|
||||
return printf(":\<C-u>call defx#call_async_action(%s, %s)\<CR>",
|
||||
\ string(a:action), string(args))
|
||||
endfunction
|
||||
function! defx#call_action(action, ...) abort
|
||||
if &l:filetype !=# 'defx'
|
||||
return
|
||||
endif
|
||||
|
||||
let context = defx#init#_context({})
|
||||
let args = defx#util#convert2list(get(a:000, 0, []))
|
||||
call defx#util#rpcrequest(
|
||||
\ '_defx_do_action', [a:action, args, context], v:false)
|
||||
endfunction
|
||||
function! defx#call_async_action(action, ...) abort
|
||||
if &l:filetype !=# 'defx'
|
||||
return
|
||||
endif
|
||||
|
||||
let context = defx#init#_context({})
|
||||
let args = defx#util#convert2list(get(a:000, 0, []))
|
||||
call defx#util#rpcrequest(
|
||||
\ '_defx_async_action', [a:action, args, context], v:true)
|
||||
endfunction
|
||||
function! defx#redraw() abort
|
||||
call defx#util#rpcrequest('_defx_redraw', [], v:false)
|
||||
endfunction
|
||||
|
||||
function! defx#get_candidate() abort
|
||||
if &l:filetype !=# 'defx'
|
||||
return {}
|
||||
endif
|
||||
|
||||
return defx#util#rpcrequest('_defx_get_candidate', [], v:false)
|
||||
endfunction
|
||||
function! defx#is_directory() abort
|
||||
return get(defx#get_candidate(), 'is_directory', v:false)
|
||||
endfunction
|
||||
function! defx#is_opened_tree() abort
|
||||
return get(defx#get_candidate(), 'is_opened_tree', v:false)
|
||||
endfunction
|
||||
function! defx#get_context() abort
|
||||
if &l:filetype !=# 'defx'
|
||||
return {}
|
||||
endif
|
||||
|
||||
return defx#util#rpcrequest('_defx_get_context', [], v:false)
|
||||
endfunction
|
62
bundle/defx.nvim/autoload/defx/custom.vim
Normal file
62
bundle/defx.nvim/autoload/defx/custom.vim
Normal file
@ -0,0 +1,62 @@
|
||||
"=============================================================================
|
||||
" FILE: custom.vim
|
||||
" AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
" License: MIT license
|
||||
"=============================================================================
|
||||
|
||||
function! defx#custom#_get() abort
|
||||
if !exists('s:custom')
|
||||
call defx#custom#_init()
|
||||
endif
|
||||
|
||||
return s:custom
|
||||
endfunction
|
||||
|
||||
function! defx#custom#_init() abort
|
||||
let s:custom = {}
|
||||
let s:custom.column = {}
|
||||
let s:custom.option = {}
|
||||
let s:custom.source = {}
|
||||
endfunction
|
||||
|
||||
function! defx#custom#column(column_name, name_or_dict, ...) abort
|
||||
let custom = defx#custom#_get().column
|
||||
|
||||
for key in defx#util#split(a:column_name)
|
||||
if !has_key(custom, key)
|
||||
let custom[key] = {}
|
||||
endif
|
||||
call s:set_custom(custom[key], a:name_or_dict, get(a:000, 0, ''))
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! defx#custom#option(buffer_name, name_or_dict, ...) abort
|
||||
let custom = defx#custom#_get().option
|
||||
|
||||
for key in defx#util#split(a:buffer_name)
|
||||
if !has_key(custom, key)
|
||||
let custom[key] = {}
|
||||
endif
|
||||
|
||||
call s:set_custom(custom[key], a:name_or_dict, get(a:000, 0, ''))
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! defx#custom#source(source_name, name_or_dict, ...) abort
|
||||
let custom = defx#custom#_get().source
|
||||
|
||||
for key in defx#util#split(a:source_name)
|
||||
if !has_key(custom, key)
|
||||
let custom[key] = {}
|
||||
endif
|
||||
call s:set_custom(custom[key], a:name_or_dict, get(a:000, 0, ''))
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:set_custom(dest, name_or_dict, value) abort
|
||||
if type(a:name_or_dict) == v:t_dict
|
||||
call extend(a:dest, a:name_or_dict)
|
||||
else
|
||||
let a:dest[a:name_or_dict] = a:value
|
||||
endif
|
||||
endfunction
|
211
bundle/defx.nvim/autoload/defx/exrename.vim
Normal file
211
bundle/defx.nvim/autoload/defx/exrename.vim
Normal file
@ -0,0 +1,211 @@
|
||||
"=============================================================================
|
||||
" FILE: exrename.vim
|
||||
" AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
" EDITOR: Alisue <lambdalisue at hashnote.net>
|
||||
" License: MIT license
|
||||
"=============================================================================
|
||||
|
||||
let s:PREFIX = has('win32') ? '[exrename]' : '*exrename*'
|
||||
|
||||
function! defx#exrename#create_buffer(candidates, ...) abort
|
||||
let options = extend({
|
||||
\ 'cwd': getcwd(),
|
||||
\ 'bufnr': bufnr('%'),
|
||||
\ 'buffer_name': '',
|
||||
\ 'post_rename_callback': v:null,
|
||||
\}, get(a:000, 0, {}))
|
||||
if options.cwd !~# '/$'
|
||||
" current working directory MUST end with a trailing slash
|
||||
let options.cwd .= '/'
|
||||
endif
|
||||
if options.buffer_name ==# ''
|
||||
let options.buffer_name = s:PREFIX
|
||||
else
|
||||
let options.buffer_name = s:PREFIX . ' - ' . options.buffer_name
|
||||
endif
|
||||
|
||||
vsplit
|
||||
redraw
|
||||
execute 'edit' fnameescape(options.buffer_name)
|
||||
|
||||
setlocal buftype=acwrite
|
||||
setlocal noswapfile
|
||||
setfiletype defx_exrename
|
||||
|
||||
syntax match defxExrenameModified '^.*$'
|
||||
|
||||
highlight def link defxExrenameModified Todo
|
||||
highlight def link defxExrenameOriginal Normal
|
||||
|
||||
let b:exrename = options
|
||||
|
||||
call defx#util#cd(b:exrename.cwd)
|
||||
|
||||
nnoremap <buffer><silent> q :<C-u>call <SID>exit(bufnr('%'))<CR>
|
||||
augroup defx-exrename
|
||||
autocmd! * <buffer>
|
||||
autocmd BufHidden <buffer> call s:exit(expand('<abuf>'))
|
||||
autocmd BufWriteCmd <buffer> call s:do_rename()
|
||||
autocmd CursorMoved,CursorMovedI <buffer> call s:check_lines()
|
||||
augroup END
|
||||
|
||||
" Clean up the screen.
|
||||
silent % delete _
|
||||
silent! syntax clear defxExrenameOriginal
|
||||
|
||||
" validate candidates and register
|
||||
let unique_filenames = []
|
||||
let b:exrename.candidates = []
|
||||
let b:exrename.filenames = []
|
||||
let cnt = 1
|
||||
for candidate in a:candidates
|
||||
" make sure that the 'action__path' is absolute path
|
||||
if !s:is_absolute(candidate.action__path)
|
||||
let candidate.action__path = b:exrename.cwd . candidate.action__path
|
||||
endif
|
||||
" make sure that the 'action__path' exists
|
||||
if !filewritable(candidate.action__path)
|
||||
\ && !isdirectory(candidate.action__path)
|
||||
redraw
|
||||
echo candidate.action__path 'does not exist. Skip.'
|
||||
continue
|
||||
endif
|
||||
" make sure that the 'action__path' is unique
|
||||
if index(unique_filenames, candidate.action__path) != -1
|
||||
redraw
|
||||
echo candidate.action__path 'is duplicated. Skip.'
|
||||
continue
|
||||
endif
|
||||
" create filename
|
||||
let filename = candidate.action__path
|
||||
if stridx(filename, b:exrename.cwd) == 0
|
||||
let filename = filename[len(b:exrename.cwd) :]
|
||||
endif
|
||||
" directory should end with a trailing slash (to distinguish easily)
|
||||
if isdirectory(candidate.action__path)
|
||||
let filename .= '/'
|
||||
endif
|
||||
|
||||
execute 'syntax match defxExrenameOriginal'
|
||||
\ '/'.printf('^\%%%dl%s$', cnt,
|
||||
\ escape(s:escape_pattern(filename), '/')).'/'
|
||||
" register
|
||||
call add(unique_filenames, candidate.action__path)
|
||||
call add(b:exrename.candidates, candidate)
|
||||
call add(b:exrename.filenames, filename)
|
||||
let cnt += 1
|
||||
endfor
|
||||
" write filenames
|
||||
let [undolevels, &undolevels] = [&undolevels, -1]
|
||||
try
|
||||
call setline(1, b:exrename.filenames)
|
||||
finally
|
||||
let &undolevels = undolevels
|
||||
endtry
|
||||
setlocal nomodified
|
||||
endfunction
|
||||
|
||||
function! s:escape_pattern(str) abort
|
||||
return escape(a:str, '~"\.^$[]*')
|
||||
endfunction
|
||||
|
||||
function! s:is_absolute(path) abort
|
||||
return a:path =~# '^\%(\a\a\+:\)\|^\%(\a:\|/\)'
|
||||
endfunction
|
||||
|
||||
function! s:do_rename() abort
|
||||
if line('$') != len(b:exrename.filenames)
|
||||
echohl Error | echo 'Invalid rename buffer!' | echohl None
|
||||
return
|
||||
endif
|
||||
|
||||
" Rename files.
|
||||
let linenr = 1
|
||||
let max = line('$')
|
||||
while linenr <= max
|
||||
let filename = b:exrename.filenames[linenr - 1]
|
||||
|
||||
redraw
|
||||
echo printf('(%'.len(max).'d/%d): %s -> %s',
|
||||
\ linenr, max, filename, getline(linenr))
|
||||
|
||||
if filename !=# getline(linenr)
|
||||
let old_file = b:exrename.candidates[linenr - 1].action__path
|
||||
let new_file = expand(getline(linenr))
|
||||
if new_file !~# '^\%(\a\a\+:\)\|^\%(\a:\|/\)'
|
||||
let new_file = b:exrename.cwd . new_file
|
||||
endif
|
||||
|
||||
if rename(old_file, new_file)
|
||||
" Rename error
|
||||
continue
|
||||
endif
|
||||
|
||||
" update b:exrename
|
||||
let b:exrename.filenames[linenr - 1] = getline(linenr)
|
||||
let b:exrename.candidates[linenr - 1].action__path = new_file
|
||||
endif
|
||||
let linenr += 1
|
||||
endwhile
|
||||
|
||||
redraw
|
||||
echo 'Rename done!'
|
||||
|
||||
setlocal nomodified
|
||||
|
||||
if b:exrename.post_rename_callback != v:null
|
||||
call b:exrename.post_rename_callback(b:exrename)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:exit(bufnr) abort
|
||||
if !bufexists(a:bufnr)
|
||||
return
|
||||
endif
|
||||
|
||||
" Switch buffer.
|
||||
if winnr('$') != 1
|
||||
close
|
||||
else
|
||||
call s:custom_alternate_buffer()
|
||||
endif
|
||||
silent execute 'bdelete!' a:bufnr
|
||||
endfunction
|
||||
|
||||
function! s:check_lines() abort
|
||||
if !exists('b:exrename')
|
||||
return
|
||||
endif
|
||||
|
||||
if line('$') != len(b:exrename.filenames)
|
||||
echohl Error | echo 'Invalid rename buffer!' | echohl None
|
||||
return
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:custom_alternate_buffer() abort
|
||||
if bufnr('%') != bufnr('#') && buflisted(bufnr('#'))
|
||||
buffer #
|
||||
endif
|
||||
|
||||
let cnt = 0
|
||||
let pos = 1
|
||||
let current = 0
|
||||
while pos <= bufnr('$')
|
||||
if buflisted(pos)
|
||||
if pos == bufnr('%')
|
||||
let current = cnt
|
||||
endif
|
||||
|
||||
let cnt += 1
|
||||
endif
|
||||
|
||||
let pos += 1
|
||||
endwhile
|
||||
|
||||
if current > cnt / 2
|
||||
bprevious
|
||||
else
|
||||
bnext
|
||||
endif
|
||||
endfunction
|
143
bundle/defx.nvim/autoload/defx/init.vim
Normal file
143
bundle/defx.nvim/autoload/defx/init.vim
Normal file
@ -0,0 +1,143 @@
|
||||
"=============================================================================
|
||||
" FILE: init.vim
|
||||
" AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
" License: MIT license
|
||||
"=============================================================================
|
||||
|
||||
function! defx#init#_initialize() abort
|
||||
if exists('g:defx#_channel_id')
|
||||
return
|
||||
endif
|
||||
|
||||
call defx#init#_channel()
|
||||
|
||||
augroup defx
|
||||
autocmd!
|
||||
augroup END
|
||||
|
||||
let g:defx#_histories = []
|
||||
endfunction
|
||||
function! defx#init#_channel() abort
|
||||
if !has('python3')
|
||||
call defx#util#print_error(
|
||||
\ 'defx requires Python3 support("+python3").')
|
||||
return v:true
|
||||
endif
|
||||
if has('nvim') && !has('nvim-0.3.0')
|
||||
call defx#util#print_error('defx requires nvim 0.3.0+.')
|
||||
return v:true
|
||||
endif
|
||||
if !has('nvim') && v:version < 801
|
||||
call defx#util#print_error('defx requires Vim 8.1+.')
|
||||
return v:true
|
||||
endif
|
||||
|
||||
try
|
||||
if defx#util#has_yarp()
|
||||
let g:defx#_yarp = yarp#py3('defx')
|
||||
call g:defx#_yarp.request('_defx_init')
|
||||
let g:defx#_channel_id = 1
|
||||
else
|
||||
" rplugin.vim may not be loaded on VimEnter
|
||||
if !exists('g:loaded_remote_plugins')
|
||||
runtime! plugin/rplugin.vim
|
||||
endif
|
||||
|
||||
call _defx_init()
|
||||
endif
|
||||
catch
|
||||
call defx#util#print_error(v:exception)
|
||||
call defx#util#print_error(v:throwpoint)
|
||||
|
||||
let python_version_check = defx#init#_python_version_check()
|
||||
if python_version_check
|
||||
call defx#util#print_error(
|
||||
\ 'defx requires Python 3.6.1+.')
|
||||
endif
|
||||
|
||||
if defx#util#has_yarp()
|
||||
if !has('nvim') && !exists('*neovim_rpc#serveraddr')
|
||||
call defx#util#print_error(
|
||||
\ 'defx requires vim-hug-neovim-rpc plugin in Vim.')
|
||||
endif
|
||||
|
||||
if !exists('*yarp#py3')
|
||||
call defx#util#print_error(
|
||||
\ 'defx requires nvim-yarp plugin.')
|
||||
endif
|
||||
else
|
||||
call defx#util#print_error(
|
||||
\ 'defx failed to load. '
|
||||
\ .'Try the :UpdateRemotePlugins command and restart Neovim. '
|
||||
\ .'See also :checkhealth.')
|
||||
endif
|
||||
|
||||
return v:true
|
||||
endtry
|
||||
endfunction
|
||||
function! defx#init#_check_channel() abort
|
||||
return exists('g:defx#_channel_id')
|
||||
endfunction
|
||||
|
||||
function! defx#init#_python_version_check() abort
|
||||
python3 << EOF
|
||||
import vim
|
||||
import sys
|
||||
vim.vars['defx#_python_version_check'] = (
|
||||
sys.version_info.major,
|
||||
sys.version_info.minor,
|
||||
sys.version_info.micro) < (3, 6, 1)
|
||||
EOF
|
||||
return g:defx#_python_version_check
|
||||
endfunction
|
||||
function! defx#init#_user_options() abort
|
||||
return {
|
||||
\ 'auto_cd': v:false,
|
||||
\ 'auto_recursive_level': 0,
|
||||
\ 'buffer_name': 'default',
|
||||
\ 'columns': 'mark:indent:icon:filename:type',
|
||||
\ 'direction': '',
|
||||
\ 'ignored_files': '.*',
|
||||
\ 'listed': v:false,
|
||||
\ 'new': v:false,
|
||||
\ 'profile': v:false,
|
||||
\ 'resume': v:false,
|
||||
\ 'root_marker': '[in]: ',
|
||||
\ 'search': '',
|
||||
\ 'session_file': '',
|
||||
\ 'show_ignored_files': v:false,
|
||||
\ 'split': 'no',
|
||||
\ 'sort': 'filename',
|
||||
\ 'toggle': v:false,
|
||||
\ 'wincol': &columns / 4,
|
||||
\ 'winheight': 30,
|
||||
\ 'winrelative': 'editor',
|
||||
\ 'winrow': &lines / 3,
|
||||
\ 'winwidth': 90,
|
||||
\ }
|
||||
endfunction
|
||||
function! s:internal_options() abort
|
||||
return {
|
||||
\ 'cursor': line('.'),
|
||||
\ 'drives': [],
|
||||
\ 'prev_bufnr': bufnr('%'),
|
||||
\ 'prev_last_bufnr': bufnr('#'),
|
||||
\ 'prev_winid': win_getid(),
|
||||
\ 'visual_start': getpos("'<")[1],
|
||||
\ 'visual_end': getpos("'>")[1],
|
||||
\ }
|
||||
endfunction
|
||||
function! defx#init#_context(user_context) abort
|
||||
let buffer_name = get(a:user_context, 'buffer_name', 'default')
|
||||
let context = s:internal_options()
|
||||
call extend(context, defx#init#_user_options())
|
||||
let custom = defx#custom#_get()
|
||||
if has_key(custom.option, '_')
|
||||
call extend(context, custom.option['_'])
|
||||
endif
|
||||
if has_key(custom.option, buffer_name)
|
||||
call extend(context, custom.option[buffer_name])
|
||||
endif
|
||||
call extend(context, a:user_context)
|
||||
return context
|
||||
endfunction
|
325
bundle/defx.nvim/autoload/defx/util.vim
Normal file
325
bundle/defx.nvim/autoload/defx/util.vim
Normal file
@ -0,0 +1,325 @@
|
||||
"=============================================================================
|
||||
" FILE: util.vim
|
||||
" AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
" License: MIT license
|
||||
"=============================================================================
|
||||
|
||||
let s:is_windows = has('win32') || has('win64')
|
||||
let s:is_mac = !s:is_windows && !has('win32unix')
|
||||
\ && (has('mac') || has('macunix') || has('gui_macvim') ||
|
||||
\ (!isdirectory('/proc') && executable('sw_vers')))
|
||||
|
||||
function! defx#util#print_error(string) abort
|
||||
echohl Error | echomsg '[defx] '
|
||||
\ . defx#util#string(a:string) | echohl None
|
||||
endfunction
|
||||
function! defx#util#print_warning(string) abort
|
||||
echohl WarningMsg | echomsg '[defx] '
|
||||
\ . defx#util#string(a:string) | echohl None
|
||||
endfunction
|
||||
function! defx#util#print_debug(string) abort
|
||||
echomsg '[defx] ' . defx#util#string(a:string)
|
||||
endfunction
|
||||
function! defx#util#print_message(string) abort
|
||||
echo '[defx] ' . defx#util#string(a:string)
|
||||
endfunction
|
||||
function! defx#util#is_windows() abort
|
||||
return s:is_windows
|
||||
endfunction
|
||||
|
||||
function! defx#util#convert2list(expr) abort
|
||||
return type(a:expr) ==# type([]) ? a:expr : [a:expr]
|
||||
endfunction
|
||||
function! defx#util#string(expr) abort
|
||||
return type(a:expr) ==# type('') ? a:expr : string(a:expr)
|
||||
endfunction
|
||||
function! defx#util#split(string) abort
|
||||
return split(a:string, '\s*,\s*')
|
||||
endfunction
|
||||
|
||||
function! defx#util#has_yarp() abort
|
||||
return !has('nvim') || get(g:, 'defx#enable_yarp', 0)
|
||||
endfunction
|
||||
|
||||
function! defx#util#execute_path(command, path) abort
|
||||
try
|
||||
execute a:command fnameescape(s:expand(a:path))
|
||||
catch /^Vim\%((\a\+)\)\=:E325\|^Vim:Interrupt/
|
||||
" Ignore swap file error
|
||||
catch
|
||||
call defx#util#print_error(v:throwpoint)
|
||||
call defx#util#print_error(v:exception)
|
||||
endtry
|
||||
endfunction
|
||||
function! s:expand(path) abort
|
||||
return s:substitute_path_separator(
|
||||
\ (a:path =~# '^\~') ? fnamemodify(a:path, ':p') :
|
||||
\ a:path)
|
||||
endfunction
|
||||
function! s:expand_complete(path) abort
|
||||
return s:substitute_path_separator(
|
||||
\ (a:path =~# '^\~') ? fnamemodify(a:path, ':p') :
|
||||
\ (a:path =~# '^\$\h\w*') ? substitute(a:path,
|
||||
\ '^\$\h\w*', '\=eval(submatch(0))', '') :
|
||||
\ a:path)
|
||||
endfunction
|
||||
function! s:substitute_path_separator(path) abort
|
||||
return s:is_windows ? substitute(a:path, '\\', '/', 'g') : a:path
|
||||
endfunction
|
||||
|
||||
function! defx#util#call_defx(command, args) abort
|
||||
let [paths, context] = defx#util#_parse_options_args(a:args)
|
||||
call defx#start(paths, context)
|
||||
endfunction
|
||||
|
||||
function! defx#util#input(prompt, ...) abort
|
||||
let text = get(a:000, 0, '')
|
||||
let completion = get(a:000, 1, '')
|
||||
try
|
||||
if completion !=# ''
|
||||
return input(a:prompt, text, completion)
|
||||
else
|
||||
return input(a:prompt, text)
|
||||
endif
|
||||
catch
|
||||
" ignore the errors
|
||||
return ''
|
||||
endtry
|
||||
endfunction
|
||||
function! defx#util#confirm(msg, choices, default) abort
|
||||
try
|
||||
return confirm(a:msg, a:choices, a:default)
|
||||
catch
|
||||
" ignore the errors
|
||||
endtry
|
||||
|
||||
return a:default
|
||||
endfunction
|
||||
|
||||
function! defx#util#_parse_options_args(cmdline) abort
|
||||
return s:parse_options(a:cmdline)
|
||||
endfunction
|
||||
function! s:re_unquoted_match(match) abort
|
||||
" Don't match a:match if it is located in-between unescaped single or double
|
||||
" quotes
|
||||
return a:match . '\v\ze([^"' . "'" . '\\]*(\\.|"([^"\\]*\\.)*[^"\\]*"|'
|
||||
\ . "'" . '([^' . "'" . '\\]*\\.)*[^' . "'" . '\\]*' . "'" . '))*[^"'
|
||||
\ . "'" . ']*$'
|
||||
endfunction
|
||||
function! s:remove_quote_pairs(s) abort
|
||||
" remove leading/ending quote pairs
|
||||
let s = a:s
|
||||
if s[0] ==# '"' && s[len(s) - 1] ==# '"'
|
||||
let s = s[1: len(s) - 2]
|
||||
elseif s[0] ==# "'" && s[len(s) - 1] ==# "'"
|
||||
let s = s[1: len(s) - 2]
|
||||
else
|
||||
let s = substitute(a:s, '\\\(.\)', "\\1", 'g')
|
||||
endif
|
||||
return s
|
||||
endfunction
|
||||
function! s:parse_options(cmdline) abort
|
||||
let args = []
|
||||
let options = {}
|
||||
|
||||
" Eval
|
||||
let cmdline = (a:cmdline =~# '\\\@<!`.*\\\@<!`') ?
|
||||
\ s:eval_cmdline(a:cmdline) : a:cmdline
|
||||
|
||||
for s in split(cmdline, s:re_unquoted_match('\%(\\\@<!\s\)\+'))
|
||||
let arg = substitute(s, '\\\( \)', '\1', 'g')
|
||||
let arg_key = substitute(arg, '=\zs.*$', '', '')
|
||||
|
||||
let name = substitute(tr(arg_key, '-', '_'), '=$', '', '')[1:]
|
||||
if name =~# '^no_'
|
||||
let name = name[3:]
|
||||
let value = v:false
|
||||
else
|
||||
let value = (arg_key =~# '=$') ?
|
||||
\ s:remove_quote_pairs(arg[len(arg_key) :]) : v:true
|
||||
endif
|
||||
|
||||
if index(keys(defx#init#_user_options()), name) >= 0
|
||||
let options[name] = value
|
||||
else
|
||||
call add(args, arg)
|
||||
endif
|
||||
endfor
|
||||
|
||||
return [args, options]
|
||||
endfunction
|
||||
function! s:eval_cmdline(cmdline) abort
|
||||
let cmdline = ''
|
||||
let prev_match = 0
|
||||
let eval_pos = match(a:cmdline, '\\\@<!`.\{-}\\\@<!`')
|
||||
while eval_pos >= 0
|
||||
if eval_pos - prev_match > 0
|
||||
let cmdline .= a:cmdline[prev_match : eval_pos - 1]
|
||||
endif
|
||||
let prev_match = matchend(a:cmdline,
|
||||
\ '\\\@<!`.\{-}\\\@<!`', eval_pos)
|
||||
let cmdline .= escape(eval(a:cmdline[eval_pos+1 : prev_match - 2]), '\ ')
|
||||
|
||||
let eval_pos = match(a:cmdline, '\\\@<!`.\{-}\\\@<!`', prev_match)
|
||||
endwhile
|
||||
if prev_match >= 0
|
||||
let cmdline .= a:cmdline[prev_match :]
|
||||
endif
|
||||
|
||||
return cmdline
|
||||
endfunction
|
||||
|
||||
function! defx#util#complete(arglead, cmdline, cursorpos) abort
|
||||
let _ = []
|
||||
|
||||
if a:arglead =~# '^-'
|
||||
" Option names completion.
|
||||
let bool_options = keys(filter(copy(defx#init#_user_options()),
|
||||
\ 'type(v:val) == type(v:true) || type(v:val) == type(v:false)'))
|
||||
let _ += map(copy(bool_options), "'-' . tr(v:val, '_', '-')")
|
||||
let string_options = keys(filter(copy(defx#init#_user_options()),
|
||||
\ 'type(v:val) != type(v:true) && type(v:val) != type(v:false)'))
|
||||
let _ += map(copy(string_options), "'-' . tr(v:val, '_', '-') . '='")
|
||||
|
||||
" Add "-no-" option names completion.
|
||||
let _ += map(copy(bool_options), "'-no-' . tr(v:val, '_', '-')")
|
||||
else
|
||||
let arglead = s:expand_complete(a:arglead)
|
||||
" Path names completion.
|
||||
let files = filter(map(glob(a:arglead . '*', v:true, v:true),
|
||||
\ 's:substitute_path_separator(v:val)'),
|
||||
\ 'stridx(tolower(v:val), tolower(arglead)) == 0')
|
||||
let files = map(filter(files, 'isdirectory(v:val)'),
|
||||
\ 's:expand_complete(v:val)')
|
||||
if a:arglead =~# '^\~'
|
||||
let home_pattern = '^'. s:expand_complete('~')
|
||||
call map(files, "substitute(v:val, home_pattern, '~/', '')")
|
||||
endif
|
||||
call map(files, "escape(v:val.'/', ' \\')")
|
||||
let _ += files
|
||||
endif
|
||||
|
||||
return uniq(sort(filter(_, 'stridx(v:val, a:arglead) == 0')))
|
||||
endfunction
|
||||
|
||||
function! defx#util#has_yarp() abort
|
||||
return !has('nvim')
|
||||
endfunction
|
||||
function! defx#util#rpcrequest(method, args, is_async) abort
|
||||
if !defx#init#_check_channel()
|
||||
return -1
|
||||
endif
|
||||
|
||||
if defx#util#has_yarp()
|
||||
if g:defx#_yarp.job_is_dead
|
||||
return -1
|
||||
endif
|
||||
if a:is_async
|
||||
return g:defx#_yarp.notify(a:method, a:args)
|
||||
else
|
||||
return g:defx#_yarp.request(a:method, a:args)
|
||||
endif
|
||||
else
|
||||
if a:is_async
|
||||
return rpcnotify(g:defx#_channel_id, a:method, a:args)
|
||||
else
|
||||
return rpcrequest(g:defx#_channel_id, a:method, a:args)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" Open a file.
|
||||
function! defx#util#open(filename) abort
|
||||
let filename = fnamemodify(a:filename, ':p')
|
||||
|
||||
" Detect desktop environment.
|
||||
if s:is_windows
|
||||
" For URI only.
|
||||
" Note:
|
||||
" # and % required to be escaped (:help cmdline-special)
|
||||
silent execute printf(
|
||||
\ '!start rundll32 url.dll,FileProtocolHandler %s',
|
||||
\ escape(filename, '#%'),
|
||||
\)
|
||||
elseif has('win32unix')
|
||||
" Cygwin.
|
||||
call system(printf('%s %s', 'cygstart',
|
||||
\ shellescape(filename)))
|
||||
elseif executable('xdg-open')
|
||||
" Linux.
|
||||
call system(printf('%s %s &', 'xdg-open',
|
||||
\ shellescape(filename)))
|
||||
elseif exists('$KDE_FULL_SESSION') && $KDE_FULL_SESSION ==# 'true'
|
||||
" KDE.
|
||||
call system(printf('%s %s &', 'kioclient exec',
|
||||
\ shellescape(filename)))
|
||||
elseif exists('$GNOME_DESKTOP_SESSION_ID')
|
||||
" GNOME.
|
||||
call system(printf('%s %s &', 'gnome-open',
|
||||
\ shellescape(filename)))
|
||||
elseif executable('exo-open')
|
||||
" Xfce.
|
||||
call system(printf('%s %s &', 'exo-open',
|
||||
\ shellescape(filename)))
|
||||
elseif s:is_mac && executable('open')
|
||||
" Mac OS.
|
||||
call system(printf('%s %s &', 'open',
|
||||
\ shellescape(filename)))
|
||||
else
|
||||
" Give up.
|
||||
call defx#util#print_error('Not supported.')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! defx#util#cd(path) abort
|
||||
if exists('*chdir')
|
||||
call chdir(a:path)
|
||||
else
|
||||
silent execute (haslocaldir() ? 'lcd' : 'cd') fnameescape(a:path)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! defx#util#truncate_skipping(str, max, footer_width, separator) abort
|
||||
let width = strwidth(a:str)
|
||||
if width <= a:max
|
||||
let ret = a:str
|
||||
else
|
||||
let header_width = a:max - strwidth(a:separator) - a:footer_width
|
||||
let ret = s:strwidthpart(a:str, header_width) . a:separator
|
||||
\ . s:strwidthpart_reverse(a:str, a:footer_width)
|
||||
endif
|
||||
return s:truncate(ret, a:max)
|
||||
endfunction
|
||||
function! s:truncate(str, width) abort
|
||||
" Original function is from mattn.
|
||||
" http://github.com/mattn/googlereader-vim/tree/master
|
||||
|
||||
if a:str =~# '^[\x00-\x7f]*$'
|
||||
return len(a:str) < a:width
|
||||
\ ? printf('%-' . a:width . 's', a:str)
|
||||
\ : strpart(a:str, 0, a:width)
|
||||
endif
|
||||
|
||||
let ret = a:str
|
||||
let width = strwidth(a:str)
|
||||
if width > a:width
|
||||
let ret = s:strwidthpart(ret, a:width)
|
||||
let width = strwidth(ret)
|
||||
endif
|
||||
|
||||
if width < a:width
|
||||
let ret .= repeat(' ', a:width - width)
|
||||
endif
|
||||
|
||||
return ret
|
||||
endfunction
|
||||
function! s:strwidthpart(str, width) abort
|
||||
let str = tr(a:str, "\t", ' ')
|
||||
let vcol = a:width + 2
|
||||
return matchstr(str, '.*\%<' . (vcol < 0 ? 0 : vcol) . 'v')
|
||||
endfunction
|
||||
function! s:strwidthpart_reverse(str, width) abort
|
||||
let str = tr(a:str, "\t", ' ')
|
||||
let vcol = strwidth(str) - a:width
|
||||
return matchstr(str, '\%>' . (vcol < 0 ? 0 : vcol) . 'v.*')
|
||||
endfunction
|
25
bundle/defx.nvim/autoload/health/defx.vim
Normal file
25
bundle/defx.nvim/autoload/health/defx.vim
Normal file
@ -0,0 +1,25 @@
|
||||
"=============================================================================
|
||||
" FILE: defx.vim
|
||||
" AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
" License: MIT license
|
||||
"=============================================================================
|
||||
|
||||
function! s:check_required_python_for_defx() abort
|
||||
if has('python3')
|
||||
call health#report_ok('has("python3") was successful')
|
||||
else
|
||||
call health#report_error('has("python3") was not successful')
|
||||
endif
|
||||
|
||||
if defx#init#_python_version_check()
|
||||
call health#report_error('Python 3.6.1+ was successful')
|
||||
else
|
||||
call health#report_ok('Python 3.6.1+ was successful')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! health#defx#check() abort
|
||||
call health#report_start('defx.nvim')
|
||||
|
||||
call s:check_required_python_for_defx()
|
||||
endfunction
|
824
bundle/defx.nvim/doc/defx.txt
Normal file
824
bundle/defx.nvim/doc/defx.txt
Normal file
@ -0,0 +1,824 @@
|
||||
*defx.txt* Dark powered file explorer for neovim/Vim8.
|
||||
|
||||
Version: 1.0
|
||||
Author: Shougo <Shougo.Matsu at gmail.com>
|
||||
License: MIT license
|
||||
|
||||
CONTENTS *defx-contents*
|
||||
|
||||
Introduction |defx-introduction|
|
||||
Install |defx-install|
|
||||
Interface |defx-interface|
|
||||
Commands |defx-commands|
|
||||
Functions |defx-functions|
|
||||
Key mappings |defx-key-mappings|
|
||||
Actions |defx-actions|
|
||||
Options |defx-options|
|
||||
Columns |defx-columns|
|
||||
External columns |defx-external-columns|
|
||||
Sources |defx-sources|
|
||||
Examples |defx-examples|
|
||||
FAQ |defx-faq|
|
||||
Compatibility |defx-compatibility|
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *defx-introduction*
|
||||
|
||||
*defx* is the abbreviation of "dark powered file explorer".
|
||||
|
||||
==============================================================================
|
||||
INSTALL *defx-install*
|
||||
|
||||
Note: defx requires Neovim 0.3.0+ or Vim8.1+ with Python3.6.1+.
|
||||
|
||||
Please install nvim-yarp plugin for Vim8.
|
||||
https://github.com/roxma/nvim-yarp
|
||||
|
||||
Please install vim-hug-neovim-rpc plugin for Vim8.
|
||||
https://github.com/roxma/vim-hug-neovim-rpc
|
||||
|
||||
1. Extract the files and put them in your Neovim or .vim directory
|
||||
(usually `$XDG_CONFIG_HOME/nvim/`).
|
||||
2. Execute the ":UpdateRemotePlugins" if Neovim.
|
||||
|
||||
If ":echo has('python3')" returns `1`, then you're done; otherwise, see below.
|
||||
|
||||
You can enable Python3 interface with pip: >
|
||||
|
||||
pip3 install --user pynvim
|
||||
|
||||
Note: defx needs pynvim ver.0.1.8+. You need update pynvim module.
|
||||
>
|
||||
pip3 install --user --upgrade pynvim
|
||||
<
|
||||
If you want to read for pynvim/python3 interface install documentation,
|
||||
you should read |provider-python| and the Wiki.
|
||||
https://github.com/zchee/deoplete-jedi/wiki/Setting-up-Python-for-Neovim
|
||||
|
||||
You can check the Python3 installation by |:checkhealth| command in neovim.
|
||||
|
||||
==============================================================================
|
||||
INTERFACE *defx-interface*
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
COMMANDS *defx-commands*
|
||||
|
||||
:Defx [{options}] {paths} *:Defx*
|
||||
Creates a new Defx buffer.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
FUNCTIONS *defx-functions*
|
||||
|
||||
defx#async_action({action}[, {args}]) *defx#async_action()*
|
||||
Fire {action} action with {args} asynchronously. You can find
|
||||
the actions list in |defx-actions|.
|
||||
{args} behavior depends on {action}.
|
||||
Note: It is only used to define mappings.
|
||||
Note: You cannot fire the next action until the previous
|
||||
action is finished.
|
||||
|
||||
*defx#call_action()*
|
||||
defx#call_action({action}[, {args}])
|
||||
Fire {action} action with {args}. You can find the actions
|
||||
list in |defx-actions|.
|
||||
{args} behavior depends on {action}.
|
||||
|
||||
*defx#call_async_action()*
|
||||
defx#call_async_action({action}[, {args}])
|
||||
Fire {action} action with {args} asynchronously. You can find
|
||||
the actions list in |defx-actions|.
|
||||
{args} behavior depends on {action}.
|
||||
Note: You cannot fire the next action until the previous
|
||||
action is finished.
|
||||
|
||||
*defx#custom#column()*
|
||||
defx#custom#column({column-name}, {option-name}, {value})
|
||||
defx#custom#column({column-name}, {dict})
|
||||
Set {column-name} column specialized variable {variable-name}
|
||||
to {value}. You may specify multiple sources with the
|
||||
separator "," in {column-name}. >
|
||||
|
||||
call defx#custom#column('icon', {
|
||||
\ 'directory_icon': '▸',
|
||||
\ 'opened_icon': '▾',
|
||||
\ 'root_icon': ' ',
|
||||
\ })
|
||||
|
||||
call defx#custom#column('filename', {
|
||||
\ 'min_width': 40,
|
||||
\ 'max_width': 40,
|
||||
\ })
|
||||
|
||||
call defx#custom#column('mark', {
|
||||
\ 'readonly_icon': '✗',
|
||||
\ 'selected_icon': '✓',
|
||||
\ })
|
||||
<
|
||||
*defx#custom#option()*
|
||||
defx#custom#option({buffer-name}, {option-name}, {value})
|
||||
defx#custom#option({buffer-name}, {dict})
|
||||
Set {option-name} option to {value} in {buffer-name}
|
||||
buffer.
|
||||
If {buffer-name} is "_", the options are used for all buffers.
|
||||
If {dict} is available, the key is {option-name} and the value
|
||||
is {value}.
|
||||
Note: The all options are in |defx-options|. However, "-" is
|
||||
substituted to "_", and "-" prefix is removed. >
|
||||
|
||||
call defx#custom#option('_', {
|
||||
\ 'columns': 'mark:indent:icon:filename:type:size:time',
|
||||
\ })
|
||||
<
|
||||
*defx#custom#source()*
|
||||
defx#custom#source({source-name}, {var-name}, {value})
|
||||
defx#custom#source({source-name}, {dict})
|
||||
Set {source-name} source specialized variable {variable-name}
|
||||
to {value}. You may specify multiple sources with the
|
||||
separator "," in {source-name}.
|
||||
>
|
||||
function! Root(path) abort
|
||||
return fnamemodify(a:path, ':t')
|
||||
endfunction
|
||||
|
||||
call defx#custom#source('file', {
|
||||
\ 'root': 'Root',
|
||||
\})
|
||||
<
|
||||
defx#do_action({action}[, {args}]) *defx#do_action()*
|
||||
Fire {action} action with {args}. You can find the actions
|
||||
list in |defx-actions|.
|
||||
{args} behavior depends on {action}.
|
||||
Note: It is only used to define mappings.
|
||||
|
||||
defx#get_candidate() *defx#get_candidate()*
|
||||
Returns the current cursor candidate as |Dictionary|.
|
||||
|
||||
defx#get_context() *defx#get_context()*
|
||||
Returns the current context as |Dictionary|.
|
||||
|
||||
defx#is_directory() *defx#is_directory()*
|
||||
Returns |v:true| if the current cursor candidate is directory.
|
||||
|
||||
Example: >
|
||||
|
||||
nnoremap <silent><buffer><expr> <CR>
|
||||
\ defx#is_directory() ?
|
||||
\ defx#do_action('open_directory') :
|
||||
\ defx#do_action('multi', ['drop', 'quit'])
|
||||
|
||||
defx#is_opened_tree() *defx#is_opened_tree()*
|
||||
Returns |v:true| if the current cursor candidate is opened
|
||||
directory tree.
|
||||
|
||||
defx#redraw() *defx#redraw()*
|
||||
Redraw all defx windows.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
KEY MAPPINGS *defx-key-mappings*
|
||||
|
||||
Defx does not provide any of default key mappings.
|
||||
You need to define original key mappings by |defx#do_action()|.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
ACTIONS *defx-actions*
|
||||
|
||||
add_session *defx-action-add_session*
|
||||
Add the current directory in current sessions and save to
|
||||
|defx-option-session-file|.
|
||||
Note: You must set to |defx-option-session-file| save current
|
||||
sessions.
|
||||
|
||||
Current session feature saves below states.
|
||||
|
||||
* current path
|
||||
* opened tree state
|
||||
|
||||
Action args:
|
||||
0. session directory path
|
||||
|
||||
call *defx-action-call*
|
||||
Call the function.
|
||||
You can get the files path as "a:context.targets".
|
||||
|
||||
Action args:
|
||||
0. function name
|
||||
Note: It must be string. You cannot use |Funcref| or
|
||||
|lambda|.
|
||||
|
||||
Example: >
|
||||
|
||||
function! Test(context) abort
|
||||
echomsg string(a:context.targets)
|
||||
endfunction
|
||||
nnoremap <silent><buffer><expr> f
|
||||
\ defx#do_action('call', 'Test')
|
||||
|
||||
" or you can use SID hack
|
||||
function! s:Test(context) abort
|
||||
echomsg string(a:context.targets)
|
||||
endfunction
|
||||
function! s:SID_PREFIX() abort
|
||||
return matchstr(expand('<sfile>'),
|
||||
\ '<SNR>\d\+_\zeSID_PREFIX$')
|
||||
endfunction
|
||||
let g:sid = s:SID_PREFIX()
|
||||
nnoremap <silent><buffer><expr> f
|
||||
\ defx#do_action('call', g:sid.'Test')
|
||||
|
||||
cd *defx-action-cd*
|
||||
Change the current directory.
|
||||
Note: If the action args is empty, it means the home
|
||||
directory.
|
||||
|
||||
Action args:
|
||||
0. new current directory path
|
||||
|
||||
change_vim_cwd *change_vim_cwd*
|
||||
Change current working directory to the current directory.
|
||||
Note: It changes global current directory if the window has
|
||||
not local current directory. If you don't like the behavior,
|
||||
you need to set local current directory.
|
||||
|
||||
clear_select_all *defx-action-clear_select_all*
|
||||
Clear the all candidates select.
|
||||
|
||||
close_tree *defx-action-close_tree*
|
||||
Close the directory tree.
|
||||
|
||||
copy *defx-action-copy*
|
||||
Copy the selected files to defx clipboard.
|
||||
|
||||
drop *defx-action-drop*
|
||||
Open the file like |:drop| command.
|
||||
|
||||
Action args:
|
||||
0. open command(The default is |:edit|)
|
||||
|
||||
execute_command *defx-action-execute_command*
|
||||
Execute the command.
|
||||
|
||||
Action args:
|
||||
0. command(The default is your input)
|
||||
|
||||
execute_system *defx-action-execute_system*
|
||||
Execute the file by system associated command.
|
||||
|
||||
move *defx-action-move*
|
||||
Move the selected files to defx clipboard.
|
||||
|
||||
multi *defx-action-multi*
|
||||
Multiple actions.
|
||||
|
||||
Action args:
|
||||
0. action 1
|
||||
1. action 2
|
||||
...
|
||||
|
||||
Example: >
|
||||
|
||||
" auto quit like behavior
|
||||
nnoremap <silent><buffer><expr> <CR>
|
||||
\ defx#do_action('multi', ['drop', 'quit'])
|
||||
nnoremap <silent><buffer><expr> s
|
||||
\ defx#do_action('multi', [['drop', 'split'], 'quit'])
|
||||
|
||||
new_directory *defx-action-new_directory*
|
||||
Create a new directory.
|
||||
|
||||
new_file *defx-action-new_file*
|
||||
Create a new file and directory if provided.
|
||||
If the input ends with "/", it means new directory.
|
||||
|
||||
*defx-action-new_multiple_files*
|
||||
new_multiple_files
|
||||
Create new files and directories if provided.
|
||||
If the input ends with "/", it means new directory.
|
||||
|
||||
open *defx-action-open*
|
||||
Open the selected candidates.
|
||||
Note: If the candidate is directory, it is same with
|
||||
|defx-action-open_directory|.
|
||||
|
||||
Action args:
|
||||
0. open command(The default is |:edit|)
|
||||
|
||||
open_directory *defx-action-open_directory*
|
||||
Open the directory.
|
||||
|
||||
Action args:
|
||||
0. open file path(The default is the selected
|
||||
directory)
|
||||
|
||||
open_or_close_tree *defx-action-open_or_close_tree*
|
||||
It is the same with |defx-action-open_tree| with "toggle"
|
||||
arg.
|
||||
Note: The action is deprecated.
|
||||
|
||||
open_tree *defx-action-open_tree*
|
||||
Open the directory tree.
|
||||
|
||||
Action args:
|
||||
0-n. options. The supported values are:
|
||||
|
||||
"nested":
|
||||
enable nested directory view if it has one
|
||||
directory only.
|
||||
"recursive":
|
||||
open the directory tree recursively.
|
||||
"recursive[:{level}]":
|
||||
open the directory tree recursively by
|
||||
max recursive {level}.
|
||||
"toggle":
|
||||
close the directory tree if the directory is
|
||||
opened.
|
||||
|
||||
|
||||
open_tree_recursive *defx-action-open_tree_recursive*
|
||||
It is the same with |defx-action-open_tree| with "recursive"
|
||||
arg.
|
||||
Note: The action is deprecated.
|
||||
|
||||
paste *defx-action-paste*
|
||||
Fire the clipboard action in the current directory.
|
||||
Note: It is used after |defx-action-copy| or
|
||||
|defx-action-move|.
|
||||
|
||||
print *defx-action-print*
|
||||
Print the filename.
|
||||
|
||||
quit *defx-action-quit*
|
||||
Quit the buffer.
|
||||
|
||||
redraw *defx-action-redraw*
|
||||
Redraw the buffer.
|
||||
|
||||
repeat *defx-action-repeat*
|
||||
Redraw the previous action.
|
||||
|
||||
rename *defx-action-rename*
|
||||
Rename the file/directory under cursor or from selected list.
|
||||
Note: If you select multiple files, it will be buffer-rename
|
||||
mode.
|
||||
|
||||
remove *defx-action-remove*
|
||||
Delete the file/directory under cursor or from selected list
|
||||
completely.
|
||||
Note: You cannot undo the action.
|
||||
|
||||
Action args:
|
||||
0. If it is "true", suppress the confirmation.
|
||||
|
||||
remove_trash *defx-action-remove_trash*
|
||||
Delete the file/directory under cursor or from selected list
|
||||
to trashbox.
|
||||
|
||||
Note: Send2Trash module is needed for the action.
|
||||
https://pypi.org/project/Send2Trash/
|
||||
|
||||
Action args:
|
||||
0. If it is "true", suppress the confirmation.
|
||||
|
||||
resize *defx-action-resize*
|
||||
Vertical resize and redraw the current window.
|
||||
|
||||
Action args:
|
||||
0. Resized window size.
|
||||
|
||||
search *defx-action-search*
|
||||
Search the path.
|
||||
|
||||
Action args:
|
||||
0. search the path
|
||||
|
||||
toggle_columns *defx-action-toggle_columns*
|
||||
Toggle the current columns.
|
||||
|
||||
Action args:
|
||||
0. ":" separated defx columns.
|
||||
|
||||
toggle_sort *defx-action-toggle_sort*
|
||||
Toggle the sort method.
|
||||
|
||||
Action args:
|
||||
0. sort method.
|
||||
|
||||
toggle_ignored_files *defx-action-toggle_ignored_files*
|
||||
Toggle the enable state of ignored files.
|
||||
|
||||
toggle_select *defx-action-toggle_select*
|
||||
Toggle the cursor candidate select.
|
||||
|
||||
toggle_select_all *defx-action-toggle_select_all*
|
||||
Toggle the all candidates select.
|
||||
|
||||
toggle_select_visual
|
||||
*defx-action-toggle_select_visual*
|
||||
Toggle the visual mode selected candidates select.
|
||||
|
||||
yank_path *defx-action-yank_path*
|
||||
Yank the all candidates path.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
OPTIONS *defx-options*
|
||||
|
||||
*defx-option-no-*
|
||||
-no-{option-name}
|
||||
Disable {option-name} flag.
|
||||
Note: If you use both {option-name} and -no-{option-name} in
|
||||
the same denite buffer, it is undefined.
|
||||
|
||||
*defx-option-auto-cd*
|
||||
-auto-cd
|
||||
Change the working directory while navigating with defx.
|
||||
Note: It changes global current directory if the window has
|
||||
not local current directory. If you don't like the behavior,
|
||||
you need to set local current directory.
|
||||
|
||||
Default: false
|
||||
|
||||
*defx-option-auto-recursive-level*
|
||||
-auto-recursive-level={level}
|
||||
The level to expand tree automatically.
|
||||
Default: 0
|
||||
|
||||
*defx-option-buffer-name*
|
||||
-buffer-name={buffer-name}
|
||||
Specify defx buffer name.
|
||||
Default: "default"
|
||||
|
||||
*defx-option-columns*
|
||||
-columns={columns1:columns2,...}
|
||||
Specify defx columns.
|
||||
Default: "mark:indent:icon:filename:type"
|
||||
|
||||
*defx-option-direction*
|
||||
-direction={direction}
|
||||
Specify the window direction as {direction} if
|
||||
|defx-option-split| is set.
|
||||
You can use "topleft" or "botright".
|
||||
Default: ""
|
||||
|
||||
*defx-option-ignored-files*
|
||||
-ignored-files={pattern}
|
||||
Specify the ignored files pattern.
|
||||
The pattern is comma separated.
|
||||
Default: ".*"
|
||||
|
||||
*defx-option-listed*
|
||||
-listed
|
||||
Enable 'buflisted' option in defx buffer.
|
||||
|
||||
Default: false
|
||||
|
||||
*defx-option-new*
|
||||
-new
|
||||
Create new defx buffer.
|
||||
|
||||
Default: false
|
||||
|
||||
*defx-option-profile*
|
||||
-profile
|
||||
Enable profile feature.
|
||||
Note: It is for debugging.
|
||||
|
||||
Default: false
|
||||
|
||||
*defx-option-resume*
|
||||
-resume
|
||||
Resume existing defx buffer.
|
||||
Note: |defx-option-listed| is needed to resume.
|
||||
|
||||
Default: false
|
||||
|
||||
*defx-option-root-marker*
|
||||
-root-marker={marker}
|
||||
Root marker.
|
||||
|
||||
Default: "[in]: "
|
||||
|
||||
*defx-option-search*
|
||||
-search={path}
|
||||
Search the {path}.
|
||||
Note: It must be full path.
|
||||
|
||||
Default: ""
|
||||
|
||||
*defx-option-session-file*
|
||||
-session-file={path}
|
||||
Session file {path}.
|
||||
Note: It must be full path.
|
||||
|
||||
Default: ""
|
||||
|
||||
*defx-option-show-ignored-files*
|
||||
-show-ignored-files
|
||||
Show ignored files by default.
|
||||
Default: false
|
||||
|
||||
*defx-options-sort*
|
||||
-sort={method}
|
||||
Sort method.
|
||||
If the method is upper case, the order will be reversed.
|
||||
|
||||
"extension": file extension sort
|
||||
"filename": file name sort
|
||||
"size": file size sort
|
||||
"time": file modified time sort
|
||||
|
||||
Default: "filename"
|
||||
|
||||
*defx-option-split*
|
||||
-split={direction}
|
||||
Specify the split direction.
|
||||
|
||||
"vertical": Split buffer vertically
|
||||
"horizontal": Split buffer horizontally
|
||||
"no": No split
|
||||
"tab": Create the new tab
|
||||
"floating": Use neovim floating window feature
|
||||
|
||||
Default: "no"
|
||||
|
||||
*defx-option-toggle*
|
||||
-toggle
|
||||
Close defx buffer window if this defx window exists.
|
||||
Default: false
|
||||
|
||||
*defx-option-wincol*
|
||||
-wincol={window-column}
|
||||
Set the column position of the Defx window if
|
||||
|defx-option-split| is "floating".
|
||||
|
||||
Default: &columns / 4
|
||||
|
||||
*defx-option-winheight*
|
||||
-winheight={window-height}
|
||||
Set the height of the window if |defx-option-split| is
|
||||
"horizontal".
|
||||
|
||||
Default: 30
|
||||
|
||||
*defx-option-winrelative*
|
||||
-winrelative={direction}
|
||||
Specify the relative position in floating window.
|
||||
|nvim_open_win()|
|
||||
|
||||
Default: "editor"
|
||||
|
||||
*defx-option-winrow*
|
||||
-winrow={window-row}
|
||||
Set the row position of the Defx window if
|
||||
|defx-option-split| is "floating".
|
||||
|
||||
Default: &lines / 3
|
||||
|
||||
*defx-option-winwidth*
|
||||
-winwidth={window-width}
|
||||
Set the width of the window if |defx-option-split| is
|
||||
"vertical".
|
||||
|
||||
Default: 90
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
COLUMNS *defx-columns*
|
||||
|
||||
*defx-column-filename*
|
||||
filename File name.
|
||||
|
||||
variables:
|
||||
min_width the minimum width of a defx buffer
|
||||
(default: 40)
|
||||
max_width the maximum width of a defx buffer
|
||||
If it is negative value, it means:
|
||||
"winwidth -max_width / 100".
|
||||
Example: "-120" max_width means 120 percent
|
||||
winwidth.
|
||||
(default: 100)
|
||||
root_marker_highlight
|
||||
the root marker highlight
|
||||
(default: "Constant")
|
||||
|
||||
*defx-column-icon*
|
||||
icon Basic icon.
|
||||
|
||||
variables:
|
||||
directory_icon the closed directory icon
|
||||
(default: "+")
|
||||
opened_icon the opened directory icon
|
||||
(default: "-")
|
||||
root_icon the root directory icon
|
||||
(default: " ")
|
||||
|
||||
*defx-column-indent*
|
||||
indent Tree indentation.
|
||||
Note: It depends on |defx-column-filename|.
|
||||
|
||||
variables:
|
||||
indent the indent marker.
|
||||
(default: " ")
|
||||
|
||||
*defx-column-mark*
|
||||
mark File selected mark.
|
||||
|
||||
variables:
|
||||
length the column length
|
||||
(default: 1)
|
||||
readonly_icon the readonly file icon
|
||||
(default: "X")
|
||||
selected_icon the selected file icon
|
||||
(default: "*")
|
||||
|
||||
*defx-column-size*
|
||||
size File size.
|
||||
|
||||
*defx-column-space*
|
||||
space One space column for padding.
|
||||
|
||||
*defx-column-time*
|
||||
time File modified time.
|
||||
|
||||
variables:
|
||||
format the time format
|
||||
(default: "%y.%m.%d %H:%M")
|
||||
|
||||
*defx-column-type*
|
||||
type File type.
|
||||
|
||||
variables:
|
||||
types the types definition
|
||||
(default: complicated)
|
||||
|
||||
EXTERNAL COLUMNS *defx-external-columns*
|
||||
|
||||
git Git status.
|
||||
https://github.com/kristijanhusak/defx-git
|
||||
|
||||
icons Nerd font icons.
|
||||
https://github.com/kristijanhusak/defx-icons
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
SOURCES *defx-sources*
|
||||
|
||||
file File
|
||||
|
||||
variables:
|
||||
root root function name
|
||||
Note: It must be string. You cannot use
|
||||
|Funcref| or |lambda|.
|
||||
(default is v:null)
|
||||
|
||||
==============================================================================
|
||||
DENITE SOURCES *defx-denite-sources*
|
||||
|
||||
*denite-source-defx/drive*
|
||||
defx/drive Gather defx drives.
|
||||
|
||||
Note: You can set drives like this:
|
||||
>
|
||||
call defx#custom#option('_', 'drives', [
|
||||
\ expand('~/Downloads'), expand('~')
|
||||
\ ])
|
||||
<
|
||||
*denite-source-defx/history*
|
||||
defx/history Gather defx histories.
|
||||
|
||||
*denite-source-defx/session*
|
||||
defx/session Gather defx sessions.
|
||||
|
||||
==============================================================================
|
||||
EXAMPLES *defx-examples*
|
||||
>
|
||||
autocmd FileType defx call s:defx_my_settings()
|
||||
function! s:defx_my_settings() abort
|
||||
" Define mappings
|
||||
nnoremap <silent><buffer><expr> <CR>
|
||||
\ defx#do_action('open')
|
||||
nnoremap <silent><buffer><expr> c
|
||||
\ defx#do_action('copy')
|
||||
nnoremap <silent><buffer><expr> m
|
||||
\ defx#do_action('move')
|
||||
nnoremap <silent><buffer><expr> p
|
||||
\ defx#do_action('paste')
|
||||
nnoremap <silent><buffer><expr> l
|
||||
\ defx#do_action('open')
|
||||
nnoremap <silent><buffer><expr> E
|
||||
\ defx#do_action('open', 'vsplit')
|
||||
nnoremap <silent><buffer><expr> P
|
||||
\ defx#do_action('open', 'pedit')
|
||||
nnoremap <silent><buffer><expr> o
|
||||
\ defx#do_action('open_tree', 'toggle')
|
||||
nnoremap <silent><buffer><expr> K
|
||||
\ defx#do_action('new_directory')
|
||||
nnoremap <silent><buffer><expr> N
|
||||
\ defx#do_action('new_file')
|
||||
nnoremap <silent><buffer><expr> M
|
||||
\ defx#do_action('new_multiple_files')
|
||||
nnoremap <silent><buffer><expr> C
|
||||
\ defx#do_action('toggle_columns',
|
||||
\ 'mark:indent:icon:filename:type:size:time')
|
||||
nnoremap <silent><buffer><expr> S
|
||||
\ defx#do_action('toggle_sort', 'time')
|
||||
nnoremap <silent><buffer><expr> d
|
||||
\ defx#do_action('remove')
|
||||
nnoremap <silent><buffer><expr> r
|
||||
\ defx#do_action('rename')
|
||||
nnoremap <silent><buffer><expr> !
|
||||
\ defx#do_action('execute_command')
|
||||
nnoremap <silent><buffer><expr> x
|
||||
\ defx#do_action('execute_system')
|
||||
nnoremap <silent><buffer><expr> yy
|
||||
\ defx#do_action('yank_path')
|
||||
nnoremap <silent><buffer><expr> .
|
||||
\ defx#do_action('toggle_ignored_files')
|
||||
nnoremap <silent><buffer><expr> ;
|
||||
\ defx#do_action('repeat')
|
||||
nnoremap <silent><buffer><expr> h
|
||||
\ defx#do_action('cd', ['..'])
|
||||
nnoremap <silent><buffer><expr> ~
|
||||
\ defx#do_action('cd')
|
||||
nnoremap <silent><buffer><expr> q
|
||||
\ defx#do_action('quit')
|
||||
nnoremap <silent><buffer><expr> <Space>
|
||||
\ defx#do_action('toggle_select') . 'j'
|
||||
nnoremap <silent><buffer><expr> *
|
||||
\ defx#do_action('toggle_select_all')
|
||||
nnoremap <silent><buffer><expr> j
|
||||
\ line('.') == line('$') ? 'gg' : 'j'
|
||||
nnoremap <silent><buffer><expr> k
|
||||
\ line('.') == 1 ? 'G' : 'k'
|
||||
nnoremap <silent><buffer><expr> <C-l>
|
||||
\ defx#do_action('redraw')
|
||||
nnoremap <silent><buffer><expr> <C-g>
|
||||
\ defx#do_action('print')
|
||||
nnoremap <silent><buffer><expr> cd
|
||||
\ defx#do_action('change_vim_cwd')
|
||||
endfunction
|
||||
<
|
||||
==============================================================================
|
||||
FREQUENTLY ASKED QUESTIONS (FAQ) *defx-faq*
|
||||
|
||||
Q: I want to explore the folder where the current file is.
|
||||
|
||||
A: >
|
||||
Defx `expand('%:p:h')` -search=`expand('%:p')`
|
||||
|
||||
Q: I want to open defx window like explorer.
|
||||
|
||||
A: >
|
||||
Defx -split=vertical -winwidth=50 -direction=topleft
|
||||
|
||||
Q: I want to open file like vimfiler explorer mode.
|
||||
|
||||
A: >
|
||||
nnoremap <silent><buffer><expr> <CR> defx#do_action('drop')
|
||||
|
||||
Q: I want to disable root marker.
|
||||
|
||||
A: >
|
||||
call defx#custom#option('_', {
|
||||
\ 'root_marker': ':',
|
||||
\ })
|
||||
call defx#custom#column('filename', {
|
||||
\ 'root_marker_highlight': 'Ignore',
|
||||
\ })
|
||||
|
||||
Q: I want to resize defx window dynamically.
|
||||
|
||||
A: >
|
||||
nnoremap <silent><buffer><expr> > defx#do_action('resize',
|
||||
\ defx#get_context().winwidth + 10)
|
||||
nnoremap <silent><buffer><expr> < defx#do_action('resize',
|
||||
\ defx#get_context().winwidth - 10)
|
||||
|
||||
|
||||
Q: I want to update defx status automatically when changing file.
|
||||
|
||||
A: >
|
||||
autocmd BufWritePost * call defx#redraw()
|
||||
|
||||
Q: I want to open defx when running `:e /some/directory/` like netrw.
|
||||
|
||||
A: https://github.com/Shougo/defx.nvim/issues/175
|
||||
|
||||
Q: I want to open file by double click.
|
||||
|
||||
A: >
|
||||
nnoremap <silent><buffer><expr> <2-LeftMouse> defx#do_action('open')
|
||||
|
||||
==============================================================================
|
||||
COMPATIBILITY *defx-compatibility*
|
||||
|
||||
2020-05-04
|
||||
* "open_tree_recursive" and "open_or_close_tree" actions are deprecated.
|
||||
|
||||
2019-03-10
|
||||
* Move "directory_icon", "opened_icon" and "root_icon" to filename column.
|
||||
|
||||
2019-02-14
|
||||
* Change column "highlight" method to "highlight_commands" method.
|
||||
|
||||
2019-01-02
|
||||
* Remove "fnamewidth" option.
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:ft=help:norl:noet:fen:noet:
|
14
bundle/defx.nvim/plugin/defx.vim
Normal file
14
bundle/defx.nvim/plugin/defx.vim
Normal file
@ -0,0 +1,14 @@
|
||||
"=============================================================================
|
||||
" FILE: defx.vim
|
||||
" AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
" License: MIT license
|
||||
"=============================================================================
|
||||
|
||||
if exists('g:loaded_defx')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_defx = 1
|
||||
|
||||
command! -nargs=* -range -bar -complete=customlist,defx#util#complete
|
||||
\ Defx
|
||||
\ call defx#util#call_defx('Defx', <q-args>)
|
82
bundle/defx.nvim/rplugin/python3/defx/__init__.py
Normal file
82
bundle/defx.nvim/rplugin/python3/defx/__init__.py
Normal file
@ -0,0 +1,82 @@
|
||||
# ============================================================================
|
||||
# FILE: __init__.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import typing
|
||||
|
||||
from importlib.util import find_spec
|
||||
from defx.rplugin import Rplugin
|
||||
|
||||
|
||||
if find_spec('yarp'):
|
||||
import vim
|
||||
else:
|
||||
import pynvim as vim
|
||||
|
||||
Args = typing.List[typing.Any]
|
||||
|
||||
if hasattr(vim, 'plugin'):
|
||||
# Neovim only
|
||||
|
||||
@vim.plugin
|
||||
class DefxHandlers:
|
||||
|
||||
def __init__(self, vim: vim.Nvim) -> None:
|
||||
self._rplugin = Rplugin(vim)
|
||||
|
||||
@vim.function('_defx_init', sync=True) # type: ignore
|
||||
def init_channel(self, args: Args) -> None:
|
||||
self._rplugin.init_channel()
|
||||
|
||||
@vim.rpc_export('_defx_start', sync=True) # type: ignore
|
||||
def start(self, args: Args) -> None:
|
||||
self._rplugin.start(args)
|
||||
|
||||
@vim.rpc_export('_defx_do_action', sync=True) # type: ignore
|
||||
def do_action(self, args: Args) -> None:
|
||||
self._rplugin.do_action(args)
|
||||
|
||||
@vim.rpc_export('_defx_async_action', sync=False) # type: ignore
|
||||
def async_action(self, args: Args) -> None:
|
||||
self._rplugin.do_action(args)
|
||||
|
||||
@vim.rpc_export('_defx_get_candidate', sync=True) # type: ignore
|
||||
def get_candidate(self, args: Args
|
||||
) -> typing.Dict[str, typing.Union[str, bool]]:
|
||||
return self._rplugin.get_candidate()
|
||||
|
||||
@vim.rpc_export('_defx_get_context', sync=True) # type: ignore
|
||||
def get_context(self, args: Args) -> typing.Dict[str, typing.Any]:
|
||||
return self._rplugin.get_context()
|
||||
|
||||
@vim.rpc_export('_defx_redraw', sync=True) # type: ignore
|
||||
def redraw(self, args: Args) -> None:
|
||||
return self._rplugin.redraw(self._rplugin._views)
|
||||
|
||||
if find_spec('yarp'):
|
||||
|
||||
global_rplugin = Rplugin(vim)
|
||||
|
||||
def _defx_init() -> None:
|
||||
pass
|
||||
|
||||
def _defx_start(args: Args) -> None:
|
||||
global_rplugin.start(args)
|
||||
|
||||
def _defx_do_action(args: Args) -> None:
|
||||
global_rplugin.do_action(args)
|
||||
|
||||
def _defx_async_action(args: Args) -> None:
|
||||
global_rplugin.do_action(args)
|
||||
|
||||
def _defx_get_candidate(args: Args
|
||||
) -> typing.Dict[str, typing.Union[str, bool]]:
|
||||
return global_rplugin.get_candidate()
|
||||
|
||||
def _defx_get_context(args: Args) -> typing.Dict[str, typing.Any]:
|
||||
return global_rplugin.get_context()
|
||||
|
||||
def _defx_redraw(args: Args) -> None:
|
||||
return global_rplugin.redraw(global_rplugin._views)
|
74
bundle/defx.nvim/rplugin/python3/defx/action.py
Normal file
74
bundle/defx.nvim/rplugin/python3/defx/action.py
Normal file
@ -0,0 +1,74 @@
|
||||
# ============================================================================
|
||||
# FILE: __init__.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from enum import auto, IntFlag
|
||||
import typing
|
||||
|
||||
from defx.context import Context
|
||||
from defx.defx import Defx
|
||||
from defx.view import View
|
||||
|
||||
|
||||
class ActionAttr(IntFlag):
|
||||
REDRAW = auto()
|
||||
MARK = auto()
|
||||
NO_TAGETS = auto()
|
||||
CURSOR_TARGET = auto()
|
||||
TREE = auto()
|
||||
NONE = 0
|
||||
|
||||
|
||||
class ActionTable(typing.NamedTuple):
|
||||
func: typing.Callable[[View, Defx, Context], None]
|
||||
attr: ActionAttr = ActionAttr.NONE
|
||||
|
||||
|
||||
def do_action(view: View, defx: Defx,
|
||||
action_name: str, context: Context) -> bool:
|
||||
"""
|
||||
Do "action_name" action.
|
||||
"""
|
||||
actions: typing.Dict[str, ActionTable] = defx._source.kind.get_actions()
|
||||
|
||||
if action_name not in actions:
|
||||
return True
|
||||
|
||||
action = actions[action_name]
|
||||
|
||||
selected_candidates = [x for x in view._candidates if x['is_selected']]
|
||||
if (selected_candidates and
|
||||
ActionAttr.NO_TAGETS not in action.attr and
|
||||
ActionAttr.TREE not in action.attr):
|
||||
# Clear marks
|
||||
for candidate in selected_candidates:
|
||||
candidate['is_selected'] = False
|
||||
view.redraw()
|
||||
|
||||
if ActionAttr.CURSOR_TARGET in action.attr:
|
||||
# Use cursor candidate only
|
||||
cursor_candidate = view.get_cursor_candidate(context.cursor)
|
||||
if not cursor_candidate:
|
||||
return True
|
||||
context = context._replace(
|
||||
targets=[cursor_candidate],
|
||||
)
|
||||
|
||||
action.func(view, defx, context)
|
||||
|
||||
if action_name != 'repeat':
|
||||
view._prev_action = action_name
|
||||
|
||||
if ActionAttr.MARK in action.attr:
|
||||
# Update marks
|
||||
view.update_candidates()
|
||||
view.redraw()
|
||||
elif ActionAttr.TREE in action.attr:
|
||||
view.update_candidates()
|
||||
view.redraw()
|
||||
elif ActionAttr.REDRAW in action.attr:
|
||||
# Redraw
|
||||
view.redraw(True)
|
||||
return False
|
56
bundle/defx.nvim/rplugin/python3/defx/base/column.py
Normal file
56
bundle/defx.nvim/rplugin/python3/defx/base/column.py
Normal file
@ -0,0 +1,56 @@
|
||||
# ============================================================================
|
||||
# FILE: column.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import typing
|
||||
|
||||
from abc import abstractmethod
|
||||
|
||||
from defx.context import Context
|
||||
from defx.util import Nvim
|
||||
from defx.util import error
|
||||
from defx.view import View
|
||||
|
||||
|
||||
class Base:
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
self.vim: Nvim = vim
|
||||
self.name: str = 'base'
|
||||
self.syntax_name: str = ''
|
||||
self.start: int = -1
|
||||
self.end: int = -1
|
||||
self.vars: typing.Dict[str, typing.Any] = {}
|
||||
self.is_start_variable: bool = False
|
||||
self.is_stop_variable: bool = False
|
||||
self.is_within_variable: bool = False
|
||||
|
||||
def on_init(self, view: View, context: Context) -> None:
|
||||
pass
|
||||
|
||||
def on_redraw(self, view: View, context: Context) -> None:
|
||||
pass
|
||||
|
||||
def get(self, context: Context,
|
||||
candidate: typing.Dict[str, typing.Any]) -> str:
|
||||
return ''
|
||||
|
||||
def get_with_variable_text(
|
||||
self, context: Context, variable_text: str,
|
||||
candidate: typing.Dict[str, typing.Any]) -> str:
|
||||
return ''
|
||||
|
||||
@abstractmethod
|
||||
def length(self, context: Context) -> int:
|
||||
pass
|
||||
|
||||
def syntaxes(self) -> typing.List[str]:
|
||||
return []
|
||||
|
||||
def highlight_commands(self) -> typing.List[str]:
|
||||
return []
|
||||
|
||||
def debug(self, expr: typing.Any) -> None:
|
||||
error(self.vim, expr)
|
332
bundle/defx.nvim/rplugin/python3/defx/base/kind.py
Normal file
332
bundle/defx.nvim/rplugin/python3/defx/base/kind.py
Normal file
@ -0,0 +1,332 @@
|
||||
# ============================================================================
|
||||
# FILE: kind.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import json
|
||||
import re
|
||||
import typing
|
||||
from pathlib import Path
|
||||
|
||||
from defx.action import ActionAttr
|
||||
from defx.action import ActionTable
|
||||
from defx.action import do_action
|
||||
from defx.context import Context
|
||||
from defx.defx import Defx
|
||||
from defx.session import Session
|
||||
from defx.util import Nvim
|
||||
from defx.view import View
|
||||
|
||||
_action_table: typing.Dict[str, ActionTable] = {}
|
||||
|
||||
ACTION_FUNC = typing.Callable[[View, Defx, Context], None]
|
||||
|
||||
|
||||
def action(name: str, attr: ActionAttr = ActionAttr.NONE
|
||||
) -> typing.Callable[[ACTION_FUNC], ACTION_FUNC]:
|
||||
def wrapper(func: ACTION_FUNC) -> ACTION_FUNC:
|
||||
_action_table[name] = ActionTable(func=func, attr=attr)
|
||||
|
||||
def inner_wrapper(view: View, defx: Defx, context: Context) -> None:
|
||||
return func(view, defx, context)
|
||||
return inner_wrapper
|
||||
return wrapper
|
||||
|
||||
|
||||
class Base:
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
self.vim = vim
|
||||
self.name = 'base'
|
||||
|
||||
def get_actions(self) -> typing.Dict[str, ActionTable]:
|
||||
return _action_table
|
||||
|
||||
|
||||
@action(name='add_session', attr=ActionAttr.NO_TAGETS)
|
||||
def _add_session(view: View, defx: Defx, context: Context) -> None:
|
||||
path = context.args[0] if context.args else defx._cwd
|
||||
if path[-1] == '/':
|
||||
# Remove the last slash
|
||||
path = path[: -1]
|
||||
|
||||
opened_candidates = [] if context.args else list(defx._opened_candidates)
|
||||
opened_candidates.sort()
|
||||
|
||||
session: Session
|
||||
if path in view._sessions:
|
||||
old_session = view._sessions[path]
|
||||
session = Session(
|
||||
name=old_session.name, path=old_session.path,
|
||||
opened_candidates=opened_candidates)
|
||||
else:
|
||||
name = Path(path).name
|
||||
session = Session(
|
||||
name=name, path=path,
|
||||
opened_candidates=opened_candidates)
|
||||
view.print_msg(f'session "{name}" is created')
|
||||
|
||||
view._sessions[session.path] = session
|
||||
|
||||
_save_session(view, defx, context)
|
||||
|
||||
|
||||
@action(name='call', attr=ActionAttr.REDRAW)
|
||||
def _call(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Call the function.
|
||||
"""
|
||||
function = context.args[0] if context.args else None
|
||||
if not function:
|
||||
return
|
||||
|
||||
dict_context = context._asdict()
|
||||
dict_context['cwd'] = defx._cwd
|
||||
dict_context['targets'] = [
|
||||
str(x['action__path']) for x in context.targets]
|
||||
view._vim.call(function, dict_context)
|
||||
|
||||
|
||||
@action(name='clear_select_all', attr=ActionAttr.MARK | ActionAttr.NO_TAGETS)
|
||||
def _clear_select_all(view: View, defx: Defx, context: Context) -> None:
|
||||
for candidate in [x for x in view._candidates
|
||||
if x['_defx_index'] == defx._index]:
|
||||
candidate['is_selected'] = False
|
||||
|
||||
|
||||
@action(name='close_tree', attr=ActionAttr.TREE | ActionAttr.CURSOR_TARGET)
|
||||
def _close_tree(view: View, defx: Defx, context: Context) -> None:
|
||||
for target in context.targets:
|
||||
if target['is_directory'] and target['is_opened_tree']:
|
||||
view.close_tree(target['action__path'], defx._index)
|
||||
else:
|
||||
view.close_tree(target['action__path'].parent, defx._index)
|
||||
view.search_file(target['action__path'].parent, defx._index)
|
||||
|
||||
|
||||
@action(name='delete_session', attr=ActionAttr.NO_TAGETS)
|
||||
def _delete_session(view: View, defx: Defx, context: Context) -> None:
|
||||
if not context.args:
|
||||
return
|
||||
|
||||
session_name = context.args[0]
|
||||
if session_name not in view._sessions:
|
||||
return
|
||||
view._sessions.pop(session_name)
|
||||
|
||||
_save_session(view, defx, context)
|
||||
|
||||
|
||||
@action(name='load_session', attr=ActionAttr.NO_TAGETS)
|
||||
def _load_session(view: View, defx: Defx, context: Context) -> None:
|
||||
session_file = Path(context.session_file)
|
||||
if not context.session_file or not session_file.exists():
|
||||
return
|
||||
|
||||
loaded_session = json.loads(session_file.read_text())
|
||||
if 'sessions' not in loaded_session:
|
||||
return
|
||||
|
||||
view._sessions = {}
|
||||
for path, session in loaded_session['sessions'].items():
|
||||
view._sessions[path] = Session(**session)
|
||||
|
||||
view._vim.current.buffer.vars['defx#_sessions'] = [
|
||||
x._asdict() for x in view._sessions.values()
|
||||
]
|
||||
|
||||
|
||||
@action(name='multi')
|
||||
def _multi(view: View, defx: Defx, context: Context) -> None:
|
||||
for arg in context.args:
|
||||
args: typing.List[str]
|
||||
if isinstance(arg, list):
|
||||
args = arg
|
||||
else:
|
||||
args = [arg]
|
||||
do_action(view, defx, args[0], context._replace(args=args[1:]))
|
||||
|
||||
|
||||
@action(name='check_redraw', attr=ActionAttr.NO_TAGETS)
|
||||
def _nop(view: View, defx: Defx, context: Context) -> None:
|
||||
pass
|
||||
|
||||
|
||||
@action(name='open_tree', attr=ActionAttr.TREE | ActionAttr.CURSOR_TARGET)
|
||||
def _open_tree(view: View, defx: Defx, context: Context) -> None:
|
||||
nested = False
|
||||
recursive_level = 0
|
||||
toggle = False
|
||||
for arg in context.args:
|
||||
if arg == 'nested':
|
||||
nested = True
|
||||
elif arg == 'recursive':
|
||||
recursive_level = 20
|
||||
elif re.search(r'recursive:\d+', arg):
|
||||
recursive_level = int(arg.split(':')[1])
|
||||
elif arg == 'toggle':
|
||||
toggle = True
|
||||
|
||||
for target in [x for x in context.targets if x['is_directory']]:
|
||||
if toggle and not target['is_directory'] or target['is_opened_tree']:
|
||||
_close_tree(view, defx, context._replace(targets=[target]))
|
||||
else:
|
||||
view.open_tree(target['action__path'],
|
||||
defx._index, nested, recursive_level)
|
||||
|
||||
|
||||
@action(name='open_tree_recursive',
|
||||
attr=ActionAttr.TREE | ActionAttr.CURSOR_TARGET)
|
||||
def _open_tree_recursive(view: View, defx: Defx, context: Context) -> None:
|
||||
level = context.args[0] if context.args else '20'
|
||||
_open_tree(view, defx, context._replace(
|
||||
args=context.args + ['recursive:' + level]))
|
||||
|
||||
|
||||
@action(name='open_or_close_tree',
|
||||
attr=ActionAttr.TREE | ActionAttr.CURSOR_TARGET)
|
||||
def _open_or_close_tree(view: View, defx: Defx, context: Context) -> None:
|
||||
_open_tree(view, defx, context._replace(args=context.args + ['toggle']))
|
||||
|
||||
|
||||
@action(name='print')
|
||||
def _print(view: View, defx: Defx, context: Context) -> None:
|
||||
for target in context.targets:
|
||||
view.print_msg(str(target['action__path']))
|
||||
|
||||
|
||||
@action(name='quit', attr=ActionAttr.NO_TAGETS)
|
||||
def _quit(view: View, defx: Defx, context: Context) -> None:
|
||||
view.quit()
|
||||
|
||||
|
||||
@action(name='redraw', attr=ActionAttr.NO_TAGETS)
|
||||
def _redraw(view: View, defx: Defx, context: Context) -> None:
|
||||
view.redraw(True)
|
||||
|
||||
|
||||
@action(name='repeat', attr=ActionAttr.MARK)
|
||||
def _repeat(view: View, defx: Defx, context: Context) -> None:
|
||||
do_action(view, defx, view._prev_action, context)
|
||||
|
||||
|
||||
@action(name='resize', attr=ActionAttr.NO_TAGETS)
|
||||
def _resize(view: View, defx: Defx, context: Context) -> None:
|
||||
if not context.args:
|
||||
return
|
||||
|
||||
view._context = view._context._replace(winwidth=int(context.args[0]))
|
||||
view._resize_window()
|
||||
view.redraw(True)
|
||||
|
||||
|
||||
@action(name='save_session', attr=ActionAttr.NO_TAGETS)
|
||||
def _save_session(view: View, defx: Defx, context: Context) -> None:
|
||||
view._vim.current.buffer.vars['defx#_sessions'] = [
|
||||
x._asdict() for x in view._sessions.values()
|
||||
]
|
||||
|
||||
if not context.session_file:
|
||||
return
|
||||
|
||||
session_file = Path(context.session_file)
|
||||
session_file.write_text(json.dumps({
|
||||
'version': view._session_version,
|
||||
'sessions': {x: y._asdict() for x, y in view._sessions.items()}
|
||||
}))
|
||||
|
||||
|
||||
@action(name='search', attr=ActionAttr.NO_TAGETS)
|
||||
def _search(view: View, defx: Defx, context: Context) -> None:
|
||||
if not context.args or not context.args[0]:
|
||||
return
|
||||
|
||||
search_path = context.args[0]
|
||||
path = Path(search_path)
|
||||
parents: typing.List[Path] = []
|
||||
while view.get_candidate_pos(
|
||||
path, defx._index) < 0 and path.parent != path:
|
||||
path = path.parent
|
||||
parents.append(path)
|
||||
|
||||
for parent in reversed(parents):
|
||||
view.open_tree(parent, defx._index, False, 0)
|
||||
|
||||
view.update_candidates()
|
||||
view.redraw()
|
||||
view.search_file(Path(search_path), defx._index)
|
||||
|
||||
|
||||
@action(name='toggle_columns', attr=ActionAttr.REDRAW)
|
||||
def _toggle_columns(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Toggle the current columns.
|
||||
"""
|
||||
columns = (context.args[0] if context.args else '').split(':')
|
||||
if not columns:
|
||||
return
|
||||
current_columns = [x.name for x in view._columns]
|
||||
if columns == current_columns:
|
||||
# Use default columns
|
||||
columns = context.columns.split(':')
|
||||
view._init_columns(columns)
|
||||
|
||||
|
||||
@action(name='toggle_ignored_files', attr=ActionAttr.REDRAW)
|
||||
def _toggle_ignored_files(view: View, defx: Defx, context: Context) -> None:
|
||||
defx._enabled_ignored_files = not defx._enabled_ignored_files
|
||||
|
||||
|
||||
@action(name='toggle_select', attr=ActionAttr.MARK | ActionAttr.NO_TAGETS)
|
||||
def _toggle_select(view: View, defx: Defx, context: Context) -> None:
|
||||
candidate = view.get_cursor_candidate(context.cursor)
|
||||
if not candidate:
|
||||
return
|
||||
|
||||
candidate['is_selected'] = not candidate['is_selected']
|
||||
|
||||
|
||||
@action(name='toggle_select_all', attr=ActionAttr.MARK | ActionAttr.NO_TAGETS)
|
||||
def _toggle_select_all(view: View, defx: Defx, context: Context) -> None:
|
||||
for candidate in [x for x in view._candidates
|
||||
if not x['is_root'] and
|
||||
x['_defx_index'] == defx._index]:
|
||||
candidate['is_selected'] = not candidate['is_selected']
|
||||
|
||||
|
||||
@action(name='toggle_select_visual',
|
||||
attr=ActionAttr.MARK | ActionAttr.NO_TAGETS)
|
||||
def _toggle_select_visual(view: View, defx: Defx, context: Context) -> None:
|
||||
if context.visual_start <= 0 or context.visual_end <= 0:
|
||||
return
|
||||
|
||||
start = context.visual_start - 1
|
||||
end = min([context.visual_end, len(view._candidates)])
|
||||
for candidate in [x for x in view._candidates[start:end]
|
||||
if not x['is_root'] and
|
||||
x['_defx_index'] == defx._index]:
|
||||
candidate['is_selected'] = not candidate['is_selected']
|
||||
|
||||
|
||||
@action(name='toggle_sort', attr=ActionAttr.MARK | ActionAttr.NO_TAGETS)
|
||||
def _toggle_sort(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Toggle the current sort method.
|
||||
"""
|
||||
sort = context.args[0] if context.args else ''
|
||||
if sort == defx._sort_method:
|
||||
# Use default sort method
|
||||
defx._sort_method = context.sort
|
||||
else:
|
||||
defx._sort_method = sort
|
||||
|
||||
|
||||
@action(name='yank_path')
|
||||
def _yank_path(view: View, defx: Defx, context: Context) -> None:
|
||||
yank = '\n'.join([str(x['action__path']) for x in context.targets])
|
||||
view._vim.call('setreg', '"', yank)
|
||||
if (view._vim.call('has', 'clipboard') or
|
||||
view._vim.call('has', 'xterm_clipboard')):
|
||||
view._vim.call('setreg', '+', yank)
|
||||
view.print_msg('Yanked:\n' + yank)
|
40
bundle/defx.nvim/rplugin/python3/defx/base/source.py
Normal file
40
bundle/defx.nvim/rplugin/python3/defx/base/source.py
Normal file
@ -0,0 +1,40 @@
|
||||
# ============================================================================
|
||||
# FILE: source.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import typing
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from defx.context import Context
|
||||
from defx.util import Nvim
|
||||
from defx.util import error
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class Base(ABC):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
self.vim = vim
|
||||
self.name = 'base'
|
||||
|
||||
from defx.base.kind import Base as Kind
|
||||
self.kind: Kind = Kind(self.vim)
|
||||
|
||||
self.vars: typing.Dict[str, typing.Any] = {}
|
||||
|
||||
@abstractmethod
|
||||
def get_root_candidate(
|
||||
self, context: Context, path: Path
|
||||
) -> typing.Dict[str, typing.Any]:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def gather_candidates(
|
||||
self, context: Context, path: Path
|
||||
) -> typing.List[typing.Dict[str, typing.Any]]:
|
||||
pass
|
||||
|
||||
def debug(self, expr: typing.Any) -> None:
|
||||
error(self.vim, expr)
|
22
bundle/defx.nvim/rplugin/python3/defx/clipboard.py
Normal file
22
bundle/defx.nvim/rplugin/python3/defx/clipboard.py
Normal file
@ -0,0 +1,22 @@
|
||||
# ============================================================================
|
||||
# FILE: clipboard.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from enum import auto, Enum
|
||||
import typing
|
||||
|
||||
|
||||
class ClipboardAction(Enum):
|
||||
MOVE = auto()
|
||||
COPY = auto()
|
||||
|
||||
|
||||
class Clipboard():
|
||||
def __init__(self,
|
||||
action: ClipboardAction = ClipboardAction.COPY,
|
||||
candidates:
|
||||
typing.List[typing.Dict[str, typing.Any]] = []) -> None:
|
||||
self.action = action
|
||||
self.candidates = candidates
|
134
bundle/defx.nvim/rplugin/python3/defx/column/filename.py
Normal file
134
bundle/defx.nvim/rplugin/python3/defx/column/filename.py
Normal file
@ -0,0 +1,134 @@
|
||||
# ============================================================================
|
||||
# FILE: filename.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from defx.base.column import Base
|
||||
from defx.context import Context
|
||||
from defx.util import Nvim
|
||||
from defx.view import View
|
||||
|
||||
import typing
|
||||
|
||||
|
||||
class Column(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'filename'
|
||||
self.vars = {
|
||||
'min_width': 40,
|
||||
'max_width': 100,
|
||||
'root_marker_highlight': 'Constant',
|
||||
}
|
||||
self.is_stop_variable = True
|
||||
|
||||
self._current_length = 0
|
||||
self._syntaxes = [
|
||||
'directory',
|
||||
'directory_marker',
|
||||
'hidden',
|
||||
'root',
|
||||
'root_marker',
|
||||
]
|
||||
self._context: Context = Context()
|
||||
self._directory_marker = '**'
|
||||
self._file_marker = '||'
|
||||
|
||||
def on_init(self, view: View, context: Context) -> None:
|
||||
self._context = context
|
||||
|
||||
def get_with_variable_text(
|
||||
self, context: Context, variable_text: str,
|
||||
candidate: typing.Dict[str, typing.Any]) -> str:
|
||||
marker = (self._directory_marker
|
||||
if candidate['is_directory'] and not candidate['is_root']
|
||||
else self._file_marker)
|
||||
return self._truncate(variable_text + marker + candidate['word'])
|
||||
|
||||
def length(self, context: Context) -> int:
|
||||
max_fnamewidth = max([self._strwidth(x['word'])
|
||||
for x in context.targets])
|
||||
max_fnamewidth += context.variable_length
|
||||
max_fnamewidth += len(self._file_marker)
|
||||
max_width = int(self.vars['max_width'])
|
||||
if max_width < 0:
|
||||
max_width = int(-max_width * context.winwidth / 100)
|
||||
self._current_length = max(
|
||||
min(max_fnamewidth, max_width),
|
||||
int(self.vars['min_width']))
|
||||
return self._current_length
|
||||
|
||||
def syntaxes(self) -> typing.List[str]:
|
||||
return [self.syntax_name + '_' + x for x in self._syntaxes]
|
||||
|
||||
def highlight_commands(self) -> typing.List[str]:
|
||||
commands: typing.List[str] = []
|
||||
|
||||
directory_marker = self.vim.call(
|
||||
'escape', self._directory_marker, r'~/\.^$[]*')
|
||||
commands.append(
|
||||
r'syntax match {0}_{1} /{2}/ conceal contained '
|
||||
'containedin={0}_directory'.format(
|
||||
self.syntax_name, 'directory_marker', directory_marker))
|
||||
commands.append(
|
||||
r'syntax match {0}_{1} /{2}\%(.{3}[{4}/]\)\+/ '
|
||||
'contained containedin={0}'.format(
|
||||
self.syntax_name, 'directory', directory_marker, r'\{-}',
|
||||
'\\' if self.vim.call('defx#util#is_windows') else ''))
|
||||
|
||||
file_marker = self.vim.call(
|
||||
'escape', self._file_marker, r'~/\.^$[]*')
|
||||
commands.append(
|
||||
r'syntax match {0}_{1} /{2}/ conceal contained '
|
||||
'containedin={0}_file'.format(
|
||||
self.syntax_name, 'file_marker', file_marker))
|
||||
commands.append(
|
||||
r'syntax match {0}_{1} /{2}.{3}/ '
|
||||
'contained containedin={0}'.format(
|
||||
self.syntax_name, 'file', file_marker, r'\{-}'))
|
||||
|
||||
root_marker = self.vim.call(
|
||||
'escape', self._context.root_marker, r'~/\.^$[]*')
|
||||
commands.append(
|
||||
r'syntax match {0}_{1} /{2}/ contained '
|
||||
'containedin={0}_root'.format(
|
||||
self.syntax_name, 'root_marker', root_marker))
|
||||
commands.append(
|
||||
r'syntax match {0}_{1} /{2}.*/ contained '
|
||||
'containedin={0}'.format(
|
||||
self.syntax_name, 'root', root_marker))
|
||||
|
||||
commands.append(
|
||||
'highlight default link {}_{} {}'.format(
|
||||
self.syntax_name, 'directory', 'PreProc'))
|
||||
commands.append(
|
||||
'highlight default link {}_{} {}'.format(
|
||||
self.syntax_name, 'hidden', 'Comment'))
|
||||
commands.append(
|
||||
'highlight default link {}_{} {}'.format(
|
||||
self.syntax_name, 'root_marker',
|
||||
self.vars['root_marker_highlight']))
|
||||
commands.append(
|
||||
'highlight default link {}_{} {}'.format(
|
||||
self.syntax_name, 'root', 'Identifier'))
|
||||
|
||||
return commands
|
||||
|
||||
def _strwidth(self, word: str) -> int:
|
||||
return (int(self.vim.call('strwidth', word))
|
||||
if len(word) != len(bytes(word, 'utf-8',
|
||||
'surrogatepass')) else len(word))
|
||||
|
||||
def _truncate(self, word: str) -> str:
|
||||
width = self._strwidth(word)
|
||||
max_length = self._current_length
|
||||
if (width > max_length or
|
||||
len(word) != len(bytes(word, 'utf-8', 'surrogatepass'))):
|
||||
return str(self.vim.call(
|
||||
'defx#util#truncate_skipping',
|
||||
word, max_length, int(max_length / 3), '...'))
|
||||
|
||||
return word + ' ' * (max_length - width)
|
68
bundle/defx.nvim/rplugin/python3/defx/column/icon.py
Normal file
68
bundle/defx.nvim/rplugin/python3/defx/column/icon.py
Normal file
@ -0,0 +1,68 @@
|
||||
# ============================================================================
|
||||
# FILE: icon.py
|
||||
# AUTHOR: GuoPan Zhao <zgpio@qq.com>
|
||||
# Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from defx.base.column import Base
|
||||
from defx.context import Context
|
||||
from defx.util import Nvim
|
||||
|
||||
import typing
|
||||
|
||||
|
||||
class Column(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'icon'
|
||||
self.vars = {
|
||||
'length': 1,
|
||||
'directory_icon': '+',
|
||||
'opened_icon': '-',
|
||||
'root_icon': ' ',
|
||||
}
|
||||
self._syntaxes = [
|
||||
'directory_icon',
|
||||
'opened_icon',
|
||||
'root_icon',
|
||||
]
|
||||
|
||||
def get(self, context: Context,
|
||||
candidate: typing.Dict[str, typing.Any]) -> str:
|
||||
icon: str = ' '
|
||||
if candidate['is_opened_tree']:
|
||||
icon = self.vars['opened_icon']
|
||||
elif candidate['is_root']:
|
||||
icon = self.vars['root_icon']
|
||||
elif candidate['is_directory']:
|
||||
icon = self.vars['directory_icon']
|
||||
|
||||
return icon
|
||||
|
||||
def length(self, context: Context) -> int:
|
||||
return typing.cast(int, self.vars['length'])
|
||||
|
||||
def syntaxes(self) -> typing.List[str]:
|
||||
return [self.syntax_name + '_' + x for x in self._syntaxes]
|
||||
|
||||
def highlight_commands(self) -> typing.List[str]:
|
||||
commands: typing.List[str] = []
|
||||
for icon, highlight in {
|
||||
'directory': 'Special',
|
||||
'opened': 'Special',
|
||||
'root': 'Identifier',
|
||||
}.items():
|
||||
commands.append(
|
||||
('syntax match {0}_{1}_icon /[{2}]{3}/ ' +
|
||||
'contained containedin={0}').format(
|
||||
self.syntax_name, icon, self.vars[icon + '_icon'],
|
||||
' ' if self.is_within_variable else ''
|
||||
))
|
||||
commands.append(
|
||||
'highlight default link {}_{}_icon {}'.format(
|
||||
self.syntax_name, icon, highlight))
|
||||
|
||||
return commands
|
31
bundle/defx.nvim/rplugin/python3/defx/column/indent.py
Normal file
31
bundle/defx.nvim/rplugin/python3/defx/column/indent.py
Normal file
@ -0,0 +1,31 @@
|
||||
# ============================================================================
|
||||
# FILE: indent.py
|
||||
# AUTHOR: GuoPan Zhao <zgpio@qq.com>
|
||||
# Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from defx.base.column import Base
|
||||
from defx.context import Context
|
||||
from defx.util import Nvim
|
||||
|
||||
import typing
|
||||
|
||||
|
||||
class Column(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'indent'
|
||||
self.vars = {
|
||||
'indent': ' ',
|
||||
}
|
||||
self.is_start_variable = True
|
||||
|
||||
def get(self, context: Context,
|
||||
candidate: typing.Dict[str, typing.Any]) -> str:
|
||||
return str(self.vars['indent'] * candidate['level'])
|
||||
|
||||
def length(self, context: Context) -> int:
|
||||
return int(max([x['level'] for x in context.targets]))
|
61
bundle/defx.nvim/rplugin/python3/defx/column/mark.py
Normal file
61
bundle/defx.nvim/rplugin/python3/defx/column/mark.py
Normal file
@ -0,0 +1,61 @@
|
||||
# ============================================================================
|
||||
# FILE: mark.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from defx.base.column import Base
|
||||
from defx.context import Context
|
||||
from defx.util import Nvim
|
||||
|
||||
import os
|
||||
import typing
|
||||
|
||||
|
||||
class Column(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'mark'
|
||||
self.vars = {
|
||||
'length': 1,
|
||||
'readonly_icon': 'X',
|
||||
'selected_icon': '*',
|
||||
}
|
||||
self._syntaxes = [
|
||||
'directory',
|
||||
'opened',
|
||||
'readonly',
|
||||
'selected',
|
||||
]
|
||||
|
||||
def get(self, context: Context,
|
||||
candidate: typing.Dict[str, typing.Any]) -> str:
|
||||
icon: str = ' ' * self.vars['length']
|
||||
if candidate['is_selected']:
|
||||
icon = self.vars['selected_icon']
|
||||
elif not os.access(str(candidate['action__path']), os.W_OK):
|
||||
icon = self.vars['readonly_icon']
|
||||
return icon
|
||||
|
||||
def length(self, context: Context) -> int:
|
||||
return typing.cast(int, self.vars['length'])
|
||||
|
||||
def syntaxes(self) -> typing.List[str]:
|
||||
return [self.syntax_name + '_' + x for x in self._syntaxes]
|
||||
|
||||
def highlight_commands(self) -> typing.List[str]:
|
||||
commands: typing.List[str] = []
|
||||
for icon, highlight in {
|
||||
'readonly': 'Comment',
|
||||
'selected': 'Statement',
|
||||
}.items():
|
||||
commands.append(
|
||||
('syntax match {0}_{1} /[{2}]/ ' +
|
||||
'contained containedin={0}').format(
|
||||
self.syntax_name, icon, self.vars[icon + '_icon']))
|
||||
commands.append(
|
||||
'highlight default link {}_{} {}'.format(
|
||||
self.syntax_name, icon, highlight))
|
||||
return commands
|
47
bundle/defx.nvim/rplugin/python3/defx/column/size.py
Normal file
47
bundle/defx.nvim/rplugin/python3/defx/column/size.py
Normal file
@ -0,0 +1,47 @@
|
||||
# ============================================================================
|
||||
# FILE: size.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from defx.base.column import Base
|
||||
from defx.context import Context
|
||||
from defx.util import Nvim, readable
|
||||
|
||||
import typing
|
||||
|
||||
|
||||
class Column(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'size'
|
||||
|
||||
def get(self, context: Context,
|
||||
candidate: typing.Dict[str, typing.Any]) -> str:
|
||||
path = candidate['action__path']
|
||||
if not readable(path) or path.is_dir():
|
||||
return ' ' * 9
|
||||
size = self._get_size(path.stat().st_size)
|
||||
return '{:>6s}{:>3s}'.format(size[0], size[1])
|
||||
|
||||
def _get_size(self, size: float) -> typing.Tuple[str, str]:
|
||||
multiple = 1024
|
||||
suffixes = ['KB', 'MB', 'GB', 'TB']
|
||||
if size < multiple:
|
||||
return (str(size), 'B')
|
||||
for suffix in suffixes:
|
||||
size /= multiple
|
||||
if size < multiple:
|
||||
return ('{:.1f}'.format(size), suffix)
|
||||
return ('INF', '')
|
||||
|
||||
def length(self, context: Context) -> int:
|
||||
return 9
|
||||
|
||||
def highlight_commands(self) -> typing.List[str]:
|
||||
commands: typing.List[str] = []
|
||||
commands.append(
|
||||
f'highlight default link {self.syntax_name} Constant')
|
||||
return commands
|
26
bundle/defx.nvim/rplugin/python3/defx/column/space.py
Normal file
26
bundle/defx.nvim/rplugin/python3/defx/column/space.py
Normal file
@ -0,0 +1,26 @@
|
||||
# ============================================================================
|
||||
# FILE: space.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from defx.base.column import Base
|
||||
from defx.context import Context
|
||||
from defx.util import Nvim
|
||||
|
||||
import typing
|
||||
|
||||
|
||||
class Column(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'space'
|
||||
|
||||
def get(self, context: Context,
|
||||
candidate: typing.Dict[str, typing.Any]) -> str:
|
||||
return ' '
|
||||
|
||||
def length(self, context: Context) -> int:
|
||||
return 1
|
46
bundle/defx.nvim/rplugin/python3/defx/column/time.py
Normal file
46
bundle/defx.nvim/rplugin/python3/defx/column/time.py
Normal file
@ -0,0 +1,46 @@
|
||||
# ============================================================================
|
||||
# FILE: time.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from defx.base.column import Base
|
||||
from defx.context import Context
|
||||
from defx.util import Nvim, readable
|
||||
from defx.view import View
|
||||
|
||||
import time
|
||||
import typing
|
||||
|
||||
|
||||
class Column(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'time'
|
||||
self._length = 0
|
||||
self.vars = {
|
||||
'format': '%y.%m.%d %H:%M',
|
||||
}
|
||||
|
||||
def on_init(self, view: View, context: Context) -> None:
|
||||
self._length = self.vim.call('strwidth',
|
||||
time.strftime(self.vars['format']))
|
||||
|
||||
def get(self, context: Context,
|
||||
candidate: typing.Dict[str, typing.Any]) -> str:
|
||||
path = candidate['action__path']
|
||||
if not readable(path):
|
||||
return str(' ' * self._length)
|
||||
return time.strftime(self.vars['format'],
|
||||
time.localtime(path.stat().st_mtime))
|
||||
|
||||
def length(self, context: Context) -> int:
|
||||
return self._length
|
||||
|
||||
def highlight_commands(self) -> typing.List[str]:
|
||||
commands: typing.List[str] = []
|
||||
commands.append(
|
||||
f'highlight default link {self.syntax_name} Identifier')
|
||||
return commands
|
74
bundle/defx.nvim/rplugin/python3/defx/column/type.py
Normal file
74
bundle/defx.nvim/rplugin/python3/defx/column/type.py
Normal file
@ -0,0 +1,74 @@
|
||||
# ============================================================================
|
||||
# FILE: type.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from defx.base.column import Base
|
||||
from defx.context import Context
|
||||
from defx.util import Nvim
|
||||
from defx.view import View
|
||||
|
||||
import re
|
||||
import typing
|
||||
|
||||
|
||||
class Column(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'type'
|
||||
types = [
|
||||
{
|
||||
'name': 'text', 'globs': ['*.txt'],
|
||||
'icon': '[T]', 'highlight': 'Constant'
|
||||
},
|
||||
{
|
||||
'name': 'image', 'globs': ['*.jpg'],
|
||||
'icon': '[I]', 'highlight': 'Type'
|
||||
},
|
||||
{
|
||||
'name': 'archive', 'globs': ['*.zip'],
|
||||
'icon': '[A]', 'highlight': 'Special'
|
||||
},
|
||||
{
|
||||
'name': 'executable', 'globs': ['*.exe'],
|
||||
'icon': '[X]', 'highlight': 'Statement'
|
||||
},
|
||||
]
|
||||
self.vars = {
|
||||
'types': types,
|
||||
}
|
||||
self._length: int = 0
|
||||
|
||||
def on_init(self, view: View, context: Context) -> None:
|
||||
self._length = max([self.vim.call('strwidth', x['icon'])
|
||||
for x in self.vars['types']])
|
||||
|
||||
def get(self, context: Context,
|
||||
candidate: typing.Dict[str, typing.Any]) -> str:
|
||||
for t in self.vars['types']:
|
||||
for glob in t['globs']:
|
||||
if candidate['action__path'].match(glob):
|
||||
return str(t['icon'])
|
||||
return ' ' * self._length
|
||||
|
||||
def length(self, context: Context) -> int:
|
||||
return self._length
|
||||
|
||||
def syntaxes(self) -> typing.List[str]:
|
||||
return [self.syntax_name + '_' + x['name'] for x
|
||||
in self.vars['types']]
|
||||
|
||||
def highlight_commands(self) -> typing.List[str]:
|
||||
commands: typing.List[str] = []
|
||||
for t in self.vars['types']:
|
||||
commands.append(
|
||||
('syntax match {0}_{1} /{2}/ ' +
|
||||
'contained containedin={0}').format(
|
||||
self.syntax_name, t['name'], re.escape(t['icon'])))
|
||||
commands.append(
|
||||
'highlight default link {}_{} {}'.format(
|
||||
self.syntax_name, t['name'], t['highlight']))
|
||||
return commands
|
42
bundle/defx.nvim/rplugin/python3/defx/context.py
Normal file
42
bundle/defx.nvim/rplugin/python3/defx/context.py
Normal file
@ -0,0 +1,42 @@
|
||||
# ============================================================================
|
||||
# FILE: context.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import typing
|
||||
|
||||
|
||||
class Context(typing.NamedTuple):
|
||||
args: typing.List[str] = []
|
||||
auto_cd: bool = False
|
||||
auto_recursive_level: int = 0
|
||||
buffer_name: str = 'default'
|
||||
columns: str = ''
|
||||
cursor: int = 0
|
||||
direction: str = ''
|
||||
drives: typing.List[str] = []
|
||||
ignored_files: str = ''
|
||||
listed: bool = False
|
||||
new: bool = False
|
||||
prev_bufnr: int = 0
|
||||
prev_last_bufnr: int = 0
|
||||
prev_winid: int = 0
|
||||
profile: bool = False
|
||||
resume: bool = False
|
||||
root_marker: str = ''
|
||||
search: str = ''
|
||||
session_file: str = ''
|
||||
sort: str = ''
|
||||
show_ignored_files: bool = False
|
||||
split: str = 'no'
|
||||
toggle: bool = False
|
||||
targets: typing.List[typing.Dict[str, typing.Any]] = []
|
||||
variable_length: int = 0
|
||||
visual_start: int = 0
|
||||
visual_end: int = 0
|
||||
wincol: int = 0
|
||||
winheight: int = 0
|
||||
winrelative: str = 'editor'
|
||||
winrow: int = 0
|
||||
winwidth: int = 0
|
127
bundle/defx.nvim/rplugin/python3/defx/defx.py
Normal file
127
bundle/defx.nvim/rplugin/python3/defx/defx.py
Normal file
@ -0,0 +1,127 @@
|
||||
# ============================================================================
|
||||
# FILE: defx.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import typing
|
||||
|
||||
from defx.source.file import Source as File
|
||||
from defx.context import Context
|
||||
from defx.sort import sort
|
||||
from defx.util import Nvim
|
||||
from defx.util import cd, error
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
Candidate = typing.Dict[str, typing.Any]
|
||||
|
||||
|
||||
class Defx(object):
|
||||
|
||||
def __init__(self, vim: Nvim, context: Context,
|
||||
cwd: str, index: int) -> None:
|
||||
self._vim = vim
|
||||
self._context = context
|
||||
self._cwd = self._vim.call('getcwd')
|
||||
self.cd(cwd)
|
||||
self._source: File = File(self._vim)
|
||||
self._index = index
|
||||
self._enabled_ignored_files = not context.show_ignored_files
|
||||
self._ignored_files = context.ignored_files.split(',')
|
||||
self._cursor_history: typing.Dict[str, Path] = {}
|
||||
self._sort_method: str = self._context.sort
|
||||
self._mtime: int = -1
|
||||
self._opened_candidates: typing.Set[str] = set()
|
||||
self._selected_candidates: typing.Set[str] = set()
|
||||
|
||||
self._init_source()
|
||||
|
||||
def _init_source(self) -> None:
|
||||
custom = self._vim.call('defx#custom#_get')['source']
|
||||
name = self._source.name
|
||||
if name in custom:
|
||||
self._source.vars.update(custom[name])
|
||||
|
||||
def debug(self, expr: typing.Any) -> None:
|
||||
error(self._vim, expr)
|
||||
|
||||
def cd(self, path: str) -> None:
|
||||
self._cwd = str(Path(self._cwd).joinpath(path))
|
||||
|
||||
if self._context.auto_cd:
|
||||
cd(self._vim, path)
|
||||
|
||||
def get_root_candidate(self) -> Candidate:
|
||||
"""
|
||||
Returns root candidate
|
||||
"""
|
||||
root = self._source.get_root_candidate(self._context, Path(self._cwd))
|
||||
root['is_root'] = True
|
||||
root['is_opened_tree'] = False
|
||||
root['is_selected'] = False
|
||||
root['level'] = 0
|
||||
root['word'] = self._context.root_marker + root['word']
|
||||
|
||||
return root
|
||||
|
||||
def tree_candidates(
|
||||
self, path: str, base_level: int, max_level: int
|
||||
) -> typing.List[Candidate]:
|
||||
gathered_candidates = self.gather_candidates_recursive(
|
||||
path, base_level, max_level)
|
||||
|
||||
if self._opened_candidates:
|
||||
candidates = []
|
||||
for candidate in gathered_candidates:
|
||||
candidates.append(candidate)
|
||||
candidate['level'] = base_level
|
||||
candidate_path = str(candidate['action__path'])
|
||||
|
||||
if (candidate_path in self._opened_candidates and
|
||||
not candidate['is_opened_tree']):
|
||||
candidate['is_opened_tree'] = True
|
||||
candidates += self.tree_candidates(
|
||||
candidate_path, base_level + 1, max_level)
|
||||
else:
|
||||
candidates = gathered_candidates
|
||||
|
||||
return candidates
|
||||
|
||||
def gather_candidates_recursive(
|
||||
self, path: str, base_level: int, max_level: int
|
||||
) -> typing.List[Candidate]:
|
||||
|
||||
candidates = self._gather_candidates(path, base_level)
|
||||
if base_level >= max_level:
|
||||
return candidates
|
||||
|
||||
ret = []
|
||||
for candidate in candidates:
|
||||
ret.append(candidate)
|
||||
if candidate['is_directory']:
|
||||
candidate['is_opened_tree'] = True
|
||||
ret += self.gather_candidates_recursive(
|
||||
str(candidate['action__path']), base_level + 1, max_level)
|
||||
return ret
|
||||
|
||||
def _gather_candidates(
|
||||
self, path: str, base_level: int = 0) -> typing.List[Candidate]:
|
||||
"""
|
||||
Returns file candidates
|
||||
"""
|
||||
candidates = self._source.gather_candidates(
|
||||
self._context, Path(path))
|
||||
|
||||
if self._enabled_ignored_files:
|
||||
for glob in self._ignored_files:
|
||||
candidates = [x for x in candidates
|
||||
if not x['action__path'].match(glob)]
|
||||
|
||||
for candidate in candidates:
|
||||
candidate['is_opened_tree'] = False
|
||||
candidate['is_root'] = False
|
||||
candidate['is_selected'] = False
|
||||
candidate['level'] = base_level
|
||||
|
||||
return sort(self._sort_method, candidates)
|
481
bundle/defx.nvim/rplugin/python3/defx/kind/file.py
Normal file
481
bundle/defx.nvim/rplugin/python3/defx/kind/file.py
Normal file
@ -0,0 +1,481 @@
|
||||
# ============================================================================
|
||||
# FILE: file.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import copy
|
||||
import importlib
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import time
|
||||
import typing
|
||||
|
||||
from defx.action import ActionAttr
|
||||
from defx.action import ActionTable
|
||||
from defx.base.kind import Base
|
||||
from defx.clipboard import ClipboardAction
|
||||
from defx.context import Context
|
||||
from defx.defx import Defx
|
||||
from defx.util import cd, cwd_input, confirm, error
|
||||
from defx.util import readable, Nvim
|
||||
from defx.view import View
|
||||
|
||||
_action_table: typing.Dict[str, ActionTable] = {}
|
||||
|
||||
ACTION_FUNC = typing.Callable[[View, Defx, Context], None]
|
||||
|
||||
|
||||
def action(name: str, attr: ActionAttr = ActionAttr.NONE
|
||||
) -> typing.Callable[[ACTION_FUNC], ACTION_FUNC]:
|
||||
def wrapper(func: ACTION_FUNC) -> ACTION_FUNC:
|
||||
_action_table[name] = ActionTable(func=func, attr=attr)
|
||||
|
||||
def inner_wrapper(view: View, defx: Defx, context: Context) -> None:
|
||||
return func(view, defx, context)
|
||||
return inner_wrapper
|
||||
return wrapper
|
||||
|
||||
|
||||
class Kind(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
self.vim = vim
|
||||
self.name = 'file'
|
||||
|
||||
def get_actions(self) -> typing.Dict[str, ActionTable]:
|
||||
actions = copy.copy(super().get_actions())
|
||||
actions.update(_action_table)
|
||||
return actions
|
||||
|
||||
|
||||
def check_overwrite(view: View, dest: Path, src: Path) -> Path:
|
||||
s_stat = src.stat()
|
||||
s_mtime = s_stat.st_mtime
|
||||
view.print_msg(f' src: {src} {s_stat.st_size} bytes')
|
||||
view.print_msg(f' {time.strftime("%c", time.localtime(s_mtime))}')
|
||||
d_stat = dest.stat()
|
||||
d_mtime = d_stat.st_mtime
|
||||
view.print_msg(f'dest: {dest} {d_stat.st_size} bytes')
|
||||
view.print_msg(f' {time.strftime("%c", time.localtime(d_mtime))}')
|
||||
|
||||
choice: int = view._vim.call('defx#util#confirm',
|
||||
f'{dest} already exists. Overwrite?',
|
||||
'&Force\n&No\n&Rename\n&Time\n&Underbar', 0)
|
||||
ret: Path = Path('')
|
||||
if choice == 1:
|
||||
ret = dest
|
||||
elif choice == 2:
|
||||
ret = Path('')
|
||||
elif choice == 3:
|
||||
ret = Path(view._vim.call('input', f'{src} -> ', str(dest),
|
||||
('dir' if src.is_dir() else 'file')))
|
||||
elif choice == 4 and d_mtime < s_mtime:
|
||||
ret = src
|
||||
elif choice == 5:
|
||||
ret = Path(str(dest) + '_')
|
||||
return ret
|
||||
|
||||
|
||||
@action(name='cd')
|
||||
def _cd(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Change the current directory.
|
||||
"""
|
||||
path = Path(context.args[0]) if context.args else Path.home()
|
||||
path = Path(defx._cwd).joinpath(path).resolve()
|
||||
if not readable(path) or not path.is_dir():
|
||||
error(view._vim, f'{path} is not readable directory')
|
||||
return
|
||||
|
||||
prev_cwd = defx._cwd
|
||||
view.cd(defx, str(path), context.cursor)
|
||||
if context.args and context.args[0] == '..':
|
||||
view.search_file(Path(prev_cwd), defx._index)
|
||||
|
||||
|
||||
@action(name='change_vim_cwd', attr=ActionAttr.NO_TAGETS)
|
||||
def _change_vim_cwd(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Change the current working directory.
|
||||
"""
|
||||
cd(view._vim, defx._cwd)
|
||||
|
||||
|
||||
@action(name='check_redraw', attr=ActionAttr.NO_TAGETS)
|
||||
def _check_redraw(view: View, defx: Defx, context: Context) -> None:
|
||||
root = defx.get_root_candidate()['action__path']
|
||||
if not root.exists():
|
||||
return
|
||||
mtime = root.stat().st_mtime
|
||||
if mtime != defx._mtime:
|
||||
view.redraw(True)
|
||||
|
||||
|
||||
@action(name='copy')
|
||||
def _copy(view: View, defx: Defx, context: Context) -> None:
|
||||
if not context.targets:
|
||||
return
|
||||
|
||||
message = 'Copy to the clipboard: {}'.format(
|
||||
str(context.targets[0]['action__path'])
|
||||
if len(context.targets) == 1
|
||||
else str(len(context.targets)) + ' files')
|
||||
view.print_msg(message)
|
||||
|
||||
view._clipboard.action = ClipboardAction.COPY
|
||||
view._clipboard.candidates = context.targets
|
||||
|
||||
|
||||
@action(name='drop')
|
||||
def _drop(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Open like :drop.
|
||||
"""
|
||||
cwd = view._vim.call('getcwd')
|
||||
command = context.args[0] if context.args else 'edit'
|
||||
|
||||
for target in context.targets:
|
||||
path = target['action__path']
|
||||
|
||||
if path.is_dir():
|
||||
view.cd(defx, str(path), context.cursor)
|
||||
continue
|
||||
|
||||
bufnr = view._vim.call('bufnr', f'^{path}$')
|
||||
winids = view._vim.call('win_findbuf', bufnr)
|
||||
|
||||
if winids:
|
||||
view._vim.call('win_gotoid', winids[0])
|
||||
else:
|
||||
if context.prev_winid != view._winid and view._vim.call(
|
||||
'win_id2win', context.prev_winid):
|
||||
view._vim.call('win_gotoid', context.prev_winid)
|
||||
else:
|
||||
view._vim.command('wincmd w')
|
||||
try:
|
||||
path = path.relative_to(cwd)
|
||||
except ValueError:
|
||||
pass
|
||||
view._vim.call('defx#util#execute_path', command, str(path))
|
||||
|
||||
|
||||
@action(name='execute_command', attr=ActionAttr.NO_TAGETS)
|
||||
def _execute_command(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Execute the command.
|
||||
"""
|
||||
save_cwd = view._vim.call('getcwd')
|
||||
cd(view._vim, defx._cwd)
|
||||
|
||||
command = context.args[0] if context.args else view._vim.call(
|
||||
'input', 'Command: ', '', 'shellcmd')
|
||||
|
||||
output = view._vim.call('system', command)
|
||||
if output:
|
||||
view.print_msg(output)
|
||||
|
||||
cd(view._vim, save_cwd)
|
||||
|
||||
|
||||
@action(name='execute_system')
|
||||
def _execute_system(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Execute the file by system associated command.
|
||||
"""
|
||||
for target in context.targets:
|
||||
view._vim.call('defx#util#open', str(target['action__path']))
|
||||
|
||||
|
||||
@action(name='move')
|
||||
def _move(view: View, defx: Defx, context: Context) -> None:
|
||||
if not context.targets:
|
||||
return
|
||||
|
||||
message = 'Move to the clipboard: {}'.format(
|
||||
str(context.targets[0]['action__path'])
|
||||
if len(context.targets) == 1
|
||||
else str(len(context.targets)) + ' files')
|
||||
view.print_msg(message)
|
||||
|
||||
view._clipboard.action = ClipboardAction.MOVE
|
||||
view._clipboard.candidates = context.targets
|
||||
|
||||
|
||||
@action(name='new_directory')
|
||||
def _new_directory(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Create a new directory.
|
||||
"""
|
||||
candidate = view.get_cursor_candidate(context.cursor)
|
||||
if not candidate:
|
||||
return
|
||||
|
||||
if candidate['is_opened_tree'] or candidate['is_root']:
|
||||
cwd = str(candidate['action__path'])
|
||||
else:
|
||||
cwd = str(Path(candidate['action__path']).parent)
|
||||
|
||||
new_filename = cwd_input(
|
||||
view._vim, cwd,
|
||||
'Please input a new directory name: ', '', 'file')
|
||||
if not new_filename:
|
||||
return
|
||||
filename = Path(cwd).joinpath(new_filename)
|
||||
|
||||
if not filename:
|
||||
return
|
||||
if filename.exists():
|
||||
error(view._vim, f'{filename} already exists')
|
||||
return
|
||||
|
||||
filename.mkdir(parents=True)
|
||||
view.redraw(True)
|
||||
view.search_file(filename, defx._index)
|
||||
|
||||
|
||||
@action(name='new_file')
|
||||
def _new_file(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Create a new file and it's parent directories.
|
||||
"""
|
||||
candidate = view.get_cursor_candidate(context.cursor)
|
||||
if not candidate:
|
||||
return
|
||||
|
||||
if candidate['is_opened_tree'] or candidate['is_root']:
|
||||
cwd = str(candidate['action__path'])
|
||||
else:
|
||||
cwd = str(Path(candidate['action__path']).parent)
|
||||
|
||||
new_filename = cwd_input(
|
||||
view._vim, cwd,
|
||||
'Please input a new filename: ', '', 'file')
|
||||
if not new_filename:
|
||||
return
|
||||
isdir = new_filename[-1] == '/'
|
||||
filename = Path(cwd).joinpath(new_filename)
|
||||
|
||||
if not filename:
|
||||
return
|
||||
if filename.exists():
|
||||
error(view._vim, f'{filename} already exists')
|
||||
return
|
||||
|
||||
if isdir:
|
||||
filename.mkdir(parents=True)
|
||||
else:
|
||||
filename.parent.mkdir(parents=True, exist_ok=True)
|
||||
filename.touch()
|
||||
|
||||
view.redraw(True)
|
||||
view.search_file(filename, defx._index)
|
||||
|
||||
|
||||
@action(name='new_multiple_files')
|
||||
def _new_multiple_files(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Create multiple files.
|
||||
"""
|
||||
candidate = view.get_cursor_candidate(context.cursor)
|
||||
if not candidate:
|
||||
return
|
||||
|
||||
if candidate['is_opened_tree'] or candidate['is_root']:
|
||||
cwd = str(candidate['action__path'])
|
||||
else:
|
||||
cwd = str(Path(candidate['action__path']).parent)
|
||||
|
||||
save_cwd = view._vim.call('getcwd')
|
||||
cd(view._vim, cwd)
|
||||
|
||||
str_filenames: str = view._vim.call(
|
||||
'input', 'Please input new filenames: ', '', 'file')
|
||||
cd(view._vim, save_cwd)
|
||||
|
||||
if not str_filenames:
|
||||
return None
|
||||
|
||||
for name in str_filenames.split():
|
||||
is_dir = name[-1] == '/'
|
||||
|
||||
filename = Path(cwd).joinpath(name)
|
||||
if filename.exists():
|
||||
error(view._vim, f'{filename} already exists')
|
||||
continue
|
||||
|
||||
if is_dir:
|
||||
filename.mkdir(parents=True)
|
||||
else:
|
||||
if not filename.parent.exists():
|
||||
filename.parent.mkdir(parents=True)
|
||||
filename.touch()
|
||||
|
||||
view.redraw(True)
|
||||
view.search_file(filename, defx._index)
|
||||
|
||||
|
||||
@action(name='open')
|
||||
def _open(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Open the file.
|
||||
"""
|
||||
cwd = view._vim.call('getcwd')
|
||||
command = context.args[0] if context.args else 'edit'
|
||||
for target in context.targets:
|
||||
path = target['action__path']
|
||||
|
||||
if path.is_dir():
|
||||
view.cd(defx, str(path), context.cursor)
|
||||
continue
|
||||
|
||||
try:
|
||||
path = path.relative_to(cwd)
|
||||
except ValueError:
|
||||
pass
|
||||
view._vim.call('defx#util#execute_path', command, str(path))
|
||||
|
||||
|
||||
@action(name='open_directory')
|
||||
def _open_directory(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Open the directory.
|
||||
"""
|
||||
if context.args:
|
||||
path = Path(context.args[0])
|
||||
else:
|
||||
for target in context.targets:
|
||||
path = target['action__path']
|
||||
|
||||
if path.is_dir():
|
||||
view.cd(defx, str(path), context.cursor)
|
||||
|
||||
|
||||
@action(name='paste', attr=ActionAttr.NO_TAGETS)
|
||||
def _paste(view: View, defx: Defx, context: Context) -> None:
|
||||
candidate = view.get_cursor_candidate(context.cursor)
|
||||
if not candidate:
|
||||
return
|
||||
|
||||
if candidate['is_opened_tree'] or candidate['is_root']:
|
||||
cwd = str(candidate['action__path'])
|
||||
else:
|
||||
cwd = str(Path(candidate['action__path']).parent)
|
||||
|
||||
action = view._clipboard.action
|
||||
dest = None
|
||||
for index, candidate in enumerate(view._clipboard.candidates):
|
||||
path = candidate['action__path']
|
||||
dest = Path(cwd).joinpath(path.name)
|
||||
if dest.exists():
|
||||
overwrite = check_overwrite(view, dest, path)
|
||||
if overwrite == Path(''):
|
||||
continue
|
||||
dest = overwrite
|
||||
|
||||
if path == dest:
|
||||
continue
|
||||
|
||||
view.print_msg(
|
||||
f'[{index + 1}/{len(view._clipboard.candidates)}] {path}')
|
||||
if action == ClipboardAction.COPY:
|
||||
if path.is_dir():
|
||||
shutil.copytree(str(path), dest)
|
||||
else:
|
||||
shutil.copy2(str(path), dest)
|
||||
elif action == ClipboardAction.MOVE:
|
||||
shutil.move(str(path), cwd)
|
||||
view._vim.command('redraw')
|
||||
view._vim.command('echo')
|
||||
|
||||
view.redraw(True)
|
||||
if dest:
|
||||
view.search_file(dest, defx._index)
|
||||
|
||||
|
||||
@action(name='remove', attr=ActionAttr.REDRAW)
|
||||
def _remove(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Delete the file or directory.
|
||||
"""
|
||||
if not context.targets:
|
||||
return
|
||||
|
||||
force = context.args[0] == 'force' if context.args else False
|
||||
if not force:
|
||||
message = 'Are you sure you want to delete {}?'.format(
|
||||
str(context.targets[0]['action__path'])
|
||||
if len(context.targets) == 1
|
||||
else str(len(context.targets)) + ' files')
|
||||
if not confirm(view._vim, message):
|
||||
return
|
||||
|
||||
for target in context.targets:
|
||||
path = target['action__path']
|
||||
|
||||
if path.is_dir():
|
||||
shutil.rmtree(str(path))
|
||||
else:
|
||||
path.unlink()
|
||||
|
||||
|
||||
@action(name='remove_trash')
|
||||
def _remove_trash(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Delete the file or directory.
|
||||
"""
|
||||
if not context.targets:
|
||||
return
|
||||
|
||||
if not importlib.util.find_spec('send2trash'):
|
||||
error(view._vim, '"Send2Trash" is not installed')
|
||||
return
|
||||
|
||||
force = context.args[0] == 'force' if context.args else False
|
||||
if not force:
|
||||
message = 'Are you sure you want to delete {}?'.format(
|
||||
str(context.targets[0]['action__path'])
|
||||
if len(context.targets) == 1
|
||||
else str(len(context.targets)) + ' files')
|
||||
if not confirm(view._vim, message):
|
||||
return
|
||||
|
||||
import send2trash
|
||||
for target in context.targets:
|
||||
send2trash.send2trash(str(target['action__path']))
|
||||
view.redraw(True)
|
||||
|
||||
|
||||
@action(name='rename')
|
||||
def _rename(view: View, defx: Defx, context: Context) -> None:
|
||||
"""
|
||||
Rename the file or directory.
|
||||
"""
|
||||
|
||||
if len(context.targets) > 1:
|
||||
# ex rename
|
||||
view._vim.call('defx#exrename#create_buffer',
|
||||
[{'action__path': str(x['action__path'])}
|
||||
for x in context.targets],
|
||||
{'buffer_name': 'defx'})
|
||||
return
|
||||
|
||||
for target in context.targets:
|
||||
old = target['action__path']
|
||||
new_filename = cwd_input(
|
||||
view._vim, defx._cwd,
|
||||
f'Old name: {old}\nNew name: ', str(old), 'file')
|
||||
view._vim.command('redraw')
|
||||
if not new_filename:
|
||||
return
|
||||
new = Path(defx._cwd).joinpath(new_filename)
|
||||
if not new or new == old:
|
||||
continue
|
||||
if str(new).lower() != str(old).lower() and new.exists():
|
||||
error(view._vim, f'{new} already exists')
|
||||
continue
|
||||
|
||||
old.rename(new)
|
||||
|
||||
view.redraw(True)
|
||||
view.search_file(new, defx._index)
|
74
bundle/defx.nvim/rplugin/python3/defx/rplugin.py
Normal file
74
bundle/defx.nvim/rplugin/python3/defx/rplugin.py
Normal file
@ -0,0 +1,74 @@
|
||||
# ============================================================================
|
||||
# FILE: rplugin.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import typing
|
||||
|
||||
from defx.clipboard import Clipboard
|
||||
from defx.view import View
|
||||
from defx.util import Nvim
|
||||
|
||||
|
||||
class Rplugin:
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
self._vim = vim
|
||||
self._views: typing.List[View] = []
|
||||
self._clipboard = Clipboard()
|
||||
|
||||
def init_channel(self) -> None:
|
||||
self._vim.vars['defx#_channel_id'] = self._vim.channel_id
|
||||
|
||||
def start(self, args: typing.List[typing.Any]) -> None:
|
||||
[paths, context] = args
|
||||
views = [x for x in self._views
|
||||
if context['buffer_name'] == x._context.buffer_name]
|
||||
if not views or context['new']:
|
||||
view = View(self._vim, len(self._views))
|
||||
views = [view]
|
||||
self._views.append(view)
|
||||
views[0].init(paths, context, self._clipboard)
|
||||
|
||||
def do_action(self, args: typing.List[typing.Any]) -> None:
|
||||
views = [x for x in self._views
|
||||
if x._bufnr == self._vim.current.buffer.number]
|
||||
if not views:
|
||||
return
|
||||
view = views[0]
|
||||
|
||||
prev_paths = [x._cwd for x in view._defxs]
|
||||
prev_candidates = view._candidates
|
||||
|
||||
view.do_action(args[0], args[1], args[2])
|
||||
|
||||
paths = [x._cwd for x in view._defxs]
|
||||
if paths == prev_paths and view._candidates != prev_candidates:
|
||||
self.redraw([x for x in self._views if x != view])
|
||||
|
||||
def get_candidate(self) -> typing.Dict[str, typing.Union[str, bool]]:
|
||||
cursor = self._vim.call('line', '.')
|
||||
for view in [x for x in self._views
|
||||
if x._bufnr == self._vim.current.buffer.number]:
|
||||
candidate = view.get_cursor_candidate(cursor)
|
||||
return {
|
||||
'word': candidate['word'],
|
||||
'is_directory': candidate['is_directory'],
|
||||
'is_opened_tree': candidate['is_opened_tree'],
|
||||
'level': candidate['level'],
|
||||
'action__path': str(candidate['action__path']),
|
||||
}
|
||||
return {}
|
||||
|
||||
def get_context(self) -> typing.Dict[str, typing.Any]:
|
||||
for view in [x for x in self._views
|
||||
if x._bufnr == self._vim.current.buffer.number]:
|
||||
return view._context._asdict()
|
||||
return {}
|
||||
|
||||
def redraw(self, views: typing.List[View]) -> None:
|
||||
call = self._vim.call
|
||||
for view in [x for x in views
|
||||
if call('bufwinnr', x._bufnr) > 0]:
|
||||
view.redraw(True)
|
13
bundle/defx.nvim/rplugin/python3/defx/session.py
Normal file
13
bundle/defx.nvim/rplugin/python3/defx/session.py
Normal file
@ -0,0 +1,13 @@
|
||||
# ============================================================================
|
||||
# FILE: session.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import typing
|
||||
|
||||
|
||||
class Session(typing.NamedTuple):
|
||||
name: str = ''
|
||||
path: str = ''
|
||||
opened_candidates: typing.List[str] = []
|
75
bundle/defx.nvim/rplugin/python3/defx/sort.py
Normal file
75
bundle/defx.nvim/rplugin/python3/defx/sort.py
Normal file
@ -0,0 +1,75 @@
|
||||
# ============================================================================
|
||||
# FILE: sort.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import re
|
||||
import typing
|
||||
|
||||
from defx.util import readable
|
||||
|
||||
|
||||
def sort(
|
||||
method: str, candidates: typing.List[typing.Dict[str, typing.Any]]
|
||||
) -> typing.List[typing.Dict[str, typing.Any]]:
|
||||
dirs = _sort_method(
|
||||
method, [x for x in candidates if x['is_directory']])
|
||||
files = _sort_method(
|
||||
method, [x for x in candidates if not x['is_directory']])
|
||||
return dirs + files
|
||||
|
||||
|
||||
def _sort_method(
|
||||
method: str, candidates: typing.List[typing.Dict[str, typing.Any]]
|
||||
) -> typing.List[typing.Dict[str, typing.Any]]:
|
||||
key = method.lower()
|
||||
if key not in SORT_METHODS:
|
||||
return candidates
|
||||
|
||||
candidates = SORT_METHODS[key](candidates)
|
||||
if re.match(r'[A-Z]', method):
|
||||
candidates = list(reversed(candidates))
|
||||
return candidates
|
||||
|
||||
|
||||
def _extension(
|
||||
candidates: typing.List[typing.Dict[str, typing.Any]]
|
||||
) -> typing.List[typing.Dict[str, typing.Any]]:
|
||||
return sorted(candidates, key=lambda x: x['action__path'].suffix)
|
||||
|
||||
|
||||
def _filename(
|
||||
candidates: typing.List[typing.Dict[str, typing.Any]]
|
||||
) -> typing.List[typing.Dict[str, typing.Any]]:
|
||||
|
||||
def numeric_key(v: str) -> typing.List[typing.Any]:
|
||||
keys = re.split(r'(\d+)', v)
|
||||
keys[1::2] = [int(x) for x in keys[1::2]] # type: ignore
|
||||
return keys
|
||||
|
||||
return sorted(candidates, key=lambda x: numeric_key(x['word'].lower()))
|
||||
|
||||
|
||||
def _size(
|
||||
candidates: typing.List[typing.Dict[str, typing.Any]]
|
||||
) -> typing.List[typing.Dict[str, typing.Any]]:
|
||||
return sorted(candidates, key=(lambda x:
|
||||
x['action__path'].stat().st_size
|
||||
if readable(x['action__path']) else -1))
|
||||
|
||||
|
||||
def _time(
|
||||
candidates: typing.List[typing.Dict[str, typing.Any]]
|
||||
) -> typing.List[typing.Dict[str, typing.Any]]:
|
||||
return sorted(candidates, key=(lambda x:
|
||||
x['action__path'].stat().st_mtime
|
||||
if readable(x['action__path']) else 0))
|
||||
|
||||
|
||||
SORT_METHODS = {
|
||||
'extension': _extension,
|
||||
'filename': _filename,
|
||||
'size': _size,
|
||||
'time': _time,
|
||||
}
|
61
bundle/defx.nvim/rplugin/python3/defx/source/file.py
Normal file
61
bundle/defx.nvim/rplugin/python3/defx/source/file.py
Normal file
@ -0,0 +1,61 @@
|
||||
# ============================================================================
|
||||
# FILE: file.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pathlib import Path
|
||||
import typing
|
||||
|
||||
from defx.base.source import Base
|
||||
from defx.context import Context
|
||||
from defx.util import error, readable, safe_call, Nvim
|
||||
|
||||
|
||||
class Source(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'file'
|
||||
|
||||
from defx.kind.file import Kind
|
||||
self.kind: Kind = Kind(self.vim)
|
||||
|
||||
self.vars = {
|
||||
'root': None,
|
||||
}
|
||||
|
||||
def get_root_candidate(
|
||||
self, context: Context, path: Path
|
||||
) -> typing.Dict[str, typing.Any]:
|
||||
word = self.vim.call('fnamemodify', str(path), ':~')
|
||||
if self.vim.call('defx#util#is_windows'):
|
||||
word = word.replace('\\', '/')
|
||||
if word[-1:] != '/':
|
||||
word += '/'
|
||||
if self.vars['root']:
|
||||
word = self.vim.call(self.vars['root'], str(path))
|
||||
word = word.replace('\n', '\\n')
|
||||
|
||||
return {
|
||||
'word': word,
|
||||
'is_directory': True,
|
||||
'action__path': path,
|
||||
}
|
||||
|
||||
def gather_candidates(
|
||||
self, context: Context, path: Path
|
||||
) -> typing.List[typing.Dict[str, typing.Any]]:
|
||||
candidates = []
|
||||
if not readable(path) or not path.is_dir():
|
||||
error(self.vim, f'"{path}" is not readable directory.')
|
||||
return []
|
||||
for entry in path.iterdir():
|
||||
candidates.append({
|
||||
'word': entry.name.replace('\n', '\\n') + (
|
||||
'/' if safe_call(entry.is_dir, False) else ''),
|
||||
'is_directory': safe_call(entry.is_dir, False),
|
||||
'action__path': entry,
|
||||
})
|
||||
return candidates
|
90
bundle/defx.nvim/rplugin/python3/defx/util.py
Normal file
90
bundle/defx.nvim/rplugin/python3/defx/util.py
Normal file
@ -0,0 +1,90 @@
|
||||
# ============================================================================
|
||||
# FILE: util.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import importlib.util
|
||||
import os
|
||||
import typing
|
||||
from pathlib import Path
|
||||
from pynvim import Nvim
|
||||
|
||||
UserContext = typing.Dict[str, typing.Any]
|
||||
Candidate = typing.Dict[str, typing.Any]
|
||||
Candidates = typing.List[Candidate]
|
||||
|
||||
|
||||
def cd(vim: Nvim, path: str) -> None:
|
||||
vim.call('defx#util#cd', path)
|
||||
|
||||
|
||||
def cwd_input(vim: Nvim, cwd: str, prompt: str,
|
||||
text: str = '', completion: str = '') -> str:
|
||||
"""
|
||||
Returns the absolute input path in cwd.
|
||||
"""
|
||||
save_cwd = vim.call('getcwd')
|
||||
cd(vim, cwd)
|
||||
|
||||
filename: str = str(vim.call('defx#util#input', prompt, text, completion))
|
||||
filename = filename.strip()
|
||||
|
||||
cd(vim, save_cwd)
|
||||
|
||||
return filename
|
||||
|
||||
|
||||
def error(vim: Nvim, expr: typing.Any) -> None:
|
||||
"""
|
||||
Prints the error messages to Vim/Nvim's :messages buffer.
|
||||
"""
|
||||
vim.call('defx#util#print_error', expr)
|
||||
|
||||
|
||||
def confirm(vim: Nvim, question: str) -> bool:
|
||||
"""
|
||||
Confirm action
|
||||
"""
|
||||
option: int = vim.call('defx#util#confirm',
|
||||
question, '&Yes\n&No\n&Cancel', 2)
|
||||
return option == 1
|
||||
|
||||
|
||||
def import_plugin(path: Path, source: str,
|
||||
classname: str) -> typing.Any:
|
||||
"""Import defx plugin source class.
|
||||
|
||||
If the class exists, add its directory to sys.path.
|
||||
"""
|
||||
module_name = 'defx.%s.%s' % (source, path.stem)
|
||||
|
||||
spec = importlib.util.spec_from_file_location(module_name, str(path))
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module) # type: ignore
|
||||
cls = getattr(module, classname, None)
|
||||
return cls
|
||||
|
||||
|
||||
def readable(path: Path) -> bool:
|
||||
"""
|
||||
Check {path} is readable.
|
||||
"""
|
||||
try:
|
||||
if os.access(str(path), os.R_OK) and path.stat():
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def safe_call(fn: typing.Callable[..., typing.Any],
|
||||
fallback: typing.Optional[bool] = None) -> typing.Any:
|
||||
"""
|
||||
Ignore OSError when calling {fn}
|
||||
"""
|
||||
try:
|
||||
return fn()
|
||||
except OSError:
|
||||
return fallback
|
678
bundle/defx.nvim/rplugin/python3/defx/view.py
Normal file
678
bundle/defx.nvim/rplugin/python3/defx/view.py
Normal file
@ -0,0 +1,678 @@
|
||||
# ============================================================================
|
||||
# FILE: view.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import copy
|
||||
import time
|
||||
import typing
|
||||
from pynvim.api import Buffer
|
||||
from pathlib import Path
|
||||
|
||||
from defx.clipboard import Clipboard
|
||||
from defx.context import Context
|
||||
from defx.defx import Defx
|
||||
from defx.session import Session
|
||||
from defx.util import error, import_plugin, safe_call, Nvim
|
||||
|
||||
|
||||
class View(object):
|
||||
|
||||
def __init__(self, vim: Nvim, index: int) -> None:
|
||||
self._vim: Nvim = vim
|
||||
self._defxs: typing.List[Defx] = []
|
||||
self._candidates: typing.List[typing.Dict[str, typing.Any]] = []
|
||||
self._clipboard = Clipboard()
|
||||
self._bufnr = -1
|
||||
self._prev_bufnr = -1
|
||||
self._winid = -1
|
||||
self._index = index
|
||||
self._bufname = '[defx]'
|
||||
self._buffer: Buffer = None
|
||||
self._prev_action = ''
|
||||
self._prev_syntaxes: typing.List[str] = []
|
||||
self._prev_highlight_commands: typing.List[str] = []
|
||||
self._winrestcmd = ''
|
||||
self._session_version = '1.0'
|
||||
self._sessions: typing.Dict[str, Session] = {}
|
||||
|
||||
def init(self, paths: typing.List[str],
|
||||
context: typing.Dict[str, typing.Any],
|
||||
clipboard: Clipboard
|
||||
) -> None:
|
||||
self._context = self._init_context(context)
|
||||
self._bufname = f'[defx] {self._context.buffer_name}-{self._index}'
|
||||
self._winrestcmd = self._vim.call('winrestcmd')
|
||||
self._prev_wininfo = self._get_wininfo()
|
||||
self._prev_bufnr = self._context.prev_bufnr
|
||||
|
||||
if not self._init_defx(paths, clipboard):
|
||||
# Skipped initialize
|
||||
self._winid = self._vim.call('win_getid')
|
||||
if paths and self._vim.call('bufnr', '%') == self._bufnr:
|
||||
self._update_defx(paths)
|
||||
self._init_columns(self._context.columns.split(':'))
|
||||
self.redraw(True)
|
||||
|
||||
def do_action(self, action_name: str,
|
||||
action_args: typing.List[str],
|
||||
new_context: typing.Dict[str, typing.Any]) -> None:
|
||||
"""
|
||||
Do "action" action.
|
||||
"""
|
||||
cursor = new_context['cursor']
|
||||
visual_start = new_context['visual_start']
|
||||
visual_end = new_context['visual_end']
|
||||
|
||||
defx_targets = {
|
||||
x._index: self.get_selected_candidates(cursor, x._index)
|
||||
for x in self._defxs}
|
||||
all_targets: typing.List[typing.Dict[str, typing.Any]] = []
|
||||
for targets in defx_targets.values():
|
||||
all_targets += targets
|
||||
|
||||
import defx.action as action
|
||||
for defx in [x for x in self._defxs
|
||||
if not all_targets or defx_targets[x._index]]:
|
||||
context = self._context._replace(
|
||||
args=action_args,
|
||||
cursor=cursor,
|
||||
targets=defx_targets[defx._index],
|
||||
visual_start=visual_start,
|
||||
visual_end=visual_end,
|
||||
)
|
||||
ret = action.do_action(self, defx, action_name, context)
|
||||
if ret:
|
||||
error(self._vim, 'Invalid action_name:' + action_name)
|
||||
return
|
||||
|
||||
def debug(self, expr: typing.Any) -> None:
|
||||
error(self._vim, expr)
|
||||
|
||||
def print_msg(self, expr: typing.Any) -> None:
|
||||
self._vim.call('defx#util#print_message', expr)
|
||||
|
||||
def quit(self) -> None:
|
||||
winnr = self._vim.call('bufwinnr', self._bufnr)
|
||||
if winnr < 0:
|
||||
return
|
||||
|
||||
if winnr != self._vim.call('winnr'):
|
||||
# Use current window
|
||||
self._context = self._context._replace(
|
||||
prev_winid=self._vim.call('win_getid'))
|
||||
|
||||
self._vim.command(f'{winnr}wincmd w')
|
||||
|
||||
if (self._context.split not in ['no', 'tab'] and
|
||||
self._vim.call('winnr', '$') != 1):
|
||||
self._vim.command('close')
|
||||
self._vim.call('win_gotoid', self._context.prev_winid)
|
||||
elif self._check_bufnr(self._prev_bufnr):
|
||||
self._vim.command('buffer ' + str(self._prev_bufnr))
|
||||
elif self._check_bufnr(self._context.prev_last_bufnr):
|
||||
self._vim.command('buffer ' +
|
||||
str(self._context.prev_last_bufnr))
|
||||
else:
|
||||
self._vim.command('enew')
|
||||
|
||||
if self._get_wininfo() and self._get_wininfo() == self._prev_wininfo:
|
||||
self._vim.command(self._winrestcmd)
|
||||
|
||||
def redraw(self, is_force: bool = False) -> None:
|
||||
"""
|
||||
Redraw defx buffer.
|
||||
"""
|
||||
|
||||
start = time.time()
|
||||
|
||||
[info] = self._vim.call('getbufinfo', self._bufnr)
|
||||
prev_linenr = info['lnum']
|
||||
prev = self.get_cursor_candidate(prev_linenr)
|
||||
|
||||
if is_force:
|
||||
self._init_candidates()
|
||||
self._init_column_length()
|
||||
|
||||
for column in self._columns:
|
||||
column.on_redraw(self, self._context)
|
||||
|
||||
lines = [
|
||||
self._get_columns_text(self._context, x)
|
||||
for x in self._candidates
|
||||
]
|
||||
|
||||
self._buffer.options['modifiable'] = True
|
||||
|
||||
# NOTE: Different len of buffer line replacement cause cursor jump
|
||||
if len(lines) >= len(self._buffer):
|
||||
self._buffer[:] = lines[:len(self._buffer)]
|
||||
self._buffer.append(lines[len(self._buffer):])
|
||||
else:
|
||||
self._buffer[len(lines):] = []
|
||||
self._buffer[:] = lines
|
||||
|
||||
self._buffer.options['modifiable'] = False
|
||||
self._buffer.options['modified'] = False
|
||||
|
||||
# TODO: How to set cursor position for other buffer when
|
||||
# stay in current buffer
|
||||
if self._buffer == self._vim.current.buffer:
|
||||
self._vim.call('cursor', [prev_linenr, 0])
|
||||
if prev:
|
||||
self.search_file(prev['action__path'], prev['_defx_index'])
|
||||
if is_force:
|
||||
self._init_column_syntax()
|
||||
|
||||
if self._context.profile:
|
||||
error(self._vim, f'redraw time = {time.time() - start}')
|
||||
|
||||
def get_cursor_candidate(
|
||||
self, cursor: int) -> typing.Dict[str, typing.Any]:
|
||||
if len(self._candidates) < cursor:
|
||||
return {}
|
||||
else:
|
||||
return self._candidates[cursor - 1]
|
||||
|
||||
def get_selected_candidates(
|
||||
self, cursor: int, index: int
|
||||
) -> typing.List[typing.Dict[str, typing.Any]]:
|
||||
if not self._candidates:
|
||||
return []
|
||||
|
||||
candidates = [x for x in self._candidates if x['is_selected']]
|
||||
if not candidates:
|
||||
candidates = [self.get_cursor_candidate(cursor)]
|
||||
return [x for x in candidates if x.get('_defx_index', -1) == index]
|
||||
|
||||
def get_candidate_pos(self, path: Path, index: int) -> int:
|
||||
for [pos, candidate] in enumerate(self._candidates):
|
||||
if (candidate['_defx_index'] == index and
|
||||
candidate['action__path'] == path):
|
||||
return pos
|
||||
return -1
|
||||
|
||||
def cd(self, defx: Defx, path: str, cursor: int) -> None:
|
||||
history = defx._cursor_history
|
||||
|
||||
# Save previous cursor position
|
||||
candidate = self.get_cursor_candidate(cursor)
|
||||
if candidate:
|
||||
history[defx._cwd] = candidate['action__path']
|
||||
|
||||
global_histories = self._vim.vars['defx#_histories']
|
||||
global_histories.append(defx._cwd)
|
||||
self._vim.vars['defx#_histories'] = global_histories
|
||||
|
||||
defx.cd(path)
|
||||
self.redraw(True)
|
||||
|
||||
self._check_session(defx._index, path)
|
||||
|
||||
self._init_cursor(defx)
|
||||
if path in history:
|
||||
self.search_file(history[path], defx._index)
|
||||
|
||||
self._update_paths(defx._index, path)
|
||||
|
||||
def search_file(self, path: Path, index: int) -> bool:
|
||||
target = str(path)
|
||||
if target and target[-1] == '/':
|
||||
target = target[:-1]
|
||||
pos = self.get_candidate_pos(Path(target), index)
|
||||
if pos < 0:
|
||||
return False
|
||||
|
||||
self._vim.call('cursor', [pos + 1, 1])
|
||||
return True
|
||||
|
||||
def update_candidates(self) -> None:
|
||||
# Update opened/selected state
|
||||
for defx in self._defxs:
|
||||
defx._opened_candidates = set()
|
||||
defx._selected_candidates = set()
|
||||
for [i, candidate] in [x for x in enumerate(self._candidates)
|
||||
if x[1]['is_opened_tree']]:
|
||||
defx = self._defxs[candidate['_defx_index']]
|
||||
defx._opened_candidates.add(str(candidate['action__path']))
|
||||
for [i, candidate] in [x for x in enumerate(self._candidates)
|
||||
if x[1]['is_selected']]:
|
||||
defx = self._defxs[candidate['_defx_index']]
|
||||
defx._selected_candidates.add(str(candidate['action__path']))
|
||||
|
||||
def open_tree(self, path: Path, index: int, enable_nested: bool,
|
||||
max_level: int = 0) -> None:
|
||||
# Search insert position
|
||||
pos = self.get_candidate_pos(path, index)
|
||||
if pos < 0:
|
||||
return
|
||||
|
||||
target = self._candidates[pos]
|
||||
if (not target['is_directory'] or
|
||||
target['is_opened_tree'] or target['is_root']):
|
||||
return
|
||||
|
||||
target['is_opened_tree'] = True
|
||||
base_level = target['level'] + 1
|
||||
|
||||
defx = self._defxs[index]
|
||||
children = defx.gather_candidates_recursive(
|
||||
str(path), base_level, base_level + max_level)
|
||||
if not children:
|
||||
return
|
||||
|
||||
if (enable_nested and len(children) == 1
|
||||
and children[0]['is_directory']):
|
||||
# Merge child.
|
||||
target['action__path'] = children[0]['action__path']
|
||||
target['word'] += children[0]['word']
|
||||
target['is_opened_tree'] = False
|
||||
return self.open_tree(target['action__path'],
|
||||
index, enable_nested, max_level)
|
||||
|
||||
for candidate in children:
|
||||
candidate['_defx_index'] = index
|
||||
|
||||
self._candidates = (self._candidates[: pos + 1] +
|
||||
children + self._candidates[pos + 1:])
|
||||
|
||||
def close_tree(self, path: Path, index: int) -> None:
|
||||
# Search insert position
|
||||
pos = self.get_candidate_pos(path, index)
|
||||
if pos < 0:
|
||||
return
|
||||
|
||||
target = self._candidates[pos]
|
||||
if not target['is_opened_tree'] or target['is_root']:
|
||||
return
|
||||
|
||||
target['is_opened_tree'] = False
|
||||
|
||||
start = pos + 1
|
||||
base_level = target['level']
|
||||
end = start
|
||||
for candidate in self._candidates[start:]:
|
||||
if candidate['level'] <= base_level:
|
||||
break
|
||||
end += 1
|
||||
|
||||
self._candidates = (self._candidates[: start] +
|
||||
self._candidates[end:])
|
||||
|
||||
def _init_context(
|
||||
self, context: typing.Dict[str, typing.Any]) -> Context:
|
||||
# Convert to int
|
||||
for attr in [x[0] for x in Context()._asdict().items()
|
||||
if isinstance(x[1], int) and x[0] in context]:
|
||||
context[attr] = int(context[attr])
|
||||
|
||||
return Context(**context)
|
||||
|
||||
def _resize_window(self) -> None:
|
||||
window_options = self._vim.current.window.options
|
||||
if (self._context.split == 'vertical'
|
||||
and self._context.winwidth > 0):
|
||||
window_options['winfixwidth'] = True
|
||||
self._vim.command(f'vertical resize {self._context.winwidth}')
|
||||
elif (self._context.split == 'horizontal' and
|
||||
self._context.winheight > 0):
|
||||
window_options['winfixheight'] = True
|
||||
self._vim.command(f'resize {self._context.winheight}')
|
||||
|
||||
def _check_session(self, index: int, path: str) -> None:
|
||||
if path not in self._sessions:
|
||||
return
|
||||
|
||||
# restore opened_candidates
|
||||
session = self._sessions[path]
|
||||
for opened_path in session.opened_candidates:
|
||||
self.open_tree(Path(opened_path), index, False)
|
||||
self.update_candidates()
|
||||
self.redraw()
|
||||
|
||||
def _init_defx(self,
|
||||
paths: typing.List[str],
|
||||
clipboard: Clipboard) -> bool:
|
||||
if not self._switch_buffer():
|
||||
return False
|
||||
|
||||
self._buffer = self._vim.current.buffer
|
||||
self._bufnr = self._buffer.number
|
||||
self._winid = self._vim.call('win_getid')
|
||||
|
||||
if not paths:
|
||||
paths = [self._vim.call('getcwd')]
|
||||
|
||||
self._buffer.vars['defx'] = {
|
||||
'context': self._context._asdict(),
|
||||
'paths': paths,
|
||||
}
|
||||
|
||||
# Note: Have to use setlocal instead of "current.window.options"
|
||||
# "current.window.options" changes global value instead of local in
|
||||
# neovim.
|
||||
self._vim.command('setlocal colorcolumn=')
|
||||
self._vim.command('setlocal conceallevel=2')
|
||||
self._vim.command('setlocal concealcursor=nc')
|
||||
self._vim.command('setlocal nocursorcolumn')
|
||||
self._vim.command('setlocal nofoldenable')
|
||||
self._vim.command('setlocal foldcolumn=0')
|
||||
self._vim.command('setlocal nolist')
|
||||
self._vim.command('setlocal nonumber')
|
||||
self._vim.command('setlocal norelativenumber')
|
||||
self._vim.command('setlocal nospell')
|
||||
self._vim.command('setlocal nowrap')
|
||||
self._vim.command('setlocal signcolumn=no')
|
||||
if self._context.split == 'floating':
|
||||
self._vim.command('setlocal nocursorline')
|
||||
|
||||
self._resize_window()
|
||||
|
||||
buffer_options = self._buffer.options
|
||||
if not self._context.listed:
|
||||
buffer_options['buflisted'] = False
|
||||
buffer_options['buftype'] = 'nofile'
|
||||
buffer_options['bufhidden'] = 'hide'
|
||||
buffer_options['swapfile'] = False
|
||||
buffer_options['modeline'] = False
|
||||
buffer_options['modifiable'] = False
|
||||
buffer_options['modified'] = False
|
||||
buffer_options['filetype'] = 'defx'
|
||||
|
||||
if not self._vim.call('has', 'nvim'):
|
||||
# In Vim8, FileType autocmd is not fired after set filetype option.
|
||||
self._vim.command('silent doautocmd FileType defx')
|
||||
|
||||
self._vim.command('autocmd! defx * <buffer>')
|
||||
self._vim.command('autocmd defx '
|
||||
'CursorHold,FocusGained <buffer> '
|
||||
'call defx#call_async_action("check_redraw")')
|
||||
self._vim.command('autocmd defx FileType <buffer> '
|
||||
'call defx#call_action("redraw")')
|
||||
|
||||
self._prev_highlight_commands = []
|
||||
|
||||
# Initialize defx state
|
||||
self._candidates = []
|
||||
self._clipboard = clipboard
|
||||
self._defxs = []
|
||||
self._update_defx(paths)
|
||||
|
||||
self._init_all_columns()
|
||||
self._init_columns(self._context.columns.split(':'))
|
||||
|
||||
self.redraw(True)
|
||||
|
||||
if self._context.session_file:
|
||||
self.do_action('load_session', [],
|
||||
self._vim.call('defx#init#_context', {}))
|
||||
for [index, path] in enumerate(paths):
|
||||
self._check_session(index, path)
|
||||
|
||||
for defx in self._defxs:
|
||||
self._init_cursor(defx)
|
||||
|
||||
self._vim.vars['defx#_drives'] = self._context.drives
|
||||
|
||||
return True
|
||||
|
||||
def _switch_buffer(self) -> bool:
|
||||
if self._context.split == 'tab':
|
||||
self._vim.command('tabnew')
|
||||
|
||||
winnr = self._vim.call('bufwinnr', self._bufnr)
|
||||
if winnr > 0:
|
||||
self._vim.command(f'{winnr}wincmd w')
|
||||
if self._context.toggle:
|
||||
self.quit()
|
||||
else:
|
||||
self._resize_window()
|
||||
return False
|
||||
|
||||
if (self._vim.current.buffer.options['modified'] and
|
||||
not self._vim.options['hidden'] and
|
||||
self._context.split == 'no'):
|
||||
self._context = self._context._replace(split='vertical')
|
||||
|
||||
if (self._context.split == 'floating'
|
||||
and self._vim.call('exists', '*nvim_open_win')):
|
||||
# Use floating window
|
||||
self._vim.call(
|
||||
'nvim_open_win',
|
||||
self._vim.call('bufnr', '%'), True, {
|
||||
'relative': self._context.winrelative,
|
||||
'row': self._context.winrow,
|
||||
'col': self._context.wincol,
|
||||
'width': self._context.winwidth,
|
||||
'height': self._context.winheight,
|
||||
})
|
||||
|
||||
# Create new buffer
|
||||
vertical = 'vertical' if self._context.split == 'vertical' else ''
|
||||
no_split = self._context.split in ['no', 'tab', 'floating']
|
||||
if self._vim.call('bufloaded', self._bufnr):
|
||||
command = ('buffer' if no_split else 'sbuffer')
|
||||
self._vim.command(
|
||||
'silent keepalt %s %s %s %s' % (
|
||||
self._context.direction,
|
||||
vertical,
|
||||
command,
|
||||
self._bufnr,
|
||||
)
|
||||
)
|
||||
if self._context.resume:
|
||||
self._resize_window()
|
||||
return False
|
||||
elif self._vim.call('exists', 'bufadd'):
|
||||
bufnr = self._vim.call('bufadd', self._bufname)
|
||||
command = ('buffer' if no_split else 'sbuffer')
|
||||
self._vim.command(
|
||||
'silent keepalt %s %s %s %s' % (
|
||||
self._context.direction,
|
||||
vertical,
|
||||
command,
|
||||
bufnr,
|
||||
)
|
||||
)
|
||||
else:
|
||||
command = ('edit' if no_split else 'new')
|
||||
self._vim.call(
|
||||
'defx#util#execute_path',
|
||||
'silent keepalt %s %s %s ' % (
|
||||
self._context.direction,
|
||||
vertical,
|
||||
command,
|
||||
),
|
||||
self._bufname)
|
||||
return True
|
||||
|
||||
def _init_all_columns(self) -> None:
|
||||
from defx.base.column import Base as Column
|
||||
self._all_columns: typing.Dict[str, Column] = {}
|
||||
|
||||
for path_column in self._load_custom_columns():
|
||||
column = import_plugin(path_column, 'column', 'Column')
|
||||
if not column:
|
||||
continue
|
||||
|
||||
column = column(self._vim)
|
||||
if column.name not in self._all_columns:
|
||||
self._all_columns[column.name] = column
|
||||
|
||||
def _init_columns(self, columns: typing.List[str]) -> None:
|
||||
from defx.base.column import Base as Column
|
||||
custom = self._vim.call('defx#custom#_get')['column']
|
||||
self._columns: typing.List[Column] = [
|
||||
copy.copy(self._all_columns[x])
|
||||
for x in columns if x in self._all_columns
|
||||
]
|
||||
for column in self._columns:
|
||||
if column.name in custom:
|
||||
column.vars.update(custom[column.name])
|
||||
column.on_init(self, self._context)
|
||||
|
||||
def _init_column_length(self) -> None:
|
||||
from defx.base.column import Base as Column
|
||||
within_variable = False
|
||||
within_variable_columns: typing.List[Column] = []
|
||||
start = 1
|
||||
for [index, column] in enumerate(self._columns):
|
||||
column.syntax_name = f'Defx_{column.name}_{index}'
|
||||
|
||||
if within_variable and not column.is_stop_variable:
|
||||
within_variable_columns.append(column)
|
||||
continue
|
||||
|
||||
# Calculate variable_length
|
||||
variable_length = 0
|
||||
if column.is_stop_variable:
|
||||
for variable_column in within_variable_columns:
|
||||
variable_length += variable_column.length(
|
||||
self._context._replace(targets=self._candidates))
|
||||
|
||||
# Note: for "' '.join(variable_texts)" length
|
||||
if within_variable_columns:
|
||||
variable_length += len(within_variable_columns) - 1
|
||||
|
||||
length = column.length(
|
||||
self._context._replace(targets=self._candidates,
|
||||
variable_length=variable_length))
|
||||
|
||||
column.start = start
|
||||
column.end = start + length
|
||||
|
||||
if column.is_start_variable:
|
||||
within_variable = True
|
||||
within_variable_columns.append(column)
|
||||
else:
|
||||
column.is_within_variable = False
|
||||
start += length + 1
|
||||
|
||||
if column.is_stop_variable:
|
||||
for variable_column in within_variable_columns:
|
||||
# Overwrite syntax_name
|
||||
variable_column.syntax_name = column.syntax_name
|
||||
variable_column.is_within_variable = True
|
||||
within_variable = False
|
||||
|
||||
def _init_column_syntax(self) -> None:
|
||||
commands: typing.List[str] = []
|
||||
|
||||
for syntax in self._prev_syntaxes:
|
||||
commands.append(
|
||||
'silent! syntax clear ' + syntax)
|
||||
|
||||
self._prev_syntaxes = []
|
||||
for column in self._columns:
|
||||
source_highlights = column.highlight_commands()
|
||||
if source_highlights:
|
||||
if (not column.is_within_variable and
|
||||
column.start > 0 and column.end > 0):
|
||||
commands.append(
|
||||
'syntax region ' + column.syntax_name +
|
||||
r' start=/\%' + str(column.start) + r'v/ end=/\%' +
|
||||
str(column.end) + 'v/ keepend oneline')
|
||||
self._prev_syntaxes += [column.syntax_name]
|
||||
|
||||
commands += source_highlights
|
||||
self._prev_syntaxes += column.syntaxes()
|
||||
|
||||
syntax_list = commands + [self._vim.call('execute', 'syntax list')]
|
||||
if syntax_list == self._prev_highlight_commands:
|
||||
# Skip highlights
|
||||
return
|
||||
|
||||
self._execute_commands(commands)
|
||||
self._prev_highlight_commands = commands + [
|
||||
self._vim.call('execute', 'syntax list')]
|
||||
|
||||
def _execute_commands(self, commands: typing.List[str]) -> None:
|
||||
# Note: If commands are too huge, vim.command() will fail.
|
||||
threshold = 15
|
||||
cnt = 0
|
||||
while cnt < len(commands):
|
||||
self._vim.command(' | '.join(commands[cnt: cnt + threshold]))
|
||||
cnt += threshold
|
||||
|
||||
def _init_candidates(self) -> None:
|
||||
self._candidates = []
|
||||
for defx in self._defxs:
|
||||
root = defx.get_root_candidate()
|
||||
defx._mtime = root['action__path'].stat().st_mtime
|
||||
|
||||
candidates = [root]
|
||||
candidates += defx.tree_candidates(
|
||||
defx._cwd, 0, self._context.auto_recursive_level)
|
||||
for candidate in candidates:
|
||||
candidate['_defx_index'] = defx._index
|
||||
self._candidates += candidates
|
||||
|
||||
def _get_columns_text(self, context: Context,
|
||||
candidate: typing.Dict[str, typing.Any]) -> str:
|
||||
texts: typing.List[str] = []
|
||||
variable_texts: typing.List[str] = []
|
||||
for column in self._columns:
|
||||
if column.is_stop_variable:
|
||||
if variable_texts:
|
||||
variable_texts.append('')
|
||||
text = column.get_with_variable_text(
|
||||
context, ' '.join(variable_texts), candidate)
|
||||
texts.append(text)
|
||||
|
||||
variable_texts = []
|
||||
else:
|
||||
text = column.get(context, candidate)
|
||||
if column.is_start_variable or column.is_within_variable:
|
||||
if text:
|
||||
variable_texts.append(text)
|
||||
else:
|
||||
texts.append(text)
|
||||
return ' '.join(texts)
|
||||
|
||||
def _update_paths(self, index: int, path: str) -> None:
|
||||
var_defx = self._buffer.vars['defx']
|
||||
if len(var_defx['paths']) <= index:
|
||||
var_defx['paths'].append(path)
|
||||
else:
|
||||
var_defx['paths'][index] = path
|
||||
self._buffer.vars['defx'] = var_defx
|
||||
|
||||
def _init_cursor(self, defx: Defx) -> None:
|
||||
self.search_file(Path(defx._cwd), defx._index)
|
||||
|
||||
# Move to next
|
||||
self._vim.call('cursor', [self._vim.call('line', '.') + 1, 1])
|
||||
|
||||
def _get_wininfo(self) -> typing.List[str]:
|
||||
return [
|
||||
self._vim.options['columns'], self._vim.options['lines'],
|
||||
self._vim.call('win_getid'), self._vim.call('tabpagebuflist')
|
||||
]
|
||||
|
||||
def _load_custom_columns(self) -> typing.List[Path]:
|
||||
rtp_list = self._vim.options['runtimepath'].split(',')
|
||||
result: typing.List[Path] = []
|
||||
|
||||
for path in rtp_list:
|
||||
column_path = Path(path).joinpath(
|
||||
'rplugin', 'python3', 'defx', 'column')
|
||||
if safe_call(column_path.is_dir):
|
||||
result += column_path.glob('*.py')
|
||||
|
||||
return result
|
||||
|
||||
def _update_defx(self, paths: typing.List[str]) -> None:
|
||||
self._defxs = self._defxs[:len(paths)]
|
||||
|
||||
for [index, path] in enumerate(paths):
|
||||
if index >= len(self._defxs):
|
||||
self._defxs.append(
|
||||
Defx(self._vim, self._context, path, index))
|
||||
else:
|
||||
self.cd(self._defxs[index], path, self._context.cursor)
|
||||
self._update_paths(index, path)
|
||||
|
||||
def _check_bufnr(self, bufnr: int) -> bool:
|
||||
return (bool(self._vim.call('bufexists', bufnr)) and
|
||||
bufnr != self._vim.call('bufnr', '%'))
|
36
bundle/defx.nvim/rplugin/python3/denite/source/defx/drive.py
Normal file
36
bundle/defx.nvim/rplugin/python3/denite/source/defx/drive.py
Normal file
@ -0,0 +1,36 @@
|
||||
# ============================================================================
|
||||
# FILE: defx/drive.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from pathlib import Path
|
||||
import typing
|
||||
|
||||
from defx.util import Nvim, UserContext, Candidates
|
||||
from denite.source.base import Base
|
||||
|
||||
|
||||
class Source(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'defx/drive'
|
||||
self.kind = 'command'
|
||||
self._drives: typing.List[str] = []
|
||||
|
||||
def on_init(self, context: UserContext) -> None:
|
||||
options = self.vim.current.buffer.options
|
||||
if 'filetype' not in options or options['filetype'] != 'defx':
|
||||
return
|
||||
|
||||
self._drives = self.vim.vars['defx#_drives']
|
||||
|
||||
def gather_candidates(self, context: UserContext) -> Candidates:
|
||||
return [{
|
||||
'word': x,
|
||||
'abbr': x + '/',
|
||||
'action__command': f"call defx#call_action('cd', ['{x}'])",
|
||||
'action__path': x,
|
||||
} for x in self._drives if Path(x).exists()]
|
@ -0,0 +1,35 @@
|
||||
# ============================================================================
|
||||
# FILE: defx/history.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
import typing
|
||||
|
||||
from defx.util import Nvim, UserContext, Candidates
|
||||
from denite.source.base import Base
|
||||
|
||||
|
||||
class Source(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'defx/history'
|
||||
self.kind = 'command'
|
||||
self._histories: typing.List[str] = []
|
||||
|
||||
def on_init(self, context: UserContext) -> None:
|
||||
options = self.vim.current.buffer.options
|
||||
if 'filetype' not in options or options['filetype'] != 'defx':
|
||||
return
|
||||
|
||||
self._histories = reversed(self.vim.vars['defx#_histories'])
|
||||
|
||||
def gather_candidates(self, context: UserContext) -> Candidates:
|
||||
return [{
|
||||
'word': x,
|
||||
'abbr': x + '/',
|
||||
'action__command': f"call defx#call_action('cd', ['{x}'])",
|
||||
'action__path': x,
|
||||
} for x in self._histories]
|
@ -0,0 +1,58 @@
|
||||
# ============================================================================
|
||||
# FILE: defx/session.py
|
||||
# AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
# License: MIT license
|
||||
# ============================================================================
|
||||
|
||||
from defx.util import Nvim, UserContext, Candidates
|
||||
from denite.kind.command import Kind as Command
|
||||
from denite.source.base import Base
|
||||
|
||||
|
||||
class Source(Base):
|
||||
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'defx/session'
|
||||
self.kind = Kind(vim)
|
||||
|
||||
def on_init(self, context: UserContext) -> None:
|
||||
self._winid = self.vim.call('win_getid')
|
||||
self._bufnr = self.vim.call('bufnr', '%')
|
||||
|
||||
def gather_candidates(self, context: UserContext) -> Candidates:
|
||||
sessions = self.vim.call(
|
||||
'getbufvar', self._bufnr, 'defx#_sessions', [])
|
||||
if not sessions:
|
||||
return []
|
||||
|
||||
max_name = max([self.vim.call('strwidth', x['name'])
|
||||
for x in sessions])
|
||||
word_format = '{0:<' + str(max_name) + '} - {1}'
|
||||
return [{
|
||||
'word': word_format.format(x['name'], x['path']),
|
||||
'action__command': "call defx#call_action('cd', '{}')".format(
|
||||
x['path']),
|
||||
'action__path': x['path'],
|
||||
'source__winid': self._winid,
|
||||
} for x in sessions]
|
||||
|
||||
|
||||
class Kind(Command):
|
||||
def __init__(self, vim: Nvim) -> None:
|
||||
super().__init__(vim)
|
||||
|
||||
self.name = 'defx/session'
|
||||
self.persist_actions += ['delete']
|
||||
self.redraw_actions += ['delete']
|
||||
|
||||
def action_delete(self, context: UserContext) -> Candidates:
|
||||
winid = self.vim.call('win_getid')
|
||||
|
||||
for candidate in context['targets']:
|
||||
self.vim.call('win_gotoid', candidate['source__winid'])
|
||||
self.vim.call('defx#call_action', 'delete_session',
|
||||
candidate['action__path'])
|
||||
|
||||
self.vim.call('win_gotoid', winid)
|
29
bundle/defx.nvim/test/autoload/defx/custom.vim
Normal file
29
bundle/defx.nvim/test/autoload/defx/custom.vim
Normal file
@ -0,0 +1,29 @@
|
||||
" set verbose=1
|
||||
|
||||
let s:suite = themis#suite('custom')
|
||||
let s:assert = themis#helper('assert')
|
||||
|
||||
function! s:suite.before_each() abort
|
||||
call defx#custom#_init()
|
||||
endfunction
|
||||
|
||||
function! s:suite.custom_column() abort
|
||||
let custom = defx#custom#_get().column
|
||||
call defx#custom#column(
|
||||
\ 'mark', 'selected_icon', 'O')
|
||||
call s:assert.equals(custom.mark.selected_icon, 'O')
|
||||
endfunction
|
||||
|
||||
function! s:suite.custom_option() abort
|
||||
let custom = defx#custom#_get().option
|
||||
|
||||
call defx#custom#option('default', 'columns', 'mark')
|
||||
call s:assert.equals(custom.default.columns, 'mark')
|
||||
endfunction
|
||||
|
||||
function! s:suite.custom_source() abort
|
||||
let custom = defx#custom#_get().source
|
||||
|
||||
call defx#custom#source('file', 'root', 'mark')
|
||||
call s:assert.equals(custom.file.root, 'mark')
|
||||
endfunction
|
7
bundle/defx.nvim/test/conftest.py
Normal file
7
bundle/defx.nvim/test/conftest.py
Normal file
@ -0,0 +1,7 @@
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
BASE_DIR = Path(__file__).parent.parent
|
||||
sys.path.insert(0, str(BASE_DIR.joinpath('rplugin/python3')))
|
5
bundle/defx.nvim/test/requirements.txt
Normal file
5
bundle/defx.nvim/test/requirements.txt
Normal file
@ -0,0 +1,5 @@
|
||||
pynvim
|
||||
pytest
|
||||
flake8
|
||||
mypy
|
||||
vim-vint
|
17
bundle/defx.nvim/test/rplugin/python3/defx/test_defx.py
Normal file
17
bundle/defx.nvim/test/rplugin/python3/defx/test_defx.py
Normal file
@ -0,0 +1,17 @@
|
||||
import pytest
|
||||
|
||||
from defx.view import View
|
||||
from pynvim import Nvim
|
||||
from unittest.mock import create_autospec
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
|
||||
def test_view():
|
||||
vim = create_autospec(Nvim)
|
||||
vim.channel_id = 0
|
||||
vim.vars = {}
|
||||
vim.call.return_value = ''
|
||||
vim.current = MagicMock()
|
||||
|
||||
context = {}
|
||||
defx = View(vim, 0)
|
38
bundle/dein.vim/.github/ISSUE_TEMPLATE.md
vendored
Normal file
38
bundle/dein.vim/.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
**Warning: I will close the bug issue without the minimal init.vim and the reproduce ways.**
|
||||
|
||||
# Problems summary
|
||||
|
||||
|
||||
## Expected
|
||||
|
||||
|
||||
## Environment Information (Required!)
|
||||
|
||||
* dein.vim version(SHA1):
|
||||
|
||||
* OS:
|
||||
|
||||
* Vim/neovim version:
|
||||
|
||||
|
||||
## Provide a minimal .vimrc with less than 50 lines (Required!)
|
||||
|
||||
```vim
|
||||
" Your minimal .vimrc
|
||||
set runtimepath^=~/path/to/dein.nvim/
|
||||
call dein#begin(path)
|
||||
call dein#end()
|
||||
```
|
||||
|
||||
|
||||
## The reproduce ways from Vim starting (Required!)
|
||||
|
||||
1. foo
|
||||
2. bar
|
||||
3. baz
|
||||
|
||||
|
||||
## Screen shot (if possible)
|
||||
|
||||
|
||||
## Upload the log messages by `:redir` and `:message` (if errored)
|
4
bundle/dein.vim/.gitignore
vendored
Normal file
4
bundle/dein.vim/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
doc/tags
|
||||
.cache
|
||||
*.py[cod]
|
||||
vim-themis/
|
13
bundle/dein.vim/.travis.yml
Normal file
13
bundle/dein.vim/.travis.yml
Normal file
@ -0,0 +1,13 @@
|
||||
dist: xenial
|
||||
|
||||
language: python
|
||||
|
||||
python:
|
||||
- 3.7
|
||||
|
||||
install:
|
||||
- eval "$(curl -Ss https://raw.githubusercontent.com/neovim/bot-ci/master/scripts/travis-setup.sh) nightly-x64"
|
||||
- make install
|
||||
|
||||
script:
|
||||
- make --keep-going test
|
21
bundle/dein.vim/LICENSE
Normal file
21
bundle/dein.vim/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
License: MIT license
|
||||
AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
|
||||
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.
|
24
bundle/dein.vim/Makefile
Normal file
24
bundle/dein.vim/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
PATH := ./vim-themis/bin:$(PATH)
|
||||
export THEMIS_VIM := nvim
|
||||
export THEMIS_ARGS := -e -s --headless
|
||||
export THEMIS_HOME := ./vim-themis
|
||||
|
||||
|
||||
install: vim-themis
|
||||
pip install --upgrade -r test/requirements.txt
|
||||
|
||||
install-user: vim-themis
|
||||
pip install --user --upgrade -r test/requirements.txt
|
||||
|
||||
lint:
|
||||
vint --version
|
||||
vint autoload
|
||||
|
||||
test:
|
||||
themis --version
|
||||
themis test/
|
||||
|
||||
vim-themis:
|
||||
git clone https://github.com/thinca/vim-themis vim-themis
|
||||
|
||||
.PHONY: install lint test
|
138
bundle/dein.vim/README.md
Normal file
138
bundle/dein.vim/README.md
Normal file
@ -0,0 +1,138 @@
|
||||
# dein.vim
|
||||
|
||||
[![Join the chat at https://gitter.im/Shougo/dein.vim](https://badges.gitter.im/Shougo/dein.vim.svg)](https://gitter.im/Shougo/dein.vim?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://travis-ci.org/Shougo/dein.vim.svg?branch=master)](https://travis-ci.org/Shougo/dein.vim)
|
||||
|
||||
Dein.vim is a dark powered Vim/Neovim plugin manager.
|
||||
|
||||
<!-- vim-markdown-toc GFM -->
|
||||
|
||||
- [Requirements](#requirements)
|
||||
- [Quick start](#quick-start)
|
||||
- [Unix/Linux or Mac OS X](#unixlinux-or-mac-os-x)
|
||||
- [Features](#features)
|
||||
- [Future works (TODO)](#future-works-todo)
|
||||
- [Options](#options)
|
||||
|
||||
<!-- vim-markdown-toc -->
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
- Vim 8.0 or above or NeoVim.
|
||||
- "xcopy" command in $PATH (Windows)
|
||||
- "git" command in $PATH (if you want to install github or vim.org plugins)
|
||||
|
||||
Note: If you use Vim 7.4, please use dein.vim ver.1.5 instead.
|
||||
|
||||
If you need vim-plug like install UI, you can use dein-ui.vim.
|
||||
https://github.com/wsdjeg/dein-ui.vim
|
||||
|
||||
|
||||
## Quick start
|
||||
|
||||
**Note**: You must define the installation directory before to use dein. The
|
||||
directory that you will want to use depends on your usage.
|
||||
|
||||
For example, `~/.vim/bundles` or `~/.cache/dein` or `~/.local/share/dein`.
|
||||
dein.vim does not define a default installation directory.
|
||||
You must **not** set the installation directory as `~/.vim/plugin` or
|
||||
`~/.config/nvim/plugin`.
|
||||
|
||||
1. Run below script.
|
||||
|
||||
For Unix/Linux or Mac OS X
|
||||
|
||||
```sh
|
||||
curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh
|
||||
# For example, we just use `~/.cache/dein` as installation directory
|
||||
sh ./installer.sh ~/.cache/dein
|
||||
```
|
||||
|
||||
For Windows(PowerShell)
|
||||
|
||||
```powershell
|
||||
Invoke-WebRequest https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.ps1 -OutFile installer.ps1
|
||||
# Allow to run third-party script
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||
# For example, we just use `~/.cache/dein` as installation directory
|
||||
./installer.ps1 ~/.cache/dein
|
||||
```
|
||||
|
||||
2. Edit your .vimrc like this.
|
||||
|
||||
```vim
|
||||
if &compatible
|
||||
set nocompatible
|
||||
endif
|
||||
" Add the dein installation directory into runtimepath
|
||||
set runtimepath+=~/.cache/dein/repos/github.com/Shougo/dein.vim
|
||||
|
||||
if dein#load_state('~/.cache/dein')
|
||||
call dein#begin('~/.cache/dein')
|
||||
|
||||
call dein#add('~/.cache/dein/repos/github.com/Shougo/dein.vim')
|
||||
call dein#add('Shougo/deoplete.nvim')
|
||||
if !has('nvim')
|
||||
call dein#add('roxma/nvim-yarp')
|
||||
call dein#add('roxma/vim-hug-neovim-rpc')
|
||||
endif
|
||||
|
||||
call dein#end()
|
||||
call dein#save_state()
|
||||
endif
|
||||
|
||||
filetype plugin indent on
|
||||
syntax enable
|
||||
```
|
||||
|
||||
3. Open vim and install dein
|
||||
|
||||
```vim
|
||||
:call dein#install()
|
||||
```
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- Faster than NeoBundle
|
||||
|
||||
- Simple
|
||||
|
||||
- No commands, Functions only to simplify the implementation
|
||||
|
||||
- Easy to test and maintain
|
||||
|
||||
- No Vundle/NeoBundle compatibility
|
||||
|
||||
- neovim/Vim8 asynchronous API installation support
|
||||
|
||||
- Local plugin support
|
||||
|
||||
- Non github plugins support
|
||||
|
||||
- Go like clone directory name ex:"github.com/{user}/{repository}"
|
||||
|
||||
- Merge the plugins directories automatically to avoid long 'runtimepath'
|
||||
|
||||
|
||||
## Future works (TODO)
|
||||
|
||||
- Other types support (zip, svn, hg, ...)
|
||||
|
||||
- Metadata repository support
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
Some common options. For a more detailed list, run `:h dein-options`
|
||||
|
||||
| Option | Type | Description |
|
||||
| -------- | -------------------- | ------------------------------------------------------------------------------------- |
|
||||
| `name` | `string` | The name for a plugin. If it is omitted, the tail of the repository name will be used |
|
||||
| `rev` | `string` | The revision number or branch/tag name for the repo |
|
||||
| `build` | `string` | Command to run after the plugin is installed |
|
||||
| `on_ft` | `string` or `list` | Load a plugin for the current filetype |
|
||||
| `on_cmd` | `string` or `list` | Load the plugin for these commands |
|
||||
| `rtp` | `string` | You can use this option when the repository has the Vim plugin in a subdirectory |
|
||||
| `if` | `string` or `number` | If it is String, dein will eval it. |
|
||||
| `merged` | `number` | If set to 0, dein doesn't merge the plugin directory. |
|
204
bundle/dein.vim/autoload/dein.vim
Normal file
204
bundle/dein.vim/autoload/dein.vim
Normal file
@ -0,0 +1,204 @@
|
||||
"=============================================================================
|
||||
" FILE: dein.vim
|
||||
" AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
||||
" License: MIT license
|
||||
"=============================================================================
|
||||
|
||||
function! dein#_init() abort
|
||||
let g:dein#_cache_version = 150
|
||||
let g:dein#_merged_format =
|
||||
\ "{'repo': v:val.repo, 'rev': get(v:val, 'rev', '')}"
|
||||
let g:dein#_merged_length = 3
|
||||
let g:dein#name = ''
|
||||
let g:dein#plugin = {}
|
||||
let g:dein#_plugins = {}
|
||||
let g:dein#_base_path = ''
|
||||
let g:dein#_cache_path = ''
|
||||
let g:dein#_runtime_path = ''
|
||||
let g:dein#_hook_add = ''
|
||||
let g:dein#_ftplugin = {}
|
||||
let g:dein#_off1 = ''
|
||||
let g:dein#_off2 = ''
|
||||
let g:dein#_vimrcs = []
|
||||
let g:dein#_block_level = 0
|
||||
let g:dein#_event_plugins = {}
|
||||
let g:dein#_is_sudo = $SUDO_USER !=# '' && $USER !=# $SUDO_USER
|
||||
\ && $HOME !=# expand('~'.$USER)
|
||||
\ && $HOME ==# expand('~'.$SUDO_USER)
|
||||
let g:dein#_progname = fnamemodify(v:progname, ':r')
|
||||
let g:dein#_init_runtimepath = &runtimepath
|
||||
|
||||
augroup dein
|
||||
autocmd!
|
||||
autocmd FuncUndefined * call dein#autoload#_on_func(expand('<afile>'))
|
||||
autocmd BufRead *? call dein#autoload#_on_default_event('BufRead')
|
||||
autocmd BufNew,BufNewFile *? call dein#autoload#_on_default_event('BufNew')
|
||||
autocmd VimEnter *? call dein#autoload#_on_default_event('VimEnter')
|
||||
autocmd FileType *? call dein#autoload#_on_default_event('FileType')
|
||||
autocmd BufWritePost *.vim,*.toml,vimrc,.vimrc
|
||||
\ call dein#util#_check_vimrcs()
|
||||
augroup END
|
||||
augroup dein-events | augroup END
|
||||
|
||||
if !exists('##CmdUndefined') | return | endif
|
||||
autocmd dein CmdUndefined *
|
||||
\ call dein#autoload#_on_pre_cmd(expand('<afile>'))
|
||||
endfunction
|
||||
function! dein#load_cache_raw(vimrcs) abort
|
||||
let g:dein#_vimrcs = a:vimrcs
|
||||
let cache = get(g:, 'dein#cache_directory', g:dein#_base_path)
|
||||
\ .'/cache_' . g:dein#_progname
|
||||
let time = getftime(cache)
|
||||
if !empty(filter(map(copy(g:dein#_vimrcs),
|
||||
\ 'getftime(expand(v:val))'), 'time < v:val'))
|
||||
return [{}, {}]
|
||||
endif
|
||||
let list = readfile(cache)
|
||||
if len(list) != 3 || string(g:dein#_vimrcs) !=# list[0]
|
||||
return [{}, {}]
|
||||
endif
|
||||
return [json_decode(list[1]), json_decode(list[2])]
|
||||
endfunction
|
||||
function! dein#load_state(path, ...) abort
|
||||
if !exists('#dein')
|
||||
call dein#_init()
|
||||
endif
|
||||
let sourced = a:0 > 0 ? a:1 : has('vim_starting') &&
|
||||
\ (!exists('&loadplugins') || &loadplugins)
|
||||
if (g:dein#_is_sudo || !sourced) | return 1 | endif
|
||||
let g:dein#_base_path = expand(a:path)
|
||||
|
||||
let state = get(g:, 'dein#cache_directory', g:dein#_base_path)
|
||||
\ . '/state_' . g:dein#_progname . '.vim'
|
||||
if !filereadable(state) | return 1 | endif
|
||||
try
|
||||
execute 'source' fnameescape(state)
|
||||
catch
|
||||
if v:exception !=# 'Cache loading error'
|
||||
call dein#util#_error('Loading state error: ' . v:exception)
|
||||
endif
|
||||
call dein#clear_state()
|
||||
return 1
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! dein#tap(name) abort
|
||||
if !has_key(g:dein#_plugins, a:name)
|
||||
\ || !isdirectory(g:dein#_plugins[a:name].path) | return 0 | endif
|
||||
let g:dein#name = a:name
|
||||
let g:dein#plugin = g:dein#_plugins[a:name]
|
||||
return 1
|
||||
endfunction
|
||||
function! dein#is_sourced(name) abort
|
||||
return has_key(g:dein#_plugins, a:name)
|
||||
\ && isdirectory(g:dein#_plugins[a:name].path)
|
||||
\ && g:dein#_plugins[a:name].sourced
|
||||
endfunction
|
||||
function! dein#begin(path, ...) abort
|
||||
return dein#util#_begin(a:path, (empty(a:000) ? [] : a:1))
|
||||
endfunction
|
||||
function! dein#end() abort
|
||||
return dein#util#_end()
|
||||
endfunction
|
||||
function! dein#add(repo, ...) abort
|
||||
return dein#parse#_add(a:repo, get(a:000, 0, {}))
|
||||
endfunction
|
||||
function! dein#local(dir, ...) abort
|
||||
return dein#parse#_local(a:dir, get(a:000, 0, {}), get(a:000, 1, ['*']))
|
||||
endfunction
|
||||
function! dein#get(...) abort
|
||||
return empty(a:000) ? copy(g:dein#_plugins) : get(g:dein#_plugins, a:1, {})
|
||||
endfunction
|
||||
function! dein#source(...) abort
|
||||
return call('dein#autoload#_source', a:000)
|
||||
endfunction
|
||||
function! dein#check_install(...) abort
|
||||
return dein#util#_check_install(get(a:000, 0, []))
|
||||
endfunction
|
||||
function! dein#check_clean() abort
|
||||
return dein#util#_check_clean()
|
||||
endfunction
|
||||
function! dein#install(...) abort
|
||||
return dein#install#_update(get(a:000, 0, []),
|
||||
\ 'install', dein#install#_is_async())
|
||||
endfunction
|
||||
function! dein#update(...) abort
|
||||
return dein#install#_update(get(a:000, 0, []),
|
||||
\ 'update', dein#install#_is_async())
|
||||
endfunction
|
||||
function! dein#check_update(...) abort
|
||||
return dein#install#_update(get(a:000, 0, []),
|
||||
\ 'check_update', dein#install#_is_async())
|
||||
endfunction
|
||||
function! dein#direct_install(repo, ...) abort
|
||||
call dein#install#_direct_install(a:repo, (a:0 ? a:1 : {}))
|
||||
endfunction
|
||||
function! dein#get_direct_plugins_path() abort
|
||||
return get(g:, 'dein#cache_directory', g:dein#_base_path)
|
||||
\ .'/direct_install.vim'
|
||||
endfunction
|
||||
function! dein#reinstall(plugins) abort
|
||||
call dein#install#_reinstall(a:plugins)
|
||||
endfunction
|
||||
function! dein#rollback(date, ...) abort
|
||||
call dein#install#_rollback(a:date, (a:0 ? a:1 : []))
|
||||
endfunction
|
||||
function! dein#save_rollback(rollbackfile, ...) abort
|
||||
call dein#install#_save_rollback(a:rollbackfile, (a:0 ? a:1 : []))
|
||||
endfunction
|
||||
function! dein#load_rollback(rollbackfile, ...) abort
|
||||
call dein#install#_load_rollback(a:rollbackfile, (a:0 ? a:1 : []))
|
||||
endfunction
|
||||
function! dein#remote_plugins() abort
|
||||
return dein#install#_remote_plugins()
|
||||
endfunction
|
||||
function! dein#recache_runtimepath() abort
|
||||
call dein#install#_recache_runtimepath()
|
||||
endfunction
|
||||
function! dein#call_hook(hook_name, ...) abort
|
||||
return call('dein#util#_call_hook', [a:hook_name] + a:000)
|
||||
endfunction
|
||||
function! dein#check_lazy_plugins() abort
|
||||
return dein#util#_check_lazy_plugins()
|
||||
endfunction
|
||||
function! dein#load_toml(filename, ...) abort
|
||||
return dein#parse#_load_toml(a:filename, get(a:000, 0, {}))
|
||||
endfunction
|
||||
function! dein#load_dict(dict, ...) abort
|
||||
return dein#parse#_load_dict(a:dict, get(a:000, 0, {}))
|
||||
endfunction
|
||||
function! dein#get_log() abort
|
||||
return join(dein#install#_get_log(), "\n")
|
||||
endfunction
|
||||
function! dein#get_updates_log() abort
|
||||
return join(dein#install#_get_updates_log(), "\n")
|
||||
endfunction
|
||||
function! dein#get_progress() abort
|
||||
return dein#install#_get_progress()
|
||||
endfunction
|
||||
function! dein#each(command, ...) abort
|
||||
return dein#install#_each(a:command, (a:0 ? a:1 : []))
|
||||
endfunction
|
||||
function! dein#build(...) abort
|
||||
return dein#install#_build(a:0 ? a:1 : [])
|
||||
endfunction
|
||||
function! dein#plugins2toml(plugins) abort
|
||||
return dein#parse#_plugins2toml(a:plugins)
|
||||
endfunction
|
||||
function! dein#disable(names) abort
|
||||
return dein#util#_disable(a:names)
|
||||
endfunction
|
||||
function! dein#config(arg, ...) abort
|
||||
return type(a:arg) != v:t_list ?
|
||||
\ dein#util#_config(a:arg, get(a:000, 0, {})) :
|
||||
\ map(copy(a:arg), 'dein#util#_config(v:val, a:1)')
|
||||
endfunction
|
||||
function! dein#set_hook(plugins, hook_name, hook) abort
|
||||
return dein#util#_set_hook(a:plugins, a:hook_name, a:hook)
|
||||
endfunction
|
||||
function! dein#save_state() abort
|
||||
return dein#util#_save_state(has('vim_starting'))
|
||||
endfunction
|
||||
function! dein#clear_state() abort
|
||||
return dein#util#_clear_state()
|
||||
endfunction
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user