ยุบ vim จะพับเป็นบรรทัดเดียวคล้ายกับ Atom หรือ Sublime Text


13

ฉันเป็นแฟนตัวยงของวิธีที่การพับบรรทัด Atom และ Sublime Text ซึ่งบรรทัดแรกของแต่ละการพับสามารถมองเห็นได้ (พร้อมการเน้นไวยากรณ์) และเครื่องหมายจะต่อท้ายบรรทัดที่บ่งชี้การพับ

ดูภาพหน้าจอด้านล่างเปรียบเทียบการเยื้องการพับของ Vim (บนสุด) และ Atom (ล่าง):Vim vs. Atom การพับโค้ด

Vim อุทิศสองบรรทัดสำหรับแต่ละเท่า บรรทัดแรกทำหน้าที่เป็นหัวเรื่องและบรรทัดที่สองอธิบายข้อมูลบางอย่างเกี่ยวกับการพับ (จำนวนบรรทัดและข้อความที่อยู่ในการพับ)

Atom ใช้เพียงหนึ่งบรรทัดและใช้เครื่องหมายเล็ก ๆ ที่ท้ายบรรทัดเพื่อระบุการพับพร้อมด้วยสีที่เพิ่มไปยังหมายเลขบรรทัดทางด้านซ้าย สไตล์การพับของ Atom ใช้อสังหาริมทรัพย์บนหน้าจอน้อยลง แต่ยังคงสื่อสารข้อมูลทั้งหมดที่ฉันต้องการ

ฉันชอบสไตล์การพับของ Atom ดูเหมือนว่าฉันจะดูสะอาดและมีความสอดคล้องกันมากขึ้นโดยเฉพาะอย่างยิ่งเมื่อแสดงรายการวิธีการหรือแอตทริบิวต์หลายอย่างในแถว (เช่นในภาพหน้าจอด้านบน)

มีวิธีประมาณคร่าวๆสไตล์การพับของ Atom ใน Vim หรือไม่?


1
ฉันคิดว่าเป็นเพราะการพับของคุณไม่ได้เริ่มต้นด้วยบรรทัดที่มีวงเล็บเปิดอยู่ Vim ใช้การพับข้อความบนบรรทัดที่การพับเริ่มต้นเท่านั้น ตัวอย่างเช่นดูว่าการจัดตำแหน่งรั้งมีผลกับมันอย่างไรใน C: imgur.com/3h70dPf,wfCLPm7
muru

แต่นี่คือ Python ไม่ต้องใช้เครื่องมือจัดฟัน ( from __future__ import braces) ... คุณกำหนดค่าการพับได้อย่างไร และคุณสามารถวางข้อมูลโค้ดนี้ (หรืออีกอันหนึ่งที่แสดงให้เห็นถึงปัญหา) ได้หรือไม่ เสียงเรียกเข้าจะพับเป็นบรรทัดเดียว แต่ตามที่ muru พูดถึงการพับของคุณจะเริ่มสาย
Martin Tournoij

@Carpetsmoker วงเล็บปีกกาเป็นเพียงภาพประกอบที่เริ่มพับ เอฟเฟ็กต์แบบเดียวกันนี้สามารถมองเห็นได้พูด Haskell
muru

@MikeHearn คำตอบก่อนหน้าของฉันไม่ถูกต้องสมบูรณ์ ฉันได้อัปเดตเพื่อรวมวิธีแก้ไขปัญหาแล้ว
รวย

คำตอบ:


12

สองบรรทัดกับหนึ่งบรรทัด

ใน Vim บรรทัดทั้งหมดภายในครึ่งหนึ่งจะถูกยุบลงในบรรทัดเดียวและ'foldtext'ตัวเลือกจะกำหนดบทสรุปของบรรทัดเหล่านั้น (โดยปกติจะเป็นขีดกลางจำนวนบรรทัดที่ถูกพับและเนื้อหาจากบรรทัดแรก (หรือทั้งหมด))

ในตัวอย่างของคุณใน Vim มีเพียง{...}ตัวบล็อกพารามิเตอร์เท่านั้นที่ถูกพับ บรรทัดด้านบน (ที่ใช้พารามิเตอร์) ไม่ได้เป็นส่วนหนึ่งของการพับ ในทางกลับกันในเอดิเตอร์อื่นบรรทัดนั้นที่ใช้พารามิเตอร์เป็นของ fold และ foldtext (เพื่อใช้คำศัพท์ Vim) คือเนื้อหาของบรรทัดนั้นบวกกับเครื่องหมายต่อท้าย

การปรับตัว

ใน Vim สามารถสร้าง folds ได้ด้วยวิธีการต่างๆ (ดู:help fold-methods) และขึ้นอยู่กับ'filetype'บัฟเฟอร์ ความยากลำบากในการรวมบรรทัดด้านบนในการพับขึ้นอยู่กับว่า; :setlocal foldmethod?ตรวจสอบกับ ด้วยการเยื้องพับไม่มีอะไรที่คุณสามารถมีอิทธิพล คุณต้องเปลี่ยนไปใช้วิธีอื่น สำหรับการพับไวยากรณ์นั้นหมายถึงการปรับคำจำกัดความของไวยากรณ์และอาจยุ่งยากมาก คุณจะมีโชคดีขึ้นหากใช้การแสดงออกแต่ก็ยังคงหมายถึงความเข้าใจและการเปลี่ยนแปลงตรรกะ (ไม่น่าเป็นไปได้ว่าผู้เขียนปลั๊กอินประเภทไฟล์ให้การกำหนดค่าเพื่อมีอิทธิพลต่อสิ่งนี้)

การเน้นไวยากรณ์ของบรรทัดที่ถูกพับ

น่าเสียดายที่มันเป็นไปไม่ได้เลย Vim ใช้Foldedกลุ่มไฮไลต์สำหรับเส้นที่ถูกพับเสมอ คุณสามารถปรับแต่งที่ผ่าน:highlightคำสั่งในของคุณ~/.vimrcแต่ความแตกต่างของแต่ละไวยากรณ์จะหายไป


5

Vim แสดงการพับเป็นบรรทัดเดียวแล้ว อย่างไรก็ตามในการindentพับของ Vim เส้นทั้งหมดที่มีการเยื้องเดียวกันจะรวมอยู่ในการพับ ดังนั้นในภาพหน้าจอของคุณบรรทัดที่คุณอ้างถึงว่าเป็น "ส่วนหัว" (เช่นเริ่มต้นcollection_base_url) ไม่ได้อยู่ในรอยพับ

คุณสามารถบรรลุสิ่งที่คล้ายกับการพับอะตอมโดยใช้ Vim's foldexpr foldmethod:

" Finds the indent of a line. The indent of a blank line is the indent of the
" first non-blank line above it.
function! FindIndent(line_number, indent_width)
    " Regular expression for a "blank" line
    let regexp_blank = "^\s*$"

    let non_blank_line = a:line_number
    while non_blank_line > 0 && getline(non_blank_line) =~ regexp_blank
        let non_blank_line = non_blank_line - 1
    endwhile
    return indent(non_blank_line) / a:indent_width
endfunction

" 'foldexpr' for Atom-style indent folding
function! AtomStyleFolding(line_number)
    let indent_width = &shiftwidth

    " Find current indent
    let indent = FindIndent(a:line_number, indent_width)

    " Now find the indent of the next line
    let indent_below = FindIndent(a:line_number + 1, indent_width)

    " Calculate indent level
    if indent_below > indent
        return indent_below
    elseif indent_below < indent
        return "<" . indent
    else
        return indent
    endif
endfunction

set foldexpr=AtomStyleFolding(v:lnum)
set foldmethod=expr

สิ่งนี้นิยามนิพจน์การพับ (ดู:help fold-expr) ดังนี้:

  • สำหรับบรรทัดก่อนหน้าบรรทัดที่เยื้องมันจะส่งคืนการเยื้องของบล็อกที่ตามมา
  • สำหรับบรรทัดที่เยื้องมันจะส่งคืนการเยื้อง (หารด้วย shiftwidth ดังนั้นแต่ละระดับของการเยื้องจะเพิ่มค่าที่ส่งคืนด้วย 1)
  • สำหรับบรรทัดที่ส่วนท้ายของบล็อกของบรรทัดที่เยื้องมันจะส่งคืนสตริง"<N"โดยที่ N ถูกตั้งค่าเป็นเยื้อง สิ่งนี้จะบอกกลุ่มว่าการพับระดับ N เสร็จสิ้นในบรรทัดนั้น

ปรับปรุง

@alxndr ถามในความคิดเห็นว่าเป็นไปได้หรือไม่ที่จะขยายสิ่งนี้เพื่อรวมรูบีของ Ruby endที่อยู่ในรอยพับ คุณสามารถเริ่มต้นด้วยการแทนที่" Calculate indent levelส่วนด้วยสิ่งต่อไปนี้:

if indent_below > indent
    return indent_below
elseif getline(a:line_number) =~ '^\s*end\s*$'
    return "<" . (indent + 1)
else
    return indent
endif

ตามที่เป็นอยู่นี่ไม่ใช่โซลูชันที่แข็งแกร่งที่สุด (เช่นจะล้มเหลวหากendข้อความอยู่ในบรรทัดเดียวกันหลังจากเซมิโคลอน) คุณสามารถปรับเปลี่ยนนิพจน์ทั่วไปและรหัสโดยรอบเพื่อแก้ไขปัญหานี้ แต่ขณะนี้คุณอยู่ในขอบเขตของการแยกวิเคราะห์ไวยากรณ์ที่แท้จริงของไฟล์ฉันสงสัยว่าสิ่งต่าง ๆ อาจมีความซับซ้อนมากขึ้นก่อนที่คุณจะมีทางออกที่ดี


วิธีการที่ยอดเยี่ยม คำตอบนี้สามารถพูดคุยกันทั่วไปเพื่อจัดการกับพูดว่า Ruby กับ outdented endเพื่อเสร็จสิ้นบล็อก?
alxndr

1
@alxndr ฉันได้แก้ไขคำตอบของฉันด้วยการสนทนา
รวย

@ ริช: ฉันยังพบ Sublime text fold ที่แสดงเครื่องหมาย...ที่ท้ายบรรทัดเป็นสัญลักษณ์ของบล็อกข้อความที่พับมากมีประโยชน์มากและทำให้ฟุ้งซ่านน้อยกว่าต้องเน้นทั้งบรรทัดแรกของบล็อกข้อความเช่นเดียวกับในกลุ่ม ฉันลองใช้โฟลด์ของคุณด้านบนด้วยค่าเริ่มต้นการพับของวีไอพีธรรมดาไม่ทำงาน ทำอย่างไรถึงจะมีรอยพับที่ทำเครื่องหมายที่ท้ายบรรทัดแรกของบล็อกข้อความด้วยไพ ธ อน? ฉันควรเปิดคำถามใหม่หรือไม่ ฉันเพิ่งทดสอบรอยพับของคุณอีกครั้งมันทำงานได้ดีกับเส้นเยื้อง สุดยอดขอบคุณ
Tuyen Pham

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