오래된 emacsen을 계속 지원하면서 prog-mode에서 어떻게 상속합니까?


10

프로그래밍 언어의 주요 모드를 작성하고 있지만 이전 Emacs 버전을 지원하고 싶습니다. prog-mode비교적 새롭습니다. prog-mode정의 된 경우 상속을 받고 싶지만 여전히 그렇지 않으면 합리적인 것을 수행합니다.

가장 좋은 방법은 무엇입니까? defalias prog-mode이전 Emacsen을 사용해야합니까 , 아니면 같은 방식으로 다른 모드를 방해합니까?


Emacs <24에 대한 지원을 중단하는 것이 좋습니다 prog-mode. 제 생각에는 더 이상 노력할 가치가 없으며보다 중요한 기능을 포기해야합니다 . 특히 어휘 바인딩이 부족하여 어려움을 겪을 것입니다.
lunaryorn

나는 줄리아 모드에 기여하고 있으며 일부 핵심 팀은 이전 Emacsen을 사용하고 우리가 지원하는 것을 선호합니다.
Wilfred Hughes

1
@lunaryorn Emacs 24는 여전히 새롭습니다. Emacs 23은 많은 OS에서 현재 버전입니다. 이맥스 22는 여전히 최신 버전입니다. 모두가 미친 것처럼 소프트웨어를 업그레이드하는 것은 아닙니다. Emacs 23에 대한 지원을 중단하면 최첨단을 갈망하는 소수의 사용자로 제한됩니다.
Gilles 'SO- 악마 그만해

1
이전 Emacs 버전을 사용하는 데는 여러 가지 이유가 있습니다. 예를 들어, Windows에서 Emacs 23은 매우 느려져서 Emacs 22를 고수하기로했습니다.
Lindydancer

@Gilles 나는 단지 "몇몇 사용자"라는 것을 의심한다. Flycheck는 처음에는 Emacs 23을 지원하지 않았지만 MELPA에서 가장 인기있는 패키지 중 하나가되었습니다.
lunaryorn

답변:


11

추가적인 최상위 심볼 바인딩을 희생시키면서 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-mode2 년 전 IIRC 에서이 문제를 생각 해냈고, 거기에서 몇 가지 다른 주요 모드로 확산 된 것 같습니다. 하여 더 중요한 것은 define-derived-mode이런 의미에서, : 매크로 부모 모드 기호 수행은 그 기능을 호출하는 코드 생성이다 defalias별칭 기능에 정확히 해당하는 새 변수하게합니다.

주의해야 할 점은 이것이 혼동 될 수 derived-mode-p있으므로 모드가 파생되었는지 확인하는 코드가 prog-mode제대로 작동하지 않을 수 있다는 것입니다. 실제로 나는 아무런 문제가 발생하지 않았다. 그런 코드가 연결되는 것이 더 일반적 prog-mode-hook이며 여전히 실행된다.

(Jorgen이 주석에서 지적한 것처럼 부모 모드 기호 define-derived-modemode-class속성 도 사용하며 defalias복사하지 않습니다. 작성 당시에는이 속성 만 사용 된 것으로 보입니다special-mode .)

업데이트 : 요즘에는 이전 버전이 오래 사용되지 않기 때문에 최소한 Emacs 24 이상을 요구하는 것이 좋습니다.


2
좋은 해결책! 주의 사항 : 이것은 작동 prog-mode하지만 모든 모드에서 작동하지는 않습니다. symbol 속성을 자식 모드로 define-derived-mode복사 mode-class합니다. 는 defalias것이다 없습니다 이 속성을 전송합니다. 경우 mode-class사용 사례와 관련이 수동으로 설정 / 복사해야합니다.
Jorgen Schäfer

그것을 알아 주셔서 감사합니다, Jorgen-나는 그 mode-class속성이 무엇을 의미 하는지에 대해 더 깊이 파고 들어야 할 것 입니다.
sanityinc

3

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사용할 수 없습니다?
Wilfred Hughes

@Jorgen 아니면 fboundp먼저 define-derived-mode문장을 사용하여 중간 모드를 파생시킬 수 있습니까? 그렇다면 전체 모드의 실제 모드는 해당 중간 모드에서 파생 될 수 있습니까? 이렇게하면 전체 모드를 두 번 정의 할 필요가 없습니다.
Kaushal Modi

1
@ WilfredHughes, 아무도 없습니다. 에서의 유도 fundamental-mode에서 파생하는 것과 같습니다 nil(실제로 및 define-derived-mode대체합니다 fundamental-mode과를 nil하면서) text-mode프로그램 코드는 텍스트 아니므로, 적합하지 않습니다. text-mode주석 이외의 프로그래밍 모드 에서는 대부분의 기본 설정 이 의미가 없습니다. 이것이 prog-modeEmacs 24에 소개 된 이유입니다 .
Jorgen Schäfer

@kaushalmodi, 중간 모드를 파생시킬 수는 있지만 최종 모드 대신 중간 모드에 대해서만 두 가지 define-derived-mode정의 if형식이 필요 합니다. defuninit 함수를 define-derived-mode최종 모드의 로 대체 합니다. 나는 이것이 특히 바람직하다고 생각하지 않습니다. prog-mode원래 질문에서 알 수 있듯이 자신 을 정의 할 수도 있지만 해당 모드 fboundp의 존재를 확인 하는 데 의존하는 다른 모드를 쉽게 혼동시킬 수 있습니다 .
Jorgen Schäfer

나는 두 가지 다른 define-derived-mode진술이 필요 하다고 생각하지 않습니다 . 몇 년 전에 필자는 별도의 답변으로 게시 한 솔루션을 생각해 냈으며 Emacs 23 및 24에서 모두 잘 작동하는 것 같습니다. 코드는 여러 가지 주요 주요 모드에서 사용됩니다.
sanityinc

0

테스트를 사용 fboundp하는 것이 더 합리적 이라고 생각 합니다.

(if (fboundp 'prog-mode)
    ...
   ...)

0

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

(경고 : 최소한의 테스트 만 필요합니다.)

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