Jak poruszać się w pionie, aż do znaku spacji?

27

W bardzo długim pliku z (dokładnie) wciętym kodem pomocne może być przejście bezpośrednio do wiersza tekstu powyżej lub poniżej kursora, który ogranicza wcięcie.

(Jednym ze sposobów na to może być metoda wcięcia, składając bieżący poziom wcięcia, który zwija linie ograniczające poziom wcięcia na odległość tylko a jlub kod kursora. Znalazłem jednak przypadki, w których składanie wcięcia nie mogłem pracować nad wcięciem, które mnie interesuje).

Oto przykład, z kursorem zaznaczonym podkreśleniem _(w kolumnie drugiego znaku między definicjami class Bazzi class Qux), ale wyobraź sobie, że liczba akapitów lub linii w ciągu modules jest nieznana lub zmienna:

module Foo
  # lots of code...
end

module Bar
  class Baz
    # ...
  end

  class Bazz
    # lots of code...
  end
 _
  class Qux
    # ...
  end

  class Quux
    # lots of code...
  end
end

... w jaki sposób mogę szybko nawigować do oz module Barnad kursorem, lub nz endponiżej kursora w ostatniej linii? Zauważ, że pionowa kolumna zawiera białe spacje, ale także żadnych znaków w drugiej kolumnie pomiędzy classdefinicjami.

alxndr
źródło
2
powiązane: „Przejdź do następnej / poprzedniej linii z tym samym wcięciem” na Wiki Vim Tips vim.wikia.com/wiki/Move_to_next/…
alxndr
Naciskając g, a następnie klawisz kierunku, można uniknąć tabulacji i poruszania się po liniach
SibiCoder 19.04.16
1
Rozwiązanie w linku @ alxndr działa dobrze, z wyjątkiem przypadku, gdy białe znaki są źle utrzymane (np. Istnieją losowe linie, które mają tylko białe znaki) i chcesz zignorować biały znak. Poniższe rozwiązanie superjer jest lepsze, jeśli ktoś jest zaniepokojony tą sprawą.
nukeguy,

Odpowiedzi:

9

A co z tą funkcją?

function FloatUp()
    while line(".") > 1
                \ && (strlen(getline(".")) < col(".")
                \ || getline(".")[col(".") - 1] =~ '\s')
        norm k
    endwhile
endfunction

Możesz nnoremap gU :call FloatUp()<CR>( gUdla „iść w górę”), a następnie wywołać za pomocą gU.

Oto wyjaśnienie:

  • Kod wielokrotnie przesuwa kursor w górę (z norm k) tak długo, jak długo whilewarunek się utrzymuje.
  • whileWarunek jest spełniony, jeśli nie jest to pierwsza linia ( line(".") > 1) i albo
    • ta linia jest za krótka (prawdopodobnie pusta); lub
    • getline(".")znak bieżącej linii ( ) w bieżącej kolumnie ( [col(".") - 1]) to biały znak ( =~ '\s'tzn. pasuje do wzorca białych znaków).
wchargin
źródło
1
Wydaje się, że działa to idealnie (i szybko) i łatwo można go również zmienić w FloatDownfunkcję. Wchodzi w moje .vimrc, dzięki! github.com/alxndr/dotfiles/commit/0e25a302
alxndr
1
Właśnie odkryłem, że to rozwiązanie nie działa w trybie wizualnym (nieco inne zachowanie w zależności od trybu wizualnego, albo pozostanie w tej samej pozycji, albo przesunie się tylko o jedną linię). Wszelkie wskazówki na temat tego, co się tam dzieje?
alxndr
13

Lubię używać wyszukiwania tych rzeczy, ponieważ wyrażenia regularne Vima zawierają niesamowitą liczbę rzeczy, których możesz szukać, na przykład konkretne numery wirtualnych kolumn, w tym przypadku:

nnoremap cd /\%<C-R>=virtcol(".")<CR>v\S<CR>

nnoremap cu ?\%<C-R>=virtcol(".")<CR>v\S<CR>

Użyj, cdaby zejść i cuzejść. Myślę tutaj o „kolumnie w górę” i „kolumnie w dół”. Jestem prawie w 100% pewien, że domyślnie nie są to operacje. Lub wybierz własne mapowania.

Powinno to działać niezależnie od tego, czy używasz tabulatorów, spacji, czy obu.

superjer
źródło
1
Mam problem z analizowaniem tych poleceń. Czy mógłbyś rozwinąć je nieco?
davidlowryduda
1
/ lub? aby wyszukiwać w dół lub w górę, \% xv ogranicza wyszukiwanie do wirtualnej kolumny o numerze „x”, „x” w tym przypadku to „<CR> = virtcol („. ”) <CR>”, która uruchamia polecenie virtcol i wstawia wirtualny numer kolumny, w której znajduje się kursor, jest wyrażeniem, \ S oznacza dowolny znak spacji.
Czad
1
Dzięki za wyjaśnienie Czadu. Dodam tylko, że <CR> w trybie wstawiania lub trybie wiersza poleceń pobiera zawartość rejestru. =Rejestr jest rejestrem wyrażenie który ocenia wyrażenia w miejscu. Jest to bardzo przydatne, jeśli nie trochę dziwne.
superjer
1
Jedną wadą tego podejścia jest to, że jeśli masz podświetlanie wyszukiwania, zauważysz, że wszystkie znaki w pionowej kolumnie kursora są teraz podświetlone po „podniesieniu kolumny” lub „przesunięciu kolumny”.
alxndr
3
Jeśli chcesz zabezpieczyć istniejące wyszukiwanie, możesz :let searchbak=@/<CR>dodać je i dołączyć :let @/=searchbak<CR>. Ale w tym momencie robi się to dość długie i niedostępne i może powinno być tylko funkcją.
superjer
7

Możesz użyć wtyczki JumpToVerticalOccurrence (domyślnie zmapowane do ]|i [|). Istnieje kilka innych podobnych, ]V{char}które działają jak f, ale pionowo. Możesz oczywiście ponownie przypisać je w razie potrzeby.


Jeśli nie chcesz korzystać z wtyczek, można spróbować skorzystać :searchz virtcol(.), na przykład:

:call search('\%' . virtcol('.') . 'v\S', 'bW')

gdzie:

  • virtcol('.') daje bieżącą kolumnę,
  • \S oznacza spacje
  • bW służy do wyszukiwania wstecz

Sprawdź, :help searchaby dowiedzieć się więcej.

Aby ułatwić obsługę, możesz go zmapować, np .:

:map <C-k> :call search('\%' . virtcol('.') . 'v\S', 'bW')<CR>
:map <C-j> :call search('\%' . virtcol('.') . 'v\S', 'W')<CR>

Alternatywnie, jeśli kod zawiera wsporniki, korzystanie %skakać między dopasowując je (na przykład {, }, [, ], itd.) Lub wykorzystać cały ustęp skoki ( {, }o Shiftile to konieczne).


Linki / źródła:

kenorb
źródło
Od :h search(): wśrodki wrap around the end of the filei Wśrodki don't wrap around the end of the file. Ale dlaczego umieściłeś je razem :map?
Jair López
@JairLopez Prawidłowo, wnie powinno tam być, więc usunąłem go, dzięki. Prawdopodobnie byłem zdezorientowany znaczeniem klawiszy ruchu.
kenorb
3

Używam zmodyfikowanej wersji wtyczki vim-indent-object, aby zapewnić takie zachowanie. Moje modyfikacje można zobaczyć tutaj .

To pozwala mi mapować, [iaby przejść do początku bieżącego poziomu wcięcia i ]iprzejść do końca.

Steve Vermeulen
źródło
2

To nie jest dokładnie to, co prosiłeś, bo to nie jest ruch pionowy, ale coś, co jest podobny, szybki i może być wystarczająco dobre dla ciebie jest w ruchu do tyłu 2 akapity: {{. To zabierze Cię do linii tuż przed module Bar.

Przestań krzywdzić Monikę
źródło
2
Wyobraź sobie, że między kursorem a modulelinią najwyższego poziomu jest nieznana liczba linii i / lub akapitów . (W szczególności sytuacja ta pojawiła się, gdy ostatnio nawigowałem po kodzie innej firmy o długości kilku tysięcy wierszy, z dokładnym wcięciem, ale bez pustych linii, i próbowałem znaleźć zewnętrzny kontekst definicji modułu.)
alxndr
Przeskakiwanie po akapitach to mój preferowany sposób poruszania się, ale nie była to opcja: cały plik był jednym „akapitem”.
alxndr
1

Używam do tego własnej wtyczki move_until_char_changes.vim .

Mapuję to na gKi gJ.

Przeskoczy przez wiele wierszy o tym samym znaku w bieżącej kolumnie (nie tylko białe znaki), co może być przydatne w plikach dziennika lub zrzutach SQL z powtarzającymi się ciągami.

Domyślnie najpierw przesuwa się o jedną linię, a następnie podnosi znak „wyszukiwania”.

Działa w trybie wizualnym, pod warunkiem, że nie spróbujesz użyć go dwa razy i nie jesteś w trybie wizualnym liniowym lub blokowym ... (poprawki mile widziane!)

joeytwiddle
źródło
1

Ponieważ nie widzę tego tutaj jako odpowiedzi ( edycja zauważyła, że superjer wspomniał o czymś bardzo podobnym). Możesz po prostu / lub? Szukaj.

Na przykład możesz wyszukać znak spacji w drugiej kolumnie w dół w następujący sposób:

/\%2v\S

Podział jest następujący:

/    "search downward (use ? for upward movement)
\%2v "for the following char in the 2nd virtual column
\S   "any non white space character

Następnie możesz użyć zwykłych operatorów, aby powtórzyć wyszukiwanie.

Aby uzyskać więcej informacji na ten temat, patrz :help \%ci :help \%v.

Eric
źródło