VIM - 文件瀏覽插件 defx 配置


安裝

vim8要求安裝pynvim
pip install  pynvim  msgpack-python
用 vim 包管理工具安裝 defx
call plug#begin('~/.vim/plugged')
    Plug 'git://github.com/Shougo/defx.nvim.git'
    Plug 'git://github.com/roxma/nvim-yarp.git'
    Plug 'git://github.com/roxma/vim-hug-neovim-rpc.git'
    Plug 'git://github.com/kristijanhusak/defx-icons.git'
call plug#end()
安裝些字體美化 defx 樹圖標,不知道要哪個,把有的 nerd 字體都裝了
$ sudo pacman -S nerd-fonts-roboto-mono  nerd-fonts-terminus ttf-nerd-fonts-symbols-mono nerd-fonts-terminus

配置

安裝以后,defx 默認是沒有多少快捷鍵配置的, 所以根據defx的幫助文檔,把默認的快捷鍵設置代碼寫到 .vimrc 里,經過一些修改,目前我的配置文件是這樣的:
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
""""" Defx配置
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
    let g:defx_icons_enable_syntax_highlight = 1
    " 開關快捷鍵,【-search=`expand('%:p')`】表示打開defx樹后,光標自動放在當前buffer上
    nmap <silent> ff :Defx  -search=`expand('%:p')` -toggle <cr>


    "打開vim自動打開defx
    func! ArgFunc() abort
        let s:arg = argv(0)
        if isdirectory(s:arg)
            return s:arg
        else
            return fnamemodify(s:arg, ':h')
        endif
    endfunc
    "autocmd VimEnter * Defx `ArgFunc()` -no-focus -search=`expand('%:p')`

    " 設置defx樹的一些格式
    call defx#custom#option('_', {
          \ 'columns': 'icons:indent:filename:size',
          \ 'winwidth': 30,
          \ 'split': 'vertical',
          \ 'direction': 'botright',
          \ 'show_ignored_files': 0,
          \ 'resume': 1,
          \ })

    " Exit Vim if defxTree is the only window left.
    autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:defx') |
    \ quit | endif

    " 在打開多個tab的情況下,當前tab里只有一個buffer和nerd樹,當關閉buffer時,自動關閉當前標簽頁的nerd樹
    autocmd BufEnter * if tabpagenr('$') > 1 && winnr('$') == 1 && exists('b:defx') |
    \ tabclose | endif

    " 在新tab頁打開文件
    func! MyT(context) abort
        if isdirectory(get(a:context.targets, 0)) == 0
            call defx#call_action('drop', 'tabe')
        endif
    endfunc


    " 給cd快捷鍵寫的
    func! MyCD(context) abort
        if isdirectory(get(a:context.targets, 0))
            execute 'cd' . get(a:context.targets, 0)
        else
            execute 'cd' . fnamemodify(defx#get_candidate().action__path, ':h')
        endif
    endfunc

    " 給 ter 快捷鍵寫的
    func! MyTER(context) abort
        call MyCD(a:context)
        shell
    endfunc

    " 給復制或剪切選中的文件或目錄寫的
    func! Mycopy_cut(mode) abort
        let s:Path = defx#get_selected_candidates()
        let s:Len = len(s:Path)
        let s:Path_list = []
        let s:counter = 0
        while s:counter < s:Len
            let s:P = s:Path[s:counter].action__path
            call add(s:Path_list, s:P)
            let s:counter = s:counter + 1
        endwhile
        let s:MyCMD = ['!~/.vim/cut_copy.py'] + s:Path_list + [a:mode]
        execute join(s:MyCMD)
        endfunc

    " 給粘貼文件寫的
    func! Mypaste() abort
        execute join(['!~/.vim/paste.py', defx#get_candidate().action__path])
    endfunc

    " 所有快捷鍵在這里設置
    autocmd FileType defx call s:defx_my_settings()
    function! s:defx_my_settings() abort
        nnoremap <silent><buffer><expr> <CR>     defx#do_action('drop')
        nnoremap <silent><buffer><expr> t        defx#do_action('call', 'MyT')
        nnoremap <silent><buffer><expr> yy       defx#do_action('yank_path')
        nnoremap <silent><buffer><expr> dd       defx#do_action('remove_trash')
        nnoremap <silent><buffer><expr> cc        defx#do_action('copy')
        nnoremap <silent><buffer><expr> mm        defx#do_action('move')
        nnoremap <silent><buffer><expr> pp        defx#do_action('paste')
        nnoremap <silent><buffer><expr> CC       Mycopy_cut('copy') . defx#do_action('clear_select_all')
        nnoremap <silent><buffer><expr> MM       Mycopy_cut('cut') . defx#do_action('clear_select_all')
        nnoremap <silent><buffer><expr> PP       Mypaste()
        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> R        defx#do_action('rename')
        nnoremap <silent><buffer><expr> j        line('.') == line('$') ? 'gg' : 'j'
        nnoremap <silent><buffer><expr> k        line('.') == 1 ? 'G' : 'k'
        nnoremap <silent><buffer><expr> h    
                    \ defx#is_opened_tree() ? 
                    \ defx#do_action('close_tree', defx#get_candidate().action__path) : 
                    \ defx#do_action('search',  fnamemodify(defx#get_candidate().action__path, ':h'))
        nnoremap <silent><buffer><expr> l        defx#do_action('open_tree')
       nnoremap <silent><buffer><expr> o        defx#do_action('open_directory')
        nnoremap <silent><buffer><expr> u        defx#do_action('cd', ['..'])
        nnoremap <silent><buffer><expr> E        defx#do_action('open', 'vsplit')
        nnoremap <silent><buffer><expr> P        defx#do_action('preview')
        "nnoremap <silent><buffer><expr> d        defx#do_action('new_directory')
        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> !        defx#do_action('execute_command')
        nnoremap <silent><buffer><expr> x        defx#do_action('execute_system')
        nnoremap <silent><buffer><expr> cd       defx#do_action('call', 'MyCD')
        nnoremap <silent><buffer><expr> ~        defx#do_action('cd')
        nnoremap <silent><buffer><expr> ter      defx#do_action('call', 'MyTER')
        nnoremap <silent><buffer><expr> .        defx#do_action('toggle_ignored_files')
        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> m        defx#do_action('clear_select_all')
        nnoremap <silent><buffer><expr> r        defx#do_action('redraw')
        nnoremap <silent><buffer><expr> pr       defx#do_action('print')
        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)
    nnoremap <silent><buffer><expr> <2-LeftMouse>
    endfunction
修改了幾處默認快捷鍵:
h鍵:改為當光標在某個文件上時,按鍵后光標移動到其父目錄;當光標在目錄上時,若目錄在打開狀態,則關閉目錄,否則光標移動到其父目錄,一直到 defxtree的根目錄
u鍵:改為進入到defxtree根目錄的父目錄l鍵:改為只能打開或關閉目錄
o鍵:改為只能進入目錄,有點跟u鍵相反,按u鍵后,按o鍵可以恢復
cd鍵:把vim的工作目錄切換到光標所在的目錄,如果光標在文件上則切換到其父目錄
增加ter鍵:當光標在目錄上時,按ter 可以在此目錄上打開一個shell外殼,當光標在文件則在其父目錄打開
t鍵:在新標簽頁打開光標處的文件, 這里打開總是很慢,原因是有快捷鍵ter,這里在等待確認是否還會輸入er,可以改名解決,下面的space鍵也類似,可改為<space><space>
dd鍵:改成刪除文件至系統回收站,需要安裝send2trash默認有文件移動mm,復制cc,粘貼pp,因為有時用到不同的終端窗口之間移動文件,所以就新增加了以下幾個鍵:
CC鍵:復制選中的文件和目錄
MM鍵:剪切選中的文件和目錄
PP鍵:粘貼上述的文件和目錄到光標所在的位置,光標在目錄上則粘貼到此目錄內,光標在文件上,則粘貼到文件所在的目錄
其實,復制和粘貼就是調用用 ~/.vim/cut_copy.py把選中的文件和目錄的路徑寫到 ~/.vim/tmp_clipboard.txt 里,並標明要復制還是粘貼。
按PP鍵的時候才用 調用~/.vim/paste.py ,把文件和目錄移動到相應的位置。
這三個鍵要用到下面的兩個文件,要放到~/.vim 目錄下。
要增加權限
chmod +x  cut_copy.py   paste.py 
 
至此,defx就配置成比較順手的了,附上用到的兩個文件cut_copy.py
#!/usr/bin/python3

"""
調用方式: ~/.vim/cut_copy.py  f1 f2 d1/ d2/ cut or copy
把相關的文件/目錄的絕對路徑寫到文件里保存
最后一個參數代表粘貼的時候是復制copy還是移動mv
"""

import sys


argv = sys.argv
with open('~/.vim/tmp_clipboard.txt', 'w') as f:
    f.write('\n'.join(argv[1:]))
paste.py
#!/usr/bin/python3

"""
需要粘貼的文件路徑已經存放在文件~/.vim/tmp_clipboard.txt
文件最后一行表示要cut還是copy, 。
調用方法: ~/.vim/paste.py dst
"""
import os
import sys
import shutil
def clean_dst(one_path, dst): """  當dst是一個目錄時,要把剪貼板上的文件和目錄都放到dst下面;  當dst是一個文件時,要把剪貼板上的文件和目錄都放到其父目錄下。  函數的功能就是清理dst,使得粘貼的時候不會發生文件存在異常。  """ dst = os.path.dirname(dst) if os.path.isfile(dst) else dst path = os.path.join(dst, os.path.basename(one_path)) if path == one_path: return None if os.path.exists(path): try: os.remove(path) except: shutil.rmtree(path) return path def paste(): """  完成粘貼任務,如果同名目標已經存在,就覆蓋  """ dst = sys.argv[1].strip() FILE = "~/.vim/tmp_clipboard.txt" if os.path.exists(FILE): with open(FILE) as f: files = f.readlines() # 查看復制還是剪切 CUT = True if files[-1].strip() == 'cut' else False for f in files[: -1]: f = f.strip() if not f: continue dst_f = clean_dst(f, dst) if dst_f is None: # 粘貼到原位置 continue if CUT: shutil.move(f, dst_f) else: try: shutil.copy(f, dst_f) except: shutil.copytree(f, dst_f) assert len(sys.argv) == 2, '輸入dst' paste()
 
參考:
https://zhuanlan.zhihu.com/p/358828723


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM