如何在GNU Emacs中模拟Vim的*搜索?

时间:2009-02-26 08:49:36

标签: vim emacs elisp dot-emacs

在Vim中,正常模式下的*键搜索光标下的单词。在GNU Emacs中,最接近的本机等价物是:

C-s C-w

但这并不完全相同。它打开增量搜索迷你缓冲区,并从当前缓冲区中的光标复制到单词的末尾。在Vim中,你会搜索整个单词,即使你按*也是在单词的中间。

我已经做了一些elisp来做类似的事情:

(defun find-word-under-cursor (arg)
  (interactive "p")
  (if (looking-at "\\<") () (re-search-backward "\\<" (point-min)))
  (isearch-forward))

在开始播放之前,它会向后退到单词的开头。我把它绑定到C- +,这很容易在我的键盘上打字,类似于*,所以当我输入C-+ C-w时,它会从单词的开头复制到搜索迷你缓冲区。

然而,这仍然不完美。理想情况下,它会regexp搜索"\<" word "\>"不显示部分匹配(搜索单词“bar”不应与“foobar”匹配,只是“bar”本身)。我尝试使用search-forward-regexp和concat'ing \&lt;&gt;但这并没有包装在文件中,没有突出显示匹配,而且通常非常蹩脚。一个isearch- *函数似乎是最好的选择,但是这些在编写脚本时表现不佳。

有什么想法吗?任何人都可以对elisp的位进行任何改进吗?还是有其他一些我忽略的方式?

9 个答案:

答案 0 :(得分:15)

根据您对我的第一个答案的反馈,这是怎么回事:

(defun my-isearch-word-at-point ()
  (interactive)
  (call-interactively 'isearch-forward-regexp))

(defun my-isearch-yank-word-hook ()
  (when (equal this-command 'my-isearch-word-at-point)
    (let ((string (concat "\\<"
                          (buffer-substring-no-properties
                           (progn (skip-syntax-backward "w_") (point))
                           (progn (skip-syntax-forward "w_") (point)))
                          "\\>")))
      (if (and isearch-case-fold-search
               (eq 'not-yanks search-upper-case))
          (setq string (downcase string)))
      (setq isearch-string string
            isearch-message
            (concat isearch-message
                    (mapconcat 'isearch-text-char-description
                               string ""))
            isearch-yank-flag t)
      (isearch-search-and-update))))

(add-hook 'isearch-mode-hook 'my-isearch-yank-word-hook)

答案 1 :(得分:7)

highlight symbol emacs扩展程序提供此功能。特别推荐.emacsrc设置:

(require 'highlight-symbol)

(global-set-key [(control f3)] 'highlight-symbol-at-point)
(global-set-key [f3] 'highlight-symbol-next)
(global-set-key [(shift f3)] 'highlight-symbol-prev)

允许跳转到当前点的下一个符号(F3),跳转到上一个符号(Shift + F3)或突出显示与光标下的符号匹配的符号(Ctrl + F3)。如果你的光标是中间字,那么命令会继续做正确的事。

与vim的超级明星不同,突出显示符号和符号之间的跳跃绑定到两个不同的命令。我个人并不介意分离,但如果你想要精确匹配vim的行为,你可以在同一个击键下绑定两个命令。

答案 2 :(得分:5)

有很多方法可以做到这一点:

http://www.emacswiki.org/emacs/SearchAtPoint

答案 3 :(得分:3)

scottfrazer的答案对我来说很有效,除了以'_'结尾的单词(或者其他非单词字符?)。我发现轻符号模式的代码根据emacs的版本使用了不同的正则表达式,并且为我修复了它。这是修改后的代码:

(defconst my-isearch-rx-start
  (if (< emacs-major-version 22)
      "\\<"
    "\\_<")
  "Start-of-symbol regular expression marker.")

(defconst my-isearch-rx-end
  (if (< emacs-major-version 22)
      "\\>"
    "\\_>")
  "End-of-symbol regular expression marker.")

(defun my-isearch-word-at-point ()
  (interactive)
  (call-interactively 'isearch-forward-regexp))

(defun my-isearch-yank-word-hook ()
  (when (equal this-command 'my-isearch-word-at-point)
    (let ((string (concat my-isearch-rx-start
                          (buffer-substring-no-properties
                           (progn (skip-syntax-backward "w_") (point))
                           (progn (skip-syntax-forward "w_") (point)))
                          my-isearch-rx-end)))
      (if (and isearch-case-fold-search
               (eq 'not-yanks search-upper-case))
          (setq string (downcase string)))
      (setq isearch-string string
            isearch-message
            (concat isearch-message
                    (mapconcat 'isearch-text-char-description
                               string ""))
            isearch-yank-flag t)
      (isearch-search-and-update))))

(add-hook 'isearch-mode-hook 'my-isearch-yank-word-hook)

答案 4 :(得分:2)

如何内置命令M-b C-s C-w(单词搜索,搜索,单词搜索)

答案 5 :(得分:2)

Mastering Emacs博客的Mickey重新引入了一个很酷的“Smart Scan”lib,它提供了M-nM-p的全局绑定,用于在缓冲区中的光标下导航符号。不影响搜索寄存器,因此它不是*替换,而是导航问题的一个聪明且可用的替代方案。

答案 6 :(得分:1)

我还没有尝试过,但有一些名为Grep-O-Matic的代码here

答案 7 :(得分:0)

有了这个,你应该能够在isearch模式下做C- *。

(define-key isearch-mode-map [?\C-*] 'kmk-isearch-yank-thing)

(defun kmk-isearch-yank-thing ()
  "Pull next thing from buffer into search string."
  (interactive)
  (let ((string (regexp-quote (thing-at-point 'word))))
    (setq isearch-string 
      (concat isearch-string "\\")
      isearch-message
      (concat isearch-message
          (mapconcat 'isearch-text-char-description
                 string ""))
      ;; Don't move cursor in reverse search.
      isearch-yank-flag t))
  (setq isearch-regexp t isearch-word nil isearch-success t isearch-adjusted t)
  (isearch-search-and-update))

答案 8 :(得分:0)

;Here is my version: Emulates Visual Studio/Windows key bindings 
; C-F3 - Start searching the word at the point
; F3 searches forward and Shift F3 goes reverse

(setq my-search-wrap nil)

(defun my-search-func (dir)
  (interactive)
  (let* ((text (car search-ring)) newpoint)
        (when my-search-wrap  
             (goto-char (if (= dir 1) (point-min) (point-max)))
             (setq my-search-wrap nil))
        (setq newpoint (search-forward text nil t dir))
        (if newpoint
          (set-mark (if (= dir 1) (- newpoint (length text))
                         (+ newpoint (length text))))
          (message "Search Failed: %s" text) (ding)
          (setq my-search-wrap text))))

(defun my-search-fwd () (interactive) (my-search-func 1))
(defun my-search-bwd () (interactive) (my-search-func -1))

(defun yank-thing-into-search ()
   (interactive)
   (let ((text (if mark-active
          (buffer-substring-no-properties (region-beginning)(region-end))
                 (or (current-word) ""))))
     (when (> (length text) 0) (isearch-update-ring text) (setq my-search-wrap nil)
            (my-search-fwd))))
(global-set-key (kbd "")    'my-search-fwd)            ; Visual Studio like search keys
(global-set-key (kbd "")  'my-search-bwd)
(global-set-key (kbd "")  'yank-thing-into-search)