Vim: auto-komentarz w nowej linii

9

Vim automatycznie wstawia komentarz, gdy rozpoczynam nowy wiersz od skomentowanej linii, ponieważ ustawiłem formatoptions=tcroql. Na przykład (kursor jest * ):

// this is a comment*

i po uderzeniu <Enter> (tryb wstawiania) lub o (tryb normalny) pozostało mi:

// this is a comment
// *

Ta funkcja jest bardzo przydatna przy pisaniu długich komentarzy wieloliniowych, ale często po prostu chcę komentarza z jedną linią. Teraz, jeśli chcę zakończyć serię komentarzy, mam kilka opcji:

  • trafienie <Esc>S
  • trafienie <BS> trzy razy

Oba zapewniają trzy naciśnięcia klawiszy, razem z <Enter> Oznacza to cztery naciśnięcia klawiszy dla nowej linii, co uważam za zbyt wiele. Idealnie chciałbym po prostu trafić <Enter> po raz drugi pozostanie z:

// this is a comment
*

Ważne jest, aby rozwiązanie działało również z różnymi poziomami wcięć, tj.

int main(void) {
    // this is a comment*
}

trafienie <Enter>

int main(void) {
    // this is a comment
    // *
}

trafienie <Enter>

int main(void) {
    // this is a comment
    *
}

Myślę, że widziałem tę funkcję w jakimś edytorze tekstu kilka lat temu, ale nie pamiętam, który to był. Czy ktoś wie o rozwiązaniu, które zrobi to dla mnie w Vimie? Bardzo mile widziane są również wskazówki dotyczące właściwego toczenia własnego rozwiązania.

Patrick Oscity
źródło
1
Możesz użyć ctrl-u w trybie wstawiania, aby usunąć automatycznie wstawione znaczniki komentarza w jednym akordie.
Etan Reisner
1
@EtanReisner, który jest rzeczywiście lepszy, ale wciąż jeden klawisz zbyt wiele dla mnie, ponieważ jest to typowy przypadek użycia :)
Patrick Oscity
Zasugerowałeś, że chcesz mieć możliwość ponownego naciśnięcia klawisza Enter, aby uzyskać pożądane zachowanie, ale ctrl-u jest za dużo? Możesz spróbować odwzorować & lt; wprowadź & gt; & lt; wprowadź & gt; w trybie wstawiania, aby automatycznie wykonać ctrl-u dla ciebie, ale spowodowałoby to opóźnienie, jeśli kiedykolwiek trafisz & lt; wpisz & gt; tylko raz (bez uderzania w cokolwiek innego).
Etan Reisner
Cóż, dodatkowo, powinno się uruchamiać tylko wtedy, gdy skomentowana linia jest pusta. Zauważalne opóźnienie podczas klikania & lt; Enter & gt; jest również niedopuszczalne.
Patrick Oscity
To tylko opóźni, jeśli nie trafisz żadnych innych kluczy, ponieważ vim będzie musiał poczekać, aby upewnić się, że nie planujesz trafić innego klucza. Możesz użyć funkcji do wykonania tego sprawdzenia, myślę jednak, że może to nie być szczególnie proste.
Etan Reisner

Odpowiedzi:

3

Spróbuj tego:

function! EnterEnter()
  if getline(".") =~ '^\s*\(//\|#\|"\)\s*$'
    return "\<C-u>"
  else
    return "\<CR>"
  endif
endfunction

imap <expr> <CR> EnterEnter()
romainl
źródło
Dzięki wygląda świetnie! Spróbuję, kiedy wrócę do domu. Czy wiesz, jak rozszerzyć wyrażenie regularne, aby dopasować język znaczników komentarzy niezależnie? Informacje powinny znajdować się w plikach składni lub coś takiego. Może mogę skorzystać z funkcji składni tego ...
Patrick Oscity
Chodzi mi o to, że w C powinno pasować // i / * i * (komentarze wielowierszowe) oraz w rubinie # i tak dalej
Patrick Oscity
Oczywiście ta funkcja wcale nie jest ogólna. Widzieć :h 'comment' i :h format-comment'.
romainl
Funkcja zmodyfikowana do pracy z # rubinu i " vimscript jako dodatek do klasyki //. Nie ma sensu robić nic dla * komentarzy wielowierszowych w stylu C, ponieważ to musi zakończyć na */ tak czy inaczej.
romainl
Hmm może <CR><CR> można użyć do zakończenia komentarza wielowierszowego ...
romainl
3

Rozszerzyłem odpowiedź @ romainl na pracę z dowolnymi językami, generując wyrażenie regularne z Vima &commentstring:

function! s:IsOnlyComment(getlineArg)
  let commentRegex='^\s*'.substitute(&commentstring,'%s','\\s*','').'$'
  return strlen(matchstr(getline(a:getlineArg), commentRegex)) > 0
endfunction

function! SmartEnter()
  if s:IsOnlyComment('.')
    return "\<Esc>S"
  else
    return "\<CR>"
  endif
endfunction

inoremap <expr> <CR> SmartEnter()

Jednak nie mogę się zmienić <CR> w ogóle to nie zadziała. Na razie używam <CR><CR> dopóki ten problem nie zostanie rozwiązany.

Patrick Oscity
źródło
Czemu <Esc>S? <C-u> robi to samo bez wychodzenia z trybu wstawiania. W każdym razie miałem funkcję niestandardową, która robiła kilka rzeczy <CR> i zmienił nazwę na SmartEnter() wczoraj po wysłaniu mojej odpowiedzi ;-). Również nie jestem pewien &commentstring jest właściwym wyborem, ponieważ zazwyczaj zawiera tylko jedną formę i może być „linewise” lub „blockwise” ( /*%s*/ w C, //%s w Javascript itp.).
romainl
1

Usuń r z opcji formatowania. To właśnie robi ta opcja. Wyłączenie go oznacza, że ​​vim nigdy nie zrobi tego za ciebie, co oznacza, że ​​będziesz musiał dodać wiodące znaczniki komentarza, kiedy rzeczywiście tego chcesz, ale to jest kompromis.

Etan Reisner
źródło
2
ja własciwie chcieć Vim, aby dodać dla mnie znaczniki komentarzy, kocham to. Ale chcę także szybki sposób na wyjście z komentarza. Dziękuję za odpowiedź.
Patrick Oscity