更通用的xxx-thing-at-point

最近转用了consult,不过发现作者有点保守,加个consult-line-thing-at-ppoint都不愿意,加上以前用swiper的时候习惯了fly(我不知道这个功能叫什么合适 :joy:

然后就自己糊(chao)了一个:

(defvar mcfly-commands
  '(consult-line))

(defvar mcfly-back-commands
  '(self-insert-command))

(defun mcfly-back-to-present ()
  (remove-hook 'pre-command-hook 'mcfly-back-to-present t)
  (cond ((and (memq last-command mcfly-commands)
              (equal (this-command-keys-vector) (kbd "M-p")))
         ;; repeat one time to get straight to the first history item
         (setq unread-command-events
               (append unread-command-events
                       (listify-key-sequence (kbd "M-p")))))
        ((memq this-command mcfly-back-commands)
         (delete-region
	  (progn (forward-visible-line 0) (point))
          (point-max)))))

(defun mcfly-time-travel ()
  (when (memq this-command mcfly-commands)
    (insert (propertize (save-excursion
			  (set-buffer (window-buffer (minibuffer-selected-window)))
			  (or (seq-some (lambda (thing) (thing-at-point thing t))
					'(region url symbol sexp))
			      "No thing at point")
			  )    'face 'shadow))
    (add-hook 'pre-command-hook 'mcfly-back-to-present nil t)
    (forward-visible-line 0)
    ))

;; setup code
(add-hook 'minibuffer-setup-hook #'mcfly-time-travel)

效果跟

差不多,不过更通用。

5 个赞

我感觉用 minibuffer-with-setup-hook 实现更简单&无副作用:

(minibuffer-with-setup-hook
    (lambda () (insert "thing-at-point"))
  (read-string "Search: "))

这个我也想过,但是我感觉有两个不好的地方

  1. 这样每次使用minibuffer的时候都会插入
  2. 需要手动删除,达不到“默认搜索光标下的符号,颜色是灰色;输入时会自动全部清除,颜色变为默认值。”这样的效果

只对特定的函数使用 minibuffer-with-setup-hook 怎么会每次?

(defun my/color-rg-search-input ()
  (interactive)
  (minibuffer-with-setup-hook
      (lambda () (insert "thing-at-point"))
    (color-rg-search-input)))

第二点不太明白。在 minibuffer-with-setup-hook 里一样可以做很多事,而且不需要判断 last-command

1 个赞

我看错函数名了,抱歉,我去试试

也可以通过 M-n 来插入 thing-at-point

不过按一次是整行,两次才是 symbol,暂时不知道怎么忽略整行。

第二点“如果不想搜索thing-at-point,不要先删除minibuffer的内容,直接输入覆盖”很不错啊,不判断last-command怎么搞 :grinning:

isearch-mb 不能用,简单配置了一下:

(defvar mcfly-commands
     '(isearch-forward))

isearch也不行,好像根本不用minibuffer。 isearch-mb 下面的配置的face不能变暗

(defun mcfly-time-travel ()
  (when (or (memq this-command mcfly-commands)
            isearch-mb-mode)
    (insert (propertize (save-excursion
                          (set-buffer (window-buffer (minibuffer-selected-window)))
                          (or (seq-some (lambda (thing) (thing-at-point thing t))
                                        '(region url symbol sexp))
                              "No thing at point")) 'face 'shadow))
    (add-hook 'pre-command-hook 'mcfly-back-to-present nil t)
    (forward-visible-line 0)))

感谢分享。

这行只能删除当前行,无法应对多行的情况,比如 thing-at-point 是 多行 sexp 时就不能删除全部。不知道应该怎么改动?

更新1: 把这行改成这个就好了: (goto-char (minibuffer-prompt-end))

更新2: 我重新糊一下好了, 感谢 VagrantJoker

(defvar mcfly-commands
  '(consult-line
    ;; consult-outline
    ;; consult-imenu
    ;; consult-ripgrep
    ;; deadgrep
    ;; isearch-forward
    ;; isearch-backward
    ;; ctrlf-forward-default
    ;; ctrlf-backward-default
    ))

(defvar mcfly-back-commands
  '(self-insert-command
    ;; 更多其他设置,可以参考: https://github.com/lynnux/.emacs.d/blob/ac552c1/settings/package_extra.el#L1225-L1299
    ))

(defun mcfly-back-to-present ()
  "Self-explained."
  (remove-hook 'pre-command-hook 'mcfly-back-to-present t)
  (cond ((and (memq last-command mcfly-commands)
              (equal (this-command-keys-vector) (kbd "M-p")))
         ;; repeat one time to get straight to the first history item
         (setq unread-command-events
               (append unread-command-events
                       (listify-key-sequence (kbd "M-p")))))
        ((memq this-command mcfly-back-commands)
         (delete-region
	        (goto-char (minibuffer-prompt-end))
          (point-max)))))

(defun mcfly-time-travel ()
  "Insert `thing-at-point'."
  (when (memq this-command mcfly-commands)
    (insert (propertize
             (save-excursion
			         (set-buffer (window-buffer (minibuffer-selected-window)))
			         (or (seq-some
                    (lambda (thing) (thing-at-point thing t))
					          '(region url symbol sexp))
			             "No thing at point"))
             'face 'shadow))
    (add-hook 'pre-command-hook 'mcfly-back-to-present nil t)
    ;; 如果喜欢光标停留在最后一行, 删掉下一行
    (goto-char (minibuffer-prompt-end))
    ))

;; setup code
(add-hook 'minibuffer-setup-hook #'mcfly-time-travel)

由于我的使用场景基本是单行,所以没有考虑多行的情况,感谢捉虫。

1 个赞

刚在原处更新了另一处 (forward-visible-line 0)。 感谢分享,用着舒服多了 :star_struck:

用这个会和一些有预填充文本的函数冲突,感觉还是在 insert 的时候用 save-excursion 比较好,这样光标就一直能在默认位置了。

(defvar mcfly-commands
  '(consult-line
    consult-outline
    consult-git-grep
    consult-ripgrep
    my-search-with-chrome))

(defvar mcfly-back-commands
  '(self-insert-command
    yank
    yank-pop
    org-yank))

(defun mcfly-back-to-present ()
  (remove-hook 'pre-command-hook 'mcfly-back-to-present t)
  (cond ((and (memq last-command mcfly-commands)
              (equal (this-command-keys-vector) (kbd "M-p")))
         ;; repeat one time to get straight to the first history item
         (setq unread-command-events
               (append unread-command-events
                       (listify-key-sequence (kbd "M-p")))))
        ((memq this-command mcfly-back-commands)
         (delete-region (point) (point-max)))))

(defun mcfly-time-travel ()
  (when (memq this-command mcfly-commands)
    (let ((pre-insert-string (with-minibuffer-selected-window
                               (or (seq-some
                                    (lambda (thing) (thing-at-point thing t))
					                '(region url symbol))
					                ;; '(symbol url region sexp))
			                       "No thing at point"))))
      (save-excursion
        (insert (propertize pre-insert-string 'face 'shadow))))
    (add-hook 'pre-command-hook 'mcfly-back-to-present nil t)))

;; setup code
(add-hook 'minibuffer-setup-hook #'mcfly-time-travel)
3 个赞

嗯确实有影响预充文本的问题。另外sexp的用处确实不大,注释掉反而好用多了。

请教,这个 'face 'shadow 是不是没有起作用?

我这里只有 consult-git-grepconsult-ripgrep 不是灰色,consult 好像清除了他们的 face ,其他都是正常颜色。

1 个赞

还真是,多谢大佬指导。

整了个只适用 consult 的精简版:

  (defun consult-delete-default-contents()
    (remove-hook 'pre-command-hook 'consult-delete-default-contents)
    (cond ((member this-command '(self-insert-command))
           (delete-minibuffer-contents))
          (t (put-text-property (minibuffer-prompt-end) (point-max) 'face 'default))))

  (consult-customize consult-line
                     :initial (when-let ((string (thing-at-point 'word)))
                                (add-hook 'pre-command-hook 'consult-delete-default-contents)
                                (propertize string 'face 'shadow)))

3 个赞