Zwiń vim składa się do pojedynczej linii, podobnie jak Atom lub Sublime Text

13

Jestem fanem sposobu, w jaki Atom i Sublime Text obsługują składanie linii, w którym widoczna jest pierwsza linia każdego zagięcia (wraz z podświetlaniem składni), a na końcu linii, który wskazuje zagięcie, dołączany jest znacznik.

Zobacz zrzut ekranu poniżej porównujący składanie wcięć Vima (u góry) w porównaniu z Atomem (u dołu):Składanie kodu Vim vs. Atom

Vim poświęca dwie linie dla każdego zagięcia. Pierwsza linia służy jako nagłówek, a druga linia opisuje niektóre informacje na temat zagięcia (liczba linii i tekstu wewnątrz zagięcia).

Atom używa tylko jednej linii i używa małego znacznika na końcu linii, aby wskazać fałd, wraz z kolorem dodanym do numerów linii po lewej stronie. Styl składania Atom wykorzystuje mniej nieruchomości na ekranie, ale nadal przekazuje wszystkie informacje, których naprawdę potrzebuję.

Jestem stronnikiem stylu składania Atom. Moim zdaniem wydaje się czystszy i bardziej spójny, szczególnie przy zestawianiu wielu metod lub atrybutów z rzędu (jak na powyższym zrzucie ekranu).

Czy istnieje sposób na przybliżenie przybliżenia stylu składania Atom w Vimie?

Mike Hearn
źródło
1
Myślę, że to dlatego, że twoje fałdy tak naprawdę nie zaczynają się od linii zawierającej nawiasy otwierające. Vim używa tylko tekstu zagięcia w linii, w której zaczyna się zagięcie. Zobacz na przykład, w jaki sposób umieszczanie nawiasów klamrowych wpływa na to w C: imgur.com/3h70dPf,wfCLPm7
muru
Ale to jest Python, bez nawiasów klamrowych ( from __future__ import braces) ... Jak skonfigurowałeś składanie? Czy możesz wkleić ten fragment kodu (lub inny, który pokazuje problem)? Vim pasuje do jednej linii, ale jak wspomniano muru, twoje foldy zaczynają linię późno.
Martin Tournoij
@Carpetsmoker nawiasy klamrowe służą jedynie zilustrowaniu miejsca rozpoczęcia składania. Ten sam efekt można zobaczyć, powiedzmy, Haskell.
muru
@MikeHearn Moja poprzednia odpowiedź była całkowicie niepoprawna. Zaktualizowałem go, aby zawierał rozwiązanie problemu.
Bogaty

Odpowiedzi:

12

Dwie linie vs. jedna linia

W Vimie wszystkie linie w folderze zostaną zwinięte do pojedynczej linii, a 'foldtext'następnie opcja określa streszczenie tych linii (zwykle myślniki, liczbę złożonych linii i treść z pierwszych (lub wszystkich) linii).

W twoim przykładzie w Vim tylko {...}sam blok parametrów jest zwinięty; linia powyżej (która wykorzystuje parametry) nie jest częścią zakładki. Natomiast w drugim edytorze ta linia z parametrami należy do fold, a jej tekstem (używając terminologii Vima) jest zawartość tego wiersza plus dołączony znacznik.

Dostosowanie

W Vimie fałdy mogą być generowane na różne sposoby (patrz :help fold-methods) i zależą 'filetype'od bufora. Trudność włączenia powyższej linii do zakładki zależy od tego; sprawdź z :setlocal foldmethod?. Dzięki składaniu wcięć nie ma na nic wpływu; musisz przejść na inną metodę. W przypadku składania składni oznaczałoby to dostosowanie definicji składni i może być bardzo trudne. Będziesz miał więcej szczęścia, jeśli użyjesz wyrażenia , ale nadal oznaczałoby to zrozumienie i zmianę logiki. (Jest mało prawdopodobne, że autor wtyczki typu pliku dostarczył konfigurację, aby na to wpłynąć).

Podświetlanie składni linii złożonej

To niestety nie jest możliwe. Vim zawsze używa Foldedgrupy wyróżnień dla całej złożonej linii. Możesz to poprawić za pomocą :highlightpoleceń w swoim pliku ~/.vimrc, ale indywidualne zróżnicowanie składni zostanie utracone.

Ingo Karkat
źródło
5

Vim już wyświetla fałdy jako pojedynczą linię. Jednak podczas indentskładania Vima wszystkie linie, które mają to samo wcięcie, są uwzględniane w fold. Tak więc na twoim zrzucie ekranu linie, które określasz jako „nagłówki” (np. Ten rozpoczynający się collection_base_url), nie mieszczą się w fałdach.

Za pomocą Vima możesz osiągnąć coś podobnego do składania Atomu 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

To definiuje wyrażenie krotnie (patrz :help fold-expr) w następujący sposób:

  • W przypadku linii bezpośrednio poprzedzających wcięte linie zwraca wcięcie następnego bloku.
  • W przypadku linii wciętych zwraca wcięcie. (Dzielone przez przesunięcie, więc każdy poziom wcięcia zwiększa zwracaną wartość o 1)
  • W przypadku linii na końcu bloku linii wciętych zwraca ciąg "<N", w którym N jest ustawione na wcięcie. To mówi Vimowi, że fałd poziomu N kończy się na tej linii.

Aktualizacja

@alxndr pyta w komentarzach, czy można to rozszerzyć tak, aby obejmowało odległe ends Ruby w foldach . Możesz zacząć od zastąpienia " Calculate indent levelsekcji następującymi:

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

W tej chwili nie jest to najbardziej niezawodne rozwiązanie (np. Nie powiedzie się, jeśli endinstrukcja znajduje się w tej samej linii, po średniku). Możesz poprawić kod wyrażenia regularnego i otaczający go kod, aby rozwiązać ten problem, ale ponieważ jesteś teraz w obszarze analizowania faktycznej składni pliku, podejrzewam, że sprawy mogą się skomplikować, zanim będziesz mieć dobre rozwiązanie.

Bogaty
źródło
Świetne podejście. Czy tę odpowiedź można uogólnić tak, aby poradziła sobie również z powiedzeniem Ruby, która jest zdystansowana enddo ukończenia bloku?
alxndr
1
@alxndr Zredagowałem swoją odpowiedź w dyskusji.
Bogaty
@Rich: Uważam też, że wysublimowane składanie tekstu, które pokazuje tylko znak ...na końcu wiersza jako symbol złożonego bloku tekstu, jest bardzo przydatne i sprawia, że ​​mniej rozpraszam uwagę niż konieczność podświetlania całego pierwszego wiersza bloku tekstu jak w vimie. Próbowałem twojego foldu powyżej z domyślnym zachowaniem foldowania vima, prosty nie działa. Jak mieć fold, który daje znak na końcu pierwszego wiersza bloku tekstowego pythonem? Czy powinienem otworzyć nowe pytanie? Właśnie testuję ponownie twój fold, to naprawdę działa bardzo dobrze z linią wcięcia. Super dzięki.
Tuyen Pham,
To jest niesamowite! Szukałem czegoś, co działa w trybie org, jak składanie, a to bardzo pomaga!
priomsrb