1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-23 13:50:05 +08:00
SpaceVim/config/plugins/defx.vim
2023-03-26 13:44:47 +08:00

341 lines
11 KiB
VimL

"=============================================================================
" defx.vim --- defx configuration
" Copyright (c) 2016-2023 Wang Shidong & Contributors
" Author: Wang Shidong < wsdjeg@outlook.com >
" URL: https://spacevim.org
" License: GPLv3
"=============================================================================
scriptencoding utf-8
let s:SYS = SpaceVim#api#import('system')
let s:FILE = SpaceVim#api#import('file')
let s:VCOP = SpaceVim#api#import('vim#compatible')
let s:WIN = SpaceVim#api#import('vim#window')
if g:spacevim_filetree_direction ==# 'right'
let s:direction = 'rightbelow'
else
let s:direction = 'leftabove'
endif
function! s:setcolum() abort
if g:_spacevim_enable_filetree_filetypeicon && !g:_spacevim_enable_filetree_gitstatus
return 'indent:icons:filename:type'
elseif !g:_spacevim_enable_filetree_filetypeicon && g:_spacevim_enable_filetree_gitstatus
return 'indent:git:filename:type'
elseif g:_spacevim_enable_filetree_filetypeicon && g:_spacevim_enable_filetree_gitstatus
return 'indent:git:icons:filename:type'
else
return 'mark:indent:icon:filename:type'
endif
endfunction
call defx#custom#option('_', {
\ 'columns': s:setcolum(),
\ 'winwidth': g:spacevim_sidebar_width,
\ 'split': 'vertical',
\ 'direction': s:direction,
\ 'show_ignored_files': g:_spacevim_filetree_show_hidden_files,
\ 'buffer_name': '',
\ 'toggle': 1,
\ 'resume': 1
\ })
call defx#custom#column('mark', {
\ 'readonly_icon': '',
\ 'selected_icon': '',
\ })
call defx#custom#column('icon', {
\ 'directory_icon': '▶',
\ 'opened_icon': '▼',
\ 'root_icon': ' ',
\ })
call defx#custom#column('filename', {
\ 'max_width': -90,
\ })
augroup vfinit
au!
autocmd FileType defx call s:defx_init()
" auto close last defx windows
autocmd BufEnter * nested if
\ (!has('vim_starting') && s:WIN.win_count() == 1 && g:_spacevim_autoclose_filetree
\ && &filetype ==# 'defx') |
\ call s:close_last_vimfiler_windows() | endif
augroup END
" in this function, we should check if shell terminal still exists,
" then close the terminal job before close vimfiler
function! s:close_last_vimfiler_windows() abort
call SpaceVim#layers#shell#close_terminal()
q
endfunction
function! s:defx_init()
setl nonumber
setl norelativenumber
setl listchars=
setl nofoldenable
setl foldmethod=manual
" disable this mappings
nnoremap <silent><buffer> <3-LeftMouse> <Nop>
nnoremap <silent><buffer> <4-LeftMouse> <Nop>
nnoremap <silent><buffer> <LeftMouse> <LeftMouse><Home>
silent! nunmap <buffer> <Space>
silent! nunmap <buffer> <C-l>
silent! nunmap <buffer> <C-j>
silent! nunmap <buffer> E
silent! nunmap <buffer> gr
silent! nunmap <buffer> gf
silent! nunmap <buffer> -
silent! nunmap <buffer> s
" nnoremap <silent><buffer><expr> st vimfiler#do_action('tabswitch')
" nnoremap <silent><buffer> yY :<C-u>call <SID>copy_to_system_clipboard()<CR>
nnoremap <silent><buffer><expr> '
\ defx#do_action('toggle_select') . 'j'
" TODO: we need an action to clear all selections
nnoremap <silent><buffer><expr> V
\ defx#do_action('toggle_select_all')
" nmap <buffer> v <Plug>(vimfiler_quick_look)
" nmap <buffer> p <Plug>(vimfiler_preview_file)
" nmap <buffer> i <Plug>(vimfiler_switch_to_history_directory)
" Define mappings
nnoremap <silent><buffer><expr> gx
\ defx#do_action('execute_system')
nnoremap <silent><buffer><expr> c
\ defx#do_action('copy')
nnoremap <silent><buffer><expr> q
\ defx#do_action('quit')
nnoremap <silent><buffer><expr> m
\ defx#do_action('move')
nnoremap <silent><buffer><expr> P
\ defx#do_action('paste')
nnoremap <silent><buffer><expr> h defx#do_action('call', g:defx_config_sid . 'DefxSmartH')
nnoremap <silent><buffer><expr> <Left> defx#do_action('call', g:defx_config_sid . 'DefxSmartH')
nnoremap <silent><buffer><expr> l defx#do_action('call', g:defx_config_sid . 'DefxSmartL')
nnoremap <silent><buffer><expr> <Right> defx#do_action('call', g:defx_config_sid . 'DefxSmartL')
nnoremap <silent><buffer><expr> o defx#do_action('call', g:defx_config_sid . 'DefxSmartL')
nnoremap <silent><buffer><expr> <Cr>
\ defx#is_directory() ?
\ defx#do_action('open_directory') : defx#do_action('drop')
nnoremap <silent><buffer><expr> <2-LeftMouse>
\ defx#is_directory() ?
\ (
\ defx#is_opened_tree() ?
\ defx#do_action('close_tree') :
\ defx#do_action('open_tree')
\ )
\ : defx#do_action('drop')
nnoremap <silent><buffer><expr> sg
\ defx#do_action('drop', 'vsplit')
nnoremap <silent><buffer><expr> sv
\ defx#do_action('drop', 'split')
nnoremap <silent><buffer><expr> st
\ defx#do_action('drop', 'tabedit')
nnoremap <silent><buffer><expr> p defx#do_action('call', g:defx_config_sid . 'DefxPreview')
nnoremap <silent><buffer><expr> K
\ defx#do_action('new_directory')
nnoremap <silent><buffer><expr> N
\ defx#do_action('new_file')
nnoremap <silent><buffer><expr> d
\ defx#do_action('remove')
nnoremap <silent><buffer><expr> r
\ defx#do_action('rename')
nnoremap <silent><buffer><expr> yy defx#do_action('call', g:defx_config_sid . 'DefxYarkPath')
nnoremap <silent><buffer><expr> yY defx#do_action('call', g:defx_config_sid . 'DefxCopyFile')
nnoremap <silent><buffer><expr> P defx#do_action('call', g:defx_config_sid . 'DefxPasteFile')
nnoremap <silent><buffer><expr> .
\ defx#do_action('toggle_ignored_files')
nnoremap <silent><buffer><expr> <C-f>
\ defx#do_action('change_filtered_files')
nnoremap <silent><buffer><expr> ~
\ defx#do_action('cd')
nnoremap <silent><buffer><expr> j
\ line('.') == line('$') ? 'gg' : 'j'
nnoremap <silent><buffer><expr> k
\ line('.') == 1 ? 'G' : 'k'
nnoremap <silent><buffer><expr> <C-r>
\ defx#do_action('redraw')
nnoremap <silent><buffer><expr> <C-g>
\ defx#do_action('print')
nnoremap <silent><buffer> <Home> :call cursor(2, 1)<cr>
nnoremap <silent><buffer> <End> :call cursor(line('$'), 1)<cr>
nnoremap <silent><buffer><expr> <C-Home>
\ defx#do_action('cd', SpaceVim#plugins#projectmanager#current_root())
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)
doautocmd User DefxInit
endf
" in this function we should vim-choosewin if possible
function! s:DefxSmartL(_)
if defx#is_directory()
call defx#call_action('open_tree')
normal! j
else
let filepath = defx#get_candidate()['action__path']
if tabpagewinnr(tabpagenr(), '$') >= 3 " if there are more than 2 normal windows
if exists(':ChooseWin') == 2
ChooseWin
else
let input = input('ChooseWin No./Cancel(n): ')
if input ==# 'n' | return | endif
if input == winnr() | return | endif
exec input . 'wincmd w'
endif
exec 'e' filepath
else
exec 'wincmd w'
exec 'e' filepath
endif
endif
endfunction
function! s:DefxPreview(_) abort
if s:preview_windows_opened()
pclose
else
if !defx#is_directory()
let filepath = defx#get_candidate()['action__path']
exe 'topleft pedit ' . filepath
endif
endif
endfunction
fun! s:preview_windows_opened()
for nr in range(1, winnr('$'))
if getwinvar(nr, "&pvw") == 1
" found a preview
return 1
endif
endfor
return 0
endfun
function! s:DefxSmartH(_)
" if cursor line is first line, or in empty dir
if line('.') ==# 1 || line('$') ==# 1
return defx#call_action('cd', ['..'])
endif
" candidate is opend tree?
if defx#is_opened_tree()
return defx#call_action('close_tree')
endif
" parent is root?
let s:candidate = defx#get_candidate()
let s:parent = fnamemodify(s:candidate['action__path'], s:candidate['is_directory'] ? ':p:h:h' : ':p:h')
let sep = s:SYS.isWindows ? '\\' : '/'
if s:trim_right(s:parent, sep) == s:trim_right(b:defx.paths[0], sep)
return defx#call_action('cd', ['..'])
endif
" move to parent.
call defx#call_action('search', s:parent)
" if you want close_tree immediately, enable below line.
call defx#call_action('close_tree')
endfunction
function! s:DefxYarkPath(_) abort
let candidate = defx#get_candidate()
let @+ = candidate['action__path']
echo 'yanked path: ' . @+
endfunction
let s:copyed_file_path = ''
function! s:DefxCopyFile(_) abort
if !executable('xclip-copyfile') && !s:SYS.isWindows
echohl WarningMsg
echo 'you need to have xclip-copyfile in your PATH'
echohl NONE
return
endif
let candidate = defx#get_candidate()
let filename = candidate['action__path']
if executable('xclip-copyfile')
call s:VCOP.systemlist(['xclip-copyfile', filename])
if v:shell_error
echohl WarningMsg
echo 'failed to copy file!'
echohl NONE
else
echo 'Yanked:' . filename
endif
elseif s:SYS.isWindows
let s:copyed_file_path = filename
echo 'Yanked:' . filename
endif
endfunction
function! s:DefxPasteFile(_) abort
if !executable('xclip-pastefile') && !s:SYS.isWindows
echohl WarningMsg
echo 'you need to have xclip-copyfile in your PATH'
echohl NONE
return
endif
let candidate = defx#get_candidate()
let path = candidate['action__path']
if !isdirectory(path)
let path = fnamemodify(path, ':p:h')
endif
" If you have xclip-pastefile in your PATH.
" this command will be run on action directory
" support paste file which is copied outside of vim.
if executable('xclip-pastefile')
let old_wd = getcwd()
if old_wd == path
call s:VCOP.systemlist(['xclip-pastefile'])
else
noautocmd exe 'cd' fnameescape(path)
call s:VCOP.systemlist(['xclip-pastefile'])
noautocmd exe 'cd' fnameescape(old_wd)
endif
return
endif
if s:SYS.isWindows && !empty(s:copyed_file_path)
" in windows, use copy command for paste file.
let destination = path . s:FILE.separator . fnamemodify(s:copyed_file_path, ':t')
let cmd = 'cmd /c copy ' . shellescape(s:copyed_file_path) . ' ' . shellescape(destination)
call s:VCOP.systemlist(cmd)
elseif !s:SYS.isWindows && !empty(s:copyed_file_path)
" in Linux or MacOS, use cp command for paste file.
let destination = path . s:FILE.separator . fnamemodify(s:copyed_file_path, ':t')
let cmd = 'cp -r ' . shellescape(s:copyed_file_path) . ' ' . shellescape(destination)
call s:VCOP.systemlist(cmd)
endif
if v:shell_error
echohl WarningMsg
echo 'failed to paste file!'
echohl NONE
else
echo 'Pasted:' . destination
endif
endfunction
function! s:trim_right(str, trim)
return substitute(a:str, printf('%s$', a:trim), '', 'g')
endfunction
function! s:SID_PREFIX() abort
return matchstr(expand('<sfile>'),
\ '<SNR>\d\+_\zeSID_PREFIX$')
endfunction
let g:defx_config_sid = s:SID_PREFIX()