따옴표 내에서 쉘 변수 강조 문서는 $PWD2

vim에서 다음 문서는 $PWD2 행과 3 행의 두 가지 방식으로 색상이 지정됩니다.

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

첫 번째 인스턴스는 $PWD나머지 문자열과 다른 색으로 표시됩니다. 이는 리터럴 텍스트로 처리되지 않고 변수가 확장 될 것이라는 명확한 시각적 표시를 제공합니다. 반대로, 두 번째 인스턴스 $PWD는 작은 따옴표로 인해 리터럴 텍스트로 취급되므로 나머지 문자열과 동일하게 색상이 지정됩니다.

이 유형의 “쉘 인용 인식”을 제공하는 기존 이맥스 모드가 있습니까?



답변

아래 코드는 정규 표현식 대신 함수와 함께 글꼴 잠금 규칙을 사용하며, 함수 $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)

답변

@Lindydancer의 답변을 다음과 같이 개선했습니다.

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

답변