【问题标题】:Sublime Text 2's "Goto Anything" (or instant search) for Emacs?Sublime Text 2 的 Emacs 的“Goto Anything”(或即时搜索)?
【发布时间】:2013-01-21 12:07:53
【问题描述】:

我最近试用了Sublime Text 2,我发现Goto Anything 对导航源代码非常有用(Ctrl-P file@symbol 似乎工作得很好)。 Emacs 有类似的东西吗?最好是可以正常工作的东西,没有大量的自定义省略号。

到目前为止我已经尝试过:

  1. 我见过HelmAnything但据我了解,它们都不能进行实际的“即时”搜索(请参阅下面的编辑)。

  2. 我用过multi-occur-in-matching-buffers,但它似乎也无法满足“即时”标准。

  3. imenu / idomenu 适用于单个文件,但不适用于跨文件。

我目前将 #2 和 #3 一起使用,作为 Goto Anything 的不良替代品。

如果不是 Goto Anything 的精确克隆,那么我可以使用一个简单的即时搜索解决方案(一种在所有打开的缓冲区中搜索给定字符串并动态显示结果的解决方案)。所以这也是可以接受的。

我使用 Emacs 24.2,所以任何仅 v24 的 elisp 也可以。

编辑:我在event_jr's suggestion 又给了 Helm 一个机会,我发现它确实支持在所有打开的缓冲区中进行即时搜索。 helm-multi-occur + helm-follow-mode 出乎意料地接近满足我的需求,唯一的小问题是(有听起来吹毛求疵的风险):

  • 当我运行helm-multi-occur 时,我还没有找到一种方法来自动打开helm-follow-mode 。我必须使用C-c C-f 手动调用它。有人愿意用 elisp 的 sn-p 来尝试一下吗?(参见下面的编辑 #2)

  • 它不像 ST2 的 Goto Anything 那样“智能”(即它不像 Goto Anything 那样理解源代码中的“符号”)。

编辑#2:感谢event_jr's answer below(当然,感谢Helm 的创建者Thierry Volpiatto),现在我已经掌握了大部分的Goto Anything。我衷心推荐给任何寻找类似功能的人。以下是我目前正在使用的 elisp:

;; instant recursive grep on a directory with helm
(defun instant-rgrep-using-helm ()
  "Recursive grep in a directory."
  (interactive)
  (let ((helm-after-initialize-hook #'helm-follow-mode))
    (helm-do-grep)))


;; instant search across all buffers with helm
(defun instant-search-using-helm ()
  "Multi-occur in all buffers backed by files."
  (interactive)
  (let ((helm-after-initialize-hook #'helm-follow-mode))
    (helm-multi-occur
     (delq nil
           (mapcar (lambda (b)
                     (when (buffer-file-name b) (buffer-name b)))
                   (buffer-list))))))

;; set keybindings
(global-set-key (kbd "C-M-s") 'instant-search-using-helm)
(global-set-key (kbd "C-M-S-s") 'helm-resume)
(global-set-key (kbd "C-M-g") 'instant-rgrep-using-helm)

【问题讨论】:

  • 这对于 superuser.com 来说可能是一个更好的问题
  • 不,关于 Emacs 在编程上下文中的问题 100% 在 SO 范围内
  • 为什么不坚持使用 sublime?
  • @event_jr 我不会仅仅因为它没有 Goto Anything 就从 Emacs 切换到 Sublime Text。如果我这样做,我会得到一件事并失去一百万:)
  • @event_jr 这与特定的“杀手级功能”无关。事实上,Emacs 甚至没有一套固定的“特性”。这是关于一般的编辑器。我喜欢修改Emacs 的最后一点 是多么容易。无限的可定制性不断复合并得到回报。我所做的每一个小定制都让它更接近我对“理想”编辑器的心目中的形象。从某种意义上说,那是 Emacs 的真正的杀手级功能。另一方面,如果我使用 ST2,我的工作效率会很快达到最高水平。

标签: emacs sublimetext emacs24 dot-emacs emacs-helm


【解决方案1】:

只需使用 helm。

它可能比您要求的配置更多,但一旦您得到它 配置成你喜欢的样子,应该还是挺舒服的。非常喜欢 Emacs ;)。

而且你应该向 Thierry 提交一个错误,以便让新手更友好 默认值。他对问题非常敏感。

掌舵-多次发生

主要是通过提供多缓冲区交互“发生” helm-multi-occur。如果你执行命令,你会注意到你有 首先选择一些缓冲区(使用 C-SPC 从列表中选择, M-SPC 全选)。然后您可以在下一个输入您的查询 迅速的。制作自己的跳过缓冲区选择的版本很容易 像这样:

(eval-after-load "helm-regexp"
    '(setq helm-source-moccur
           (helm-make-source "Moccur"
               'helm-source-multi-occur :follow 1)))

(defun my-helm-multi-all ()
  "multi-occur in all buffers backed by files."
  (interactive)
  (helm-multi-occur
   (delq nil
         (mapcar (lambda (b)
                   (when (buffer-file-name b) (buffer-name b)))
                 (buffer-list)))))

掌舵缓冲区列表

通常您并不关心查询字符串的确切出现次数,而是想要一个 包含它的所有缓冲区的列表。

helm-buffers-list 有一些技巧。你的第一个符号 指定是按主要模式过滤,您可以使用“@”前缀来缩小 包含字符串的缓冲区列表。

也就是说,“ruby @prompt”将显示一个缓冲区列表,其主要模式 包含“ruby”,其内容包含“prompt”。或者您可以只使用“@prompt”来显示所有包含“prompt”的缓冲区。


一旦你习惯了它就会变得强大而舒适。


EDIT 修改 my-helm-multi-all 以启用 helm-follow-mode。

EDIT 2 更新 helm-follow-mode 代码以反映 helm 更改。

EDIT 3再次更新以反映helm changes

【讨论】:

  • 这很棒。根据您的建议,我再次尝试了 Helm,我认为 my-helm-multi-all + helm-follow-mode(通过 Helm 缓冲区中的 C-c C-f 访问)非常接近我想要的。所以首先谢谢你。现在唯一的主要问题是我在运行my-helm-multi-all时必须手动打开helm-follow-mode;有没有办法让它自动打开? (请注意,Helm 似乎没有helm-mode-hook,所以这种方法行不通)。
  • 可以在 helm-modehelm-multi-occur 上使用 defadvice 完成此操作(即在 Helm 缓冲区中自动打开 helm-follow-mode)吗?
  • 嗨。我试过这个,我得到Wrong type argument: number-or-marker-p, nil。我正在使用 Emacs 24。
  • 最近对 helm 的更新似乎再次打破了这一点。
  • 确实如此。 @nispio 我已根据您拒绝的编辑修复了代码。
【解决方案2】:

对于 emacs,我自定义和修改了这个解决方案(用于 install helm):

(defun helm-occur-from-point (initial-value)
  "Invoke `helm-occur' from point."
  (interactive)
  (let ((input initial-value)
        (bufs (list (buffer-name (current-buffer)))))
    ;; (isearch-exit)
    (helm-occur-init-source)
    (helm-attrset 'moccur-buffers bufs helm-source-occur)
    (helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
    (helm-set-local-variable
     'helm-multi-occur-buffer-tick
     (cl-loop for b in bufs
              collect (buffer-chars-modified-tick (get-buffer b))))
    (helm :sources 'helm-source-occur
          :buffer "*helm occur*"
          :history 'helm-grep-history
          :input input
          :truncate-lines t)))

(defun get-point-text ()
    "Get 'interesting' text at point; either word, or region"
    (if mark-active
        (buffer-substring (mark) (point))
      (thing-at-point 'symbol)))
  (defun helm-occur-1 (initial-value)
    "Preconfigured helm for Occur with initial input."
    (helm-occur-from-point initial-value))
  (defun bk-helm-occur ()
    "Invoke helm-occur with initial input configured from text at point"
    (interactive)
    (helm-occur-1 (get-point-text)))
  (global-set-key (kbd "M-s-o") 'bk-helm-occur)

主要基于 @see https://news.ycombinator.com/item?id=6872508 但在最后的 helm 版本中不起作用,但我的更改已修复(只需从一些内部 helm 模块复制/粘贴)

【讨论】:

    【解决方案3】:
    1. Heml 远非 ST3 的模糊搜索。

    2. Fiplr 看起来很有前途,但在我的笔记本电脑上不起作用(请参阅 github 上的第一期)

    3. Simp.el 看起来像 Fiplr,但对我来说也不起作用。

    4. Projectile 为我工作!这是您的解决方案!

    我还使用了 ido-mode 和 flx-ido 进行模糊搜索,

    对于显示结果的垂直方式,我在我的 .emacs 中使用它:

    ;; Display ido results vertically, rather than horizontally
    (setq ido-decorations (quote ("\n-> " "" "\n   " "\n   ..." "[" "]" " [No match]" " [Matched]" " [Not readable]" " [Too big]" " [Confirm]")))
    (defun ido-disable-line-truncation () (set (make-local-variable 'truncate-lines) nil))
    (add-hook 'ido-minibuffer-setup-hook 'ido-disable-line-truncation)
    (defun ido-define-keys () ;; C-n/p is more intuitive in vertical layout
      (define-key ido-completion-map (kbd "C-n") 'ido-next-match)
      (define-key ido-completion-map (kbd "C-p") 'ido-prev-match))
    (add-hook 'ido-setup-hook 'ido-define-keys)
    

    【讨论】:

    • 这没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方发表评论。
    • 我提供的答案对我无效,但可能对其他人有效。
    • 我假设您正在使用 flx 在弹丸中进行模糊搜索?
    • 更像 ido + flx-ido
    【解决方案4】:

    Icicles 提供了一些与您正在寻找的功能相似的功能。

    1. C-x bC-x C-f,选择缓冲区或文件,允许多重完成:您可以键入模式以匹配缓冲区/文件名和/或模式以匹配 match content 在 @987654323 @/file。候选人在您键入时被过滤incrementally(您所说的“即时”是 Emacs 所说的“增量”)。您可以细化一个或两个搜索模式progressively,以不同的方式缩小选择范围。您可以同时访问任意数量的匹配缓冲区/文件。您也可以使用相同的方法在 Dired 中搜索标记的文件:C-F

    2. C-c`(icicle-search) 以增量方式搜索多个缓冲区或文件。同样,渐进式细化等。

    #1 和#2 的主要区别在于:

    • 对于#1,您只想找到匹配的缓冲区或文件。您不会立即关心找到特定的事件 --- 任何匹配就足够了。

    • 对于 #2,您提供要搜索的缓冲区或文件,并且您希望在搜索命中之间导航。

    您还可以使用 #1 定位所需的缓冲区和文件,然后搜索它们的内容:您上次使用的内容匹配模式可用作 Isearch (C-s) 的搜索模式。

    【讨论】:

      【解决方案5】:

      Emacs 有Projectile 满足你的需求:

      • 跳转到项目中的文件
      • 在项目缓冲区中多次出现

      【讨论】:

      • 它还可以跳转到测试和项目缓冲区,项目中的grep,项目中的替换,重新生成etags表和其他很酷的东西。 Projectile 还有一个 helm 后端。
      • 正如我在问题中所说,我使用了multi-occur,但它不能即时搜索(“即时”在“Google Instant”的意义上) .使用multi-occur,您必须输入整个查询,按RET,然后才能看到结果。此外,如果您需要更改搜索查询,则必须使用新的搜索词再次运行 multi-occur。这不是我要找的。​​span>
      • Vicky:FWIW,在你提到“Google Instant”之前,我不知道“即时搜索”应该是什么意思——直到我在谷歌上搜索了“Google Instant”这个短语之后才知道是什么那是。除非您已经知道 Google 的意思,否则“即时搜索”的表述非常含糊不清。我建议像“动态搜索结果”这样的描述会更清晰。
      • @phils 这正是我链接到演示该功能的视频的原因,就在我的问题中:youtube.com/watch?v=36NIIgcrYzEyoutube.com/watch?v=Q0OtfjgnoLA#t=1m00s
      猜你喜欢
      • 1970-01-01
      • 2012-08-28
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 2013-09-17
      • 1970-01-01
      • 2012-11-22
      • 1970-01-01
      相关资源
      最近更新 更多