인터리빙 라인으로 블록 병합


15

다음과 같이 줄을 인터리빙하여 두 개의 텍스트 블록을 병합하는 전용 방법이 있습니까?

a1
a2
a3
a4
  b1
  b2
  b3
  b4

그것에 :

a1
  b1
a2
  b2
a3
  b3
a4
  b4

몇 가지 명령으로?

편집 : Sato Katsura의 솔루션이 정말 마음에 듭니다 . 구현 방법은 다음과 같습니다.

function! Interleave()
    " retrieve last selected area position and size
    let start = line(".")
    execute "normal! gvo\<esc>"
    let end = line(".")
    let [start, end] = sort([start, end], "n")
    let size = (end - start + 1) / 2
    " and interleave!
    for i in range(size - 1)
        execute (start + size + i). 'm' .(start + 2 * i)
    endfor
endfunction

" Select your two contiguous, same-sized blocks, and use it to Interleave ;)
vnoremap <pickYourMap> <esc>:call Interleave()<CR>

이제 궁금합니다. 사용 사례는 무엇입니까? TV 시즌에 자막을 자르고 있습니까?
VanLaser

@ VanLaser Haha는 아닙니다. 주로 프로그램의 출력을 눈으로 파싱하고 있는데, 생성 순서 / 객체 읽기 지연과 관련된 일관성을 확인해야합니다. 인터리빙 블록을 사용하면 지연된 출력 블록에서 해당 라인을보다 쉽게 ​​일치시킬 수 있습니다. 또한 때때로 로깅 또는 벤치마킹에 대한 반복적이고 유사한 지침으로 코드 줄을 인터리브해야합니다. 이러한 명령어를 생성하는 것은 매크로를 사용하여 쉽게 수행 할 수 있으며 실제 코드로 인터리빙하는 것은 이제이 기능을 사용하여 몇 번의 키 입력으로 해결됩니다.
iago-lito

1
@ lago-lito-답변 주셔서 감사합니다! 그렇습니다, Vim은 매우 다재다능합니다 :) "눈동자 분석"이라는 표현으로 scroll-binding두 개의 Vim 창을 생각하게되었습니다 .
VanLaser

이것을 사용하는 데 문제가 있습니다. 두 개의 연속 블록을 어떻게 선택합니까? 인접해야합니까?
cbcoutinho

@cbcoutinho 그렇습니다. :) 그렇지 않으면 둘 다 선택할 수 있는지 잘 모르겠습니다. 내가 보여준 예에서, 커서를 (예를 들어) 위에 놓고 전체 청크를 선택하기 위해 b1누르 십시오 . 그것은 당신 편에서 작동하지 않습니까? vip,it<map-I've-Picked>
iago-lito

답변:


8

그것을하는 전용 방법은 없지만 (아는 한) 몇 가지 명령으로 수행 할 수 있습니다.

function! Interleave(start, end, where)
    if a:start < a:where
        for i in range(0, a:end - a:start)
            execute a:start . 'm' . (a:where + i)
        endfor
    else
        for i in range(a:end - a:start, 0, -1)
            execute a:end . 'm' . (a:where + i)
        endfor
    endif
endfunction

로 실행할 수 있습니다 :call Interleave(5, 8, 1). 첫 번째 매개 변수는 이동할 첫 번째 행이고 두 번째 매개 변수는 마지막 행이며 세 번째 매개 변수는 이동할 행입니다. 행 번호를 켜서 수행중인 작업을 확인하고 싶을 것입니다 ( :set number).

블록이 겹치지 않는다고 가정합니다. 참조 :help :move:help range()기능 작동 방식을 이해 할 수 있습니다.

두 블록을 집어 올리는 더 좋은 방법이있을 것입니다. 두 블록을 교환 할 수있는 플러그인이 떠 있습니다. 나는 플러그인의 이름을 기억할 수 없지만 저자 (아마 유명한 Dr. Chip?)는 인터페이스를 찾는 것보다 더 많은 생각을했습니다. :)


단! 난 단지 두 블록이 인접하고 같은 크기를 가지고 있기 때문에 두 개의 인수가 필요 start하고 size. 선택에서 해당 값을 검색하는 홈 브루 크 기능을 사용하면 완벽합니다. 나는 노력하고 있습니다. :)
iago-lito

흥미로운 가교 ? ;)
iago-lito

13

다른 대안이 있습니다.

:g/^a/+4t .
:+,+5d 

먼저 현재 라인 (후 아래 4 개 라인은 라인 복사 :h :t)을 (B 연속 라인을 삭제 :h :d)

이 명령이 더 좋습니다.

 :g/^a//^\s*b/m .

즉, 시작으로 시작하는 각 줄에 대해 'b'로 시작하는 다음 줄을 찾아 현재 줄 아래로 이동하십시오.


1
두 번째 명령에 "E16 : Invalid range"가 있습니다. .+,$d대신 시도했지만 그랬습니다 ( .+,.+4d).
Peter Lewerin

확실하지 왜 이런 일이 발생
기독교 Brabandt

1
아뇨. 읽기 : h : 범위, 정규식 검색 대신 항상 직접 번호 매기기를 사용할 수 있습니다.
Christian Brabandt

2
@ iago-lito 두 번째 트릭은 항상 작동하지만 /^\s*b다른 트릭으로 변경해야합니다 :range. 예를 들면 : 선택 1 블록은 실행'<,'>g/^/'>+1m.
dedowsdi

1
@ iago-lito 그것은 본질적으로 Christian의 대답과 동일합니다. 첫 번째 블록을 시각적으로 선택하고 '>+1두 번째 블록의 시작을 표시 하면 아무것도 코딩되지 않습니다 .
dedowsdi

3

매크로와 마크로 약간의 재미를 원한다면 다음과 같이 시도해보십시오.

  • 먼저 와 함께 a포함 된 줄에 마크 (여기 )를 넣으십시오.a1ma

  • 포함하는 행으로 이동 b1과 함께 표시mb

  • 원하는 레지스터 (여기서 레지스터 q) 에서 매크로 기록을 시작하십시오.qq

  • 매크로에 다음을 삽입하십시오. ddmb'apjma'b

  • 로 매크로 기록 중지 q

  • 재생 시간은 X@q어디에서 필요한만큼 X재생하십시오.

매크로를 자세히 설명하려면

dd mb 'a p j ma 'b
 |  |  | | |    |
 |  |  | | |    go back to line marked `b`
 |  |  | | |
 |  |  | | move of one line and replace the mark `a`
 |  |  | insert the deleted line under the line marked `a`
 |  |  go to line marked `a`
 |  mark the future line to move with `b`
 delete the line to move

설명에서 lago-lito가 언급했듯이이 방법은 마크와 버퍼를 덮어 씁니다.

  • 나는 그것이 진짜 문제라고 생각하지 않는다. 나는 버퍼에 26 개의 마크를 거의 사용하지 않으며 대부분 2 개의 프리 마크를 찾게 될 것이라고 생각한다.

  • 버퍼의 경우 임시 변수 :let saveReg=getreg('"')에 저장할 수 있습니다. 매크로를 기록하기 전에 레지스터를 저장하고 동작이 완료 :call setreg('"', saveReg)되면 레지스터를 이전 상태로 되 돌리는 데 사용 합니다.

어쨌든 나는이 솔루션이 빠른 해결 방법이며 최적이 아니라는 것을 인정해야합니다. 제 생각에 Christan의 대답 은 가장 좋으며 버퍼와 마크를 엉망으로 만들지 않기 때문에 받아 들여야합니다. 사용자가 만들지 마십시오. 함수와 전역 명령의 힘을 보여줍니다.


흥미 롭군 불행하게도, 이것은 내가 사용하고있는 마크와 레지스터의 내용을 덮어 씁니다.;)
iago-lito

@ lago-lito : 실제로 마크와 버퍼를 덮어 씁니다. 마크의 경우 버퍼에 26 마크를 모두 사용하지 않으므로 실제로 문제가되지 않습니다. 버퍼의 경우 더 큰 문제 일 수 있습니다. 사용하지 않는 버퍼를 찾거나 실제로 할 수없는 경우 임시 변수와 함수를 사용 getreg()하고 setreg()버퍼를 저장하십시오. 그러나 나는 그것이 최적의 해결책이 아니라는 것에 동의한다 :-)
statox

1

방금 다른 유사한 질문을 보았 으며 솔루션은 다음으로 구성됩니다.

중간 더하기 1로 이동 :

Mj

그리고 다음을 실행하십시오.

:,$g/./exe 'm' 2*line('.')-line('$')-1

흥미롭게도 :) 이것은 선택한 단락뿐만 아니라 전체 파일을 인터리브한다는 점에 유의하십시오!
iago-lito
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.