Bir kat-ifade nasıl yazılır?


10

Fold-expr ( :h fold-expr) hakkında yardım sayfasını okudum ama ifadede kullanılan sözdiziminin ne olduğunu açıklamadı.

Dört örnek vardı:

  1. :set foldexpr=getline(v:lnum)[0]==\"\\t\"
  2. :set foldexpr=MyFoldLevel(v:lnum)
  3. :set foldexpr=getline(v:lnum)=~'^\\s*$'&&getline(v:lnum+1)=~'\\S'?'<1':1
  4. :set foldexpr=getline(v:lnum-1)=~'^\\s*$'&&getline(v:lnum)=~'\\S'?'>1':1

v:lnumBir girinti düzeyine ihtiyaç duyan çizgi olduğunu ve iki ifadenin bir fonksiyon çağrısı olduğunu anladım .

1,3 ve 4 ifadeleri ne olacak? Birisi lütfen bana açıklayabilir mi?


Anladığım kadarıyla, ifadenin bir sayı döndürmesi gerekir ve bu sayı, verilen satırın hangi düzeyde katlanacağını belirlemek için kullanılacaktır. 0 katlanmamış, 1 en dış kat, 2 seviye 1 kat içine yerleştirilmiş bir kat, vb.
tommcdo

Yanıtlar:


12

Gönderen :help 'foldexpr':

Katlama seviyesini elde etmek için her satır için değerlendirilir

Bu foldexprdeğerlendirilir, bu yüzden VimL kodu olması gerekir; "özel sözdizimi" veya benzerlerinden bahsedilmez. Bu değerlendirmenin sonucu, Vim'in neyi katladığını veya neyi dikkate almadığını kontrol eder.

Olası değerler

  0                     the line is not in a fold
  1, 2, ..              the line is in a fold with this level
  "<1", "<2", ..        a fold with this level ends at this line
  ">1", ">2", ..        a fold with this level starts at this line

Bu tam liste değildir ; sadece sorunuzdaki örneklerde kullanılanlar. Tüm :help foldexprliste için bakınız .


İlk

Birincisi boşluk eklediğimizde ve ters eğik çizgileri kaldırdığımızda, bunu bir :setkomutta çalıştırmamız için oldukça basit :

getline(v:lnum)[0] == "\t"
  1. getline(v:lnum) tüm hattı alır.
  2. [0] bunun ilk karakterini alır
  3. ve == "\t"bunun bir sekme karakteri olup olmadığını kontrol eder.
  4. VimL'de "true" veya "false" yoktur, sadece false için "0" ve true için "1" kullanır. Yani bu çizgi bir sekme ile başlıyorsa, 1. düzey katında katlanır. Değilse, bir kat (0) içinde olmaz.

Girintiye dayalı katlama yapacağınız sekme sayısını saymak için bunu genişletirseniz (en azından expandtabetkin olmadığında).


Üçüncü

Üçüncüsü, birincisi kadar karmaşık değil; ilk örnekte olduğu gibi, önce daha okunabilir hale getirmek istiyoruz:

getline(v:lnum) =~ '^\s*$' && getline(v:lnum + 1) =~ '\S' ? '<1' : 1
  1. Tüm çizgiyi getline(v:lnum)
  2. Biz bir regexp olarak eşleşecek =~için '^\s*$'; ^başlangıca \sbağlanır , herhangi bir boşluk karakteri *anlamına gelir, önceki sıfırı veya daha çok kez tekrar eder $ve sonuna kadar tutturur. Dolayısıyla bu normal ifade boş satırlarla veya yalnızca boşluklu satırlarla eşleşir (true değerini döndürür) .
  3. getline(v:lnum + 1)sonraki satırı alır .
  4. Bunu \S, bu satırın herhangi bir yerinde boşluk olmayan herhangi bir karakterle eşleştiriyoruz.
  5. Bu 2 koşul doğruysa <1, aksi takdirde değerlendiririz 1. Bu "üçlü" ile yapılır ifC'den bilinmektedir ve bazı diğer diller: condition ? return_if_true : return_if_false.
  6. <1"Katlama" terimi, bu çizgi üzerinde bir katlama ucu anlamına gelir ve katlama 1seviyesi bir demektir.

Yani, biz ise son çizgi boş ve sonraki çizgi ise bir kat değil boş. Aksi takdirde, 1. kattayız. Ya da :h foldexprdediği gibi:

Bu, boş satırlarla ayrılmış paragrafları katlar.


Dördüncü

Dördüncü, üçüncü olanla aynı şekilde davranır, ancak biraz farklı bir şekilde yapar. Genişletilmiş, bu:

getline(v:lnum - 1) =~ '^\s*$' && getline(v:lnum) =~ '\S' ? '>1' : 1

Eğer önceki hat boş bir satır olduğunu ve şimdiki çizgi olmayan bir boş satır, biz bir bu hat (on kat başlatmak >1, biz 1 olarak foldlevel ayarladığımız değilse).


Sonsöz

Bu nedenle, 3 örneğin hepsindeki mantık gerçekten oldukça basittir. Zorluğun çoğu, boşlukların olmaması ve bazı ters eğiklik kullanımından kaynaklanmaktadır.

Bir işlevi çağırmanın bazı ek yükleri olduğundan şüpheleniyorum ve bu, iyi bir performansa sahip olmak istediğiniz her satır için değerlendirildiğinden. Modern makinelerdeki farkın ne kadar büyük olduğunu bilmiyorum ve performans problemleriniz yoksa bir işlev (2. örnekte olduğu gibi) kullanmanızı öneririz. The Knuth'u hatırlayın: "erken optimizasyon tüm kötülüklerin köküdür" .

Bu soru aynı zamanda biraz farklı bir cevabı olan StackOverflow'da da var. Ama benimki elbette daha iyi ;-)


3

Aslında, bu ifadelerdeki diğer öğelerin ne olduğunu soruyorsunuz, bu da :helpbunlardan herhangi birini arayarak bulunabilir :

v:lnum: the line being evaluated
getline(): get the line of text for a line number
==: equals
=~: matches
<cond>?<if-true>:<if-false>: evaluates to <if-true> if <cond> is true, else to <if-false>

Bu ifadeleri, anlamlarını göstermeye yardımcı olmak için aşağıdaki bölümlerine göre ayırdım:

1 Bir sekme ile başlayan tüm satırlar için 1, diğer satırlar için 0 döndürür:

v:lnum                      the current line number
getline(v:lnum)             the text of the current line
getline(v:lnum)[0]          the first character of the current line
getline(v:lnum)[0]==\"\\t\" the first char of the current line is 'tab'

3 Paragraflardan sonra boş satırlardaki kıvrımları sonlandırır:

 getline(v:lnum)=~'^\\s*$'                                       current line is only spaces
                              getline(v:lnum+1)=~'\\S'           next line has non-space
(getline(v:lnum)=~'^\\s*$' && getline(v:lnum+1)=~'\\S') ? '<1'   if both of these: <1
                                                              :1 otherwise: 1
(getline(v:lnum)=~'^\\s*$' && getline(v:lnum+1)=~'\\S') ? '<1':1

4 Paragraflardan başlayarak boş satırlarda kıvrımlar başlatır:

(getline(v:lnum-1)=~'^\\s*$'                                     previous line only spaces
                                getline(v:lnum)=~'\\S'           this line has non-space
(getline(v:lnum-1)=~'^\\s*$' && getline(v:lnum)=~'\\S') ? '>1'   if both of these: >1
                                                              :1 otherwise: 1
(getline(v:lnum-1)=~'^\\s*$' && getline(v:lnum)=~'\\S') ? '>1':1 

Anlamları <1, >1vb bu ifadelerin altındaki haklısın:help fold-expr


1

Yanlışlıkla cevabımı bir yorum olarak gönderdi ve erken gönderdi. Kahretsin.

Anladığım kadarıyla, ifadenin bir sayı döndürmesi gerekir ve bu sayı, verilen satırın hangi düzeyde katlanacağını belirlemek için kullanılacaktır. 0 katlanmamıştır, 1 en dış kat, 2 seviye 1 kat içine yerleştirilmiş bir kat vb.

Örneklerdeki ifadeler doğru ya da yanlış olarak değerlendirilmiş gibi görünürler. VimScript'in uygun bir Boolean türü yoktur, bu yüzden bu geçerli kat seviyeleri olan gerçekten 1 veya 0 olacaktır.

İç içe katlamalara izin veren 1 veya 0 döndürmek kadar basit veya daha karmaşık VimScript kullanarak kendi ifadenizi yazabilirsiniz.


Sadece sayıları kullanmak işe yarayacaktır, ancak foldexpr'lerin =, a1, s1,> 1, <1, -1
Matt Boehm
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.