2015-10-31 23 views
6

Sto cercando una buona soluzione per un thesaurus vim. La funzionalità è integrata, ovviamente, ma il file che tutti sembrano utilizzare è il mthesaur.txt. Mentre "funziona" nel senso che i comandi in modalità inserimento fanno apparire una lista, mi sembra che i risultati siano programmaticamente corretti ma non super utili. Il plugin per thesaurus online di Vim funziona molto bene, ma la latenza sul filo e la necessità di utilizzare una divisione per il buffer restituito non è l'ideale. Qualcuno ha un'opinione su questo?Vim thesaurus file

risposta

4

Ho scritto un plug-in che può risolvere i due problemi sollevati qui.

Multi-language Thesaurus Query plugin for Vim

Migliora l'esperienza con sotto due aspetti: sinonimo più sensato scegliere meccanismo; e fonti di sinonimi migliori e più flessibili.

Thesaurus_query.vim screen cast

Per impostazione predefinita, il plug-in utilizza messagebox di vim per la visualizzazione candidato, con ogni sinonimo etichettato da un numero. E permette all'utente di scegliere quello adatto per sostituire la parola sotto il cursore digitando il suo numero. Funziona in modo simile al prompt di correzione ortografica predefinito di di vim di vim. E drasticamente ridotto il tempo di operazione per scegliendo il sinonimo appropriato da una lunga lista di candidati.

Per migliorare la qualità dei candidati dei sinonimi, più backend di query sono stati utilizzati . Per l'utente inglese, due sono degni di nota.

  • thesaurus_com backend utilizzando Thesaurus.com come fonte sinonimo
  • mthesaur_txt backend utilizzando mthesaur.txt come fonte sinonimo

thesaurus_com backend funzionerà subito. Per eseguire il backend di Query locale, devi scaricare mthesaur.txt e indicare al plug-in dove si trova o impostando la variabile thesaurus o specificando variabile g:tq_mthesaur_file. Oppure solo il back-end online sarà funzionale.

Per impostazione predefinita, verrà utilizzato prima il backend della query online. Tuttavia, se Internet non è disponibile a o troppo lento, la query futura nella sessione vim corrente verrà gestita dal backend Query locale prima per ridurre il tempo di latenza. Anche la priorità di questi due backend può essere modificata manualmente (vedere documentation).

Per risolvere il problema della latenza (che di solito risalta quando la parola non viene trovata), ho introdotto un meccanismo di timeout. È possibile impostare

let g:tq_online_backends_timeout = 0.6 

se la vostra connessione internet è abbastanza veloce. In modo che la latenza potrebbe essere ridotta a meno di 0,6 secondi.

Il plugin è scritto in Python, però. Quindi potresti volerlo usare con Vim compilato con il supporto Python e/o Python3.

+0

Wow, è incredibile. Molto bello e molto impressionante. –

+0

@ThadBrown Fai un salto ~ E il feedback è ben accetto. : D – Chong

+0

La cosa complicata per me (sia in termini di latenza che di plug-in complessivo) è la mancanza di un file del thesaurus veramente buono. Ad esempio, si desidera il completamento automatico per un enorme database, è sufficiente eseguire una query per i nomi di colonna/tabella, eseguire un'altra query per le stored procedure e così via e inserire i risultati in un file di dizionario. Questa può essere una fonte di completamento automatico di base. Esiste un file del thesaurus che è concesso in licenza in modo tale che possa essere ridistribuito e modificato? Potrei racimolare un sito Web per me, ma questo non aiuterebbe nessuno se non potesse essere ridistribuito. Pensieri? –

1

Se il sistema è unix-like e se avete installato awk, poi ho una soluzione semplice al vostro problema che consente di accedere a thesauri in più lingue senza connessione internet e senza una finestra divisa neanche.

Prima scaricare LibreOffice thesauri da:

https://cgit.freedesktop.org/libreoffice/dictionaries/tree/

per esempio.

(Prenditi cura ° _ *. Dat file, questi sono quelli che avete bisogno, non il .aff e file .dic che funzionano solo per il controllo ortografico con Hunspell.) Scarica il * .dat thesauri di vostro gradimento e copia in una sottodirectory della cartella in cui verrà inserito il plug-in; questa sottodirectory dovrebbe essere chiamata "thes".

Ora creare un nuovo file nella cartella Plugin (la cartella in cui si dovrebbe avere sottodirectory "thes" con il * .dat thesauri all'interno) e mettere il seguente in questo file:

" 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() 

Ciò ti consentirà di scegliere il thesaurus di tua scelta digitando :Thesaurus in modalità comando di Vim.

(In realtà, se si prevede di utilizzare un solo thesaurus allora non è necessario alcun di questo, basta assegnare il nome completo del file thesaurus alla variabile buffer locale, b:thesaurus).

Infine, aggiungere il seguente al file plugin:

" 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 

Questo vi permetterà di ottenere i sinonimi qualsiasi parola durante la digitazione in modalità di inserimento . Mentre sei ancora in modalità di inserimento, premi Ctrl-X Ctrl-O (o qualsiasi combinazione di tasti mappata in modo omnicompleto) e un menu a comparsa visualizza con l'elenco dei sinonimi.

Questa soluzione è molto grezza rispetto al potente plug-in di Chong (vedere sopra), ma è leggero e funziona abbastanza bene per me. Lo uso con thesauri in quattro lingue diverse.

+0

Interessante, mi chiedo in quale fase sia attiva la funzione di thesaurus di LibreOffice. Le versioni ufficiali del pacchetto non contengono la fonte del thesaurus; e la sorgente che hai indicato sembra molto simile alla sorgente del thesaurus di OpenOffice, tranne che non ha i file idx, che è in realtà abbastanza utile per localizzare rapidamente la parola in questi enormi file dat ... – Chong

+0

Queste sono le versioni recenti per lo sviluppo, e io penso che il thesaurus portoghese (per esempio) sia più completo di uno che ho scaricato dalla pagina di estensione ufficiale di LibreOffice. –

1

Script per ~/.vimrc, richiede il file thesaurii.txt (dizionari uniti da https://github.com/moshahmed/vim/blob/master/thesaurus/thesaurii.txt) e perl.exe nel percorso per la ricerca di sinonimi. Script testato su win7 e cygwin perl.

Le chiamate devono eseguire la correzione ortografica, se non vengono trovati sinonimi.

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 
+0

Si prega di non inserire solo alcuni strumenti o librerie come risposta. Dimostrare almeno [come risolve il problema] (http://meta.stackoverflow.com/a/251605) nella risposta stessa. –

+1

@BaummitAugen, Ok ha incluso lo script stesso, avevo fornito il collegamento perché il dizionario thesaurii.txt è enorme (12M) era la parte più difficile per questa risposta. – mosh