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


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.