mmm-mode:将C ++模式实现为子模式

时间:2013-01-08 17:21:12

标签: emacs elisp

我们使用内部脚本语言(我们称之为pkc),它允许嵌入C ++代码。 C ++代码段由{{{}}}标记分隔。

我使用Generic Modemmm-mode为此语言创建了emacs模式。

这是我得到的(剥离非必要部分在这里张贴):

(require 'generic-x)

(setq pkc-imenu-generic-expression
      '(("macros" "^[ \t]*macro[ \n\t]+\\([a-zA-Z0-9_]+\\)" 1)
        ("functions" "function[ \n\t]+\\([a-zA-Z0-9_]+\\)" 1)
        ))

(require 'cc-mode)      ;; for c++-mode
(require 'mmm-auto)
(setq mmm-global-mode 'maybe)

(define-generic-mode
  'pkc-mode                                  ;; name of the mode to create
  '("//" ("/*" . "*/"))                      ;; comments are same C++ comments
  '( ... )                                   ;; some keywords
  '("\\.pkc$")                               ;; files for which to activate this mode

  ;; other functions to call
  '((lambda ()
      (mmm-mode 1)
      (setq mmm-submode-decoration-level 2)
      (setq imenu-generic-expression pkc-imenu-generic-expression)
      (which-function-mode 1)

      (c-initialize-cc-mode t)
      (c-init-language-vars-for 'c++-mode)
      (c-common-init 'c++-mode)
      (c-update-modeline)

      (message "pkc-mode[mmm] is on")))

  "A mode for pkc source files"                  ;; doc string for this mode
  )

(mmm-add-classes
 '((embedded-c++
    :submode c++-mode
    :face mmm-default-submode-face
    :front "{{{"
    :front-offset -1
    :back "}}}"
    :back-offset 1)))

(mmm-add-mode-ext-class 'pkc-mode nil 'embedded-c++)

当我使用嵌入式C ++代码段加载源文件时,它们的突出显示程度略低于C ++模式是主要模式时的情况(但这不是我的问题)。当光标在C ++代码中时,模式行变为pkc/l[C++/l](如预期的那样)。

问题是,每当我按 TAB 缩进一行时,我都会收到错误Wrong type argument: stringp, nil。当我打开调试器时,这是我看到的堆栈跟踪:

Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  c-syntactic-skip-backward(nil nil t)
  c-looking-at-decl-block(nil t)
  c-guess-basic-syntax()
  c-indent-line()
  #[nil \302>\203)\212\303 \210\304\305x\210\303 \210\306 )i\306 X\203\"\307    !\202'\212\307  !))\20 \207" [indent-line-function column (indent-relative indent-relative-maybe) beginning-of-line "\n     " nil current-indentation indent-line-to] 2 1908700 nil]()
  c-indent-command(nil)
  c-indent-line-or-region(nil nil)
  call-interactively(c-indent-line-or-region nil nil)

查看c-looking-at-decl-block的定义,特别是调用`c-syntactic-skip-backward,我发现:

    (c-syntactic-skip-backward c-block-prefix-charset limit t)

检查第一个参数c-block-prefix-charset会发现其值为nil。从普通C ++缓冲区执行相同操作会显示非nil值。因此,我怀疑C ++模式需要一些未正确完成的初始化。

所以,我的问题是:

  1. 我的实现中的C ++模式初始化部分缺少什么?
  2. 我使用正确的方法(合并generic-xmmm-mode)?有更好的方法吗?
  3. 当我加载文件时,我也看到另一个错误(File mode specification error),但我怀疑问题是相同或类似的。

    感谢您的时间。

1 个答案:

答案 0 :(得分:1)

(在评论中讨论之后重写,对于任何后来的访问者)。

问题中的设置基本上没问题,但要使用当前c++-mode,您需要使用mmm-mode的更新版本。它位于the GitHub project pageMelpa

相关修补程序(onetwothree)在mmm-save-local-variables的值中添加了新条目,mmm-mode用于确定哪些局部变量离开或进入子模式区域时保存或恢复。

根据我的理解,cc-mode的未来更新可能会添加更多此类变量,因此列表可能需要不时更新。

额外提示:要在子区域中有更好的缩进,您可能希望将子模式的indent-line-function包含一些代码,这些代码会在调用缓冲区之前缩小缓冲区(example here)。根据缩进功能(以及是否调用widen),它可能会有所帮助,也可能没有帮助。