Làm thế nào để tìm kiếm mẫu trong các vùng cú pháp nhất định?


10

Tôi đang sử dụng vim để chỉnh sửa tài liệu latex. Thông thường, tôi sẽ muốn thay đổi tên của một biến thành một cái khác. Tuy nhiên, thật khó chịu khi phải lội qua các trận đấu không liên quan khi tôi tìm kiếm tên biến. Tôi chỉ muốn tìm kiếm trong "vùng toán học" như được định nghĩa trong tệp cú pháp tex. Có cách nào dễ dàng để giới hạn tìm kiếm trong một vùng cú pháp cụ thể không?


1
Tôi nghĩ câu trả lời là không: không có cách nào dễ dàng để giới hạn tìm kiếm trong một vùng cú pháp cụ thể.
Karl Yngve Lervåg

2
Ánh xạ này sử dụng synIDattr()để có được các nhóm cú pháp cho ký tự dưới con trỏ. Bạn có thể viết một hàm thực hiện tìm kiếm (hoặc không normal n) và sau đó sử dụng synIDattr()để quyết định xem có nên ở vị trí này hay tiếp tục tìm kiếm về phía trước.
joeytwiddle

@joeytwiddle Tôi vừa thấy bình luận của bạn sau khi đăng câu trả lời với chức năng như vậy. Có giống như những gì bạn đã nghĩ trong đầu?
jjaderberg

@jjaderberg Đúng vậy. Bạn đã làm rất tốt!
joeytwiddle

Chỉ để hoàn thiện (tôi thấy đó là một câu trả lời hay): stackoverflow.com/a/2696143/5000478
VanLaser

Câu trả lời:


4

Đây là một chức năng mà bạn có thể thử. Tôi chỉ thử nghiệm nó một chút nhưng có vẻ như nó hoạt động tốt.

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>)

Hàm này gọi hàm tìm kiếm của Vim trong một vòng lặp cho đến khi nó tìm thấy một kết quả khớp 'bình thường' cũng phù hợp 'đủ điều kiện' với một mục cú pháp cụ thể hoặc cho đến khi đến cuối bộ đệm.

Phải mất hai đối số. Đầu tiên là mẫu tìm kiếm và nó được chuyển không thay đổi theo search()chức năng của Vim . Xem :help search()cách thức hoạt động của chức năng đó. Đối số thứ hai là tên của mục cú pháp mà bạn muốn lọc các kết quả khớp này. Đây cũng có thể là một mẫu và được so sánh như một biểu thức chính quy không phân biệt chữ hoa chữ thường.

Để tìm mẫu 'alpha' trong các vùng toán học, bạn có thể làm

:JJSyntaxSearch alpha texMathZone.

Các .ở cuối là các nguyên tử mẫu cho bất cứ ký tự đơn, xem :help /.. Điều này là do có nhiều mục cú pháp vùng toán học được gọi texMathZoneA, texMathZoneBv.v.

Các search()chức năng di chuyển con trỏ đến trận đấu 'bình thường' bên cạnh. Sau đó, hàm của chúng tôi nhận được tất cả các ID mục cú pháp cho vị trí con trỏ mới đó với synstack(). Vòng qua chúng, nó lần lượt lấy tên của từng vật phẩm và kiểm tra nó chống lại syntaxitemđối số. Xem :help synstack():help synIDattr(). Nếu có kết quả 'đủ điều kiện', nó sẽ trả về số dòng. Nếu nó đạt đến cuối bộ đệm mà không tìm thấy bất kỳ kết quả 'đủ điều kiện' nào, nó sẽ trả về 0. Điểm quan trọng của chức năng là đưa con trỏ đến trận đấu 'đủ điều kiện' tiếp theo để bạn có thể thực hiện một số thao tác ở đó, nhưng rất hữu ích khi trả về "số dòng hoặc 0" để cho biết liệu có ý nghĩa khi gọi lại hàm không, cho ví dụ nếu bạn muốn gọi hàm liên tục từ hàm khác hoặc macro.

Tôi đã chọn sử dụng Wcờ cho search()vì nó ngăn 'bao quanh' phần cuối của bộ đệm. Mặt khác, chức năng có thể bị kẹt khi nó tiếp tục tìm các kết quả trùng khớp 'thông thường' nhưng không có kết quả 'đủ điều kiện'.


Cảm ơn bạn đã giúp đỡ! Tôi chưa thử chức năng này, nhưng có vẻ như tôi muốn.
Rob F.


1

Trong trường hợp "vùng toán học" của bạn đủ điều kiện theo một số mẫu cú pháp, giả sử, chuỗi "toán học", thì ít nhất bạn có thể sử dụng các chuỗi mẫu để tìm một dòng có mẫu phù hợp, như trong:

:/math//your pattern/

(Lưu ý: hai mẫu có thể nằm trên các dòng khác nhau!)

Điều này có thể không giới hạn các trận đấu của bạn trong các khu vực - vì bạn cần xác định kết thúc của khu vực - nhưng nó sẽ chỉ hiển thị các trận đấu đó sau một mẫu / toán học ban đầu. Bạn có thể lặp lại tìm kiếm cho lần xuất hiện tiếp theo bằng cách sử dụng lịch sử chế độ cũ ( : up-arrow enter).


Lưu ý: ISTR rằng trong các phiên bản vim / vi trước đó tôi cũng có thể sử dụng phương thức đó trực tiếp làm lệnh tìm kiếm (trái ngược với lệnh chế độ cũ) /math//your pattern/với ưu điểm là ít nhập và sử dụng các lệnh nN, nhưng tôi không thể xác nhận phiên bản vim hiện tại của tôi


1

Nếu bạn đang tìm kiếm chuỗi foobên trong $...$hoặc $$...$$, điều này sẽ hoạt động:

\$.*\zsfoo

Điều này neo khớp với một $ký tự nhưng chỉ chọn chuỗi foo.

Đây thực sự không phải là một giải pháp dễ dàng, nhưng người ta có thể sử dụng dấu :global+ :substituteđể tìm "vùng toán học" và tìm kiếm bên trong chúng:

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

Giả sử đó :substitutelà một lệnh tìm kiếm, bạn có thể đi đến lần xuất hiện tiếp theo nvà thoát với q. Nếu bạn xác nhận thay thế bởi nhầm lẫn thì không nên có bất kỳ vấn đề.

Bạn sẽ phải đặt danh sách bên trong %(... )thành tên của các môi trường toán học bạn sử dụng (danh sách đầy đủ là một chút nặng align|alignat|displaymath|eqnarray|equation|flalign|gather|math|multline|subequations|xalignat|xxalignat:). Lưu ý rằng tôi đang sử dụng một mẫu rất kỳ diệu ( \v) ở đây.

Giải trình:

:globalthực hiện một lệnh Ex ( :s) trên mỗi dòng nơi các trận đấu mẫu ( :help :global)
/\vbắt đầu một mô hình rất kỳ diệu ( :h /, :h pattern, :h magic)
\\begin\{phù hợp với một chữ \begin{
%(align|alignat|displaymath)phù hợp bất kỳ của những lời này ( :h /\%(, :h /bar)
\}/phù hợp với một đen }và kết thúc mô hình.

+1,/\\end/-1một phạm vi bao gồm dòng tiếp theo (tính từ dòng được tìm thấy :global) cho đến dòng trước mẫu được tìm thấy bởi mẫu tìm kiếm /\\end. Trong phạm vi đó,

s/foo/&/gctìm kiếm và thay thế mọi lần xuất hiện của chữ foobằng chính nó, sau khi xác nhận ( :h :substitute)


Đây chắc chắn là một sự khởi đầu, nhưng tôi thường xuyên sử dụng các phương trình, căn chỉnh và môi trường IEEEeqnarray và tôi không muốn loại trừ chúng khỏi tìm kiếm của mình.
Rob F.

@RobF.: Hoàn toàn có thể phù hợp với một loạt các môi trường, nhưng sẽ không dễ dàng trừ khi có một kịch bản. Tuy nhiên, nếu bạn luôn sử dụng \mathitxung quanh các tên biến, việc tìm kiếm chúng dễ dàng hơn nhiều.
Peter Lewerin

0

Nếu bạn đang tìm kiếm chuỗi 'sáng' bên trong tập tin /morningsau đó entervà nhấn nđể di chuyển hướng về phía trước


1
Câu hỏi cho biết I would like to search only in "math zones"phương pháp của bạn tìm kiếm toàn bộ tệp mà nó không phân định vùng nghiên cứu.
statox

0

Không có tùy chọn nào ngoài việc viết một chức năng chuyên dụng cho việc này. Tôi đã viết một hàm tìm kiếm chuỗi bạn muốn và chỉ dừng lại nếu:

  1. nó hết trận
  2. có một trận đấu trong môi trường toán học (nó sẽ dừng lại ở trận đấu)

Bạn chỉ cần gọi nó với chuỗi bạn muốn tìm kiếm.

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

Tôi dự định viết một hàm tương tự cho GrammerousCheck chỉ dừng lại ở các lỗi ngữ pháp ngoài toán học.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.