3

我是一名 C++ 程序员,使用的设置包括当然cc-mode还有CEDET我们心爱的 emacs (v24.2)。

我缺少的一个功能是一个通过参数列表快速移动点的函数。考虑这个例子:

void takesManyArgs( int a1, int a2, int a3, std::pair<int,int> a4, int a5 ){  
    // does something nifty!  
}  
// [...]
takesManyArgs( b1, b2, b3, make_pair( b4, b5 ), b6 );

其中点就在第一个之前int。现在我想要一种简单的方法来快速浏览参数列表,即一个forward-argumentbackward-argument以及)在第一个非空白字符之前移动到逗号(参数分隔符)之前的函数。
我已经编写了一个小函数来完成它,但它并不是我想要的工作方式:

(defun arg-forward ()  
  "Move point forward in the file until we hit an argument separator, i.e. comma, colon or semicolon."  
  (interactive)  
  (progn  
    (re-search-forward "[,]")))  

原则上,这个函数只是跳转到下一个逗号。这不是我想要的行为。

我想要一个功能:

  • 编辑:跳转到下一个参数分隔符(即 C++ 的逗号)并将点放在该参数分隔符之后
  • 检查逗号后是否有空格;如果有一个,点将移动到第一个非空白字符(即,而不是,| int它看起来像标记指向 的, |int位置)|
  • 在参数列表的末尾停止并打印一条消息(例如“在参数列表的末尾”)
  • 停留在它的“范围”内,即它会从标记指向 |int b3|make_pair( int b4, int b5 )地方|int a6到达|

elisp感谢您“黑客”的任何帮助!

编辑:添加了一些说明。
Edit2:修复了该示例“代码”

4

3 回答 3

5

此功能似乎可以满足您的要求:

(defun arg-forward ()
  "Move point forward until we hit an argument separator, the comma, colon, semicolon"
  (interactive)
  (condition-case nil
      (let ((separator-regexp "[,:;]"))
        (forward-sexp)
        (while (not (or (looking-at (format "[ \t]*%s" separator-regexp))
                        (save-excursion (forward-char -1)
                                        (looking-at (format "[]\"')}]*[ \t]*%s " separator-regexp)))))
          (forward-sexp))
        (if (looking-at separator-regexp)
            (forward-char 1))
        ;; going forward one sexp and back puts point at front of sexp
        ;; essentially skipping the whitespace, but also ensuring we don't
        ;; jump out of a larger closing set of parentheses 
        (forward-sexp)
        (forward-sexp -1))
    (error
     (beep)
     (message "At end of argument list"))))
于 2012-11-26T20:53:22.263 回答
2

您可以编写一个函数,使用forward-sexp并检查您是否处于“参数分隔符”或“参数列表结尾”之一。

我现在似乎没有手边的 emacs,所以我不能简单地检查示例实现,但是有了手头的那些,你应该一切顺利。

以下未经测试的代码:

(defun forward-argument ()
  (interactive)
  (let ((argument-terminator "[),]"))              ;; Arguments stop at commas or close
     (while (not (looking-at argument-terminator)) ;; until we're at end-of-argument...
        (forward-sexp 1))))                        ;; move forward

这可能会受益于将参数终止符拉出到 defvar 中,因此很容易使其特定于模式。它可能会受益于具有计数前缀(将其包装在 (while (> count 0) ... (setq count (1- count)) 中,如果没有给出前缀则默认计数为 1)和其他一些东西。 , 更不用说根据实时 emacs 实际检查代码,而不是试图记住函数采用什么参数以及它们被称为什么。

于 2012-11-26T20:56:28.620 回答
2

由于您在 C++ 代码中使用 CEDET,因此您可以利用 TAG 导航命令。我使用 CEDET bzr 存储库中的 CEDET 版本进行了尝试。

检查开发菜单,靠近底部的是导航标签。您将在以下位置找到前进/后退标签的键绑定:

C-c , n - 下一个标签

C-c , p - 上一个标签

这些将使您在函数之间、参数之间以及各种事物之间移动。

这些功能并不能完成您所询问的所有事情,但它们是一个好的开始。

于 2012-11-28T00:53:23.750 回答