Belirli sözdizimi bölgelerinde kalıp nasıl aranır?


10

Lateks belgeleri düzenlemek için vim kullanıyorum. Genellikle, bir değişkenin adını başka bir şeye değiştirmek isteyeceğim. Ancak, değişken adını aradığımda alakasız eşleşmelerle uğraşmak biraz can sıkıcı. Ben sadece tex sözdizimi dosyasında tanımlandığı gibi "matematik bölgeleri" aramak istiyorum. Aramayı belirli bir sözdizimi bölgesi ile sınırlamanın kolay bir yolu var mı?


1
Bence cevap hayır: Bir aramayı belirli bir sözdizimi bölgesi ile sınırlamanın kolay bir yolu yok .
Karl Yngve Lervåg

2
Bu eşleme kullanan synIDattr()imlecin altındaki karakteri için sözdizimi gruplarını elde etmek. Aramayı gerçekleştiren (veya yapan normal n) ve ardından synIDattr()bu konumda kalmaya veya aramaya devam etmeye karar vermek için kullanılan bir işlev yazabilirsiniz .
joeytwiddle

@joeytwiddle Böyle bir işlevle bir cevap gönderdikten hemen sonra yorumunuzu gördüm. Aklındaki gibi mi?
jjaderberg

@jjaderberg Evet, öyle. İyi iş!
joeytwiddle

Sadece bütünlük için (iyi bir cevap buldum): stackoverflow.com/a/2696143/5000478
VanLaser

Yanıtlar:


4

İşte deneyebileceğiniz bir işlev. Ben sadece biraz test ettik ama işe yarıyor gibi görünüyor.

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

İşlev, belirli bir sözdizimi öğesiyle 'nitelikli' eşleşme olan 'sıradan' bir eşleşme bulana kadar veya arabellek sonuna ulaşıncaya kadar Vim'in arama işlevini bir döngüde çağırır.

İki argüman alır. Birincisi arama örüntüsüdür ve değişmeden Vim search()işlevine geçirilir . Bkz :help search()o işlevin nasıl için. İkinci argüman, bu eşleşmeleri filtrelemek istediğiniz sözdizimi öğesinin adıdır. Bu aynı zamanda bir model olabilir ve büyük / küçük harf duyarsız bir düzenli ifade olarak karşılaştırılır.

Matematik bölgelerinde 'alfa' desenini bulmak için şunları yapabilirsiniz

:JJSyntaxSearch alpha texMathZone.

.Ucunda tek bir karakter için model atomu, bkz :help /.. Bunun nedeni texMathZoneA, texMathZoneBvb. Adı verilen birçok matematik bölgesi sözdizimi öğesinin olmasıdır .

search()Fonksiyon sonraki 'sıradan' maç için imleci hareket ettirir. Daha sonra işlevimiz, yeni imleç konumu için tüm sözdizimi öğe kimliklerini alır synstack(). Bunların üzerinden geçerek, her bir öğenin adını sırayla alır ve syntaxitemtartışmaya karşı test eder . Bkz :help synstack()ve :help synIDattr(). 'Nitelikli' bir eşleşme varsa, satır numarasını döndürür. Herhangi bir 'kalifiye' eşleşme bulmadan tamponun sonuna ulaşırsa geri döner 0. İşlevin amacı imleci bir sonraki 'kalifiye' eşleşmeye götürmektir, böylece orada bir işlem yapabilirsiniz, ancak işlevi tekrar çağırmanın anlamlı olup olmadığını belirtmek için "satır numarası veya 0" döndürmek yararlıdır. örneğin, işlevi başka bir işlevden veya makrodan tekrar tekrar çağırmak istiyorsanız.

Kullanmak için tercih Wiçin bayrağı search()'etrafında sarma' çünkü o Kireçlenmeyi önler tampon ucu. Aksi takdirde, aynı 'sıradan' eşleşmeleri bulmaya devam ettiği, ancak 'nitelikli' eşleşmeleri bulunmadığı için işlev sıkışabilir.


Yardımın için teşekkürler! Bu işlevi henüz denemedim, ama istediğim gibi görünüyor.
Rob


1

"Matematik bölgelerinizin" sözde "matematik" dizesi gibi bazı sözdizimsel desenlerle nitelendirilmesi durumunda, en az aşağıdaki gibi eşleşen desene sahip bir çizgi bulmak için desen dizilerini kullanabilirsiniz :

:/math//your pattern/

(Not: iki desen farklı çizgiler üzerinde olabilir!)

Bu, eşleşmelerinizi bölgelerle sınırlamayabilir - zira bölgenin sonunu tanımlamanız gerekir - ancak yalnızca ilk kalıp / matematik / sonrasındaki eşleşmeleri görüntüler. Eski mod geçmişini ( : up-arrow enter) kullanarak aramayı bir sonraki tekrar için tekrarlayabilirsiniz .


Not: Önceki vim / vi sürümlerinde, bu yöntemi ve komutlarını /math//your pattern/daha az yazıp kullanma avantajıyla doğrudan bir arama komutu olarak da (eski mod komutunun aksine) kullanabildim, ancak onaylayamıyorum mevcut vim sürümüm için.nN


1

fooİçerideki dizeyi $...$veya arıyorsanız $$...$$, bunun çalışması gerekir:

\$.*\zsfoo

Bu, eşleşmeyi bir $karakterle tutturur, ancak yalnızca dizeyi seçer foo.

Bu gerçekten kolay bir çözüm değil, ancak "matematik bölgeleri" bulmak ve içinde arama yapmak için :global+ işaretini kullanabilirsiniz :substitute:

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

Gibi yapmak :substitutebir arama komutu, görebilmek ile sonraki geçtiği gidebilir nve birlikte çıkın q. Bir değiştirmeyi yanlışlıkla onaylarsanız, herhangi bir sorun olmamalıdır.

İçindeki listeyi %(... )kullandığınız matematik ortamlarının adlarına ayarlamanız gerekir (tam liste biraz iri:) align|alignat|displaymath|eqnarray|equation|flalign|gather|math|multline|subequations|xalignat|xxalignat. Burada çok sihirli ( \v) bir desen kullandığımı unutmayın .

Açıklama:

:globalBir Ex komutu (yürütmek :sdesen maçlar (burada her satırda) :help :global)
/\vçok sihirli desen başlatmak ( :h /, :h pattern, :h magic)
\\begin\{bir hazır eşleşmesi \begin{
%(align|alignat|displaymath)maçı bu kelimelerden herhangi biri ( :h /\%(, :h /bar)
\}/bir hazır eşleşecek }ve desen sonunda.

+1,/\\end/-1sonraki satırdan (bulduğu satırdan sayarak :global) arama deseni tarafından bulunan satırdan önceki satıra kadar olan bir aralık /\\end. Bu aralık dahilinde,

s/foo/&/gcfooonaydan sonra değişmez kelimenin her örneğini kendisiyle ara ve değiştir ( :h :substitute)


Bu kesinlikle bir başlangıç, ama denklemi, hizalamayı ve IEEEeqnarray ortamlarını sık sık kullanıyorum ve bunları aramamdan çıkarmak istemiyorum.
Rob F.

@RobF .: bir dizi ortamın içinde eşleşmek oldukça mümkün, ancak bir komut dosyası yazmadıkça kolay olmayacak. Bununla birlikte, \mathitdeğişken adları etrafında sürekli olarak kullanırsanız , bunları bulmak çok daha kolaydır.
Peter Lewerin

0

Dosya içindeki dize 'sabah' için konum arama Eğer varsa /morningo zaman enterve basın nileriye doğru gitmeye


1
Soru I would like to search only in "math zones", yöntemin bir araştırma bölgesini sınırlamadığı dosyanın tamamını aradığını söyledi .
statox

0

Bunun için özel bir işlev yazmaktan başka seçenek yoktur. İstediğiniz dize arar ve sadece ya durursa bir işlev yazdı:

  1. maçlar bitiyor
  2. matematik ortamında olan bir maç var (maçta duracak)

Sadece aramak istediğiniz dizeyle çağırırsınız.

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

Ben sadece matematik dışında dilbilgisi hataları durur GrammerousCheck için benzer bir işlev yazmak niyetinde.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.