VIM同义词库文件

时间:2015-10-31 15:47:04

标签: vim thesaurus

我一直在为一个vim词库找到一个好的解决方案。显然,该功能是内置的,但每个人似乎都使用的文件是mthesaur.txt。虽然它在插入模式中的命令显示列表的意义上“有效”,但在我看来,结果是编程正确但不是非常有用。 vim在线同义词库插件工作得非常好,但是线路上的延迟和使用拆分返回缓冲区的必要性并不理想。有人对此有意见吗?

3 个答案:

答案 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