लाइन की लंबाई की गणना के बिना बैश के PS1 में कमांड कैसे शामिल करें?


13

टोनिन ने मेरे डिफ़ॉल्ट प्रॉम्प्ट में एक बग बताया । न्यूनतम उदाहरण:

  1. PS1 सेट करें:

    PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s $(tput setaf 1) $exit_code $(tput sgr0) " ")$ '

    इस बिंदु पर, संकेत इस तरह दिखता है:

    $ 
  2. अब बाहर निकलने के लिए बाहर निकलें कोड उत्पादन ट्रिगर:

    false

    अब प्रॉम्प्ट में लाइन की शुरुआत में लाल रंग में निकास कोड होता है:

    1 $ 
  3. प्रेस Ctrl- r।
  4. "गलत" टाइप करें। अब प्रॉम्प्ट में केवल खोज शामिल है:

    (reverse-i-search)`false': false
  5. प्रेस करें Enter।

परिणामी टर्मिनल इतिहास में अब निम्नलिखित शामिल हैं:

1 $ch)`false': false

अपेक्षित उत्पादन:

1 $ false

यही है, ऐसा लगता है कि इतिहास खोज आउटपुट को प्रॉम्प्ट और वास्तविक कमांड को छिपाने के साथ मिलाया गया है जिसे चलाया गया था।

मैंने इसका उपयोग करके इसकेPROMPT_COMMAND आसपास काम करने की कोशिश की :

set_exit_code() {
    exit_code=$?
    [[ $exit_code -eq 0 ]] || printf %s $(tput setaf 1) $exit_code $(tput sgr0) " "
}
set_bash_prompt() {
    PS1='$(set_exit_code)$ ' # Double quotes give the same result
}
PROMPT_COMMAND=set_bash_prompt

यह काम नहीं करता है - खोज और चलाने के बाद लाइन पहले जैसी ही दिखती है।

मैं इसे कैसे ठीक करूं?


1
ऐसा लगता है कि यह unix.stackexchange.com/a/71012
— 1948

जवाबों:


8

मुझे askubuntu.com पर जवाब मिला । @qeirha ने उल्लेख किया कि आपको बैश को बताना होगा कि वर्णों के अनुक्रम को प्रॉम्प्ट की लंबाई में नहीं गिना जाना चाहिए, और आप इसे संलग्न करके करते हैं \[ \]। दिए गए उदाहरण के आधार पर, यहाँ एक समाधान है:

red=$(tput setaf 1)

reset=$(tput sgr0)

[ "$PS1" = "\\s-\\v\\\$ " ] && PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s \[$red\] $exit_code \[$reset\] " ")$ '

इसके लिए Ask Ubuntu पर जाने की आवश्यकता नहीं है। हमारे पास पहले से ही इस प्रश्न के पर्याप्त उत्तर हैं।
— मैनटवर्क

सलाह के लिए धन्यवाद @manatwork! मैं स्पष्टीकरण के लिए उचित श्रेय देना चाहता था और शिष्टाचार के नाते संदर्भ की आपूर्ति करता था।
— टिमोथी मार्टिन

क्रेडिट देना कोई समस्या नहीं है। लेकिन समस्या के बारे में बात करते समय: मार्कडाउन से गायब हुए बैकस्लैश का उपयोग किया जाता है, इसलिए आपके पोस्ट में आपका सादा [बन गया], इस प्रकार प्रदर्शित कोड टर्मिनल में कॉपी-पेस्ट करके कार्यात्मक नहीं था। इनलाइन कोड या कोड ब्लॉक मार्कअप का उपयोग करके इससे बचा जा सकता है। ( मैं
— मार्कडाउन

1
डी 'ओह! मैंने पहले ही अन्य PS1कोड के लिए एक ही मुद्दा तय कर दिया है, मैंने उसे क्यों नहीं देखा?
— l0b0

1
PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s \[$(tput setaf 1)\] $exit_code \[$(tput sgr0)\] " ")$ '

(क्षमा करें, यहां कोई स्पष्टीकरण नहीं है। देखें कि PS1 को ठीक से कैसे अनुकूलित किया जाए? या शीघ्र लंबाई गणना के मुद्दों और \[.. के बारे में कोई अन्य प्रश्न \])।


दूसरे @ l0b0 प्रश्न पर, मैं जोड़ दूंगा कि PS1 का उपयोग करके और \[...\]ठीक काम करता है जब तक कि आप एक ही स्ट्रिंग में अपना प्रांप्ट उत्पन्न करना चाहते हैं सभी कोड डाल सकते हैं। हालाँकि, यदि आप अपने कोड को छोटे-छोटे कार्यों में विभाजित करना चाहते हैं, तो आप एक ऐसे बिंदु पर आते हैं, जहाँ आप शुरुआती और अंतिम कोष्ठकों को एक ही स्ट्रिंग / फ़ंक्शन में नहीं डाल सकते। और वह लाइन रैप को तोड़ देती है। जब तक आप प्रत्येक प्रॉम्प्ट पर PROMPT_COMMANDअपने पुन: उपयोग करने के लिए उपयोग नहीं करते हैं PS1।
— टोनिन

1

@Manatwork उत्तर पर विस्तार करना लेकिन अपने कोड PS1को अलग-अलग कार्यों में कंप्यूट को विभाजित करते हुए , आप अपना संकेत निम्नलिखित तरीके से लिख सकते हैं:

set_exit_code() {
    exit_code=$?
    [[ $exit_code -eq 0 ]] || printf "\[$(tput setaf 1)\] $exit_code \[$(tput sgr0)\] "
}
set_bash_prompt() {
    PS1="$(set_exit_code)$ " # with double quotes!
}
PROMPT_COMMAND=set_bash_prompt

फ़ंक्शन में PS1उपयोग करते समय और जब दोनों दोहरे उद्धरण अनिवार्य हैं printf।


भविष्य के संदर्भ के लिए, अपने bash फ़ंक्शन का उपयोग करें .bashrc- एक अलग फ़ाइल में कोड न डालें और कॉल करें।
— Starbeamrainbowlabs
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.