Thu gọn vim gấp thành một dòng duy nhất, tương tự như Văn bản nguyên tử hoặc Sublime


13

Tôi là người hâm mộ cách thức xếp nếp của Atom và Sublime Text, trong đó có thể nhìn thấy dòng đầu tiên của mỗi nếp gấp (hoàn thành với tô sáng cú pháp) và một điểm đánh dấu được gắn vào cuối dòng cho biết nếp gấp.

Xem ảnh chụp màn hình bên dưới so sánh nếp gấp thụt lề của Vim (trên cùng) so với của Atom (dưới):Gấp mã Vim so với nguyên tử

Vim dành hai dòng cho mỗi lần gấp. Dòng đầu tiên đóng vai trò là một tiêu đề và dòng thứ hai mô tả một số thông tin về nếp gấp (số dòng và văn bản bên trong nếp gấp).

Nguyên tử chỉ sử dụng một dòng và sử dụng một điểm đánh dấu nhỏ ở cuối dòng để chỉ ra nếp gấp, cùng với màu được thêm vào các số dòng bên trái. Phong cách gấp của Atom sử dụng bất động sản màn hình ít hơn nhưng vẫn truyền đạt tất cả thông tin tôi thực sự cần.

Tôi là một phần của phong cách gấp nguyên tử. Theo tôi, nó có vẻ sạch sẽ và nhất quán hơn, đặc biệt là khi liệt kê nhiều phương thức hoặc thuộc tính liên tiếp (như trong ảnh chụp màn hình ở trên).

Có cách nào để xấp xỉ phong cách gấp của Atom trong Vim không?


1
Tôi nghĩ đó là vì nếp gấp của bạn không thực sự bắt đầu bằng dòng chứa dấu ngoặc mở. Vim chỉ sử dụng văn bản gấp trên dòng bắt đầu gấp. Xem, ví dụ, vị trí niềng răng
muru

Nhưng đây là Python, không có dấu ngoặc nhọn nào ( from __future__ import braces) ... Bạn đã cấu hình gấp như thế nào? Và bạn có thể dán đoạn mã này (hoặc đoạn mã khác thể hiện vấn đề) không? Vim gấp thành một dòng duy nhất, nhưng như muru đã đề cập, nếp gấp của bạn bắt đầu một dòng muộn.
Martin Tournoij 24/2/2015

@Carpetsmoker niềng răng chỉ để minh họa nơi bắt đầu gấp. Hiệu ứng tương tự có thể được nhìn thấy trên, nói, Haskell.
muru

@MikeHearn Câu trả lời trước của tôi là hoàn toàn không chính xác. Tôi đã cập nhật nó để bao gồm một giải pháp cho vấn đề.
Giàu

Câu trả lời:


12

Hai dòng so với một dòng

Trong Vim, tất cả các dòng trong một nếp gấp sẽ được thu gọn thành một dòng duy nhất'foldtext'sau đó tùy chọn sẽ xác định tóm tắt của các dòng đó (thường là dấu gạch ngang, số dòng gấp và nội dung từ các dòng đầu tiên (hoặc tất cả)).

Trong ví dụ của bạn, trong Vim chỉ có {...}khối tham số được gập lại; dòng trên (sử dụng các tham số) không phải là một phần của nếp gấp. Ngược lại, trong trình soạn thảo khác, dòng đó sử dụng các tham số thuộc về nếp gấp và đoạn văn bản của nó (để sử dụng thuật ngữ Vim) là nội dung của dòng đó cộng với điểm đánh dấu được nối thêm.

Thích nghi

Trong Vim, các nếp gấp có thể được tạo thông qua các phương tiện khác nhau (xem :help fold-methods) và phụ thuộc vào 'filetype'bộ đệm. Khó khăn của việc bao gồm các dòng trên trong nếp gấp phụ thuộc vào điều đó; kiểm tra với :setlocal foldmethod?. Với cách thụt lề , không có gì bạn có thể ảnh hưởng; bạn phải chuyển sang phương pháp khác Đối với việc gấp cú pháp , điều đó có nghĩa là điều chỉnh các định nghĩa cú pháp và có thể rất khó. Bạn sẽ gặp may mắn hơn nếu một biểu thức được sử dụng, nhưng nó vẫn có nghĩa là hiểu và thay đổi logic. (Không chắc là tác giả plugin filetype đã cung cấp cấu hình để ảnh hưởng đến điều này.)

Cú pháp tô sáng của đường gấp

Thật không may, điều đó là không thể. Vim luôn sử dụng Foldednhóm tô sáng cho toàn bộ đường gấp. Bạn có thể điều chỉnh thông qua :highlightcác lệnh trong lệnh của mình ~/.vimrc, nhưng sự khác biệt của cú pháp sẽ bị mất.


5

Vim đã hiển thị các nếp gấp như một dòng duy nhất. Tuy nhiên, trong cách indentgấp của Vim , tất cả các dòng có cùng một vết lõm được bao gồm trong một nếp gấp. Vì vậy, trong ảnh chụp màn hình của bạn, các dòng bạn đang gọi là "tiêu đề" (ví dụ: dòng bắt đầu collection_base_url) không nằm trong các nếp gấp.

Bạn có thể đạt được thứ gì đó tương tự như cách gấp của Atom bằng cách sử dụng Vim 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

Điều này định nghĩa một biểu thức gấp (xem :help fold-expr) như sau:

  • Đối với các dòng ngay trước dòng thụt lề, nó trả về độ thụt của khối theo sau.
  • Đối với các dòng thụt lề, nó trả về thụt lề. (Được chia theo độ rộng dịch chuyển để mỗi cấp độ thụt đầu dòng tăng giá trị được trả về 1)
  • Đối với các dòng ở cuối một khối các dòng thụt lề, nó trả về một chuỗi "<N", trong đó N được đặt thành thụt lề. Điều này nói với Vim rằng một cấp độ N kết thúc trên dòng đó.

Cập nhật

@alxndr hỏi trong các nhận xét liệu có thể mở rộng điều này để bao gồm các lỗi thời của Ruby endtrong các nếp gấp hay không. Bạn có thể bắt đầu bằng cách thay thế " Calculate indent levelphần bằng cách sau:

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

Vì nó là, đây không phải là giải pháp mạnh mẽ nhất (ví dụ: nó sẽ thất bại nếu endcâu lệnh nằm trên cùng một dòng, sau dấu chấm phẩy). Bạn có thể điều chỉnh biểu thức chính quy và mã xung quanh để giải quyết vấn đề này, nhưng vì bây giờ bạn đang ở trong lĩnh vực phân tích cú pháp thực tế của tệp, tôi nghi ngờ mọi thứ có thể phức tạp hơn nhiều trước khi bạn có giải pháp tốt.


Cách tiếp cận tuyệt vời. Câu trả lời này có thể được khái quát để xử lý Ruby nói, với lỗi thời của nó endđể hoàn thành một khối?
alxndr

1
@alxndr Tôi đã chỉnh sửa câu trả lời của mình bằng một số thảo luận.
Giàu

@Rich: Tôi cũng thấy nếp gấp văn bản Sublime chỉ hiển thị một dấu ...ở cuối dòng là biểu tượng của khối văn bản được gấp rất hữu ích và làm giảm sự phân tâm hơn là phải làm nổi bật toàn bộ dòng văn bản đầu tiên như trong vim. Tôi đã thử gấp của bạn ở trên với hành vi gấp mặc định của vim, đơn giản không hoạt động. Làm thế nào để có nếp gấp cho một dấu ở cuối dòng đầu tiên của khối văn bản với python? Tôi có nên mở một câu hỏi mới? Tôi chỉ kiểm tra lại nếp gấp của bạn, nó thực sự hoạt động rất tốt với dòng thụt lề. siêu cảm ơn
Tuyên Phạm

Thật đáng kinh ngạc! Tôi đã tìm kiếm thứ gì đó có chế độ org như gấp và điều này giúp ích rất nhiều!
Priomsrb
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.