我一直在为一个vim词库找到一个好的解决方案。显然,该功能是内置的,但每个人似乎都使用的文件是mthesaur.txt。虽然它在插入模式中的命令显示列表的意义上“有效”,但在我看来,结果是编程正确但不是非常有用。 vim在线同义词库插件工作得非常好,但是线路上的延迟和使用拆分返回缓冲区的必要性并不理想。有人对此有意见吗?
答案 0 :(得分:5)
我写了一个插件,可以解决你在这里提出的两个问题。
Multi-language Thesaurus Query plugin for Vim
它在两个方面改善了使用体验:更明智的同义词选择 机制;更好,更灵活的同义词来源。
Thesaurus_query.vim screen cast
默认情况下,插件使用vim的消息框进行候选显示 由数字标记的同义词。它让用户选择合适的替代品 键入光标下的单词。它的工作原理与vim类似 默认拼写纠正提示。并大大缩短了操作时间 从一长串候选人中选择适当的同义词。
为了提高同义词候选者的质量,有多个查询后端 用过的。对于英语用户来说,有两个值得注意。
thesaurus_com
后端使用Thesaurus.com作为同义词来源mthesaur_txt
后端使用mthesaur.txt作为同义词源 thesaurus_com
后端将立即开始工作。对于本地查询后端工作,
您需要下载mthesaur.txt
并告诉插件它在哪里
通过设置变量thesaurus
或指定来定位
变量g:tq_mthesaur_file
。否则只有在线后端
功能
默认情况下,将首先使用Online Query Backend。但如果互联网不是 可用或太慢,将处理当前vim会话中的未来查询 通过Local Query Backend首先减少延迟时间。这两个的优先级 后端也可以手动修改(参见documentation)。
为了解决延迟问题(通常在找不到单词时突出),我引入了一种超时机制。你可以设置
let g:tq_online_backends_timeout = 0.6
如果您的互联网速度相当快。这样可以将延迟减少到 不到0.6秒。
该插件是用Python编写的。因此,您可能希望将其与使用Python和/或Python3支持编译的Vim一起使用。
答案 1 :(得分:2)
如果你的系统是unix-like,如果你安装了awk,那么我有一个 您的问题的简单解决方案,使您可以访问叙词表 没有互联网连接且没有分割的多种语言 窗口要么。
首先从以下网址下载LibreOffice叙词表:
https://cgit.freedesktop.org/libreoffice/dictionaries/tree/
例如。
(看看_ * .dat文件,这些是你需要的,而不是.aff和 .dic文件仅适用于与Hunspell进行拼写检查。)下载 您喜欢的* .dat叙词表,并将它们复制到。的子目录中 你要插入插件的文件夹;这个子目录应该是 叫做“thes。”
现在在插件文件夹中创建一个新文件(您应该在的文件夹中) 有“thes”子目录与* .dat叙词表里面)并把 在此文件中关注:
" offer choice among installed thesauri
" ==================================================
let s:thesaurusPath = expand("<sfile>:p:h") . "/thes"
function! s:PickThesaurus()
" 1, 1: glob does not ignore any pattern, returns a list
let thesaurusList = glob(s:thesaurusPath . "/*", 1, 1)
if len(thesaurusList) == 0
echo "Nothing found in " . s:thesaurusPath
return
endif
let index = 0
let optionList = []
for name in thesaurusList
let index = index + 1
let shortName = fnamemodify(name, ":t:r")
let optionList += [index . ". " . shortName]
endfor
let choice = inputlist(["Select thesaurus:"] + optionList)
let indexFromZero = choice - 1
if (indexFromZero >= 0) && (indexFromZero < len(thesaurusList))
let b:thesaurus = thesaurusList[indexFromZero]
endif
endfunction
command! Thesaurus call s:PickThesaurus()
这将允许您通过在Vim的命令模式下键入
:Thesaurus
来选择您选择的同义词库。
(实际上,如果您打算只使用一个词库,那么您不需要任何词库
这个的;只需将同义词库文件的全名分配给
缓冲局部变量b:thesaurus
)。
最后,将以下内容添加到您的插件文件中:
" run awk on external thesaurus to find synonyms
" ==================================================
function! OmniComplete(findstart, base)
if ! exists("b:thesaurus")
return
endif
if a:findstart
" first, must find word
let line = getline('.')
let wordStart = col('.') - 1
" check backward, accepting only non-white space
while wordStart > 0 && line[wordStart - 1] =~ '\S'
let wordStart -= 1
endwhile
return wordStart
else
" a word with single quotes would produce a shell error
if match(a:base, "'") >= 0
return
endif
let searchPattern = '/^' . tolower(a:base) . '\|/'
" search pattern is single-quoted
let thesaurusMatch = system('awk'
\ . " '" . searchPattern . ' {printf "%s", NR ":" $0}' . "'"
\ . " '" . b:thesaurus . "'"
\)
if thesaurusMatch == ''
return
endif
" line info was returned by awk
let matchingLine = substitute(thesaurusMatch, ':.*$', '', '')
" entry count was in the thesaurus itself, right of |
let entryCount = substitute(thesaurusMatch, '^.*|', '', '')
let firstEntry = matchingLine + 1
let lastEntry = matchingLine + entryCount
let rawOutput = system('awk'
\ . " '" . ' NR == ' . firstEntry . ', NR == ' . lastEntry
\ . ' {printf "%s", $0}' . "'"
\ . " '" . b:thesaurus . "'"
\)
" remove dash tags if any
let rawOutput = substitute(rawOutput, '^-|', '', '')
let rawOutput = substitute(rawOutput, '-|', '|', 'g')
" remove grammatical tags if any
let rawOutput = substitute(rawOutput, '(.\{-})', '', 'g')
" clean spaces left by tag removal
let rawOutput = substitute(rawOutput, '^ *|', '', '')
let rawOutput = substitute(rawOutput, '| *|', '|', 'g')
let listing = split(rawOutput, '|')
return listing
endif
endfunction
" configure completion
" ==================================================
set omnifunc=OmniComplete
set completeopt=menuone
这将允许您获取在insert中键入的任何单词的同义词 模式。在仍处于插入模式时,按Ctrl-X Ctrl-O(或任何键 您在omnicompletion上映射的组合),将显示一个弹出菜单 与同义词列表。
与Chong的强大插件(见上文)相比,这个解决方案非常粗糙,但它很轻巧,对我来说效果很好。我用四种不同语言的叙词表来使用它。
答案 2 :(得分:2)
〜/ .vimrc的脚本,它需要文件thesaurii.txt(来自https://github.com/moshahmed/vim/blob/master/thesaurus/thesaurii.txt的合并词典)和路径中的perl.exe来搜索同义词。脚本在win7和cygwin perl上测试。
如果未找到同义词,则调用aspell进行拼写纠正。有关如何在按[tab]的情况下调用此功能,请参阅https://stackoverflow.com/a/53825144/476175。
set thesaurus=thesaurii.txt
let s:thesaurus_pat = "thesaurii.txt"
set completeopt+=menuone
set omnifunc=MoshThesaurusOmniCompleter
function! MoshThesaurusOmniCompleter(findstart, base)
" == First call: find-space-backwards, see :help omnifunc
if a:findstart
let s:line = getline('.')
let s:wordStart = col('.') - 1
" Check backward, accepting only non-white space
while s:wordStart > 0 && s:line[s:wordStart - 1] =~ '\S'
let s:wordStart -= 1
endwhile
return s:wordStart
else
" == Second call: perl grep thesaurus for word_before_cursor, output: comma separated wordlist
" == Test: so % and altitude[press <C-x><C-o>]
let a:word_before_cursor = substitute(a:base,'\W','.','g')
let s:cmd='perl -ne ''chomp; '
\.'next if m/^[;#]/;'
\.'print qq/$_,/ if '
\.'/\b'.a:word_before_cursor.'\b/io; '' '
\.s:thesaurus_pat
" == To: Debug perl grep cmd, redir to file and echom till redir END.
" redir >> c:/tmp/vim.log
" echom s:cmd
let s:rawOutput = substitute(system(s:cmd), '\n\+$', '', '')
" echom s:rawOutput
let s:listing = split(s:rawOutput, ',')
" echom join(s:listing,',')
" redir END
if len(s:listing) > 0
return s:listing
endif
" Try spell correction with aspell: echo mispeltword | aspell -a
let s:cmd2 ='echo '.a:word_before_cursor
\.'|aspell -a'
\.'|perl -lne ''chomp; next unless s/^[&]\s.*?:\s*//; print '' '
let s:rawOutput2 = substitute(system(s:cmd2), '\n\+$', '', '')
let s:listing2 = split(s:rawOutput2, ',\s*')
if len(s:listing2) > 0
return s:listing2
endif
" Search dictionary without word delimiters.
let s:cmd3='perl -ne ''chomp; '
\.'next if m/^[;#]/;'
\.'print qq/$_,/ if '
\.'/'.a:word_before_cursor.'/io; '' '
\.&dictionary
let s:rawOutput3 = substitute(system(s:cmd3), '\n\+$', '', '')
let s:listing3 = split(s:rawOutput3, ',\s*')
if len(s:listing3) > 0
return s:listing3
endif
" Don't return empty list
return [a:word_before_cursor, '(no synonyms or spell correction)']
endif
endfunction