शेल प्रोफाइल और करंट डाइरेक्टरी हुक (उदा। डिरेनव) का उपयोग करके शेल-कमांड रन कैसे करें


9

मैं अपनी फ़ाइल में कुछ कार्यक्रमों के साथ समेकित रूप से प्राप्त करने shell-commandऔर async-shell-commandएकीकृत करने की कोशिश कर रहा हूं .bashrc, विशेष रूप से इस उदाहरण में direnv

मैंने पाया कि यदि मैं अनुकूलित करता हूं shell-command-switch, तो मुझे अपनी प्रोफ़ाइल लोड करने के लिए शेल प्रक्रियाएं मिल सकती हैं जैसे कि यह एक नियमित इंटरेक्टिव लॉगिन शेल था:

(सेट शेल-कमांड-स्विच (प्योरकोपी "-ic"))
(सेट-क्लीयर-बैश-आर्ग्स '("-ic" "निर्यात EMACS =; स्टिकी इच; बाइट" "))

मैं निष्पादन-पथ-से-शेल का भी उपयोग कर रहा हूं ।

कहो कि मेरे पास एक ~/.bashrcफ़ाइल है:

...

eval "$ (direnv हुक $ 0)"
इको "फू"

अंदर ~/code/fooमेरे पास एक .envrcफाइल है:

निर्यात पथ = $ पीडब्ल्यूडी / बिन: $ पथ
इको "बार"

अगर मैं सेट के M-x shellसाथ दौड़ता हूं , तो एक bash शेल मेरी प्रोफाइल को सही ढंग से लोड करेगा और उसे मेरे पथ में जोड़ने के लिए direnv हुक चलाएगा:default-directory~/code/foo

direnv: loading .envrc
बार
direnv: निर्यात ~ पथ
~ / कोड / फू $ इको $ पाथ
/ उपयोगकर्ता / उपयोगकर्ता नाम / कोड / foo / bin: / usr / स्थानीय / बिन: ... # शेष $ पेट

हालांकि, अगर default-directoryअभी भी है ~/code/fooऔर मैं चलाता हूं M-! echo $PATH, तो यह मेरे .bashrc को सही ढंग से लोड करता है, लेकिन वर्तमान निर्देशिका के direnv हुक को निष्पादित नहीं करता है:

foo
/ usr / स्थानीय / बिन: ... # $ PATH के बिना बाकी ।/bin

अगर मैं दौड़ता हूं तो मुझे वही परिणाम मिलता है M-! cd ~/code/foo && echo $PATH

वहाँ एक रास्ता मैं सलाह देने के लिए या में हुक कर सकते हैं shell-commandया start-processजैसे कि यह एक इंटरैक्टिव खोल बफर से भेजे जा रहे थे यह व्यवहार करते हैं बनाने के लिए?


आपका डेरेनव हुक कैसा दिखता है? यदि इसे ~ / .bashrc में परिभाषित किया गया है और आप इसे स्पष्ट करते हैं, (setq shell-command-switch "-ic")तो इसका मूल्यांकन ~ / .bashrc में हर दूसरे कमांड के साथ किया जाना चाहिए।
7

मेरी ~ / .bashrc में लाइन है eval "$(direnv hook $0)"। यह निष्पादित हो रहा है, लेकिन जब आप एक विशिष्ट निर्देशिका में होते हैं तो एक .envrcफाइल के साथ तंत्र को निकाल दिया जाना चाहिए ।
वेन्डमांडो

क्या .envrcफ़ाइल में कुछ भी मूल्यांकन नहीं किया गया है? या यह सिर्फ पर्यावरण चर है जो निर्यात नहीं किए जाते हैं? क्या आप कृपया एक पूर्ण उदाहरण प्रदान कर सकते हैं ताकि मैं इसे पुन: पेश करने का प्रयास कर सकूं?
रेकडो

@ ट्रेकाडो - इस पर एक नज़र लेने के लिए धन्यवाद। मैंने अपने प्रश्न को पुन: प्रस्तुत करने के लिए अधिक स्पष्ट होने के लिए अद्यतन किया।
वेन्डमांडो

जवाबों:


5

यह Emacs लेकिन बैश के साथ एक समस्या नहीं लगती है। shell-commandबस call-processशेल पर निष्पादित होता है और तर्क पारित करता है। मैंने इसे एक नियमित शेल पर आज़माया:

bash -ic "cd ~/code/foo && echo $PATH"

~/.bashrcखट्टा है, लेकिन direnv हुक नहीं चलाया जाता है। जब direnv hook bashनिष्पादित किया जाता है, तो एक फ़ंक्शन _direnv_hookआउटपुट होता है और प्रीपेन्ड किया जाता है PROMPT_COMMAND

_direnv_hook() {
  eval "$(direnv export bash)";
};
if ! [[ "$PROMPT_COMMAND" =~ _direnv_hook ]]; then
  PROMPT_COMMAND="_direnv_hook;$PROMPT_COMMAND";
fi

मुझे संदेह है कि PROMPT_COMMANDबस काम नहीं करेगा। हालांकि, यह एक समस्या नहीं है, क्योंकि _direnv_hookयह वास्तव में सरल है। हम केवल eval $(direnv export bash)शेल कमांड को प्रस्तुत कर सकते हैं और यह काम करेगा:

(let ((default-directory "~/code/foo/"))
  (shell-command "eval \"$(direnv export bash)\" && echo $PATH"))

यह संदेश बफ़र के लिए संवर्धित पथ मुद्रित करेगा। वैकल्पिक रूप से, इसके साथ निष्पादित करें M-!:

cd ~/code/foo && eval "$(direnv export bash)" && echo $PATH

इसके लिए आपको (setq shell-command-switch "-ic")काम करने की आवश्यकता नहीं है ।


धन्यवाद, इसने वास्तव में मुझे सही रास्ते पर लाने में मदद की। मैं एक ऐसे समाधान की तलाश में था, जिसमें शामिल न हो eval "$(direnv export bash)", लेकिन यह बेहद मददगार था और मुझे सही रास्ते पर ले गया।
वेन्डामांडो

5

रनिंग eval "$(direnv hook $0)"एक फ़ंक्शन को परिभाषित करता है जो हुक करता है $PROMPT_COMMAND, जिसे कभी भी नहीं कहा जाता है जब बैश को चलाया जाता है bash -icक्योंकि कोई संकेत नहीं है। आप लाइन बदल सकते हैं:

eval "$(direnv hook $0)"

सेवा:

eval "$(direnv hook $0)" && _direnv_hook

स्पष्ट रूप से हुक फ़ंक्शन को कॉल करने के लिए।

संपादित करें: बस एहसास हुआ रेकाडो ने बहुत ही समान उत्तर दिया।


यह सबसे संक्षिप्त उत्तर है कि मेरी अपरिचितता इस बात की ओर इशारा करती है कि डेरेनव किस तरह से काम करता है $PROMPT_COMMAND
वेन्डामांडो

4

रेकेडो और एरिक को यह इंगित करने के लिए धन्यवाद कि कैसे उपयोग करके direnv हुक काम करता है $PROMPT_COMMAND। चूंकि shell-commandएक प्रॉम्प्ट का उपयोग नहीं होता है, इसलिए इसे निष्पादित नहीं किया जा रहा था।

एरिक के जवाब के साथ एक शेल कमांड को बुलाने की मेरी उदाहरण में काम करता है M-!के साथ default-directoryसेट, यह होगा कि निम्न उदाहरण में काम नहीं:

(let ((default-directory "~/code/"))
  (shell-command "cd ~/code/foo && echo $PATH"))

कुछ गुगली करने के बाद, मुझे कमांड को निष्पादित करने से पहले कुछ निष्पादित करने के लिए बैश में एक preexec हुक बनाने का एक तरीका मिला । मैंने यह विचार लिया और direnv के लिए अपनी आवश्यकता को फिट करने के लिए संशोधित किया। यहाँ मेरे ~ / .bashrc का प्रासंगिक हिस्सा अब कैसा दिखता है:

eval "$(direnv hook $0)"
direnv_preexec () {
  [ -n "$COMP_LINE" ] && return # don't execute on completion
  [ "$BASH_COMMAND" \< "$PROMPT_COMMAND" ] && return # don't double execute on prompt hook
  eval "$(direnv export bash)"
}
trap "direnv_preexec && $BASH_COMMAND" DEBUG

0

आजकल आप संभवतः https://github.com/wbolster/emacs-direnv का उपयोग करना चाहते हैं

यह हुक के समान काम करता है जो direnv आपके शेल में स्थापित होता है। emacs पर्यावरण अनुरोध पर अद्यतन किया जाता है (या स्वचालित रूप से बफ़र्स स्विच करते समय) मिलान करने के लिए कि क्या direnv राज्य वर्तमान निर्देशिका के लिए सही वातावरण है।

संशोधित करके exec-pathऔर process-environmentएमएसीएस ऐसा व्यवहार करेंगे जैसे आपका शेल करेगा: सही रास्तों से और सही वातावरण के साथ कार्यक्रमों को निष्पादित करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.