Czy mogę łączyć linie przecinkiem (lub innym znakiem)?

19

Wiem, że mogę łączyć linie w Vimie z Jkilkoma ich wariantami ( gJitp.); Jspowoduje „Usunięcie wcięcia i wstawienie maksymalnie dwóch spacji” .

Ale czy istnieje również prosty sposób wstawienia innej postaci zamiast dwóch spacji? Na przykład przecinek ( ,) czy przecinek i spacja ( ,)?

Dany:

8
9
10
32

Chciałbym skończyć z:

8, 9, 10, 32

lub:

8,9,10,32
Martin Tournoij
źródło
Możesz także polubić github.com/sk1418/Join (nie testowane).
VanLaser,

Odpowiedzi:

5

Napisałem wtyczkę Join, mogę robić, co chcesz i wiele więcej.

Oprócz wszystkich funkcji udostępnianych przez polecenie wbudowane: dołączenie, Join może:

  • Połącz linie z separatorem (ciąg)
  • Połącz linie z lub bez przycinania wiodących / końcowych białych znaków
  • Łącz linie z liczbą ujemną (łączenie wstecz)
  • Połącz linie w odwrotnej kolejności
  • Połącz linie i zachowaj połączone linie (bez usuwania połączonych linii)
  • Połącz linie z dowolnymi kombinacjami powyższych opcji

więcej szczegółów i zrzuty ekranu:

https://github.com/sk1418/Join

Kent
źródło
23

Prosty sposób jest następujący: po prostu wybierz swoje linie (wszystkie oprócz ostatniego) - lub użyj %- i uruchom:

:'<,'>s/\n/,/

lub

:'<,'>s/\n/, /

(gdzie oczywiście '<,'>część została już wstawiona :przez Vima, aby celować w wybór)


(2.) Aktualizacja:

Opierając się na powyższym (i komentarzu Sato Katsury ), oto możliwa implementacja „interaktywnego łączenia” z liczeniem i opcjonalną obsługą powtarzania:

" ================ script ===============================================
" interactive 'J', 'gJ' replacement with optional 'vim-repeat' support
" The last used separator is automatically reused as:
" a. default choice
" b. when repeating (=> non-interactive repeats: same range, same separator)
let g:last_join_separator = " "
function! s:interactiveJoin(use_last_sep,...) range
    if (a:use_last_sep == 0) "interactive, ask for separator to use
        call inputsave()
        echohl Question
        let l:sep = input("Separator:", g:last_join_separator)
        echohl None
        call inputrestore()
        redraw!
        let g:last_join_separator = l:sep "update last separator value
    else "non-interactive (when repeating with '.')
        let l:sep = g:last_join_separator
    endif
    if (a:0 == 0) "with no argument, remove indentation *and trailing spaces*
        let l:subst = 's/\s*\n\+\s*/\=' . "'" . l:sep . "'/"
    else " don't remove indentation or trailing spaces (act like 'gJ')
        let l:subst = 's/\n\+/\=' . "'" . l:sep . "'/"
    endif
    if a:firstline < a:lastline "join given range
        execute a:firstline . ',' . (a:lastline - 1) . l:subst
        let l:count = a:lastline - a:firstline + 1 "default count for repeat
    else "or join only with next line
        execute l:subst
        let l:count = 1 "default count for repeat
    endif
    "make command repeatable
    "(with the tpope/vim-repeat plugin: optional, recommended)
    if (a:0 == 0)
        silent! call repeat#set("\<Plug>(repeatJoin)", l:count)
    else
        silent! call repeat#set("\<Plug>(repeatGJoin)", l:count)
    endif
endfunction

noremap <silent> <Plug>(interactiveJoin)  :call <SID>interactiveJoin(0)<CR>
noremap <silent> <Plug>(interactiveGJoin) :call <SID>interactiveJoin(0,'g')<CR>
noremap <silent> <Plug>(repeatJoin)       :call <SID>interactiveJoin(1)<CR>
noremap <silent> <Plug>(repeatGJoin)      :call <SID>interactiveJoin(1,'g')<CR>

I rzeczywiste mapowanie:

"================= vimrc ================================================
nmap J <Plug>(interactiveJoin)
xmap J <Plug>(interactiveJoin)
nmap gJ <Plug>(interactiveGJoin)
xmap gJ <Plug>(interactiveGJoin)

Jest to trochę (*) J, ale interaktywne - będzie monitować o ciąg separatora. Domyślnym ciągiem jest spacja - na przykład, aby połączyć linie bez separatora, nacisnąć Backspacepo wyświetleniu monitu, aby usunąć domyślny znak spacji i Enterzaakceptować (teraz) pusty separator. Policz np. 3JTeż działa. Jeśli tpope/vim-repeatwtyczka jest zainstalowana, powtarzanie za pomocą „.” będzie również działać, ponownie wykorzystując ostatni separator i (jeśli nie zostanie zmieniony - np. 10.) ostatnią liczbę lub zakres linii wizualnej.


(*) Nie jest to jednak dokładnie tak J: chociaż usunie wcięcia, nie będzie sprawdzać .!?(końca frazy) wstawienia 2 spacji zamiast jednego lub wstawiania spacji tylko wtedy, gdy jej brakuje (ciężko jest zrobić coś takiego to, ponieważ ciąg separatora może być teraz dowolny). Usunie także końcowe spacje (ma to większy sens).

Myślę, że może to być dobry sposób na przeciążenie ograniczonej przestrzeni na litery operatorów :)

Cóż, technicznie rzecz biorąc, Jnie jest operatorem, ale zbliżonym do jednego - na przykład nie możesz tego zrobić Jaw, aby dołączyć do „słowa”.

(sugestie są mile widziane)

wprowadź opis zdjęcia tutaj

VanLaser
źródło
2
Jeszcze lepiej: :'<,'>-1s/\n/, /dla zaznaczonych linii lub :1,$-1s/\n/, /dla całego pliku.
Sato Katsura,
Rzeczywiście, to jeszcze lepiej :)
VanLaser
@SatoKatsura czy możesz to wyjaśnić -1?
alxndr
1
@alxndr - służy do pominięcia ostatniej linii w zakresie / pliku: np. w przykładzie OP nie chcesz przecinka po 32, a także nie chcesz dołączać go do następnego wiersza, jeśli istnieje . Możesz nawet użyć '<,'>-s/\n/, /lub 1,$-s/\n/, /tak -samo jak -1.
VanLaser,
1
Jeśli l:sepjest &, to zamiennik będzie działał niepoprawnie, ponieważ &ma magię w zastępstwie. Być może lepiej będzie użyć \=literału, aby użyć literału let l:subst = 's/\n\+/\=' . "'" . l:sep . "'/"- zamiast próbować obsługiwać ucieczkę.
jamessan,
3

Oto przykład użycia zewnętrznego polecenia:

:%!paste -sd,

gdzie %!zastępuje bieżący bufor (zawartość pliku) poleceniem: paste -sd,(parametry -ssłużą do łączenia wielu linii i -dustawia znak separatora na ,).

kenorb
źródło
3

Na wypadek, gdyby ktoś nie lubił wpisywać Regex i zapamiętywać więcej poleceń Ex wtyczki:

Dołącz blok wizualny

Visual-block Append jest dostępny w trybie Visual Block ( <C-v>) i może wykonać blok A ppend (i blok I nsert dla prepend). (zob .: :help v_b_A, :help v_b_I)

A jeśli ostatnim ruchem w trybie blokowym jest $, dołączanie zostanie wykonane na końcu wszystkich wyborów; w przeciwnym razie spacje zostaną wstawione przed dodanym tekstem (wyobraź sobie wyrównanie zamykania )na końcu kilku wywołań metod w kodzie).

Z przykładowym tekstem poniżej i kursorem na 8:

8
9
10
12

<C-v>}$A,<C-c>. Po powrocie do trybu normalnego możemy zobaczyć, że ,jest dołączany do wszystkich wybranych linii. (Spróbuj bez $)

Następnie zrób, gvaby ponownie wybrać obszar i Jlub gJ. Mamy problem ,: 8,9,10,12,i $xgotowe.

Użyj Wstaw dla braku spływu ,

Cofnijmy nasz tekst ( uu..uczy to fantazyjny :ea 1d<cr>:lat 1) i wypróbuj Visual Insert:

j<C-v>}I, <C-c>a następnie możemy połączyć linie gJbez spacji.

Czekaj czekaj czekaj, czegoś brakuje. Jak ponownie wybrać całą „tablicę”? Tym razem nie wybraliśmy pierwszej linii ... więc gvto nie pomaga.

- Lub może pomóc, gvokto ponownie wybrać ( gv), opposite rogu i do kgóry.

PS My Pinky nie jest wystarczająco szybkie i dokładne wpisywanie /\do /\n, więc lubię połączenie Vim wbudowany w operacjach i ruchów, aby uniknąć przy użyciu regex. Jednak jeśli robię to wystarczająco często, używając mapowania - być może takie, które mapują na wtyczki powinny być lepsze.

Sunny Pun
źródło
1

Znacznie prostszy sposób bez wtyczek i zewnętrznych poleceń do zmiany mapowania join ( J) ze spacji na dowolny znak, który lubisz. Na przykład, aby dołączyć przecinek i spację:

:nmap J :s/\n/, /^M

Aby wstawić nowy znak specjalny na końcu ( ^M), naciśnij, Ctrl-Va następnie Return / Enter. To samo dzieje się, jeśli chcesz zastąpić tabulatorem ( ^I), wpisz Ctrl-Iwtedy Tab.

:nmap J :s/\n/^I/^M

Działa to poprzez zastąpienie nowej linii tabulatorem w bieżącym wierszu i ponowne przypisanie tego zachowania do znaku J.

Działa to również z kombinacjami, jak w 4Jcelu dołączenia kolejnych 4 linii.

Tryby Wesa
źródło
0

Możesz nagrać makro, aby połączyć linie przecinkiem. Jest to przydatne, jeśli jest to rzadkie lub jednorazowe zadanie i nie pamiętasz, jak napisać polecenie zastępcze i wyrażenie regularne w celu wykonania zadania, ale pamiętasz, jak nagrać i uruchomić makro.

Aby połączyć linie przecinkiem, wpisz, qjgJi,Escqaby zarejestrować makro w rejestrze j. Następnie możesz uruchomić makro za pomocą @j. Możesz ponownie uruchomić makro za pomocą @@, co pozwala zaoszczędzić na pisaniu podczas wielokrotnego uruchamiania go z rzędu - możesz nawet przytrzymać, @aż zbliżysz się do końca linii, do której chcesz dołączyć. Możesz także użyć prefiksu numerycznego na @jlub @@powtórzyć go określoną liczbę razy. Pozostawia to nienaruszone początkowe i końcowe spacje, więc przed lub po przecinku będą spacje, jeśli w oryginalnym tekście były spacje.

Aby połączyć przecinkiem i spacją, wstaw znak Spacemiędzy ,i Escpodczas rejestrowania makra.

Możesz także użyć Jzamiast gJpodczas nagrywania makra, które zwykle łączy linie przecinkiem i spacją. Jeśli jednak bieżąca linia ma końcowe białe znaki, przecinek pojawi się za białymi literami bez spacji. Ponadto, nie obejmuje miejsca, jeśli następny wiersz zaczyna się ), a to stawia dwa miejsca po przecinku, jeśli joinspacesjest ustawiona, a obecne końce linii z ., !lub ?. Te zastrzeżenia zostały opisane poniżej :help J.

Lithis
źródło