1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-23 07:00:04 +08:00

Add: A better way to use find with vim (#1777)

This commit is contained in:
Wang Shidong 2018-10-03 21:47:43 +08:00 committed by GitHub
parent c4be5b44d4
commit 27200eee8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 281 additions and 8 deletions

View File

@ -167,6 +167,7 @@ function! SpaceVim#layers#core#config() abort
\ . string(s:_function('s:delete_current_buffer_file')) . ', [])',
\ 'delete-current-buffer-file', 1)
call SpaceVim#mapping#space#def('nnoremap', ['f', 'F'], 'normal! gf', 'open-cursor-file', 1)
call SpaceVim#mapping#space#def('nnoremap', ['f', '/'], 'call SpaceVim#plugins#find#open()', 'find-files', 1)
if g:spacevim_filemanager ==# 'vimfiler'
call SpaceVim#mapping#space#def('nnoremap', ['f', 't'], 'VimFiler', 'toggle_file_tree', 1)
call SpaceVim#mapping#space#def('nnoremap', ['f', 'T'], 'VimFiler -no-toggle', 'show_file_tree', 1)

View File

@ -0,0 +1,256 @@
"=============================================================================
" find.vim --- vim plugin for find
" Copyright (c) 2016-2017 Wang Shidong & Contributors
" Author: Wang Shidong
" URL: https://spacevim.org
" License: GPLv3
"=============================================================================
" Loadding SpaceVim api {{{
scriptencoding utf-8
let s:MPT = SpaceVim#api#import('prompt')
let s:JOB = SpaceVim#api#import('job')
" let s:SYS = SpaceVim#api#import('system')
" let s:BUFFER = SpaceVim#api#import('vim#buffer')
" let s:LIST = SpaceVim#api#import('data#list')
"}}}
let s:MPT._prompt.mpt = ' find '
let s:options_en = {
\ '-amin' : 'File was last accessed n minutes ago.',
\ '-anewer' : 'File was last accessed more recently than file was modified.',
\ '-atime' : 'File was last accessed n*24 hours ago.',
\ '-cmin' : "File's status was last changed n minutes ago.",
\ '-cnewer' : "File's status was last changed more recently than file was modified.",
\ '-ctime' : "File's status was last changed n*24 hours ago.",
\ '-daystart' : 'Measure times from the beginning of today rather than from 24 hours ago.',
\ '-depth' : "Process each directory's contents before the directory itself.",
\ '-exec' : 'Execute command',
\ '-false' : 'make find command return false',
\ '-fls' : 'True; like -ls but write to file like -fprint.',
\ '-follow' : 'a diagnostic message is issued when find encounters a loop of symbolic links.',
\ '-fprint' : 'True; print the full file name into file file.',
\ '-fprintf' : 'True; like -printf but write to file like -fprint.',
\ '-fstype' : 'Only list files or directorys with specific filesysten type',
\ '-gid' : 'Only list files with specific group ID.',
\ '-group' : 'Only list files with specific group name.',
\ '-help' : 'show help info',
\ '-ilname' : '此参数的效果和指定“-lname”参数类似但忽略字符大小写的差别',
\ '-iname' : '指定字符串作为寻找符号连接的范本样式',
\ '-inum' : '查找符合指定的inode编号的文件或目录',
\ '-ipath' : '此参数的效果和指定“-path”参数类似但忽略字符大小写的差别',
\ '-iregex' : '此参数的效果和指定“-regexe”参数类似但忽略字符大小写的差别',
\ '-links' : '查找符合指定的硬连接数目的文件或目录',
\ '-ls' : 'If find command return True, then send all files names to stdout',
\ '-maxdepth' : 'specific the max path depath',
\ '-mindepth' : 'specific the min path depath',
\ '-mmin' : '查找在指定时间曾被更改过的文件或目录,单位以分钟计算',
\ '-mount' : '此参数的效果和指定“-xdev”相同',
\ '-mtime' : '查找在指定时间曾被更改过的文件或目录单位以24小时计算',
\ '-name' : '指定字符串作为寻找文件或目录的范本样式',
\ '-newer' : '查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录',
\ '-nogroup' : '找出不属于本地主机群组识别码的文件或目录',
\ '-noleaf' : '不去考虑目录至少需拥有两个硬连接存在',
\ '-nouser' : '找出不属于本地主机用户识别码的文件或目录',
\ '-ok' : '此参数的效果和指定“-exec”类似但在执行指令之前会先询问用户若回答“y”或“Y”则放弃执行命令',
\ '-path' : '指定字符串作为寻找目录的范本样式',
\ '-perm' : '查找符合指定的权限数值的文件或目录',
\ '-print' : '假设find指令的回传值为Ture就将文件或目录名称列出到标准输出。格式为每列一个名称每个名称前皆有“./”字符串',
\ '-print0' : '假设find指令的回传值为Ture就将文件或目录名称列出到标准输出。格式为全部的名称皆在同一行',
\ '-printf' : '假设find指令的回传值为Ture就将文件或目录名称列出到标准输出。格式可以自行指定',
\ '-prune' : '不寻找字符串作为寻找文件或目录的范本样式',
\ '-regex' : '指定字符串作为寻找文件或目录的范本样式',
\ '-size' : '查找符合指定的文件大小的文件',
\ '-true' : '将find指令的回传值皆设为True',
\ '-type' : '只寻找符合指定的文件类型的文件',
\ '-uid' : '查找符合指定的用户识别码的文件或目录',
\ '-used' : '查找文件或目录被更改之后在指定时间曾被存取过的文件或目录,单位以日计算',
\ '-user' : '查找符和指定的拥有者名称的文件或目录',
\ '-version' : 'Show version',
\ '-xdev' : '将范围局限在先行的文件系统中',
\ '-xtype' : '此参数的效果和指定“-type”参数类似差别在于它针对符号连接检查'
\ }
let s:options = {
\ '-amin' : '查找在指定时间曾被存取过的文件或目录,单位以分钟计算',
\ '-anewer' : '查找其存取时间较指定文件或目录的存取时间更接近现在的文件或目录',
\ '-atime' : '查找在指定时间曾被存取过的文件或目录单位以24小时计算',
\ '-cmin' : '查找在指定时间之时被更改过的文件或目录',
\ '-cnewer' : '查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录',
\ '-ctime' : '查找在指定时间之时被更改的文件或目录单位以24小时计算',
\ '-daystart' : '从本日开始计算时间',
\ '-depth' : '从指定目录下最深层的子目录开始查找',
\ '-exec' : '假设find指令的回传值为True就执行该指令',
\ '-false' : '将find指令的回传值皆设为False',
\ '-fls' : '此参数的效果和指定“-ls”参数类似但会把结果保存为指定的列表文件',
\ '-follow' : '排除符号连接',
\ '-fprint' : '此参数的效果和指定“-print”参数类似但会把结果保存成指定的列表文件',
\ '-fprintf' : '此参数的效果和指定“-printf”参数类似但会把结果保存成指定的列表文件',
\ '-fstype' : '只寻找该文件系统类型下的文件或目录',
\ '-gid' : '查找符合指定之群组识别码的文件或目录',
\ '-group' : '查找符合指定之群组名称的文件或目录',
\ '-help' : '——help在线帮助',
\ '-ilname' : '此参数的效果和指定“-lname”参数类似但忽略字符大小写的差别',
\ '-iname' : '指定字符串作为寻找符号连接的范本样式',
\ '-inum' : '查找符合指定的inode编号的文件或目录',
\ '-ipath' : '此参数的效果和指定“-path”参数类似但忽略字符大小写的差别',
\ '-iregex' : '此参数的效果和指定“-regexe”参数类似但忽略字符大小写的差别',
\ '-links' : '查找符合指定的硬连接数目的文件或目录',
\ '-ls' : '假设find指令的回传值为Ture就将文件或目录名称列出到标准输出',
\ '-maxdepth' : '设置最大目录层级',
\ '-mindepth' : 'Do not apply any tests or actions at levels less than n.',
\ '-mmin' : '查找在指定时间曾被更改过的文件或目录,单位以分钟计算',
\ '-mount' : '此参数的效果和指定“-xdev”相同',
\ '-mtime' : '查找在指定时间曾被更改过的文件或目录单位以24小时计算',
\ '-name' : '指定字符串作为寻找文件或目录的范本样式',
\ '-newer' : '查找其更改时间较指定文件或目录的更改时间更接近现在的文件或目录',
\ '-nogroup' : '找出不属于本地主机群组识别码的文件或目录',
\ '-noleaf' : '不去考虑目录至少需拥有两个硬连接存在',
\ '-nouser' : '找出不属于本地主机用户识别码的文件或目录',
\ '-ok' : '此参数的效果和指定“-exec”类似但在执行指令之前会先询问用户若回答“y”或“Y”则放弃执行命令',
\ '-path' : '指定字符串作为寻找目录的范本样式',
\ '-perm' : '查找符合指定的权限数值的文件或目录',
\ '-print' : '假设find指令的回传值为Ture就将文件或目录名称列出到标准输出。格式为每列一个名称每个名称前皆有“./”字符串',
\ '-print0' : '假设find指令的回传值为Ture就将文件或目录名称列出到标准输出。格式为全部的名称皆在同一行',
\ '-printf' : '假设find指令的回传值为Ture就将文件或目录名称列出到标准输出。格式可以自行指定',
\ '-prune' : '不寻找字符串作为寻找文件或目录的范本样式',
\ '-regex' : '指定字符串作为寻找文件或目录的范本样式',
\ '-size' : '查找符合指定的文件大小的文件',
\ '-true' : '将find指令的回传值皆设为True',
\ '-type' : '只寻找符合指定的文件类型的文件',
\ '-uid' : '查找符合指定的用户识别码的文件或目录',
\ '-used' : '查找文件或目录被更改之后在指定时间曾被存取过的文件或目录,单位以日计算',
\ '-user' : '查找符和指定的拥有者名称的文件或目录',
\ '-version' : '显示版本信息',
\ '-xdev' : '将范围局限在先行的文件系统中',
\ '-xtype' : '此参数的效果和指定“-type”参数类似差别在于它针对符号连接检查'
\ }
let s:second_option_en = {
\ '-type' :
\ {
\ 'f' : 'regular file',
\ 'l' : 'symbolic link',
\ 'd' : 'directory',
\ 'c' : 'character (unbuffered) special',
\ 'b' : 'block (buffered) special',
\ 's' : 'socket',
\ 'p' : 'named pipe (FIFO)',
\ },
\ }
let s:second_option = {
\ '-type' :
\ {
\ 'f' : '普通文件',
\ 'l' : '符号连接',
\ 'd' : '目录',
\ 'c' : '字符设备',
\ 'b' : '块设备',
\ 's' : '套接字',
\ 'p' : 'Fifo',
\ },
\ }
let s:finded_files = []
function! s:start_find() abort
let cmd = 'find -not -iwholename "*.git*" ' . s:MPT._prompt.begin . s:MPT._prompt.cursor . s:MPT._prompt.end
call s:MPT._clear_prompt()
let s:MPT._quit = 1
let line = getline('.')
noautocmd q
redraw!
call s:JOB.start(cmd,
\ {
\ 'on_stdout' : function('s:find_on_stdout'),
\ 'on_exit' : function('s:find_on_exit'),
\ }
\ )
endfunction
function! s:find_on_stdout(id, data, event) abort
let s:finded_files += a:data
endfunction
function! s:find_on_exit(id, data, event) abort
let files = map(filter(s:finded_files, '!empty(v:val)'), "{'filename' : v:val}")
if !empty(files)
call setqflist(files)
copen
else
echo 'Can not find anything'
endif
endfunction
function! s:close_buffer() abort
noautocmd pclose
noautocmd q
endfunction
let s:MPT._onclose = function('s:close_buffer')
function! s:next_item() abort
if line('.') == line('$')
normal! gg
else
normal! j
endif
let argv = matchstr(getline('.'), '^-[a-zA-Z0-9]')
let s:MPT._prompt.begin = substitute(s:MPT._prompt.begin, '-[a-zA-Z]*$', argv, 'g')
redraw
call s:MPT._build_prompt()
endfunction
function! s:previous_item() abort
if line('.') == 1
normal! G
else
normal! k
endif
let argv = matchstr(getline('.'), '^-[a-zA-Z0-9]')
let s:MPT._prompt.begin = substitute(s:MPT._prompt.begin, '-[a-zA-Z]*$', argv, 'g')
redraw
call s:MPT._build_prompt()
endfunction
function! SpaceVim#plugins#find#open() abort
let s:MPT._handle_fly = function('s:handle_command_line')
let s:MPT._function_key = {
\ "\<Return>" : function('s:start_find'),
\ "\<Tab>" : function('s:next_item'),
\ "\<C-j>" : function('s:next_item'),
\ "\<S-tab>" : function('s:previous_item'),
\ "\<C-k>" : function('s:previous_item'),
\ }
noautocmd rightbelow split __spacevim_find_argv__
let s:find_argvs_buffer_id = bufnr('%')
setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline nospell nonu norelativenumber
setf SpaceVimFindArgv
call s:MPT.open()
endfunction
function! s:handle_command_line(cmd) abort
normal! "_dG
if empty(a:cmd)
redraw
call s:MPT._build_prompt()
return
endif
let argv = split(a:cmd)[-1]
if a:cmd[-1:] ==# ' ' && argv ==# '-type'
let line = []
for item in items(s:second_option_en['-type'])
call add(line, ' ' . item[0] . repeat(' ', 8 - len(item[0])) . item[1])
endfor
call setline(1, line)
elseif argv =~# '^-[a-zA-Z0-1]*'
let argvs = filter(deepcopy(s:options_en), 'v:key =~ argv')
let line = []
for item in items(argvs)
call add(line, item[0] . repeat(' ', 15 - len(item[0])) . item[1])
endfor
call setline(1, line)
endif
redraw
call s:MPT._build_prompt()
endfunction

View File

@ -829,12 +829,12 @@ call SpaceVim#custom#SPC('nnoremap', ['f', 't'], 'echom "hello world"', 'test cu
Denite/Unite 是一个强大的信息筛选浏览器,这类似于 emacs 中的 [Helm](https://github.com/emacs-helm/helm)。以下这些快捷键将帮助你快速获取需要的帮助信息:
| 快捷键 | 描述 |
| ----------- | -------------------------------------------- |
| `SPC h SPC` | 使用 fuzzy find 模块展示 SpaceVim 帮助文档章节目录 |
| `SPC h i` | 获取光标下单词的帮助信息 |
| `SPC h k` | 使用快捷键导航,展示 SpaceVim 所支持的前缀键 |
| `SPC h m` | 使用 Unite 浏览所有 man 文档 |
| 快捷键 | 描述 |
| ----------- | -------------------------------------------------- |
| `SPC h SPC` | 使用 fuzzy find 模块展示 SpaceVim 帮助文档章节目录 |
| `SPC h i` | 获取光标下单词的帮助信息 |
| `SPC h k` | 使用快捷键导航,展示 SpaceVim 所支持的前缀键 |
| `SPC h m` | 使用 Unite 浏览所有 man 文档 |
报告一个问题:
@ -979,8 +979,8 @@ merged = 0
| `SPC w TAB`/`<Tab>` | 在统一标签内进行窗口切换 |
| `SPC w =` | 对齐分离的窗口 |
| `SPC w b` | force the focus back to the minibuffer (TODO) |
| `SPC w c` | 进入阅读模式,浏览当前窗口 (需要 tools 模块) |
| `SPC w C` | 选择某一个窗口,并且进入阅读模式 (需要 tools 模块) |
| `SPC w c` | 进入阅读模式,浏览当前窗口 (需要 tools 模块) |
| `SPC w C` | 选择某一个窗口,并且进入阅读模式 (需要 tools 模块) |
| `SPC w d` | 删除一个窗口 |
| `SPC u SPC w d` | delete a window and its current buffer (does not delete the file) (TODO) |
| `SPC w D` | 选择一个窗口,并且关闭 |
@ -1062,6 +1062,7 @@ Buffer 操作相关快捷键都是已 `SPC b` 为前缀的:
| 快捷键 | 描述 |
| ----------- | ------------------------------------------------------ |
| `SPC f /` | 使用 `find` 命令查找文件,支持参数提示 |
| `SPC f b` | 跳至文件书签 |
| `SPC f c` | copy current file to a different location(TODO) |
| `SPC f C d` | 修改文件编码 unix -> dos |

View File

@ -1103,6 +1103,7 @@ Files manipulation commands (start with f):
| Key Binding | Description |
| ----------- | -------------------------------------------------------------- |
| `SPC f /` | Find files with `find` command |
| `SPC f b` | go to file bookmarks |
| `SPC f c` | copy current file to a different location(TODO) |
| `SPC f C d` | convert file from unix to dos encoding |

View File

@ -0,0 +1,14 @@
if exists("b:current_syntax")
finish
endif
let b:current_syntax = "SpaceVimFindArgv"
syntax case ignore
syn match CMDFindArgvOpt /-[a-zA-Z]*\ /
syn match CMDFindSecArgvOpt /^\s\+[a-z]\s\+/
syn match CMDFindArgvDesc /\(-[a-zA-Z0-1]*\ \)\@<=.*/
syn match CMDFindSecArgvDesc /\(^\s\+[a-z]\s\+\)\@<=.*/
hi def link CMDFindArgvOpt Number
hi def link CMDFindSecArgvOpt Number
hi def link CMDFindArgvDesc Comment
hi def link CMDFindSecArgvDesc Comment