向前搜索令牌

时间:2014-01-09 22:56:25

标签: search emacs elisp

在我的.emacs文件中,我有以下功能:

    ; Search for token forward and backward
    (defun search-token-forward()
      "Search forward for the ucode token at the point."
      (interactive) ; Makes the function available as a command
      (let (target-string)
        (setq target-string (buffer-substring 
                    (+ (re-search-backward "[^A-Za-z0-9/_.@#\$]") 1) 
                    (- (re-search-forward "[^A-Za-z0-9/_.@#\$]" nil t 2) 1)))
        ; post a message saying what we're looking for
        (message "Search for \`%s\`" target-string)
    ;    (setq case-fold-search nil)
        (search-forward target-string)))
    (global-set-key [f5]           'search-token-forward)

(defun search-token-backward()
  "Search backward for the ucode token at the point."
  (interactive)
  (point)
  (let (target-string)
    (setq target-string (buffer-substring 
                  (+ (re-search-backward "[^A-Za-z0-9/_.@#\$]") 1) 
                  (- (re-search-forward  "[^A-Za-z0-9/_.@#\$]" nil t 2) 1)))
    (message "backward search for \`%s\`" target-string)
;    (setq case-fold-search nil)
    ;
    ; here the search for the target string is done twice.  Once
    ; for the string that the cursor is on, and once more to go
    ; backwards for the next occurance.  
    ;
    (search-backward target-string nil nil 2)))
    (global-set-key [C-f5]           'search-token-backward)

在第一次搜索之后,光标移动到表达式的最后一个字符之后,这很好,因为我仍然可以使用我拥有的另一个函数执行“search-token-backward”。不幸的是,当在表达式的最后一次出现之后进行搜索时,光标移动到行尾,因此我不能顺利地尝试向后搜索,因为光标不在表达式“position”上。导致此行为的原因是什么,以及如何修复它?

基本上我希望光标停留在表达式的最后一个字符之后的空格处,即使它没有前向出现。

这是一个例子: 在光标位于函数foo_func的下一个代码中,我点击f5,它与search-token-forward相关联。 X标记每次单击后光标所在的位置:

int foo_func(int w, int y);
       x cursor here to begin with.

some code...

foo_func(1, 2);
        x After first click
some code...   

foo_func(3,4);
        x after second click
some code...

return foo_func(5,6);
               x after third click

现在文件中没有更多的foo_func,所以点击f5 更多时间将光标向右移动一个字符,如下所示:

return foo_func(5,6);
                x after forth click, this is the same line above.

所以我不能简单地按ctrl-f5向后搜索foo_func,因为光标不再与函数相邻。

2 个答案:

答案 0 :(得分:1)

记录找到的最后一个成功搜索位置(参见match-end)。将t作为NOERROR arg传递,如果返回值为nil,则表示未找到该字符串,因此您可以返回上一个成功位置(实际上,仍然在那里。

抱歉,忘记我在那里说的话。我以为你遇到search-forward的问题。毫无疑问,您的问题是想要搜索的目标字符串。目前还不清楚你真正想要搜索什么。就像现在一样,你正在这两个地方之间拿起缓冲区文本:

  • 第一个向后的字符后面的一个字符不是这些字符中的任何字符:A-Za-z0-9/_.@#\$
  • 第二个前锋之前的一个字符,不是那些相同的字符。

如果失败,第二次搜索不会引发错误或将光标从起始位置前进。

我怀疑你目前的正则表达不是你想要的。例如,请注意它匹配换行符。请记住,在[](一个字符替代)中,除了^(如果它是第一个)之外,没有特殊字符。请参阅(elisp) Regexp Special

描述您真正尝试从缓冲区中提取的文本,以用作search-forward搜索字符串(target-string)。用英语指定它,我们将帮助您想出如何从缓冲区文本中提取它。也许举一个你在缓冲区中的典型文本的例子,显示你想要选择的部分,以便搜索。

*更新*

好吧,我猜,其中任何一个都应该按照你的要求行事,但它们非常难看。 (第二个更强大。)从头开始你可能会更好......

 (defun search-token-forward()
   "..."
   (interactive)
   (let* ((opoint            (point))
          (case-fold-search  nil)
          (back              (re-search-backward "[^A-Za-z0-9/_.@#\$]"))
          (fwd               (re-search-forward "[^A-Za-z0-9/_.@#\$]" nil t 2))
          (target-string     (and back fwd (buffer-substring (+ back 1) (- fwd 1)))))
     (when target-string
       (message "Search for `%s'" target-string)
       (unless (search-forward target-string nil t)
         (goto-char opoint)
         (message "Search failed for `%s'" target-string)))))

 (defun search-token-forward()
   "..."
   (interactive)
   (let* ((opoint            (point))
          (case-fold-search  nil)
          (back              (re-search-backward "[^A-Za-z0-9/_.@#\$]"))
          (fwd               (re-search-forward "[^A-Za-z0-9/_.@#\$]" nil t 2))
          (target-string     (and back fwd (buffer-substring (+ back 1) (- fwd 1)))))
     (when target-string
       (message "Search for `%s'" target-string)
       (condition-case err
           (search-forward target-string)
         (search-failed (goto-char opoint) (error (error-message-string err)))))))

* UPDATE2 *

 (defun search-token-backward()
   "..."
   (interactive)
   (let ((opoint            (point))
         (case-fold-search  nil)
         back fwd target-string)
     (save-excursion
       (setq back  (re-search-backward "[^A-Za-z0-9/_.@#\$]")
             fwd   (re-search-forward "[^A-Za-z0-9/_.@#\$]" nil t 2)))
     (setq target-string  (and back  fwd
                               (buffer-substring (+ back 1) (- fwd 1))))
     (when target-string
       (message "Search for `%s'" target-string)
       (condition-case err
           (search-backward target-string)
         (search-failed (goto-char opoint) (error (error-message-string err)))))))

答案 1 :(得分:1)

我不是在调试你的elisp,而是提供有关如何向前搜索令牌的其他解决方案。

1-使用邪恶的功能

Evil-mode附带了*绑定的功能。它调用函数evil-search-symbol-forward(VS …-backward,绑定到#)。

如果你不想,你可以在不使用邪恶模式的情况下调用该函数。安装evil,需要在〜/ .emacs中使用(require 'evil),如果你不想使用模式,请不要写(evil-mode 1),然后将你的键绑定到给定的函数。

2-请参阅掌握Emacs的帖子

该博客的作者写了一个等效函数:http://www.masteringemacs.org/articles/2013/10/31/smart-scan-jump-symbols-buffer/

它的优点是它还有两个功能:替换整个缓冲区或当前defun中的符号。

ps:evil-goto-definition也非常方便:转到定义或第一次出现符号。