2

It has been impossible for me to find an offline Spanish thesaurus in a format that worked in Vim. Libreoffice Spanish Thesaurus looks good, needs some conditional modifications and is 66000 lines long or so. Are vim macros so powerful to accomplish that task?.

The Libreoffice thesaurus looks something like this:


abacora|1
-|avasalla|somete|sojuzga|supedita|rinde|acosa|hostiga
abacorar|1
(tr.)|acosar|acometer|sujetar
abad|1
-|superior|rector|prior|prelado|cura|sacerdote
abada|2
(f.)|bada|rinoceronte
(f.)|rinoceronte|bada
abadejo|5
(m.)|bacalao
(m.)|cant?rida
(m.)|reyezuelo|r?gulo
-|cant?rida
-|r?gulo|reyezuelo
abadengo|1
-|abacial|mon?stico|monacal|clerical|eclesi?stico
abadiato|1
(f.)|abad?a|monasterio|convento|priorato|cenobio|r?bida
abad?a|1
(f.)|monasterio|convento|priorato|cenobio|r?bida|abadiato
abajadero|1
-|bajada|declive|descenso|cuesta|pendiente|desnivel|ladera|declinaci?n|descendimiento|ocaso
abajar|1
-|desvalorar|desvalorizar|bajar|depreciar|devaluar|abaratar|rebajar|decrecer|bajarse|menguar|disminuir|reducir|achicar
abaje?o|1
-|sure?o|meridional
abajo|1
(adv.)|debajo
abalanzar|2
-|equilibrar|igualar
-|expeler|arrojar|despedir|echar|eliminar|emitir|expulsar|lanzar|tirar|proyectar|disparar|derramar|emanar|extender|empujar|impeler|verter|soltar|despe?ar

And I have to make it look something like this

abacora,avasalla,somete,sojuzga,supedita,rinde,acosa,hostiga
abacorar,acosar,acometer,sujetar
abad,superior,rector,prior,prelado,cura,sacerdote
abada,bada,rinoceronte,rinoceronte,bada
abadejo,bacalao,cant?rida,reyezuelo,r?gulo,cant?rida,r?gulo,reyezuelo
abadengo,abacial,mon?stico,monacal,clerical,eclesi?stico
abadiato,abad?a,monasterio,convento,priorato,cenobio,r?bida
abad?a,monasterio,convento,priorato,cenobio,r?bida,abadiato,abajadero,bajada,declive,descenso,cuesta,pendiente,desnivel,ladera,declinaci?n,descendimiento,ocaso
abajar,desvalorar,desvalorizar,bajar,depreciar,devaluar,abaratar,rebajar,decrecer,bajarse,menguar,disminuir,reducir,achicar
abaje?o,sure?o,meridional
abajo,debajo
abalanzar,equilibrar,igualar,expeler,arrojar,despedir,echar,eliminar,emitir,expulsar,lanzar,tirar,proyectar,disparar,derramar,emanar,extender,empujar,impeler,verter,soltar,despe?ar

I'm trying to use Vim for writing, my programming skills are very limited, I would very much appreciate any help. Thanks in advance.

PS: Source of Libreoffice Spanish thesaurus available here https://github.com/LibreOffice/dictionaries/blob/master/es/th_es_v2.dat

EDIT,

I've been playing with this function in my .vimrc so Vim can read the first format, but I don't fully understand what it reaally does / how it works, that's why I asked to export the format rather than making Vim to "translate" it. As I said, my coding skills are very limited.

" 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

Source: https://stackoverflow.com/questions/33453468/vim-thesaurus-file

4
  • Just to be clear: the questions is essentially "How can I efficiently use Vim to convert the first format to the second?", right?
    – D. Ben Knoble
    Commented Dec 25, 2022 at 22:51
  • Well, any way of doing it is OK, I thought a macro would be the straight forward way, but what I want is to convert that format to be usable for Vim, don't mind if its done trough Vim or not. And yes, I need to convert first format to the second.
    – MrM
    Commented Dec 25, 2022 at 23:10
  • What did you try?
    – romainl
    Commented Dec 26, 2022 at 7:52
  • I've edited the thread to add it
    – MrM
    Commented Dec 26, 2022 at 13:15

2 Answers 2

1

VIM-thesaurus-files provides a script to convert a thesaurus file for Libre Office to one for Vim. You can also find thesaurus files in my repo vim-thesauri. Please be aware of the caveat that two words are considered synonym by Vim if there is a line that contains both of them, leading to more suggestions than one might expect.

0

OmniComplete is not necessary in this case because there is already a thesaurus option (:h thesaurus) and thesaurusfunc (:h thesaurusfunc). Additionally, adding too many expensive operations to OmniComplete can cause a delay before the menu is displayed. Therefore, your initial idea of converting the LibreOffice format to csv is the most efficient solution.

Simply run the following commands in your file th_es_v2.dat

:v/^[^-(]/-1j
:%s/|\d\+.\{-}|/|/
:%s/|/,/g
:1d

enter image description here

You might want to clean some entries a little bit more, but that's the general idea.

1
  • By the way, if your thesaurus file is too large, vim will be slow to show the completion menu. As a solution, create your own function to match a subset of the results according to :h E840 or even better, wrap the whole thing into a binary and call it directly (e.g. system("thesaurus " .. a:base))
    – r_31415
    Commented Dec 26, 2022 at 22:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.