"============================================================================= " 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 <3-LeftMouse> nnoremap <4-LeftMouse> nnoremap silent! nunmap silent! nunmap silent! nunmap silent! nunmap E silent! nunmap gr silent! nunmap gf silent! nunmap - silent! nunmap s " nnoremap st vimfiler#do_action('tabswitch') " nnoremap yY :call copy_to_system_clipboard() nnoremap ' \ defx#do_action('toggle_select') . 'j' " TODO: we need an action to clear all selections nnoremap V \ defx#do_action('toggle_select_all') " nmap v (vimfiler_quick_look) " nmap p (vimfiler_preview_file) " nmap i (vimfiler_switch_to_history_directory) " Define mappings nnoremap gx \ defx#do_action('execute_system') nnoremap c \ defx#do_action('copy') nnoremap q \ defx#do_action('quit') nnoremap m \ defx#do_action('move') nnoremap P \ defx#do_action('paste') nnoremap h defx#do_action('call', g:defx_config_sid . 'DefxSmartH') nnoremap defx#do_action('call', g:defx_config_sid . 'DefxSmartH') nnoremap l defx#do_action('call', g:defx_config_sid . 'DefxSmartL') nnoremap defx#do_action('call', g:defx_config_sid . 'DefxSmartL') nnoremap o defx#do_action('call', g:defx_config_sid . 'DefxSmartL') nnoremap \ defx#is_directory() ? \ defx#do_action('open_directory') : defx#do_action('drop') nnoremap <2-LeftMouse> \ defx#is_directory() ? \ ( \ defx#is_opened_tree() ? \ defx#do_action('close_tree') : \ defx#do_action('open_tree') \ ) \ : defx#do_action('drop') nnoremap sg \ defx#do_action('drop', 'vsplit') nnoremap sv \ defx#do_action('drop', 'split') nnoremap st \ defx#do_action('drop', 'tabedit') nnoremap p defx#do_action('call', g:defx_config_sid . 'DefxPreview') nnoremap K \ defx#do_action('new_directory') nnoremap N \ defx#do_action('new_file') nnoremap d \ defx#do_action('remove') nnoremap r \ defx#do_action('rename') nnoremap yy defx#do_action('call', g:defx_config_sid . 'DefxYarkPath') nnoremap yY defx#do_action('call', g:defx_config_sid . 'DefxCopyFile') nnoremap P defx#do_action('call', g:defx_config_sid . 'DefxPasteFile') nnoremap . \ defx#do_action('toggle_ignored_files') nnoremap \ defx#do_action('change_filtered_files') nnoremap ~ \ defx#do_action('cd') nnoremap j \ line('.') == line('$') ? 'gg' : 'j' nnoremap k \ line('.') == 1 ? 'G' : 'k' nnoremap \ defx#do_action('redraw') nnoremap \ defx#do_action('print') nnoremap :call cursor(2, 1) nnoremap :call cursor(line('$'), 1) nnoremap \ defx#do_action('cd', SpaceVim#plugins#projectmanager#current_root()) nnoremap > defx#do_action('resize', \ defx#get_context().winwidth + 10) nnoremap < 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(''), \ '\d\+_\zeSID_PREFIX$') endfunction let g:defx_config_sid = s:SID_PREFIX()