मैं zsh के vi मोड को bash के vi मोड की तरह कैसे व्यवहार कर सकता हूं?


24

मैं वास्तव में zsh की सामान्य गति को पसंद कर रहा हूं, लेकिन दो चीजें मुझे बाहर निकालने के लिए परेशान कर रही हैं।

  1. मुझे भागने से बचने और इतिहास की खोज के लिए स्लैश मारने के बीच एक पल रुकना पड़ता है (यदि यह बहुत जल्दी टकराता है तो यह कहता है zsh: do you wish to see all 514 possibilities (172 lines))
  2. मारने के कारण प्रविष्टि मोड में प्रवेश करने के बाद aया A, मैं उस बिंदु से पीछे नहीं जा सकता जहाँ मैंने प्रविष्टि मोड में प्रवेश किया है।

मुझे पता है कि 2 क्लासिक vi की तरह है, लेकिन मुझे विम स्टाइल ज्यादा पसंद है।


अगर कोई भी डबल भागने के बहुत कष्टप्रद मुद्दे में चल रहा है, जिससे आपको iमोड डालने के लिए दो बार हिट करना पड़े, तो मैं इस फिक्स की अत्यधिक अनुशंसा करूंगा !
cchamberlain

यहाँ एक अच्छा सारांश भी है: dougblack.io/words/zsh-vi-mode.html
jackcogdill

जवाबों:


22

(1)। किसी कारण से, जब यह "/": के रूप में व्याख्या की <esc>जाती /है तो बिंडकी अजीब तरह से व्यवहार करती है <esc-/>। (मैंने दूसरे दिन इस व्यवहार को देखा; निश्चित रूप से इसका कारण नहीं है।) मुझे नहीं पता कि यह एक बग या एक विशेषता है, और अगर यह एक सुविधा है अगर इसे अक्षम किया जा सकता है, लेकिन आप इसके चारों ओर काफी आसानी से काम कर सकते हैं ।

यह कुंजी कॉम्बो शायद बाध्य है _history-complete-older, जो अवांछित परिणाम उत्पन्न कर रहा है - आप यह bindkey -Lदेखने के लिए उपयोग कर सकते हैं कि क्या यह मामला है।

किसी भी दर पर, यदि आपको वास्तविक <esc-/> (एक साथ, एक राग के रूप में दबाया हुआ) बंधन को त्यागने में कोई आपत्ति नहीं है, तो आप इसे vi-mode इतिहास खोज कमांड में फिर से बाँध सकते हैं, ताकि <esc>उसके बाद /टाइपिंग किसी भी टाइपिंग में समान हो। गति। =)

चूँकि इसे एक राग के रूप में माना जाएगा, इसलिए इसमें पहले vi कमांड मोड में प्रवेश करने का प्रभाव नहीं होगा, इसलिए हमें यह सुनिश्चित करना होगा कि पहले ऐसा हो। सबसे पहले, आपको एक फ़ंक्शन को परिभाषित करने की आवश्यकता है; fpathयदि आप इसका उपयोग करते हैं, तो इसे कहीं और रख दें या इसे अपने .zshrc अन्यथा में डाल दें:

vi-search-fix() {
zle vi-cmd-mode
zle .vi-history-search-backward
}

बाकी सब आपके रास्ते में चला जाता है:

autoload vi-search-fix
zle -N vi-search-fix
bindkey -M viins '\e/' vi-search-fix

जाने के लिए अच्छा होना चाहिए।

(2)। आप बैकस्पेस कुंजी को निम्नानुसार ठीक कर सकते हैं:

`bindkey "^?" backward-delete-char`

इसके अलावा, यदि आप अन्य vi शैली कमांड के लिए समान व्यवहार चाहते हैं:

bindkey "^W" backward-kill-word 
bindkey "^H" backward-delete-char      # Control-h also deletes the previous char
bindkey "^U" backward-kill-line            

यह ^[/नहीं था \e/, लेकिन उन दोनों को भागने का वैध तरीका कहा जाता है। परिवर्तन पूरी तरह से काम करता है। अब जब मैं इसके साथ पूरी तरह से खेल रहा हूं, तो यह लग रहा है कि बाश की तुलना में zsh का vi मोड बेकार है (या कम से कम पूरी तरह से डिफ़ॉल्ट रूप से कॉन्फ़िगर नहीं किया गया है)। इसका एक उदाहरण यह तथ्य है कि यह आपको खोज इतिहास के बाद सम्मिलित मोड में छोड़ देता है। मुझे अगली खोज आइटम खोजने के लिए n हिट करने के लिए कमांड मोड पर वापस जाना होगा।
चास। ओवंस

1
ठीक है, मैं नहीं जानता कि क्या आपके पास कोई अन्य उदाहरण है, लेकिन आप जिस पर उल्लेख करते हैं वह मेरी गलती है, न कि ज़ीएस की। =) क्या हुआ है मैं vi सम्मिलित मोड में एक vi-cmd मोड संपादक कमांड को बाध्य करता हूं - कमांड शेल को पहले से ही cmd मोड में होने की उम्मीद करता है और तदनुसार व्यवहार करता है। हमें एक संपादक कमांड लिखने की ज़रूरत है, जो पहले "एनटीडी मोड दर्ज करें" कमांड को कॉल करता है , और फिर निष्पादित करता है .vi-history-search-backward। मैं इसे लिखूंगा और अपना उत्तर संपादित करूंगा - आज बाद में वापस देखूंगा।
मार्शल यौवन

ठीक है, मैंने अपना उत्तर अपडेट कर दिया। कोशिश करके देखो।
मार्शल Eubanks

(2) के संबंध में, जब मैं bindkey | grep <searchterm>किसी भी पद के लिए करता हूं , तो वे सभी उपसर्ग करते हैं vi-। क्या मुझे bindkeyउन आदेशों को स्थापित करने की आवश्यकता है जो पहले से नहीं हैं vi-?
adam_0

1
धन्यवाद। ये हैक्स (और नीचे के wjv, भी) zsh के vi मोड को nigh- अनुपयोगी से उत्कृष्ट तक जाते हैं। मैंने एक सुपरसुअर खाता बनाया ताकि मैं आपको वोट दे सकूं। :-)
ctrueden

14

मैं केवल प्रश्न (1) को संबोधित करने जा रहा हूं।

आपकी समस्या KEYTIMEOUT है। मैं zshzle (1) से बोली:

जब ZLE टर्मिनल से एक कमांड पढ़ रहा होता है, तो यह एक अनुक्रम पढ़ सकता है जो कुछ कमांड के लिए बाध्य होता है और एक लंबे समय तक चलने वाले स्ट्रिंग का एक उपसर्ग भी होता है। इस मामले में ZLE यह देखने के लिए एक निश्चित समय प्रतीक्षा करेगा कि क्या अधिक वर्ण टाइप किए गए हैं, और यदि नहीं (या वे किसी भी लंबे स्ट्रिंग से मेल नहीं खाते हैं) तो यह बाध्यकारी निष्पादित करेगा। यह टाइमआउट KEYTIMEOUT पैरामीटर द्वारा परिभाषित किया गया है; इसका डिफ़ॉल्ट 0.4 ​​सेकंड है। कोई समयबाह्य नहीं है यदि उपसर्ग स्ट्रिंग स्वयं एक कमांड के लिए बाध्य नहीं है।

ईएससी से टकराने के बाद आपको जो देरी हो रही है, वह 0.4s है। फिक्स को शेल स्टार्टअप स्टार्टअप फ़ाइलों में से एक में 0.01% तक सही सेट करना है:

export KEYTIMEOUT=1

दुर्भाग्य से यह एक दस्तक पर प्रभाव है: अन्य चीजें गलत होने लगती हैं ...

सबसे पहले, vi कमांड मोड में अब एक समस्या है: टाइपिंग ESC कर्सर को लटका देता है, और फिर आप जो भी टाइप करते हैं, वह अगले निगल जाता है। ऐसा इसलिए है क्योंकि ESC vi कमांड मोड में डिफ़ॉल्ट रूप से किसी भी चीज़ के लिए बाध्य नहीं है, फिर भी बहु-वर्ण विजेट हैं जो ES (कर्सर कुंजी!) से शुरू होते हैं। इसलिए जब आप ESC से टकराते हैं, तो ZLE अगले चरित्र की प्रतीक्षा करता है ... और फिर उसका उपभोग करता है।

ईएससी को कमांड मोड में किसी चीज़ से बाँधने के लिए यह फिक्स है , इस प्रकार यह सुनिश्चित करना कि $ KEYTIMEOUT सेंटीसेकंड के बाद कुछ ZLE को पास हो जाए। अब हम बिना इन प्रभावों के कमांड मोड में ईएससी से शुरू होने वाली बाइंडिंग को चालू रख सकते हैं। मैं ईएससी को घंटी के पात्र से बांधता हूं, जो मुझे आत्म-सम्मिलन की तुलना में कम दखल देने वाला लगता है (और मेरा खोल चुप हो जाता है):

bindkey -sM vicmd '^[' '^G'

अपडेट 2017:

मैंने तब से ESC - undefined-keyविजेट को बांधने के लिए एक और बेहतर समाधान ढूंढ लिया है । मुझे यकीन नहीं है कि जब यह मूल रूप से मैंने यह उत्तर लिखा था, तो यह विजेट zsh में उपलब्ध था या नहीं।

bindkey -M vicmd '^[' undefined-key

अगली समस्या: डिफ़ॉल्ट रूप से ^ एक्स वि इन इन्सर्ट मोड में शुरू होने वाले कुछ दो-कुंजी विजेट हैं; अगर $ KEYTIMEOUT सभी तरह से नीचे सेट है तो ये बेकार हो जाते हैं। मैं क्या करता हूं, निर्गमन ^ X को vi आवेषण मोड में (यह डिफ़ॉल्ट रूप से स्व-सम्मिलित है); यह उन दो-कुंजी विजेट को काम जारी रखने की अनुमति देता है।

bindkey -rM viins '^X'

आप सेल्फ-इंसर्ट के लिए बाइंडिंग खो देते हैं, लेकिन आप इसे किसी और चीज़ से बाँध सकते हैं। (मैं नहीं, क्योंकि मेरे पास इसका कोई उपयोग नहीं है।)

आखिरी समस्या (मैंने अब तक पाया है): कुछ शेष डिफ़ॉल्ट कीबाइंडिंग हैं, जिन्हें हम सही रूप से $ KEYTIMEOUT सेट करने के कारण "खो" देते हैं, बुद्धि के लिए: जो ESC के साथ vi आवेषण मोड में शुरू होते हैं जो कर्सर कुंजी नहीं हैं । मैं व्यक्तिगत रूप से उन्हें ^ X के साथ शुरू करने के लिए विद्रोह करता हूं:

bindkey -M viins '^X,' _history-complete-newer \
                 '^X/' _history-complete-older \
                 '^X`' _bash_complete-word

अपडेट 2018:

यह ऊपर पूरे खंड को बदल देता है ("अपडेट 2017" के बाद) आवश्यक नहीं है। कीबोर्ड मैपिंग में ESC के बराबर होने के लिए META कुंजी को सेट करना संभव है:

bindkey -mv

इसलिए यह संभव है कि ^ X को अनबाइंड न किया जाए और इसके बजाय एक लीडर के रूप में META दबाकर ESC में शुरू होने वाली कीबाइंडिंग को एक्सेस किया जाए (आधुनिक कीबोर्ड पर ALT या OPT)।

यदि आपके पास पुस्तक से बैश से जेड शेल तक कील्ड एट अल।, कीबाइंडिंग में ईएससी और मेटा की समानता अध्याय 4 साइडबार में पीपी 78-79 पर चर्चा की गई है।


धन्यवाद। ये हैक्स (और ऊपर के मार्शौल भी) zsh के vi मोड को nigh- अनुपयोगी से उत्कृष्ट तक ले जाते हैं। मैंने एक सुपरसुअर खाता बनाया ताकि मैं आपको वोट दे सकूं। :-)
ctrueden

1
धन्यवाद! मुझे यह थोड़ा चिंताजनक लगता है कि, इस समय के बाद, हमें अभी भी जरूरत है कि मूल रूप से हैक और वर्कश्रेन्ड बनाने के लिए क्या ज़रूरी है कि zsh की कार्यक्षमता का एक छोटा हिस्सा उपयोगी हो!
wjv
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.