IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    lookupfile.vim插件详解【OK】

    rock发表于 2015-01-07 10:00:06
    love 0

    转自:http://www.blogdaren.com/post-1632.html


    lookupfile.vim是Vim的一个五星级的插件,它允许用户只输入部分文件名甚 至使用正 则表达式快速查找并打开目标文件,尤其对于程序员来说,lookupfile的作用绝对称得上“Life changing”。

    lookupfile支持多种查找方式,大体分为三种,即在Buffer中查找、在指定路径下查找和在Tags文件中查找。其中,最使 lookupfile熠熠生辉的就是根据Tag文件查找和打开文件。

    假设现有一个包含数百个源码文件的工程,首先使用某种手段或工具生成Vim兼容的Tags文件(稍后详述),然后打开Vim并使 lookupfile使用此Tags文件作为查找源。此后即可使用“:LookupFile”命令打开一个输入窗口, 输入部分文件名或一个正则表达式,则所有匹配项会显示在一个下拉列表中,最后选中任意匹配项即可快速打开该文件:


    1.jpg

    这种方式使Vim从浩如烟海的源码中查找和打开文件变得易如反掌,它意味着你不必再把时间浪费在NERDTree或 者简单的“:set wildmenu”+“:cd”,甚至邪恶的 “Windows Explorer”上;也不必再来回地切换窗口,甚至手都不需要离开键盘就把这一切搞定了。

    lookupfile的安装方法如下:

    1. 下载lookupfile和genutils, 后者是lookupfile依赖的一个通用函数库。
    2. 解压这两个压缩包,并将得到的多个文件夹覆盖到Vim的运行时环境下,如Linux下为“~/.vim”,Windows下可为Vim安装目录下 的“vimfiles”目录。
    3. 进入Vim运行时环境下的“doc”目录,用Vim打开任一文件,输入命令“:helptags .”并回 车。

    至此,lookupfile的安装已经完成。但要使用它提升工作效率,还需要做些额外的工作,毕竟你总不能每次都要到工程根目录下手动生成Tags 文件,再“:let g:LookupFile_TagExpr='"./filenametags"'”,然后每次 找文件的候还要“:LookupFile”!

    首先就是Tags文件的生成,对于Linux用户,这个可以使用Shell脚本实现:

    BASH:
    1. #!/bin/sh
    2. # generate tag file for lookupfile plugin
    3. echo -e "!_TAG_FILE_SORTED\t2\t/2=foldcase/"> filenametags
    4. find . -not -regex '.*\.\(png\|gif\)' ! -path "*svn*" -type f -printf "%f\t%p\t1\n" | sort -f>>filenametags

    将此段Shell命令保存成名为“genfiletags”的文件并设置权限为“755”, 然后将“genfiletags”复制到环境变量“PATH”下的一个目录中(目的是允许直接执行“genfiletags”而无须输入该文件的完整路径)。以后只需在工程根目录下执行“genfiletags”, 即可在该目录下生成名为“filenametags”的Tags文件。

    而对于Windows用户,事情开始变得邪恶起来,批处理显 然很难胜任这在Linux下只需两行命令就轻松搞定的工作,所幸我安装了Cygwin并将其安装目录下的“bin” 目录添加到了环境变量“PATH”中,理论上上面的Shell脚本可以使用“bash genfiletags”执行,但是Windows偏偏东施效颦,也有“find”和“sort” 命令,所以我只好将Cygwin的“find.exe”和“sort.exe”各 复制一份,分别命名为“true_find.exe”和“true_sort.exe”, 并将上面的脚本改为:

    BASH:
    1. #!/bin/sh
    2. # generate tag file for lookupfile plugin
    3. echo -e "!_TAG_FILE_SORTED\t2\t/2=foldcase/"> filenametags
    4. true_find . -not -regex '.*\.\(png\|gif\)' ! -path "*svn*" -type f -printf "%f\t%p\t1\n" | true_sort -f>> filenametags

    然后保存为“genfiletags.sh”。另外创建一个批处理文件“genfiletags.bat”, 内容如下:

    @echo off
    bash genfiletags.sh

    最后,将这两个文件复制到环境变量“PATH”包含的一个目录中。

    到这里,lookupfile已经可以正常工作了,只需在Vim中cd到项目的根目录,然后使用“:!genfiletags” 命令生成Tags文件,最后使用命令“:let g:LookupFile_TagExpr='"./filenametags"'” 告诉lookupfile使用这个文件作为查找源,就可以使用“:LookupFile”命令查找和打开文件了。

    但我希望效率更高一些,因此在Vim的配置文件中加入以下代码:

    VIM:

    1. " 指定英文逗号作为<leader>键
    2. let mapleader=","
    3. " 在指定目录生成filenametags,并使lookupfile将这个文件作为查找源
    4. function SetRootOfTheProject(path)
    5. " 进入指定目录
    6. exe 'cd '.a:path
    7. " 生成文件标签
    8. exe '!genfiletags'
    9. " 获取标签文件的路径
    10. let tagFilePath = genutils#CleanupFileName(a:path.'/filenametags')
    11. " 设置LookupFile插件的全局变量,使之以上面生成的标签文件作为查找源
    12. exe "let g:LookupFile_TagExpr='\"".tagFilePath."\"'"
    13. endfunction
    14. " 设置当前位置为工程的根目录
    15. function SetHereTheRoot()
    16. call SetRootOfTheProject('.')
    17. endfunction
    18. nmap <leader>root :call SetHereTheRoot()<CR>
    19. " 从用户的输入获取指定路径,并设置为工程的根目录
    20. function SetSpecifiedPathTheRoot()
    21. call SetRootOfTheProject(input('请输入工程根目录的路径:'))
    22. endfunction
    23. nmap <leader>xroot :call SetSpecifiedPathTheRoot()<CR>
    24. " 使用LookupFile打开文件
    25. nmap <leader>o :LookupFile<CR>

    以后只需要在Vim中cd到项目的根目录并在常规模式下输入“,root” 即可完成从生成Tags文件到指定该文件作为LookupFile查找源的工作,然后每次在常规模式下输入“,o”即 可打开LookupFile窗口输入查询条件了。

    下面是一些LookupFile常用的技巧:

    1. 每次打开LookupFile窗口时,会默认显示上一次的查询条件或上一次打开的文件的完整路径,可以使用“Ctrl+U” 快捷键清空
    2. 对于查询出来的匹配项,在Windows下可以使用上下方向箭头选择,但在Linux下不能这样做,可使用“Ctrl+N” 进行选择
    3. 回车会直接在当前Buffer中打开选中的匹配项,可以使用“Ctrl+O”在Split窗口中打开

    LookupFile使写程序变得更加妙趣横生,它使文件的查询和打开也可以变得非常地高效和优雅,唯独Windows下那极端邪恶的黑窗口,像个 无法摆脱的梦魇,龇牙咧嘴地嘲笑着WinSlave们。

    2009-07-03 更新:

    对于Windows用户,要特别注意的是,在将上面的genfiletags.sh脚本的内容复制到文本编辑器并保存时,一定要保存为Unix格式的文本 文件。

    一种方法为,使用Vim打开genfiletags.sh,使用命令“:set fileformat=unix”并 保存。

    下图是使用lookupfile插件查找文件的一个例子:

    3.jpg
    在 屏幕最上方的窗口就是lookupfile窗口,在这个窗口中输入“gui.*x11”几个字符,查找到6个匹配文件,使用CTRL-N选中 gui_x11.c文件,然后按回车,就会在前一个窗口中打开src/gui_x11.c文件,lookupfile窗口也自动关闭了。是不是非常方便?

    [缓冲区查找]

    在开发过程中,我经常会同时打开数十甚至上百个文件。即使是使用BufExplorer插件,想在这么多buffer中切换到自己所要的文件,也不是件容易的事。

    Lookupfile插件提供了一个按缓冲区名字查找缓冲区的方式,只要输入缓冲区的名字(可以是正则表达式),它就可以把匹配的缓冲区列在下拉列表中,同时还会列出该缓冲区内文件的路径,当你的buffer中有多个同名文件时,这可以帮你迅速找到你想要的文件。

    使用“:LUBufs”命令开始在缓冲区中查找,输入缓冲区的名字,在你输入的过程中,符合条件的缓冲区就显示在下拉列表中了,选中所需缓冲区后,按回车,就会切换你所选的缓冲区。下图是一个示例:

    4.jpg
    [浏览目录]

    Lookupfile 插件还提供了目录浏览的功能,使用“:LUWalk”打开lookupfile窗口后,就可以输入目录,lookupfile 会在下拉列表中列出这个目录中的所有子目录及文件供选择,如果选择了目录,就会显示这个目录下的子目录和文件;如果选择了文件,就在VIM中打开这个文 件。

    下图是使用LUWalk的一个抓图:

    lookupfile.vim插件详解【OK】 - PHP程序员 - 李国华【PHP程序员C++】博客
    Lookupfile插件还提供了LUPath和LUArgs两个功能,这两个功能我用的不多,就不在这里介绍了。感兴趣的朋友读一下lookupfile的帮助页。

    [Lookupfile配置]

    Lookupfile插件提供了一些配置选项,通过调整这些配置选项,使它更符合你的工作习惯。下面是我的vimrc中关于lookupfile的设置,供参考:


    """"""""""""""""""""""""""""""
    " lookupfile setting
    """"""""""""""""""""""""""""""
    let g:LookupFile_MinPatLength = 2 "最少输入2个字符才开始查找
    let g:LookupFile_PreserveLastPattern = 0 "不保存上次查找的字符串
    let g:LookupFile_PreservePatternHistory = 1 "保存查找历史
    let g:LookupFile_AlwaysAcceptFirst = 1 "回车打开第一个匹配项目
    let g:LookupFile_AllowNewFiles = 0 "不允许创建不存在的文件
    if filereadable("./filenametags") "设置tag文件的名字
    let g:LookupFile_TagExpr = '"./filenametags"'
    endif
    nmap lk LookupFile "映射LookupFile为,lk
    nmap ll :LUBufs "映射LUBufs为,ll
    nmap lw :LUWalk "映射LUWalk为,lw

    有了上面的定义,当我输入”,lk”时,就会在tag文件中查找指定的文件名;当输入”,ll”时,就会在当前已打开的buffer中查找指定名字的buffer;当输入”,lw”时,就会在指定目录结构中查找。

    另外,我还在项目相关的配置文件vim70sx.vim(参考本系列第4篇文章)中加入了lookupfile所使用的tag文件的信息:


    let g:LookupFile_TagExpr = '"filenametags"'

    这样,在恢复前次会话时就给lookupfile插件定义了tag文件。

    在 用lookupfile插件查找文件时,是区分文件名的大小写的,如果想进行忽略大小写的匹配,可以使用VIM忽略大小写的正则表达式,即在文件 名的前面加上“\c”字符。举个例子,当你输入“\cab.c”时,你可能会得到“ab.c”、“Ab.c”、“AB.c”……。

    注:如果想加快lookupfile忽略大小写查找的速度,在生成文件名tag文件时,使用混合大小写排序。这在本系列的第5篇文章中有所提及。

    通常情况下我都进行忽略大小写的查找,每次都输入“\c”很麻烦。没关系,lookupfile插件提供了扩展功能,把下面这段代码加入你的vimrc中,就可以每次在查找文件时都忽略大小写查找了:


    " lookup file with ignore case
    function! LookupFile_IgnoreCaseFunc(pattern)
    let _tags = &tags;
    try
    let &tags; = eval(g:LookupFile_TagExpr)
    let newpattern = '\c' . a:pattern
    let tags = taglist(newpattern)
    catch
    echohl ErrorMsg | echo "Exception: " . v:exception | echohl NONE
    return ""
    finally
    let &tags; = _tags
    endtry

    " Show the matches for what is typed so far.
    let files = map(tags, 'v:val["filename"]')
    return files
    endfunction
    let g:LookupFile_LookupFunc = 'LookupFile_IgnoreCaseFunc'

    有时在LUBufs时也需要忽略缓冲区名字的大小写,我是通过直接修改lookupfile插件的方法,在LUBufs查找的字符串前都加上“\c”,使之忽略大小写。如果你不想这样,可以每次在缓冲区名字前手动加上“\c”。



    1. 翻译成windows平台上的shell命令,大致为:
    2. dir /B /S /A-D /ON *.fnc *.prc *.trg *.pck *.typ *.spc *.bdy *.tps *.tpb *.txt *.sql > filenametags
    3. dir /B /S /A-D /ON | findstr /V ".class$ .xls$ .doc$ .ppt$ .pdf$ .jpg$ .gif$ .zip$ .rar$ .jar$ .dat$ .mdb$ .dmp$ " > filenametags
    4. 但这样最终输出的tag文件还不复合lookupfile的tag文件格式要求(文件名+tab键+文件全路径+tab键+数字1),所有还需要再处理一下,
    5. 这里采用的一个办法是使用vim内嵌函数的方法,所以需要继续处理一下,这里贴出一段vim脚本,写到_vimrc文件中后每次启动vim后加载,
    6. 然后调用call ProjectTagUpdateLookupFile()方法(或map一个命令)即可刷新tag文件了。
    7. 其中参考了happyvim(水木bbs的vim版)编写的project.vim插件代码,在此表示感谢。
    8. " Lookup File
    9. " Author: happyvim
    10. " Function: ProjectTagUpdateLookupFile
    11. " Args:
    12. " Description: regenerate lookupfile tags
    13. function! ProjectTagUpdateLookupFile()
    14. echo "generate lookupfile.tag"
    15. if filereadable(g:project_lookup_file)
    16. call delete(g:project_lookup_file)
    17. endif
    18. execute "cd " . g:this_project_base_dir
    19. let l:lookup_tags = ["!_TAG_FILE_SORTED 2 \/2=foldcase\/"]
    20. if has("win32")
    21. let l:this_project_base_dir = substitute(g:this_project_base_dir, "/", "\\", "g") . "\\"
    22. else
    23. let l:this_project_base_dir = g:this_project_base_dir
    24. endif
    25. "let l:lookup_tags_file_string = system(g:project_find_program . " " . l:this_project_base_dir . " " . g:project_find_param)
    26. let l:lookup_tags_file_string = system(g:project_find_program . " " . g:project_find_param)
    27. let l:lookup_tags_file_list = split(l:lookup_tags_file_string, '\n')
    28. let l:lookup_tags_file_list = sort(l:lookup_tags_file_list)
    29. let l:item = ""
    30. let l:count = 0
    31. for l:item in l:lookup_tags_file_list
    32. let l:item = fnamemodify(l:item, ':t') . "\t" . l:item . "\t" . "1"
    33. let l:lookup_tags_file_list[l:count] = l:item
    34. let l:count = l:count + 1
    35. endfor
    36. call extend(l:lookup_tags, l:lookup_tags_file_list)
    37. call writefile(l:lookup_tags, g:project_lookup_file)
    38. echo "generate lookupfile tag done"
    39. endfunction
    40. "dir /B /S /A-D /ON *.fnc *.prc *.trg *.pck *.typ *.spc *.bdy *.tps *.tpb *.txt *.sql > filenametags
    41. "dir /B /S /A-D /ON | findstr /V ".class$ .xls$ .doc$ .ppt$ .pdf$ .jpg$ .gif$ .zip$ .rar$ .jar$ .dat$ .mdb$ .dmp$ " > filenametags
    42. let g:project_lookup_file = "D:/Harvest/filenametags"
    43. let g:project_find_program = "dir /B /S /A-D /ON"
    44. let g:project_find_param = "*.fnc *.prc *.trg *.pck *.typ *.spc *.bdy *.tps *.tpb *.txt *.sql"
    45. let g:this_project_base_dir = "D:/Harvest"
    46. let g:LookupFile_TagExpr = '"D:/Harvest/filenametags"'


沪ICP备19023445号-2号
友情链接