특정 구문 영역에서 패턴을 검색하는 방법은 무엇입니까?


10

라텍스 문서를 편집하기 위해 vim을 사용하고 있습니다. 종종 변수 이름을 다른 것으로 바꾸고 싶습니다. 그러나 변수 이름을 검색 할 때 관련이없는 경기를 극복 해야하는 것은 약간 성가신 일입니다. tex 구문 파일에 정의 된 "math zones"에서만 검색하고 싶습니다. 검색을 특정 구문 영역으로 제한하는 쉬운 방법이 있습니까?


1
대답은 '아니요'라고 생각합니다 . 특정 구문 영역으로 검색을 제한하는 쉬운 방법 은 없습니다 .
Karl Yngve Lervåg

2
이 맵핑synIDattr()커서 아래 문자의 구문 그룹을 얻는 데 사용 됩니다. 검색을 수행하는 기능 (또는 수행 normal n)을 사용 synIDattr()하여이 위치에 머무를 지 또는 검색을 계속 할지를 결정하는 데 사용할 수 있습니다.
joeytwiddle

@joeytwiddle 나는 그런 기능으로 답변을 게시 한 직후 귀하의 의견을 보았습니다. 생각했던 것과 같은가요?
jjaderberg

@jjaderberg 그렇습니다. 잘 했어!
joeytwiddle

그냥 완성도 (나는 그것이 좋은 답변 있음) : stackoverflow.com/a/2696143/5000478
VanLaser

답변:


4

시도해 볼 수있는 기능은 다음과 같습니다. 나는 조금 테스트했지만 잘 작동하는 것 같습니다.

function! JJSyntaxSearch(pattern, syntaxitem)
  while search(a:pattern, 'W') > 0
    for id in synstack(line("."),col("."))
      if synIDattr(id,"name") =~? a:syntaxitem
        return line(".")
      endif
    endfor
  endwhile
  return 0
endfunc

command! -nargs=* JJSyntaxSearch call JJSyntaxSearch(<f-args>)

이 함수는 특정 구문 항목과 '자격이있는'일치하는 '일반적인'일치를 찾거나 버퍼의 끝에 도달 할 때까지 루프에서 Vim의 검색 함수를 호출합니다.

두 가지 주장이 있습니다. 첫 번째는 검색 패턴이며 변경되지 않은 상태로 Vim의 search()함수 로 전달됩니다 . :help search()해당 기능의 작동 방식을 참조하십시오 . 두 번째 인수는 이러한 일치 항목을 필터링하려는 구문 항목의 이름입니다. 또한 패턴 일 수 있으며 대소 문자를 구분하지 않는 정규식으로 비교됩니다.

수학 영역에서 패턴 '알파'를 찾으려면

:JJSyntaxSearch alpha texMathZone.

.끝은 단일 문자 패턴 원자 참조 :help /.. 이 많은 수학 영역 문법 항목이라고 때문이다 texMathZoneA, texMathZoneB

search()함수는 커서를 다음 '일반'일치로 이동합니다. 그런 다음 함수는을 사용하여 새 커서 위치에 대한 모든 구문 항목 ID를 가져옵니다 synstack(). 그것들을 반복하면서 각 항목의 이름을 차례로 검색하여 syntaxitem인수 와 비교하여 테스트합니다 . 참조 :help synstack():help synIDattr(). 'qualified'일치가 있으면 행 번호를 리턴합니다. 'qualified'일치를 찾지 않고 버퍼의 끝에 도달하면를 반환합니다 0. 함수의 요점은 커서를 다음 '한정된'일치로 가져 와서 일부 작업을 수행 할 수 있지만 "행 번호 또는 0"을 반환하여 함수를 다시 호출하는 것이 의미가 있는지 여부를 나타내는 것이 유용합니다. 다른 함수 또는 매크로에서 함수를 반복적으로 호출하려는 경우.

나는 버퍼의 끝을 감싸는 것을 막기 때문에 W플래그 를 사용하기로 결정했다 search(). 그렇지 않으면 함수는 동일한 '일반적인'일치를 찾지 만 '한정된'일치는 찾지 못하여 중단 될 수 있습니다.


당신의 도움을 주셔서 감사합니다! 아직이 기능을 시도하지는 않았지만 원하는 것 같습니다.
Rob F.


1

"math zones"가 문자열 "math"와 같은 구문 패턴에 의해 규정 된 경우 최소한 다음 과 같이 패턴 시퀀스 를 사용 하여 일치하는 패턴이있는 행을 찾을 수 있습니다.

:/math//your pattern/

(참고 : 두 패턴이 다른 줄에있을 수 있습니다!)

이렇게하면 일치하는 영역으로 제한되지 않을 수 있습니다. 영역의 끝을 식별해야하기 때문에 초기 패턴 / math / 이후의 일치 항목 만 표시합니다. ex-mode history ( : up-arrow enter) 를 사용하여 다음 발생에 대한 검색을 반복 할 수 있습니다 .


참고 : ISTR 이전 vim / vi 버전 /math//your pattern/에서 nand N명령 을 덜 타이핑하고 사용하는 이점을 가지고 검색 모드로 직접 (전 모드 명령과 달리) 해당 방법을 사용할 수 있었지만 확인할 수는 없습니다. 내 현재 vim 버전의 경우.


1

또는 foo안의 문자열을 검색하는 경우 다음 과 같이 작동합니다.$...$$$...$$

\$.*\zsfoo

이것은 $문자에 일치하는 것을 고정 시키지만 문자열 만 선택합니다 foo.

실제로 쉬운 해결책은 아니지만 :global+ :substitute를 사용하여 "수학 영역"을 찾아서 그 내부를 검색 할 수 있습니다.

:global /\v\\begin\{%(align|alignat|displaymath)\}/ +1,/\\end/-1 s/foo/&/gc

:substitute검색 명령 인 척 하면 다음 항목으로 이동하여를 n종료 할 수 있습니다 q. 실수로 교체를 확인하면 아무런 문제가 없습니다.

당신은 목록 내부를 설정해야합니다 %(... )당신이 사용하는 수학 환경의 이름으로 (전체 목록은 약간 무거운이다 align|alignat|displaymath|eqnarray|equation|flalign|gather|math|multline|subequations|xalignat|xxalignat). \v여기서는 매우 마술 ( ) 패턴을 사용하고 있습니다.

설명:

:global전직 명령을 (실행 :s패턴 일치 (여기서 각 줄에) :help :global)
/\v매우 매직 패턴을 시작 ( :h /, :h pattern, :h magic)
\\begin\{리터럴 일치 \begin{
%(align|alignat|displaymath)일치에게 이러한 단어 중 하나를 ( :h /\%(, :h /bar)
\}/문자 그대로 일치 }하고 패턴을 종료합니다.

+1,/\\end/-1다음 행으로 이루어진 범위 (하나의 계산에 의해 발견 :global한 검색 패턴을 발견하기 전에 행까지)를 /\\end. 그 범위 내에서

s/foo/&/gc리터럴 발생할 때마다 교체 수색 foo(확인 후, 자체를 :h :substitute)


이것은 분명히 시작이지만 방정식, 정렬 및 IEEEeqnarray 환경을 자주 사용하므로 검색에서 해당 환경을 제외하고 싶지 않습니다.
Rob F.

@RobF .: 다양한 환경에서 일치시킬 수는 있지만 스크립트를 작성하지 않으면 쉽지 않을 것입니다. 그러나 \mathit변수 이름 을 일관되게 사용하면 훨씬 쉽게 찾을 수 있습니다.
Peter Lewerin

0

파일 내의 문자열 '아침'에있는 거 검색 당신은 만약 /morning다음 enter을 누릅니다 n앞으로 방향을 이동


1
문제는 I would like to search only in "math zones"당신의 방법이 연구 영역을 제한하지 않는 전체 파일을 검색 한다고 말했다 .
statox

0

이를위한 전용 함수를 작성하는 것 외에는 옵션이 없습니다. 원하는 문자열을 검색하고 다음 중 하나에 만 중지하는 함수를 작성했습니다.

  1. 일치하지 않습니다
  2. 수학 환경 내부에 일치하는 항목이 있습니다 (일치하는 경우 중지됨)

검색하려는 문자열로 호출하면됩니다.

function! Finmath(nextstr)
    while 1
        if search(a:nextstr)==0
            break
        endif
        if searchpairpos('\(', '','\)','n')!=[0,0]
            break
        endif
        if searchpairpos('\[', '','\]','n')!=[0,0]
            break
        endif
        let a = getcurpos() 
        if count(strpart(getline('.'),0,a[2]),'$')%2==1
            break
        endif 
    endwhile 
endfunction

GrammerousCheck와 비슷한 함수를 작성하여 수학 외부의 문법 오류에서만 중지하려고합니다.

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