프로그래밍 언어의 주요 모드를 작성하고 있지만 이전 Emacs 버전을 지원하고 싶습니다. prog-mode
비교적 새롭습니다. prog-mode
정의 된 경우 상속을 받고 싶지만 여전히 그렇지 않으면 합리적인 것을 수행합니다.
가장 좋은 방법은 무엇입니까? defalias
prog-mode
이전 Emacsen을 사용해야합니까 , 아니면 같은 방식으로 다른 모드를 방해합니까?
프로그래밍 언어의 주요 모드를 작성하고 있지만 이전 Emacs 버전을 지원하고 싶습니다. prog-mode
비교적 새롭습니다. prog-mode
정의 된 경우 상속을 받고 싶지만 여전히 그렇지 않으면 합리적인 것을 수행합니다.
가장 좋은 방법은 무엇입니까? defalias
prog-mode
이전 Emacsen을 사용해야합니까 , 아니면 같은 방식으로 다른 모드를 방해합니까?
답변:
추가적인 최상위 심볼 바인딩을 희생시키면서 define-derived-mode
양식을 반복하지 않는 매우 깔끔한 솔루션이 있습니다 .
(defalias 'my-fancy-parent-mode
(if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))
(define-derived-mode my-fancy-mode my-fancy-parent-mode
...)
모든 Emacs> = 23에서 잘 작동합니다. 저는 haml-mode
2 년 전 IIRC 에서이 문제를 생각 해냈고, 거기에서 몇 가지 다른 주요 모드로 확산 된 것 같습니다. 하여 더 중요한 것은 define-derived-mode
이런 의미에서, : 매크로 부모 모드 기호 수행은 그 기능을 호출하는 코드 생성이다 defalias
별칭 기능에 정확히 해당하는 새 변수하게합니다.
주의해야 할 점은 이것이 혼동 될 수 derived-mode-p
있으므로 모드가 파생되었는지 확인하는 코드가 prog-mode
제대로 작동하지 않을 수 있다는 것입니다. 실제로 나는 아무런 문제가 발생하지 않았다. 그런 코드가 연결되는 것이 더 일반적 prog-mode-hook
이며 여전히 실행된다.
(Jorgen이 주석에서 지적한 것처럼 부모 모드 기호 define-derived-mode
의 mode-class
속성 도 사용하며 defalias
복사하지 않습니다. 작성 당시에는이 속성 만 사용 된 것으로 보입니다special-mode
.)
업데이트 : 요즘에는 이전 버전이 오래 사용되지 않기 때문에 최소한 Emacs 24 이상을 요구하는 것이 좋습니다.
prog-mode
하지만 모든 모드에서 작동하지는 않습니다. symbol 속성을 자식 모드로 define-derived-mode
복사 mode-class
합니다. 는 defalias
것이다 없습니다 이 속성을 전송합니다. 경우 mode-class
사용 사례와 관련이 수동으로 설정 / 복사해야합니다.
mode-class
속성이 무엇을 의미 하는지에 대해 더 깊이 파고 들어야 할 것 입니다.
tl; dr : 사용 if
및 자체 초기화 기능 :
(if (fboundp 'prog-mode)
(define-derived-mode your-cool-mode prog-mode "Cool"
"Docstring"
(your-cool--init))
(define-derived-mode your-cool-mode nil "Cool"
"Docstring"
(your-cool--init)))
그런 다음의 모든 모드 초기화를 수행하십시오 your-cool-init
.
더 긴 설명 :
문제는 파생 된 주요 모드를 작성하는 공식적인 방법은 define-derived-mode
매크로 를 사용하는 것입니다 .
(define-derived-mode your-cool-mode prog-mode ...)
이전 Emacsen (24 이전)에서는이 때 중단됩니다 prog-mode
. 그리고 (if (fboundp 'prog-mode) ...)
매크로는 리터럴 기호를 기대하고 확장에서 당신을 위해 인용 할 것이기 때문에 거기에서 사용할 수 없습니다 .
define-derived-mode
부모를 다양한 방법으로 사용합니다. 그것들을 사용하기 위해서는 자신의 모드 정의에있는 것들을 모두 복사해야하며, 이는 지루하고 오류가 발생하기 쉽습니다.
따라서 유일한 방법은 존재 define-derived-mode
여부에 따라 두 개의 다른 명령문 을 사용하는 것입니다 prog-mode
. 초기화 코드를 두 번 작성하는 문제가 있습니다. 물론 나쁘기 때문에 위에서 설명한대로 자체 기능으로 추출합니다.
(가장 좋은 해결책은 물론 23.x에 대한 지원을 중단하고 어휘 범위를 사용하는 것입니다. 그러나 이미 그 옵션을 고려하고 삭제했다고 생각합니다. :-))
prog-mode
구형 Emacsen에서 가장 가까운 것은 무엇입니까 ? 그것에서 파생 감각을 만들 것 text-mode
또는 fundamental-mode
경우에하는 것은 prog-mode
사용할 수 없습니다?
fboundp
먼저 define-derived-mode
문장을 사용하여 중간 모드를 파생시킬 수 있습니까? 그렇다면 전체 모드의 실제 모드는 해당 중간 모드에서 파생 될 수 있습니까? 이렇게하면 전체 모드를 두 번 정의 할 필요가 없습니다.
fundamental-mode
에서 파생하는 것과 같습니다 nil
(실제로 및 define-derived-mode
대체합니다 fundamental-mode
과를 nil
하면서) text-mode
프로그램 코드는 텍스트 아니므로, 적합하지 않습니다. text-mode
주석 이외의 프로그래밍 모드 에서는 대부분의 기본 설정 이 의미가 없습니다. 이것이 prog-mode
Emacs 24에 소개 된 이유입니다 .
define-derived-mode
정의 if
형식이 필요 합니다. defun
init 함수를 define-derived-mode
최종 모드의 로 대체 합니다. 나는 이것이 특히 바람직하다고 생각하지 않습니다. prog-mode
원래 질문에서 알 수 있듯이 자신 을 정의 할 수도 있지만 해당 모드 fboundp
의 존재를 확인 하는 데 의존하는 다른 모드를 쉽게 혼동시킬 수 있습니다 .
define-derived-mode
진술이 필요 하다고 생각하지 않습니다 . 몇 년 전에 필자는 별도의 답변으로 게시 한 솔루션을 생각해 냈으며 Emacs 23 및 24에서 모두 잘 작동하는 것 같습니다. 코드는 여러 가지 주요 주요 모드에서 사용됩니다.
define-derived-mode
인수를 평가 하는 랩퍼 매크로를 정의 할 수 있습니다 .
(defmacro define-derived-mode* (child parent name &optional docstring &rest body)
(macroexpand `(define-derived-mode ,(eval child) ,(eval parent) ,(eval name)
,(eval docstring) . ,body)))
(define-derived-mode* 'toy-mode
(if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode)
"Toy"
"Major mode for my favorite toy language"
(toy-mode-setup))
(경고 : 최소한의 테스트 만 필요합니다.)
prog-mode
. 제 생각에는 더 이상 노력할 가치가 없으며보다 중요한 기능을 포기해야합니다 . 특히 어휘 바인딩이 부족하여 어려움을 겪을 것입니다.