""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Filename: grepit.vim
"功能: 依据文件类型, 在一系列同类型的文件中查找关键字符串
"author: hjjdebug
"date: 2022年 07月 29日 星期五 10:07:02 CST
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
if exists("g:grepit_loaded")
finish
endif
let g:grepit_loaded=1 "避免重复加载
"设置3个全局bool变量,是否高亮搜索词,是否跳转到第一条匹配,是否打开quickfix窗口
function! s:CfgHightlightSearch()
if exists('g:grepit_hlsearch')
return g:grepit_hlsearch
endif
return 1
endfunction
function! s:CfgGotoFirstMatch()
if exists('g:grepit_goto_first_match')
return g:grepit_goto_first_match
endif
return 1
endfunction
function! s:CfgOpenQuickFix()
if exists('g:grepit_open_quickfix')
return g:grepit_open_quickfix
endif
return 1
endfunction
"获取搜索的选项
function! s:CfgOption()
if exists('g:grepit_option')
return g:grepit_option
endif
return ""
endfunction
"设置搜索选项
function! s:CfgSetOption()
if !exists('g:grepit_option')
let g:grepit_option=''
endif
let g:grepit_option = input("grep option:-w -i etc:",g:grepit_option)
echo "\nGrepIt option:" . g:grepit_option
endfunction
"构成一个原始的语言map
"每个语言对应一系列文件后缀
"language : extentions
let s:lang_map = {
\ "cpp" : "h,cpp,c,s,S" ,
\ "S" : "s,S" ,
\ }
"获取语言map
function! s:CfgLangeMap()
let l:lang_map = s:lang_map
if exists("g:grepit_lang_map")
extend(l:lang_map, g:grepit_lang_map)
endif
return l:lang_map
endfunction
"根据文件后缀及语言map, 获取语言(搜索)
function! s:GetLanguage(extension, lang_map)
for [l:language, l:extensions] in items(a:lang_map)
for l:candidate in split(l:extensions, ",")
if l:candidate == a:extension
return l:language
endif
endfor
endfor
return ""
endfunction
"根据语言及map, 构建所有后缀列表
function! s:GetExtensions(languages, lang_map)
let l:extensions = ""
for l:lang in a:languages "从一系列语言中构成所有的搜索文件后缀
let l:lang_extensions = get(a:lang_map, l:lang, "") "获取语言对应的文件后缀
if l:lang_extensions == ""
let l:lang_extensions = tolower(expand("%:e")) "若无语言后缀,令文件后缀为语言后缀
endif
if strlen(l:extensions) > 0
let l:lang_extensions = "," . l:lang_extensions
endif
let l:extensions = l:extensions . l:lang_extensions "将文件后缀合成
endfor
return l:extensions
endfunction
"根据后缀列表构建搜索参数
function! s:GetGrepParams(needle, extensions)
let l:params = "-R"
let l:params = l:params . ' ' . s:CfgOption()
for l:extension in split(a:extensions, ",")
let l:params = l:params . " --include=*." . l:extension
endfor
return l:params . " " . shellescape(a:needle ) . " ."
endfunction
"根据后缀列表和搜索词进行搜索
function! s:GrepItInExtensions(extensions, needle)
let l:params = s:GetGrepParams(a:needle, a:extensions)
let l:commandline = ""
if s:CfgGotoFirstMatch()
let l:commandline = "grep"
else
let l:commandline = "grep!" "不跳转到第一条
endif
let l:extlist = join(split(a:extensions, ","), "|")
echo "Searhing for" shellescape(a:needle) "in *.(" . l:extlist . ")"
silent execute l:commandline . " " . l:params
if s:CfgHightlightSearch()
let @/ = a:needle
set hlsearch
endif
if len(getqflist()) == 0
echo "Nothing found"
return
endif
if s:CfgOpenQuickFix()
botright copen " Quickfix always occupies the entire bottom of the window
endif
endfunction
"从指定的后缀中查找
function! s:GrepItCmdExt(extensions, ...)
let l:needle = join(a:000)
if strlen(l:needle) == 0
echoerr "usage: GrepItExt
return
endif
call s:GrepItInExtensions(a:extensions, l:needle)
endfunction
"从指定的语言中查找
function! s:GrepItLangCmd(languages, ...)
let l:needle = join(a:000)
if strlen(l:needle) == 0
echoerr "usage: GrepItLang
return
endif
let l:lang_map = s:CfgLangeMap()
let l:languages = split(a:languages, ",")
let l:extensions = s:GetExtensions(l:languages, l:lang_map)
call s:GrepItInExtensions(l:extensions, l:needle)
endfunction
"主流使用命令,因为多敲一个字符都是浪费
function! s:GrepItCmd(...)
let l:needle = join(a:000)
if strlen(l:needle) == 0
echoerr "usage: GrepIt
return
endif
let l:lang_map = s:CfgLangeMap()
let l:extension = tolower(expand("%:e")) "获取文件后缀
let l:language = s:GetLanguage(l:extension, l:lang_map) "找到语言
let l:extensions = s:GetExtensions([l:language], l:lang_map) "从语言再扩展到一系列后缀文件
call s:GrepItInExtensions(l:extensions, l:needle) "在一系列后缀文件中查找
endfunction
"与用户交互接口,设置搜索选项
function! GrepItSetOption()
call s:CfgSetOption()
endfunction
"与用户交互接口,选择模式搜索
function! GrepItOperator(type)
let l:old_register_value = @@
if a:type ==# 'v'
normal! `
elseif a:type ==# 'char'
normal! `[v`]y
else
return
endif
let l:needle = @@
let @@ = l:old_register_value
call s:GrepItCmd(l:needle)
endfunction
"定义三个搜索命令
"常用的方式,由程序决定从那些定义的文件后缀中查找
command! -nargs=+ GrepIt call
"直接指明文件类型后缀来查找
command! -nargs=+ GrepItExt call
"指明了语言来查找
command! -nargs=+ GrepItLang call