उद्धरणों के भीतर शेल चरों को हाइलाइट करना


13

Vim में, निम्नलिखित दस्तावेज़ $PWD2 और 3 लाइनों पर दो अलग-अलग तरीकों से रंगीन होने का कारण होगा :

#/bin/sh
echo "Current Directory: $PWD"
echo 'Current Directory: $PWD'

इसका पहला उदाहरण $PWDबाकी स्ट्रिंग से एक अलग रंग में होगा। यह एक स्पष्ट दृश्य संकेत देता है कि वेरिएबल का विस्तार किया जाएगा, बजाय शाब्दिक पाठ के रूप में। इसके विपरीत, दूसरा उदाहरण $PWDबाकी स्ट्रिंग के समान रंग का होगा, क्योंकि एकल उद्धरण इसका कारण शाब्दिक पाठ के रूप में माना जाता है।

क्या कोई मौजूदा emacs मोड हैं जो इस प्रकार की "शेल-कोटिंग जागरूकता" प्रदान करते हैं?


1
निश्चित रूप से, यह जोड़ने के लिए बहुत कठिन नहीं होगा sh-mode? शायद इसे Emacs में ही जोड़ा जा सकता है।
पाइथननॉट

जवाबों:


11

नीचे दिया गया कोड एक रेन्जएक्सपी के बजाय एक फ़ंक्शन के साथ एक फॉन्ट-लॉक नियम का उपयोग करता है, फ़ंक्शन $VARकेवल घटनाओं के लिए खोज करता है, लेकिन केवल जब वे दोहरे-उद्धृत स्ट्रिंग के अंदर होते हैं। (syntax-ppss)इसे निर्धारित करने के लिए फ़ंक्शन का उपयोग किया जाता है।

फ़ॉन्ट-लॉक नियम prependध्वज का उपयोग मौजूदा स्ट्रिंग हाइलाइटिंग के ऊपर खुद को जोड़ने के लिए करता है। (ध्यान दें कि कई पैकेज इसके लिए उपयोग tकरते हैं। दुर्भाग्य से, यह मौजूदा हाइलाइटिंग के सभी पहलुओं को अधिलेखित करता है। उदाहरण के लिए, prependफोरग्राउंड रंग को बदलने के दौरान एक स्ट्रिंग बैकग्राउंड रंग (यदि कोई है) को बरकरार रखेगा।)

(defun sh-script-extra-font-lock-is-in-double-quoted-string ()
  "Non-nil if point in inside a double-quoted string."
  (let ((state (syntax-ppss)))
    (eq (nth 3 state) ?\")))

(defun sh-script-extra-font-lock-match-var-in-double-quoted-string (limit)
  "Search for variables in double-quoted strings."
  (let (res)
    (while
        (and (setq res
                   (re-search-forward
                    "\\$\\({#?\\)?\\([[:alpha:]_][[:alnum:]_]*\\|[-#?@!]\\)"
                    limit t))
             (not (sh-script-extra-font-lock-is-in-double-quoted-string))))
    res))

(defvar sh-script-extra-font-lock-keywords
  '((sh-script-extra-font-lock-match-var-in-double-quoted-string
     (2 font-lock-variable-name-face prepend))))

(defun sh-script-extra-font-lock-activate ()
  (interactive)
  (font-lock-add-keywords nil sh-script-extra-font-lock-keywords)
  (if (fboundp 'font-lock-flush)
      (font-lock-flush)
    (when font-lock-mode
      (with-no-warnings
        (font-lock-fontify-buffer)))))

आप पिछले फ़ंक्शन को उपयुक्त हुक में जोड़कर इसका उपयोग कर सकते हैं, उदाहरण के लिए:

(add-hook 'sh-mode-hook 'sh-script-extra-font-lock-activate)

यह मेरे लिए काम करता है, लेकिन स्ट्रिंग को उजागर करने के साथ "$" छोड़ देता है।
इरीकॉस्टोक

यह डिजाइन द्वारा है, क्योंकि यह एक स्ट्रिंग के बाहर एक चर को कैसे हाइलाइट किया गया था। हालाँकि, इसे आसानी से बदला जा सकता है। यदि आप 2फ़ॉन्ट-लॉक नियम से प्रतिस्थापित करते हैं तो 0इसे काम करना चाहिए। (आपको ठीक }से हाइलाइट करने के लिए एक अनुगामी को शामिल करने के लिए regexp को विस्तारित करने की आवश्यकता हो सकती ${FOO}है।) यह संख्या मैच के regexp उपसमूह को संदर्भित करती है, 0जिसका अर्थ है कि पूरे मैच को हाइलाइट किया जाना चाहिए।
लिंडनाइडर

किसी को भी दिलचस्पी होने पर इसे मेरे .emacs.d रिपॉजिटरी में जोड़ते हुए पैक किया गया: github.com/moonlite/.emacs.d/blob/… @Lindydancer Is GPLv3 + है और आप उस फाइल में लेखक हैं? (मैं एक अद्यतन धक्का दूँगा अगर नहीं)।
मटियास बेंग्सन

बढ़िया है। मुझे संभवत: इसे उचित पैकेज में बदलने के लिए समय नहीं चाहिए। हालाँकि, मैं चाहूंगा कि आप मेरा ईमेल पता छोड़ दें और इसके बजाय मेरे EmacsWiki पेज ( emacswiki.org/emacs/AndersLindgren ) पर एक पंक्ति जोड़ें । इसके अलावा, आप कॉपीराइट साइन को हटा सकते हैं क्योंकि यह आवश्यक नहीं है और यह स्रोत कोड को गैर-एएससीआई बनाता है।
लिंडनाइज़र

3

मैंने निम्नलिखित तरीकों से @ लिंडनाइज़र के उत्तर में सुधार किया:

  • फ़ंक्शन को झुकाएं sh-script-extra-font-lock-is-in-double-quoted-string, क्योंकि यह केवल एक बार उपयोग किया गया था
  • परिवर्तनशील कार्यों से बचना।
  • संख्यात्मक चर ( $10और $1, आदि) पर प्रकाश डाला गया है।

कोड के लिए ब्रेक

(defun sh-script-extra-font-lock-match-var-in-double-quoted-string (limit)
  "Search for variables in double-quoted strings."
  (let (res)
    (while
        (and (setq res (progn (if (eq (get-byte) ?$) (backward-char))
                              (re-search-forward
                               "[^\\]\\$\\({#?\\)?\\([[:alpha:]_][[:alnum:]_]*\\|[-#?@!]\\|[[:digit:]]+\\)"
                               limit t)))
             (not (eq (nth 3 (syntax-ppss)) ?\")))) res))

(defvar sh-script-extra-font-lock-keywords
  '((sh-script-extra-font-lock-match-var-in-double-quoted-string
     (2 font-lock-variable-name-face prepend))))

(defun sh-script-extra-font-lock-activate ()
  (interactive)
  (font-lock-add-keywords nil sh-script-extra-font-lock-keywords)
  (if (fboundp 'font-lock-flush)
      (font-lock-flush)
    (when font-lock-mode (with-no-warnings (font-lock-fontify-buffer)))))

के [^\\\\]रूप में लिखा जा सकता है [^\\], यह उन पात्रों का एक सेट है, जिनका मिलान नहीं होना चाहिए, और आपके कोड में दो बार बैकस्लैश शामिल है। पुराने Emacs संस्करणों में उपयोग करना चाहिए font-lock-fontify-buffer, नए में आप कॉल करने वाले हैं font-lock-flushऔर font-lock-fontify-bufferelisp से कॉल करना पदावनत है। मेरे मूल कोड ने इसका अनुसरण किया, आपका कोड नहीं। वैसे भी, यह एक GitHub पुरालेख के लिए इसे स्थानांतरित करने और प्रयास में शामिल होने के लिए एक बेहतर विचार हो सकता है।
लिंड्सकैंसर

@ लिंडनेसर [^\\]बच नहीं सकता है ]? जैसा कि मुझे पता है कि जावा में रेगेक्स कैसे काम करता है।
Czipperz

@ लिंडकैंसर ऐसा लगता है जैसे यह नहीं है कि एलीस्प आपको चरित्र समूहों में भागने के पात्रों का उपयोग करने की अनुमति नहीं देता है
Czipperz

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