기능이 완료 될 때까지 화면 새로 고침 방지


10

현재 vim 버퍼로 텍스트를 많이 이동하고 출력하는 기능이 있으며, 실행할 때 맹목적인 속도로 발생하는 모든 것을 보는 것은 약간 당황합니다.

기능이 완료 될 때까지 어떻게 화면을 정지시킬 수 있습니까?

문제의 기능은 다음과 같습니다.

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

2
합니까의 :set lazyredraw도움?
VanLaser

죄송합니다 매크로에만 도움이됩니다. 방금 시도했지만 기능이 작동하지 않았습니다.
Flurrywinde

2
터미널 창을 정지시키는 것 외에는 (gVim에서는 작동하지 않음)이를 수행하는 방법을 모르겠습니다. 그러나 적은 화면 업데이트로 기능을 실행하는 다른 방법이 있습니까? 함수를 게시하면 도움이 될 것입니다 ;-)
Martin Tournoij

당신은 그것을 요청했습니다, @Carpetsmoker. ;-) 기능이 추가되었습니다.
Flurrywinde

답변:


5

나는 :lazyredraw문서에서 알 수 있듯이 함수에서 작동 해야하는 문제가 아니라고 생각합니다 ( :help :redraw"스크립트 또는 함수를 실행하여 화면을 반쯤 업데이트하는 데 유용합니다"참조).

문제는 normal버퍼를 업데이트 하는 데 사용 하며 실제로 무언가를 입력 :lazyredraw해도 효과가없는 것처럼 작동한다는 것 입니다.

대신 normal텍스트 조작 기능 ( setline()예 :)과 ex 명령 (예 :) 을 사용해야합니다 :delete.

이 두 기능을 비교해보십시오. 첫 번째 기능 MakeChangesNorm()은 미친 화면 업데이트를 수행하고 두 번째 MakeChangesFunctions()기능은 즉시 업데이트를 수행합니다.

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

내가 테스트 한 파일은 다음과 같습니다.

*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 ...

확실하게; 후속 "화면 복원"명령까지 몇 가지 일반 명령을 실행하고 화면 업데이트를 완전히 연기 할 수있는 방법이 없습니까? 나의 이해는 winsaveview하고 winrestview단순히 커서 위치와 창에서 라인의 상대 위치를 저장합니다.
Luke Davis

나는 다른 질문으로 이것을 물을 것이다.
Luke Davis
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.