따옴표 내에서 쉘 변수 강조


13

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

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

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

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


1
확실히, 이것은 추가하기 어렵지 sh-mode않을까요? 아마도 Emacs 자체에 추가 될 수 있습니다.
PythonNut

답변:


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)

이것은 나를 위해 작동하지만 문자열을 강조 표시하여 "$"를 남겨 둡니다.
erikstokes 2016 년

문자열 외부의 변수가 강조 표시되는 방식이므로 의도적으로 설계된 것입니다. 그러나 이것은 쉽게 변경 될 수 있습니다. 당신이 교체되면 2로모그래퍼 글꼴 잠금 규칙 0이 작동합니다. ( 정확하게 }강조 표시 ${FOO}하려면 후행을 포함하도록 정규 표현식을 확장해야 할 수도 있습니다 .)이 숫자는 일치하는 정규 표현식 하위 그룹을 0나타내므로 전체 일치를 강조 표시해야합니다.
Lindydancer

github.com/moonlite/.emacs.d/blob/… 관심있는 사람이 있다면 이것을 .emacs.d 저장소에 추가하면서 이것을 패키지로 만들었 습니다 . @Lindydancer GPLv3 +입니까? (아니면 업데이트를 푸시하겠습니다).
Mattias Bengtsson 2016 년

좋은 데요 아마 적절한 패키지로 만들 시간이 필요하지 않을 것입니다. 그러나 이메일 주소를 삭제하고 대신 EmacsWiki 페이지 ( emacswiki.org/emacs/AndersLindgren )에 줄을 추가하고 싶습니다 . 또한 필요하지 않은 저작권 표시를 제거 할 수 있으며 소스 코드를 ASCII가 아닌 것으로 만듭니다.
Lindydancer

3

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

[^\\\\]같이 쓸 수 [^\\]는 일치하지 않아야 문자의 집합, 그리고 코드가 두 번 백 슬래시 포함되어 있습니다. 이전 이맥스 버전을 사용해야에서 font-lock-fontify-buffer, 새로운 당신이 전화를 해야하는 font-lock-flush및 호출 font-lock-fontify-bufferelisp에서하는 것은 지원되지 않습니다. 내 원래 코드는이를 따르지만 코드는 그렇지 않습니다. 어쨌든, 이것을 GitHub 아카이브로 마이그레이션하고 노력에 참여하는 것이 좋습니다.
Lindydancer

@Lindydancer [^\\]탈출 하지 ]않습니까? 내가 아는 것처럼 Java에서 정규식이 작동하는 방식입니다.
Czipperz

@Lindydancer ELisp 를 사용하면 문자 그룹에서 이스케이프 문자를 사용할 수 없기 때문에 그렇지 않습니다 .
Czipperz

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.