0

我们使用一种内部脚本语言(我们称之为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-xand mmm-mode)?有更好的方法吗?

加载文件时,我还看到另一个错误 ( File mode specification error),但我怀疑问题相同或类似。

谢谢你的时间。

4

1 回答 1

1

(在评论中讨论后重写,供以后的访问者使用)。

问题中的设置基本上没问题,但是要使用当前c++-mode版本,您需要使用mmm-mode. 它可以在GitHub 项目页面Melpa上找到。

相关补丁()为 的值添加了新条目mmm-save-local-variablesmmm-mode用于决定在离开或进入子模式区域时保存或恢复哪些局部变量。

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

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

于 2013-01-08T21:58:30.860 回答