Empêcher le rafraîchissement de l'écran jusqu'à la fin de la fonction

10

J'ai une fonction qui fait beaucoup de déplacement et de sortie de texte dans le tampon vim actuel, et quand je l'exécute, voir tout ce qui se passe à une vitesse aveuglante est un peu déconcertant.

Comment puis-je figer l'écran jusqu'à ce que la fonction soit terminée?

Voici la fonction en question:

function! MakeChoices()
    :let save_view = winsaveview()
    let start = line('.')

    "Locate previous *choice. (b=backwards, W=nowrap, n=doNot move cursor)
    let choiceStartLine = search('^*choice', 'bW')

    if !choiceStartLine
        echo "No *choice found. (*choice must not be indented. This is to avoid finding *choice blocks nested in another *choice block.)"
        return -1
    endif
    "return getline(target_line_num, target_line_num+4)
    "Locate end of *choice block
    "echo getline(choiceStartLine, choiceStartLine+2)
    let choiceEndLine = search('^\S.*', 'W') "End is first line that starts with non-whitespace

    "If above search fails, might be at bottom of buffer
    if choiceEndLine == 0
        let choiceEndLine = search('^$', 'W') "End is first empty line
    endif

    "Now go back up to the last *goto
    let choiceEndLine = search('*goto', 'bW')

    "Get the entire *choice block and put it in gotoBlock
    let gotoBlock = getline(choiceStartLine, choiceEndLine)

    "Make labelArray (contains all labels to goto)
    let labelArray = []

    for cur in gotoBlock
        if match(cur, '*goto') != -1
            "echo 'cur: '.cur
            let curParsed = matchlist(cur, '*goto \(\S\+\)')
            "echo curParsed
            if len(curParsed) > 1
                let curLabel = curParsed[1]
            else
                echo 'ERROR: Bad *goto ('.cur.')'
                return -1
            endif
            call add(labelArray, curLabel)  
        endif
    endfor

    "Restore window to what it looked like (in case the searches scrolled
    "it)
    call winrestview(save_view)

    "Make newline after choice block if needed
    if strlen(getline(choiceEndLine+1)) > 0
        echo 'big line: '.getline(choiceEndLine+1)
        call cursor(choiceEndLine, 1)
        put=''
    endif

    call cursor(choiceEndLine+1, 1)

    "Put the new label blocks
    let skippedLabels = ''
    let numNewLabels = 0
    for cur in labelArray
        if !search('*label '.cur, 'wn')
            let numNewLabels += 1
            put='*label '.cur
            put='[This option is yet to be written.]'
            put=''
        else
            let skippedLabels .= cur.' '
        endif
    endfor

    "Remove trailing blank lines (Up to a point)
    let nextlines = getline(line('.')+1, line('.')+3)
    if len(nextlines) == 3
        if nextlines[0] == '' && nextlines[1] == '' && nextlines[2] == ''
            normal "_3dd
        elseif nextlines[0] == '' && nextlines[1] == ''
            normal "_2dd
        elseif nextlines[0] == ''
            normal "_dd
        endif
    endif

    "Move to first label's text (use ctrl-v ctrl-m to input the <CR> at
    "end)
    if numNewLabels != 0
        call cursor(choiceEndLine, 1)
        normal /\[This option is yet to be written.\]
        let @/='\[This option is yet to be written\.\]'
    endif

    "Print status message
    if len(skippedLabels) > 0
        echo 'Skipped: '.skippedLabels
    else
        echo 'New labels created: '.numNewLabels
    endif
endfunction
Flurrywinde
la source
2
Ça :set lazyredrawaide?
VanLaser
Non désolé. Cela n'aide que pour les macros. Je viens de l'essayer et cela n'a pas fonctionné pour ma fonction.
Flurrywinde
2
Je ne connais aucun moyen de le faire, à part peut-être geler la fenêtre du terminal (qui ne fonctionnera pas pour gVim). Mais peut-être existe-t-il une autre façon de faire fonctionner votre fonction avec moins de mises à jour d'écran? Il serait utile que vous
postiez
Vous l'avez demandé, @Carpetsmoker. ;-) Fonction ajoutée. (C'est assez long.)
Flurrywinde

Réponses:

5

Je pense que le problème n'est pas :lazyredrawqui, si je comprends bien des documents, devrait fonctionner pour les fonctions (voir :help :redraw, il dit "Utile pour mettre à jour l'écran à mi-chemin en exécutant un script ou une fonction").

Le problème est que vous utilisez normalpour mettre à jour le tampon et cela fonctionne comme si vous tapez réellement quelque chose et ici :lazyredrawn'a pas d'effet.

Au lieu de cela, normalvous devez utiliser des fonctions de manipulation de texte (comme setline()) et des commandes ex (comme :delete).

Comparez ces deux fonctions, la première MakeChangesNorm()fera des mises à jour d'écran folles, tandis que la seconde MakeChangesFunctions()fera la mise à jour instantanément:

function! MakeChangesNorm()
    let lastline = line('$')
    norm gg
    let linenum = line('.')
    let lastline = line('$')
    while linenum < lastline
        norm ^
        norm s/choice/test/
        norm j
        normal "_3dd
        let linenum = line('.')
        let lastline = line('$')
    endwhile
endfunction


function! MakeChangesFunctions()
    norm gg
    let linenum = line('.')
    let lastline = line('$')
    while linenum < lastline
        let line = getline(linenum)
        " Substitute using substitute() and setline()
        let line = substitute(line, 'choice', 'test', '')
        call setline(linenum, line)
        " Delete lines using :delete
        execute '.,.+2delete _'
        let linenum = line('.')
        let lastline = line('$')
    endwhile
endfunction

Le fichier sur lequel je l'ai testé ressemble à ceci:

*choice test2 test3 super
*choice test2 test3 super
*choice test2 test3 super
*choice test2 test3 super
*choice test2 test3 super
*choice test2 test3 super
*choice test2 test3 super
*choice test2 test3 super
*choice test2 test3 super
*choice test2 test3 super
... 60 lines like this ...
Boris Serebrov
la source
Pour être clair; n'y a-t-il aucun moyen d'émettre plusieurs commandes normales et de reporter entièrement la mise à jour de l'écran jusqu'à une commande "restaurer l'écran" ultérieure? Je crois comprendre winsaveviewet winrestviewsimplement stocker l'emplacement du curseur et la position relative de la ligne dans la fenêtre.
Luke Davis
Je vais poser cette question dans une autre question.
Luke Davis