Tırnak içindeki kabuk değişkenlerini vurgulama


13

Vim'de, aşağıdaki belge $PWD2 ve 3 numaralı satırların iki farklı şekilde renklenmesine neden olacaktır :

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

İlk örneği, $PWDiçinde bulunduğu dizenin geri kalanından farklı bir renkte olacaktır. Bu, değişkenin değişmez metin olarak işlemden ziyade genişletileceğini açık bir görsel olarak verir. Buna karşılık, ikinci örneği $PWDdizginin geri kalanıyla aynı renkte olacaktır, çünkü tek tırnaklar değişmez metin olarak ele alınmasına neden olur.

Bu tür "kabuk alıntılama farkındalığı" sağlayan mevcut emacs modları var mı?


1
Şüphesiz, bu eklemek çok zor olmaz mıydı sh-mode? Belki Emacs'ın kendisine eklenebilir.
PythonNut

Yanıtlar:


11

Aşağıdaki kod, regexp yerine bir işleve sahip bir font kilidi kuralı kullanır; işlev, $VARyalnızca çift tırnaklı bir dizenin içindeyken oluşumları arar . İşlev (syntax-ppss)bunu belirlemek için kullanılır.

Yazı tipi kilidi kuralı, prependkendisini mevcut dize vurgulamasının üstüne eklemek için bayrağı kullanır . (Bunun için birçok paketin kullanıldığını unutmayın t. Maalesef bu, mevcut vurgulamanın tüm yönlerinin üzerine yazar. Örneğin, kullanmak prepend, ön plan rengini değiştirirken dize arka plan rengini (varsa) korur.)

(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)))))

Son işlevi uygun bir kancaya ekleyerek bunu kullanmayı arayabilirsiniz, örneğin:

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

Bu benim için çalışıyor, ancak dize vurgulama ile "$" bırakır.
erikstokes

Dizge dışındaki bir değişkenin nasıl vurgulandığı için tasarım gereğidir. Ancak, bu kolayca değiştirilebilir. 2Font kilidi kuralındaki bir ile değiştirirseniz, 0çalışması gerekir. (Normal şekilde }vurgulamak için bir iz eklemek üzere normal ifadeyi genişletmeniz gerekebilir ${FOO}.) Bu sayı, eşleşmenin normal ifade alt grubunu 0ifade eder, tüm eşleşmenin vurgulanması gerektiği anlamına gelir.
Lindydancer

Anyonlar ilgiliyse bunu .emacs.d deposuma eklerken paketledim : github.com/moonlite/.emacs.d/blob/… @Lindydancer GPLv3 + ve bu dosyada yazar olarak siz misiniz? (Değilse bir güncelleme gönderirim).
Mattias Bengtsson

Kulağa iyi geliyor. Muhtemelen uygun bir pakete dönüştürmek için zamanım olmayacaktı. Ancak, e-posta adresimi bırakmanızı ve bunun yerine EmacsWiki sayfama ( emacswiki.org/emacs/AndersLindgren ) bir satır eklemenizi istiyorum . Ayrıca, gerekli olmadığından ve kaynak kodunu ascii yapmadığı için telif hakkı işaretini kaldırabilirsiniz.
Lindydancer

3

@ Lindydancer'ın cevabını aşağıdaki şekillerde geliştirdim:

  • sh-script-extra-font-lock-is-in-double-quoted-stringYalnızca bir kez kullanıldığından , işlevi satır içine aldım
  • Değişkenlerden kaçmak çalışır.
  • Sayısal değişkenler ( $10, $1vb.) Vurgulanır.

Kod sonu

(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)))))

[^\\\\]Olarak yazılmış olabilir [^\\]o eşleştirilmemelidir bir karakter kümesi vardır ve kodunuzu iki kez ters eğik çizgi içerir. Daha eski Emacs sürümlerinde kullanmanız gerekir font-lock-fontify-buffer, daha yenisinde aramanız gerekiyor font-lock-flushve font-lock-fontify-bufferelisp'den çağrı reddediliyor. Orijinal kodum bunu izledi, kodunuz gelmedi. Her neyse, bunu GitHub arşivine geçirmek ve çabaya katılmak daha iyi bir fikir olabilir.
Lindydancer

@Lindydancer yapmaz [^\\]kaçış ]? Bildiğim gibi regex Java'da böyle çalışır.
Czipperz

@Lindydancer ELisp karakter gruplarında kaçış karakterleri kullanmanıza izin vermediği için öyle görünmüyor .
Czipperz

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.