通过参数列表移动

时间:2012-11-26 20:37:09

标签: emacs elisp cc-mode

我是一名C ++程序员,使用的设置包括cc-modeCEDET,当然还有我们心爱的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-argument(和backward-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“黑客”的任何帮助表示赞赏!

修改:添加了一些说明 编辑2:修复了示例“代码”

3 个答案:

答案 0 :(得分: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"))))

答案 1 :(得分: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(&gt; count 0)...(setq count(1- count))中,如果没有给出前缀则默认计数为1)以及其他一些东西更确切地说,实际上是根据实时的emacs来检查代码,而不是试图记住函数所采用的参数以及它们被调用的内容。

答案 2 :(得分:2)

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

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

C-c , n - 下一个标记

C-c , p - 之前的标记

这些将在各种功能之间,在参数之间,各种事物之间移动。

这些功能并不能满足您的所有要求,但这是一个良好的开端。