Yanıtlar:
Muhtemelen daha basit bir yöntem var ama belki aşağıdakileri deneyebilirsiniz.
Diyelim ki q
özyinelemeli makronuzu kaydetmek için kayıt kullanacaksınız .
Kaydın en başında şunu yazın:
:let a = line('.')
Ardından, kaydın en sonunda @q
, makro özyinelemeli hale getirmek yerine vurmak yerine aşağıdaki komutu yazın:
:if line('.') == a | exe 'norm @q' | endif
Son olarak makronun kaydını ile bitirin q
.
Yazdığınız son komut makrosu q
( exe 'norm @q'
) tekrar oynatır, ancak sadece geçerli satır numarası ( line('.')
) değişkente başlangıçta saklananla aynı ise a
.
:normal
Komutu (gibi normal komutları yazın sağlar @q
Ex modundan).
Ve komut komutuyla bir dize içine sarılmış ve idam nedeni :execute
önlemektir :normal
(yazarak) komutu geri kalanı (tüketmesini |endif
).
Kullanım örneği.
Diyelim ki şu ara belleğe sahipsiniz:
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
Ve rasgele bir satırdaki tüm sayıları yinelemeli bir makro ile artırmak istiyorsunuz.
0
İmlecinizi satırın başına götürmek için yazabilir , ardından makronun kaydını başlatabilirsiniz:
qqq
qq
:let a=line('.')
<C-a>
w
:if line('.')==a|exe 'norm @q'|endif
q
qqq
q
makronun tanımı sırasında başlangıçta aradığınızda, karışmayacağı şekilde kayıt içeriğini temizlerqq
kaydı başlatır:let a=line('.')
geçerli satır numarasını değişkenin içinde saklar a
w
imleci bir sonraki sayıya taşır:if line('.')==a|exe 'norm @q'|endif
ancak satır numarası değişmediyse makroyu hatırlarq
kaydı durdururMakronuzu tanımladıktan sonra, imlecinizi üçüncü satıra konumlandırırsanız, satırın 0
başına taşımak için düğmesine @q
basın , ardından makroyu tekrar oynatmak için düğmesine basın q
, diğerlerini değil yalnızca geçerli satırı etkilemelidir:
1 2 3 4
1 2 3 4
2 3 4 5
1 2 3 4
Kayıttan sonra makro yinelemeli hale getirme
İsterseniz, bir kaydın içindeki bir dizede saklandığını ve iki dizeyi nokta .
işleciyle birleştirebildiğinizi kullanarak, kaydınızdan sonra yinelemeli hale getirebilirsiniz .
Bu size birkaç avantaj sağlar:
@q
tanımlandıktan sonra ve orada bulunan eski içeriklerin üzerine yazdıktan sonra makroya eklenirMakronuzu her zamanki gibi (özyinelemesiz olarak) kaydederseniz, aşağıdaki komutla daha sonra yinelemeli yapabilirsiniz:
let @q = @q . "@q"
Veya daha kısa: let @q .= "@q"
.=
bir dizgiyi başka bir dizeye eklemeye izin veren bir operatördür.
Bu, @q
yazmaç içinde saklanan tuş vuruşları dizisinin en sonuna 2 karakteri eklemelidir q
. Özel bir komut da tanımlayabilirsiniz:
command! -register RecursiveMacro let @<reg> .= "@<reg>"
:RecursiveMacro
Bir kaydın adını bekleyen komutu argüman olarak tanımlar ( -register
geçilen öznitelik nedeniyle :command
).
Daha önce aynı komutu var, tek fark her geçtiği yerini ise q
ile <reg>
. Komut yürütüldüğünde, Vim girdiğiniz <reg>
kayıt adıyla her tekrarlandığında otomatik olarak genişler .
Şimdi, yapmanız gereken tek şey makronuzu her zamanki gibi (özyinelemesiz olarak) kaydetmek, daha sonra :RecursiveMacro q
kayıt içinde saklanan makro q
özyinelemeli yapmak için yazın .
Bir makroyu geçerli satırda kalması koşuluyla özyinelemeli yapmak için de aynı işlemi yapabilirsiniz:
let @q = ":let a=line('.')\r" . @q . ":if line('.')==a|exe 'norm @q'|endif\r"
Bu, kayıttan sonra yaptığınız hariç, yazının başında açıklananla aynı şeydir. Sadece q
şu anda kayıtta bulunan tuş vuruşlarından önce ve sonra iki dizeyi birleştirirsiniz :
let @q =
kaydın içeriğini yeniden tanımlar q
":let a=line('.')\r"
a
Makroyu yapmadan önce geçerli satır numarasını değişkenin içinde saklar, \r
Vim'e Enter tuşuna basmasını ve komutu yürütmesini bildirmek için gereklidir :help expr-quote
, benzer özel karakterlerin bir listesine bakın , . @q .
q
kaydın mevcut içeriğini bir önceki dize ve bir sonrakiyle birleştirir ,":if line('.')==a|exe 'norm @q'|endif\r"
q
çizginin değişmemesi şartıyla makroyu hatırlarYine, bazı tuş vuruşlarını kaydetmek için, aşağıdaki özel komutu tanımlayarak işlemi otomatikleştirebilirsiniz:
command! -register RecursiveMacroOnLine let @<reg> = ":let a=line('.')\r" . @<reg> . ":if line('.')==a|exe 'norm @<reg>'|endif\r"
Ve yine, tek yapmanız gereken makronuzu her zamanki gibi (özyinelemesiz olarak) kaydetmek, daha sonra :RecursiveMacroOnLine q
yazmaç içinde saklanan makroyu q
geçerli satırda kalması koşuluyla yinelemeli hale getirmek için yazın .
2 komutu birleştir
Ayrıca :RecursiveMacro
2 vakayı kapsayacak şekilde ince ayar yapabilirsiniz :
Bunu yapmak için, ikinci bir argümanı iletebilirsiniz :RecursiveMacro
. İkincisi sadece değerini test eder ve değere bağlı olarak önceki 2 komuttan birini yürütür. Böyle bir şey verirdi:
command! -register -nargs=1 RecursiveMacro if <args> | let @<reg> .= "@<reg>" | else | let @<reg> = ":let a=line('.')\r" . @<reg> . ":if line('.')==a|exe 'norm @<reg>'|endif\r" | endif
Veya (biraz daha okunabilir hale getirmek için çizgi devamlarını / ters eğik çizgileri kullanarak):
command! -register -nargs=1 RecursiveMacro
\ if <args> |
\ let @<reg> .= "@<reg>" |
\ else |
\ let @<reg> = ":let a = line('.')\r" .
\ @<reg> .
\ ":if line('.')==a | exe 'norm @<reg>' | endif\r" |
\ endif
Öncekiyle aynı, ancak bu kez :RecursiveMacro
( -nargs=1
nitelik nedeniyle) 2. bir argüman sağlamanız gerekiyor .
Bu yeni komut yürütüldüğünde, Vim <args>
verdiğiniz değerle otomatik olarak genişler .
Bu 2. bağımsız değişken sıfır / true ( if <args>
) değilse , komutun ilk sürümü (bir makroyu koşulsuz olarak yinelemeli yapan) çalıştırılır, aksi takdirde sıfır / yanlış ise ikinci sürüm yürütülür ( geçerli satırda kalması koşuluyla özyinelemeli bir makro).
Yani bir önceki örneğe geri dönersek, şu şeyi verirdi:
qq
<C-a>
w
q
:RecursiveMacro q 0
3G
0@q
qq
yazmaç içindeki bir makro kaydını başlatır q
<C-a>
imlecin altındaki sayıyı artırırw
imleci bir sonraki sayıya taşırq
kaydı bitirir:RecursiveMacro q 0
kayıtta saklanan makroyu q
yalnızca satır sonuna kadar yinelemeli hale getirir (ikinci bağımsız değişken nedeniyle 0
)3G
imlecinizi rastgele bir satıra taşır (örneğin 3)0@q
özyinelemeli makroyu satırın başından itibaren yeniden oynatırÖncekiyle aynı sonucu vermelidir:
1 2 3 4
1 2 3 4
2 3 4 5
1 2 3 4
Ancak bu kez makronuzun kaydı sırasında dikkat dağıtıcı komutları yazmak zorunda kalmadınız, sadece çalışan bir komut yapmaya odaklanabilirsiniz.
Ve adım 5 sırasında, komuta sıfır dışında bir argüman iletmiş olsaydınız , yani :RecursiveMacro q 1
bunun yerine :RecursiveMacro q 0
yazmış q
olsaydınız , makro , koşulsuz olarak özyinelemeli olurdu ve bu da aşağıdaki arabelleği vermiş olurdu:
1 2 3 4
1 2 3 4
2 3 4 5
2 3 4 5
Bu kez makro 3. satırın sonunda değil, ara belleğin sonunda dururdu.
Daha fazla bilgi için bakınız:
:help line()
:help :normal
:help :execute
:help :command-nargs
:help :command-register
1 2 3 4 5 6 7 8 9 10
alıyorum . Nedenini bilmiyorum, belki bir şeyler yanlış yazdım. Her neyse, benim basit yaklaşımımdan daha sofistike görünüyor ve makronun imleci nereye taşıyacağını tanımlamak için düzenli ifadeler ve bu şekilde hiç görmediğim bir konum listesi içeriyor. Onu çok severim! 2 3 4 5 6 7 8 9 10 12
2 3 4 5 6 7 8 9 10 11
\d\+
birden fazla basamak numarasını tanımlamak için kullanmalıydım .
:lv ...
komuttan sonra, komut :lla
son eşleşmeye atlamak için kullanılabilir ve :lp
komut eşleşmeleri ters sırayla ilerletmek için kullanılabilir.
Özyinelemeli bir makro, başarısız olan bir komutla karşılaşır karşılaşmaz duracaktır. Bu nedenle, bir satırın sonunda durmak için, satırın sonunda başarısız olacak bir komuta ihtiyacınız vardır.
Varsayılan olarak *, l
komut böyle bir komuttur, böylece özyinelemeli bir makroyu durdurmak için kullanabilirsiniz. İmleç satırın sonunda değilse , komutla daha sonra geri hareket etmeniz yeterlidir h
.
Yani, saginaw ile aynı örnek makrosu kullanmak :
qqqqq<c-a>lhw@qq
Bozuldu:
qqq
: Q kaydını temizle,qq
: Kayıt q
defterine bir makro kaydetmeye başlayın ,<c-a>
: İmlecin altındaki sayıyı arttırır,lh
: Satırın sonundaysak makroyu iptal et. Aksi takdirde, hiçbir şey yapmayın.w
: Satırdaki bir sonraki kelimeye ilerleyin.@q
: Eğitimq
: Kaydetmeyi bırak.Daha sonra makroyu, 0@q
saginaw tarafından açıklanan komutla çalıştırabilirsiniz .
* Bu 'whichwrap'
seçenek, bir satırın başında veya sonunda olduğunuzda hangi hareket tuşlarının bir sonraki satıra sarılacağını tanımlamanızı sağlar (Bkz. :help 'whichwrap'
). Eğer varsa l
bu seçenekte belirtilen, o zaman yukarıda açıklanan çözüm kıracak.
Ancak, yalnızca tek bir karakter ilerletmek üzere üç varsayılan normal mod komutları birini kullanın (olasıdır <Space>
, l
ve <Right>
sen gelmiş eğer öyleyse,) l
sizin dahil 'whichwrap'
belirleme, sen diğerini kaldırın edebilirsiniz yok kullanmak 'whichwrap'
seçeneği, örneğin <Space>
:
:set whichwrap-=s
Sonra l
makronun 4. adımındaki <Space>
komutu bir komutla değiştirebilirsiniz.
virtualedit=onemore
için kullanılmaya müdahale edeceğini unutmayın . l
whichwrap=l
've'
:lv /\%3l\d/g %<CR>qqqqq<C-a>:lne<CR>@qq@q
3 satırındaki tüm sayıları artıracağı sürece, bir makrodaki arama eşleşmelerinde ilerlemek için kullanılabilir . Belki de bu çözümü daha az kırılgan hale getirmenin bir yolu var mı?