ป้องกันการรีเฟรชหน้าจอจนกว่าฟังก์ชั่นจะเสร็จสมบูรณ์


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เพียงเก็บตำแหน่งเคอร์เซอร์และตำแหน่งสัมพัทธ์ของบรรทัดในหน้าต่าง
ลุคเดวิส

ฉันจะถามคำถามนี้ในคำถามอื่น
ลุคเดวิส
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.