जवाबों:
वहाँ शायद एक सरल विधि है, लेकिन हो सकता है कि आप निम्नलिखित की कोशिश कर सकें।
मान लीजिए कि आप q
अपने पुनरावर्ती मैक्रो को रिकॉर्ड करने के लिए रजिस्टर का उपयोग करेंगे ।
रिकॉर्डिंग की शुरुआत में, टाइप करें:
:let a = line('.')
फिर, रिकॉर्डिंग के बहुत अंत में, @q
मैक्रो को पुनरावर्ती बनाने के लिए मारने के बजाय , निम्न कमांड टाइप करें:
:if line('.') == a | exe 'norm @q' | endif
अंत में मैक्रो की रिकॉर्डिंग को समाप्त करें q
।
आपके द्वारा टाइप किया गया अंतिम कमांड मैक्रो q
( exe 'norm @q'
) को फिर से करेगा, लेकिन केवल तभी जब वर्तमान लाइन नंबर ( line('.')
) वैरिएबल में शुरू में संग्रहीत के समान हो a
।
:normal
आदेश आप (जैसे सामान्य आदेशों टाइप करने के लिए अनुमति देता है @q
पूर्व मोड से)।
और यही कारण है कि कमांड को एक स्ट्रिंग में लपेटा गया है और कमांड द्वारा निष्पादित किया गया :execute
है ताकि :normal
बाकी कमांड ( |endif
) का उपभोग (टाइपिंग) करने से रोका जा सके ।
उदाहरण का उपयोग करें।
मान लें कि आपके पास निम्न बफर हैं:
1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4
और आप एक पुनरावर्ती मैक्रो के साथ एक मनमाना लाइन से सभी संख्याओं को बढ़ाना चाहते हैं।
आप 0
अपने कर्सर को एक पंक्ति की शुरुआत में स्थानांतरित करने के लिए टाइप कर सकते हैं फिर मैक्रो की रिकॉर्डिंग शुरू करें:
qqq
qq
:let a=line('.')
<C-a>
w
:if line('.')==a|exe 'norm @q'|endif
q
qqq
रजिस्टर की सामग्री को साफ करता है q
ताकि जब आप शुरू में इसे मैक्रो की परिभाषा के दौरान कहते हैं, तो यह हस्तक्षेप नहीं करेगाqq
रिकॉर्डिंग शुरू करता है:let a=line('.')
चर के अंदर वर्तमान लाइन संख्या को संग्रहीत करता है a
w
कर्सर को अगले नंबर पर ले जाता है:if line('.')==a|exe 'norm @q'|endif
मैक्रो को याद करता है, लेकिन केवल अगर लाइन नंबर नहीं बदलाq
रिकॉर्डिंग बंद कर देता हैएक बार जब आप अपने मैक्रो को परिभाषित कर लेते हैं, यदि आप अपने कर्सर को तीसरी लाइन पर रखते हैं, तो 0
इसे लाइन की शुरुआत में ले जाने के लिए हिट करें, फिर @q
मैक्रो को फिर से चलाने के लिए हिट करें q
, यह केवल वर्तमान लाइन को प्रभावित करना चाहिए, अन्य को नहीं:
1 2 3 4
1 2 3 4
2 3 4 5
1 2 3 4
रिकॉर्डिंग के बाद एक मैक्रो पुनरावर्ती बनाएं
यदि आप चाहें, तो आप अपनी मैक्रो को इस रिकॉर्डिंग के बाद अपनी पुनरावृत्ति कर सकते हैं कि यह एक रजिस्टर के अंदर एक स्ट्रिंग में संग्रहीत है और आप डॉट .
ऑपरेटर के साथ दो तारों को जोड़ सकते हैं ।
इससे आपको कई लाभ मिलेंगे:
@q
इसे परिभाषित किए जाने के बाद पात्रों को मैक्रो में जोड़ दिया जाएगा, और आपके द्वारा पुरानी सामग्री जो भी थी उसे ओवरराइट करने के बादयदि आप अपने मैक्रो को हमेशा की तरह रिकॉर्ड करते हैं (गैर-पुनरावर्ती), तो आप इसे निम्न कमांड के साथ बाद में पुनरावर्ती बना सकते हैं:
let @q = @q . "@q"
या इससे भी कम: let @q .= "@q"
.=
एक ऑपरेटर है जो एक स्ट्रिंग को दूसरे में जोड़ने की अनुमति देता है।
यह @q
रजिस्टर के अंदर संग्रहीत कीस्ट्रोक्स के अनुक्रम के बहुत अंत में 2 अक्षरों को जोड़ना चाहिए q
। आप एक कस्टम कमांड को भी परिभाषित कर सकते हैं:
command! -register RecursiveMacro let @<reg> .= "@<reg>"
यह उस कमांड को परिभाषित करता है :RecursiveMacro
जो एक तर्क के रूप में एक रजिस्टर के नाम की प्रतीक्षा करता है (क्योंकि -register
पारित विशेषता के कारण :command
)।
यह पहले की तरह ही आदेश है, फर्क सिर्फ इतना है कि आप में से हर घटना की जगह है q
के साथ <reg>
। जब आदेश निष्पादित किया जाएगा, विम <reg>
आपके द्वारा प्रदान किए गए रजिस्टर नाम के साथ हर घटना का स्वचालित रूप से विस्तार करेगा ।
अब, आपको बस इतना करना है कि अपने मैक्रो को सामान्य (गैर-पुनरावर्ती) के रूप में रिकॉर्ड करें, फिर :RecursiveMacro q
मैक्रो को रजिस्टर के अंदर संग्रहीत करने के लिए टाइप करें q
।
आप वर्तमान लाइन पर बने रहने की स्थिति पर स्थूल पुनरावर्ती बनाने के लिए एक ही काम कर सकते हैं:
let @q = ":let a=line('.')\r" . @q . ":if line('.')==a|exe 'norm @q'|endif\r"
यह पोस्ट की शुरुआत में वर्णित एक ही बात है, इस समय को छोड़कर जब आप रिकॉर्डिंग के बाद करते हैं। आप बस दो स्ट्रिंग्स को समेटते हैं, एक से पहले और एक के बाद जो कुछ भी कीस्ट्रोक्स q
रजिस्टर वर्तमान में होता है:
let @q =
रजिस्टर की सामग्री को फिर से परिभाषित करता है q
":let a=line('.')\r"
वैरिएबल के अंदर वर्तमान लाइन नंबर को स्टोर a
करता है इससे पहले कि मैक्रो अपना काम करता \r
है वीम को एंटर को दबाने और कमांड को निष्पादित करने के लिए कहना आवश्यक है, :help expr-quote
समान विशेष वर्णों की सूची देखें , . @q .
q
पिछले स्ट्रिंग और अगले एक के साथ रजिस्टर की वर्तमान सामग्री को साझा करता है ,":if line('.')==a|exe 'norm @q'|endif\r"
मैक्रो q
को इस शर्त पर याद करते हैं कि लाइन परिवर्तित नहीं हुई थीफिर से, कुछ कीस्ट्रोक्स को बचाने के लिए, आप निम्नलिखित कस्टम कमांड को परिभाषित करके प्रक्रिया को स्वचालित कर सकते हैं:
command! -register RecursiveMacroOnLine let @<reg> = ":let a=line('.')\r" . @<reg> . ":if line('.')==a|exe 'norm @<reg>'|endif\r"
और फिर, आपको बस इतना करना है कि अपने मैक्रो को सामान्य (गैर-पुनरावर्ती) के रूप में रिकॉर्ड करें, फिर :RecursiveMacroOnLine q
रजिस्टर q
लाइन के अंदर मैक्रो को संग्रहीत करने के लिए टाइप करें , यह उस स्थिति पर पुनरावर्ती है जो वर्तमान लाइन पर रहता है।
2 कमांड मर्ज करें
आप भी ट्विक कर सकते हैं :RecursiveMacro
ताकि यह 2 मामलों को कवर करे:
ऐसा करने के लिए, आप एक दूसरा तर्क पारित कर सकते हैं :RecursiveMacro
। उत्तरार्द्ध बस इसके मूल्य का परीक्षण करेगा और, मूल्य के आधार पर, पिछले 2 कमांडों में से एक को निष्पादित करेगा। यह इस तरह से कुछ देगा:
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
या (लाइन निरंतरता / बैकस्लैश का उपयोग करके इसे थोड़ा अधिक पठनीय बनाने के लिए):
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
यह पहले की तरह ही है, इस समय को छोड़कर आपको :RecursiveMacro
( -nargs=1
विशेषता के कारण) 2 तर्क देना होगा ।
जब इस नए आदेश को निष्पादित किया जाएगा, तो विम <args>
आपके द्वारा प्रदान किए गए मूल्य के साथ स्वचालित रूप से विस्तार करेगा ।
यदि यह 2 तर्क गैर-शून्य / सत्य है ( if <args>
) कमांड के पहले संस्करण को निष्पादित किया जाएगा (एक जो बिना किसी स्थूल पुनरावर्ती बनाता है), अन्यथा यदि यह शून्य / गलत है, तो दूसरा संस्करण निष्पादित किया जाएगा (एक जो बनाता है इस स्थिति पर एक स्थूल पुनरावर्ती वर्तमान रेखा पर रहता है)।
इसलिए पिछले उदाहरण पर वापस जा रहे हैं, यह निम्नलिखित बात देगा:
qq
<C-a>
w
q
:RecursiveMacro q 0
3G
0@q
qq
रजिस्टर के अंदर एक मैक्रो की रिकॉर्डिंग शुरू करता है q
<C-a>
कर्सर के तहत संख्या में वृद्धिw
कर्सर को अगले नंबर पर ले जाता हैq
रिकॉर्डिंग समाप्त करता है:RecursiveMacro q 0
मैक्रो को q
पुनरावर्ती के अंदर संग्रहीत किया जाता है, लेकिन केवल पंक्ति के अंत तक (दूसरे तर्क के कारण 0
)3G
अपने कर्सर को एक मनमानी लाइन पर ले जाता है (उदाहरण के लिए 3)0@q
रेखा की शुरुआत से पुनरावर्ती मैक्रो को फिर से देखता हैइसे पहले जैसा परिणाम देना चाहिए:
1 2 3 4
1 2 3 4
2 3 4 5
1 2 3 4
लेकिन इस बार आपको अपने मैक्रो की रिकॉर्डिंग के दौरान ध्यान भंग करने वाली कमांड टाइप करने की ज़रूरत नहीं थी, आप बस एक काम करने पर ध्यान केंद्रित कर सकते हैं।
और चरण 5 के दौरान, यदि आपने कमांड के लिए एक गैर-शून्य तर्क पारित किया था, अर्थात यदि आपने :RecursiveMacro q 1
इसके बजाय टाइप किया था :RecursiveMacro q 0
, तो मैक्रो q
बिना शर्त के पुनरावर्ती हो जाएगा, जिसने निम्नलिखित बफर दिया होगा:
1 2 3 4
1 2 3 4
2 3 4 5
2 3 4 5
इस बार मैक्रो तीसरी पंक्ति के अंत में नहीं बल्कि बफर के अंत में बंद हो जाएगा।
अधिक जानकारी के लिए देखें:
:help line()
:help :normal
:help :execute
:help :command-nargs
:help :command-register
1 2 3 4 5 6 7 8 9 10
मिलता 2 3 4 5 6 7 8 9 10 12
है 2 3 4 5 6 7 8 9 10 11
। मुझे पता नहीं क्यों, शायद मैंने कुछ गलत किया। वैसे भी यह मेरे सरल दृष्टिकोण की तुलना में अधिक परिष्कृत लगता है, और इसमें यह वर्णन करना शामिल है कि मैक्रो को कर्सर को कहां ले जाना चाहिए, साथ ही एक स्थान सूची भी जिसे मैंने कभी इस तरह से उपयोग नहीं किया है। मुझे बहुत पसंद है!
\d\+
कई अंकों की संख्याओं का वर्णन करना चाहिए था ।
:lv ...
कमांड के बाद, कमांड का :lla
उपयोग अंतिम मैच में कूदने के लिए किया जा सकता है और :lp
कमांड का उपयोग रिवर्स ऑर्डर में मैचों को आगे बढ़ाने के लिए किया जा सकता है।
जैसे ही यह विफल होता है एक कमांड का सामना करता है एक पुनरावर्ती मैक्रो बंद हो जाएगा। इसलिए, एक पंक्ति के अंत में रुकने के लिए, आपको एक कमांड की आवश्यकता है जो पंक्ति के अंत में विफल हो जाएगी।
डिफ़ॉल्ट रूप से *, l
कमांड एक ऐसा कमांड है, इसलिए आप इसका उपयोग एक रिकर्सिव मैक्रो को रोकने के लिए कर सकते हैं। यदि कर्सर लाइन के अंत में नहीं है , तो आपको बस इसे कमांड के साथ बाद में वापस ले जाने की आवश्यकता है h
।
तो, saginaw के रूप में एक ही उदाहरण मैक्रो का उपयोग कर :
qqqqq<c-a>lhw@qq
टूटा:
qqq
: Q रजिस्टर साफ़ करें,qq
: q
रजिस्टर में एक मैक्रो रिकॉर्ड करना शुरू करें ,<c-a>
: कर्सर के नीचे संख्या बढ़ाना,lh
: यदि हम पंक्ति के अंत में हैं, तो मैक्रो को निरस्त करें। नहीं तो कुछ न करें।w
: लाइन पर अगले शब्द के लिए अग्रिम।@q
: पुनर्जीवितq
: रिकॉर्डिंग बंद करें।तब आप 0@q
मैगिन को उसी आदेश के साथ चला सकते हैं जैसा कि saginaw द्वारा वर्णित है।
* 'whichwrap'
विकल्प आपको यह परिभाषित करने की अनुमति देता है कि जब आप किसी पंक्ति के आरंभ या अंत में होते हैं तो कौन सी आंदोलन कुंजियाँ अगली पंक्ति में घूमेंगी (देखें :help 'whichwrap'
)। यदि आपने l
इस विकल्प में सेट किया है, तो यह ऊपर वर्णित समाधान को तोड़ देगा।
हालांकि, यह संभावना है कि आप केवल एक ही चरित्र को आगे बढ़ाने के लिए तीन डिफ़ॉल्ट सामान्य मोड से कोई एक आदेश का उपयोग करें (है <Space>
, l
और <Right>
), इसलिए यदि आप है l
अपने में शामिल 'whichwrap'
की स्थापना, आप एक है कि आप निकाल सकते हैं नहीं है से उपयोग करें 'whichwrap'
विकल्प, उदाहरण के लिए <Space>
:
:set whichwrap-=s
फिर आप l
मैक्रो के चरण 4 में कमांड को कमांड से बदल सकते हैं <Space>
।
virtualedit=onemore
हस्तक्षेप करेगी l
, भले ही वह उतनी गंभीर न हो whichwrap=l
।
've'
:lv /\%3l\d/g %<CR>qqqqq<C-a>:lne<CR>@qq@q
लाइन पर सभी संख्याओं में वृद्धि होगी 3. शायद इस समाधान को कम नाजुक बनाने का एक तरीका है?