일련의 별표 글 머리 기호를 번호가 매겨진 목록으로 바꿉니다.


16

다음과 같은 텍스트가 있다고 상상해보십시오.

some random stuff
* asdf
* foo
* bar
some other random stuff

별표 글 머리 기호를 숫자로 바꾸고 싶습니다.

some random stuff
1. asdf
2. foo
3. bar
some other random stuff

이것은 vim에서 어떻게 할 수 있습니까?


왜 플러그인을 사용하지 않습니까? 비슷한 것은 Github의 incremental.vim
SibiCoder

모두 놀라워 서 모두가 답을 만들어 숫자를 늘 렸지만 Markdown이 번호를 매기므로 왜 모두를 만들지 1.않습니까? 그렇게 :%s/^* /1. /할 것입니다. 훨씬 적은 작업처럼 보입니다.
병아리

답변:


14

다음 명령을 시도 할 수 있습니다.

:let c=0 | g/^* /let c+=1 | s//\=c.'. '

먼저 변수 c( let c=0)를 초기화 한 다음 전역 명령 g을 실행 하여 패턴 ^*(줄의 시작, 별표 및 공백) 을 찾습니다 .

이 패턴을 포함하는 행이 발견 될 때마다 전역 명령은 명령을 실행합니다.
let c+=1 | s//\=c.'. '
변수를 증가시키고 c( let c+=1), |( s) 이전에 검색된 패턴 ( //)을 표현식 평가 ( )로 대체 합니다 ( \=) : 연결된
변수의 내용 문자열이있는 c( .)'. '


버퍼에서 모든 행을 수정하지 않고 특정 단락 만 수정하려는 경우 전역 명령에 범위를 전달할 수 있습니다. 예를 들어, 번호가 5와 10 사이 인 행만 수정하려면 다음을 수행하십시오.

:let c=0 | 5,10g/^* /let c+=1 | s//\=c.'. '

변환하려는 여러 유사한 목록이 포함 된 파일이있는 경우 예를 들면 다음과 같습니다.

some random stuff                 some random stuff                      
* foo                             1. foo                                 
* bar                             2. bar                                 
* baz                             3. baz                                 
some other random stuff           some other random stuff                
                           ==>                                                
some random stuff                 some random stuff                      
* foo                             1. foo                                 
* bar                             2. bar                                 
* baz                             3. baz                                 
* qux                             4. qux                                 
some other random stuff           some other random stuff                

다음 명령으로이를 수행 할 수 있습니다.

:let [c,d]=[0,0] | g/^* /let [c,d]=[line('.')==d+1 ? c+1 : 1, line('.')] | s//\=c.'. '

다른 명령으로 c전환 할 때 변수를 재설정하는 이전 명령의 변형 일뿐 입니다. 다른 목록에 있는지 여부를 감지하기 위해 변수 d는 대체 된 마지막 행의 번호를 저장하는 데 사용됩니다.
전역 명령은 현재 줄 번호 ( line('.')) 를와 비교합니다 d+1. 그들은 같은 경우는 우리가 전에 지금과 같은 목록에있는 의미 c(증가 c+1때문에, 그렇지 않으면 우리가 다른 목록에 의미) c리셋은 ( 1).

함수 내에서 다음과 같이 명령 let [c,d]=[line('.')==d+1 ? c+1 : 1, line('.')]을 다시 작성할 수 있습니다.

let c = line('.') == d+1 ? c+1 : 1
let d = line('.')

또는 이렇게 :

if line('.') == d+1
    let c = c+1
else
    let c = 1
endif
let d = line('.')

일부 키 입력을 저장하기 위해 사용자 지정 명령을 정의 할 수도 있습니다.이 명령 :NumberedLists은 기본값이 1,$( -range=%) 인 범위를 허용합니다 .

command! -range=% NumberedLists let [c,d]=[0,0] | <line1>,<line2>g/^* /let [c,d]=[line('.')==d+1 ? c+1 : 1, line('.')] | s//\=c.'. '

경우는 :NumberedLists실행됩니다, <line1>그리고 <line2>자동으로 사용 범위로 대체됩니다.

따라서 버퍼의 모든 목록을 변환하려면 다음을 입력하십시오. :NumberedLists

10 행과 20 행 사이의 목록 만 : :10,20NumberedLists

시각적 선택 만 : :'<,'>NumberedLists


자세한 내용은 다음을 참조하십시오.

:help :range
:help :global
:help :substitute
:help sub-replace-expression
:help list-identity    (section list unpack)
:help expr1
:help :command

9

이것은 최신 Vim 버전 (을 가진 :h v_g_CTRL-A) 에서만 작동합니다 .

  1. 목록 글 머리 기호 ( *)를 차단하고 선택하고 0(커서가 먼저 있음 *)로 바꿉니다 Ctrl-v j j r 0.
  2. 이전 블록을 다시 선택 하고 카운터를 사용 하여 증가시킵니다 .gv g Ctrl-a

... 그리고 그게 다야 :)


(각 숫자 뒤에 점을 표시하려면 첫 번째 단계를 다음으로 변경하십시오. Ctrl-v j j s 0 . Esc)


9

행을 시각적으로 선택하고이 대체 명령을 실행하십시오.

:'<,'>s/*/\=line('.') - line("'<") + 1 . '.'

참조 :help sub-replace-expression, :help line():help '<.

라인을 선택하지 않아도되도록 오프셋을 사용한 역방향 및 정방향 검색을 사용하여 다음과 같이 대체 범위를 지정할 수 있습니다.

:?^[^*]?+1,/^[^*]/-1s/*/\=line('.') - search('^[^[:digit:]]', 'bn') . '.'

보다 :help cmdline-ranges


2

또 다른 방법:

:let n = 1 | g/^* /s//\=printf('%d. ', n)/g | let n = n + 1

0

사용자 정의 연산자를 정의 할 수도 있습니다

키 시퀀스 '*및에 매핑 할 수 있습니다 '#. 마크는 *하고 #어떤 기본 기능을 무시하지 않도록, 존재하지 않습니다. '접두사 로 선택하는 이유 는 일종의 니모닉을 얻는 것입니다. 일부 줄 앞에 표시 / 마크를 추가하고 있습니다. 그리고 일반적으로 표시로 이동하려면 접두사를 사용하십시오 '.

fu! s:op_list_bullet(...) abort range

    if a:0
        let [lnum1, lnum2] = [line("'["), line("']")]
    else
        let [lnum1, lnum2] = [line("'<"), line("'>")]
    endif

    if !empty(matchstr(getline(lnum1), '^\s*\d\s*\.'))
        let pattern     = '\d\s*\.\s\?'
        let replacement = '* '

    elseif count(['-', '*'], matchstr(getline(lnum1), '\S'))
        let pattern     = '\v\S\s*'
        let replacement = ''

    else
        let pattern     = '\v\ze\S'
        let replacement = '* '
    endif

    let cmd = 'keepj keepp %s,%s s/%s/%s'

    sil exe printf(cmd, lnum1, lnum2, pattern, replacement)
endfu

fu! s:op_list_digit(...) abort range
    let l:c = 0

    if a:0
        let [lnum1, lnum2] = [line("'["), line("']")]
    else
        let [lnum1, lnum2] = [a:firstline, a:lastline]
    endif

    if count(['-', '*'], matchstr(getline(lnum1), '\S'))
        let pattern     = '\S\s*'
        let replacement = '\=l:c.". "'

    elseif !empty(matchstr(getline(lnum1), '^\s*\d\s*\.'))
        let pattern     = '\d\s*\.\s\?'
        let replacement = ''

    else
        let pattern     = '\v^\s*\zs\ze\S'
        let replacement = '\=l:c.". "'
    endif

    let cmd = 'keepj keepp %s,%s g/%s/let l:c = line(".") == line("'']")+1 ?
                                                \ l:c+1 : 1 |
                                                \ keepj keepp s/%s/%s'

    sil exe printf(cmd, lnum1, lnum2, pattern, pattern, replacement)
endfu

nno <silent> '*     :<C-U>set opfunc=<SID>op_list_bullet<CR>g@
nno <silent> '**    :<C-U>set opfunc=<SID>op_list_bullet
                    \<Bar>exe 'norm! ' . v:count1 . 'g@_'<CR>
xno <silent> '*     :call <SID>op_list_bullet()<CR>

nno <silent> '#     :<C-U>set opfunc=<SID>op_list_digit<CR>g@
nno <silent> '##    :<C-U>set opfunc=<SID>op_list_digit
                    \<Bar>exe 'norm! ' . v:count1 . 'g@_'<CR>
xno <silent> '#     :call <SID>op_list_digit()<CR>

시각적 모드에서도 작동합니다.
Ex 명령은 스크립팅에는 좋지만 대화식으로 사용하는 경우 모션 또는 텍스트 객체와 결합 할 수 있으므로 일반 연산자가 더 좋습니다.

예를 들어,을 누르면 현재 단락 내에서 별표 또는 빼기 부호가있는 목록을 토글 할 수 있습니다 '*ip. 여기는 '*연산자이며 작동 ip하는 텍스트 개체입니다.

그리고을 눌러 다음 10 행에 숫자가 접두사로 붙인 목록에 대해서도 동일한 작업을 수행하십시오 '#10j. 여기 '#또 다른 연산자 10j가 있으며 연산자가 작동하는 선을 덮는 동작입니다.

사용자 정의 연산자를 사용하는 또 다른 이점은 dot 명령을 사용하여 마지막 버전을 반복 할 수 있다는 것입니다.

여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.