多谢PR!这样可以删除了。
问下为何要去ivy化呢,有什么特殊原因?而且也没有选用vertico和selectrum。来几张最后的效果图更好
多谢PR!这样可以删除了。
问下为何要去ivy化呢,有什么特殊原因?而且也没有选用vertico和selectrum。来几张最后的效果图更好
主要是我想仅只用少量一点的包,并且越来越觉得 counsel/swiper 不是那么重要,于是就先把这2个给干掉了。然后就觉得 ivy-mode 是不是也不是那么重要?就尝试了一下去 ivy 化。
总体来说还是想令自己的 Emacs 依赖的外部包少一点
有时候想去掉一个包就是单纯看不顺眼了 我干过好多这样的事情
28内置的project也够用了,其实
理解了。我也干过同样的事情,比如用内置的electric-pair替代smartparens。
去掉一个包容易,但是要去掉一个生态有时挺麻烦的,比如楼上说的project。内置的功能够用了,但是还需要时间发展下生态,第三方扩展包要跟上才行。现在projectile和flycheck我暂时没法去掉,包括ivy,很多好用的功能还没找到替代者
BTW,内置的不一定是最好的,当然是最方便的。
这个包是干啥的?minibuffer补全吗?
和mct和楼主的方案类似,使用原生补全时自动化了completion buffer的行为,但更优雅、高效 (个人认为
貌似和vertico功能差不多
我现在也转到 Emacs 29 + aggressive-completion 了。
看起来还是有很多人在推动原生 completions buffer 的。几乎所有的补全框架都是着眼于为 completing-read
函数提供更友好的界面,但是原生的实现实际上才是对输入体验干扰最小的。
依次尝试过下面几种,都是专门针对特定版本的 Emacs 的,作者都不打算继续兼容新版本 Emacs 了,估计内置的 completions buffer 就足够好用的那一天也不远了。
Emacs 27: live-completions
Emacs 28: mct
Emacs 29: aggressive-completion
;; ignore cases when complete
(setq read-file-name-completion-ignore-case t)
(setq read-buffer-completion-ignore-case t)
(setq completion-ignore-case t)
;; disable help message in the minibuffer
(setq completion-show-help nil)
(setq completion-show-inline-help nil)
(setq completion-auto-help 'always)
(setq completion-styles '(basic partial-completion substring))
(setq completion-category-overrides '((buffer (styles . (substring flex)))
(file (styles . (substring flex)))))
(setq completions-format 'one-column)
(setq completions-max-height 20)
(setq completions-detailed t)
(add-to-list 'display-buffer-alist
'("\\*Completions\\*"
(display-buffer-reuse-window display-buffer-in-side-window)
(side . bottom)
(slot . 0)))
;; delete a whole repo name in a path
(defun my/minibuffer-backward-kill (arg)
"When minibuffer is completing a file name delete up to parent
folder, otherwise delete a word"
(interactive "p")
(if minibuffer-completing-file-name
;; Borrowed from https://github.com/raxod502/selectrum/issues/498#issuecomment-803283608
(if (string-match-p "/." (minibuffer-contents))
(zap-up-to-char (- arg) ?/)
(delete-minibuffer-contents))
(delete-word (- arg))))
(define-key minibuffer-mode-map (kbd "M-d") #'my/minibuffer-backward-kill)
(define-key minibuffer-local-completion-map (kbd "SPC") nil)
(define-key minibuffer-mode-map (kbd "C-n") #'minibuffer-next-completion)
(define-key minibuffer-mode-map (kbd "C-p") #'minibuffer-previous-completion)
(aggressive-completion-mode 1)
多谢,我试试看。
aggressive-completion 表现迟钝&怪异?
我用最小配置体验了一下:
$ emacsq.sh -P aggressive-completion -M aggressive-completion-mode
也许 aggressive 的意思就是它会自做主张帮用户补齐输入内容, 以缩小候选范围吧,例如当用户输入:
`M-x agg|`
等待 aggressive-completion-delay
(默认0.3秒) 时长之后,自动补齐为:(候选项缩小到 3 条)
`M-x aggressive-completion-|`
初次使用有点不知所措,总是“抢拍”。
似乎作者的理念是,只要手速够快,你就感觉不到 aggressive-completion 的存在。aggressive-completion
就不来“打扰”
aggressive-completion-delay
除了控制自动补完输入之外,也控制着弹窗延时。对于 helm/ivy/selctrum 用户来说,总是会在输入之后习惯性的期待弹窗出现,而这个延时就让这群用户觉得有点迟钝。
但又不能把延时设为 0,这样你永远都抢不过 aggressive-completion
。
$ emacsq.sh -P aggressive-completion --eval "(progn {code-from-#38})"
由于先前的体验,在我输入 M-x agg
之后,已经不惊讶出现以下画面了:
但是当我按下 C-n
的时候,它居然直接选择了第一项,把其它选项都过滤掉了:
这完全超出了我的理解范畴。还是我哪里配置/操作不对?
我直接试用了solatle的配置(卸载了vertico),也感觉差不多,补全非常的“aggressive”,操作必须得非常快,稍一停顿,就会把第一个选项作为过滤条件了。而且选好了以后,需要多一次确认。
如果直接从ivy/vertico的逻辑转到aggressive-completion来看确实如楼上二位所说。C-n和C-p是我没用ac之前的配置(纯原生手动toggle completion buffer)保留下来的,用了ac就不经常用了,直接用输入过滤。如果不想那么aggressive可以M-t关闭,比如新建文件的时候,但是C-n C-p还是会像二位所说过滤其它选项,这个确实可以提交改进。
原生的补全机制还在慢慢完善,目前从效果来看肯定没用其它的第三方成熟。但选择原生的人就是喜欢少一点的弹出干扰和简单一致的minibuffer体验,跟ivy/vertico的出发点还是不太一样的,如果没有这方面的偏好,vertico功能性是更完善的,突然变到ac的逻辑肯定不习惯
需设置 aggressive-completion-auto-complete
为 nil
,我只使用 M-<数字>
来选择候选项.
(defun my/completion-goto-line (n)
"Select candidate by M-<number> or input a line number.
Just insert selection with prefix argument."
(interactive
(list (let* ((type (event-basic-type last-command-event))
(char (if (characterp type)
;; Number on the main row.
type
;; Keypad number, if bound directly.
(car (last (string-to-list (symbol-name type))))))
(n (- char ?0)))
(if (zerop n) 10 n))))
(switch-to-completions)
(let ((line (if (<= n 10) n
(read-number "Select line: ")))
(completion-no-auto-exit (equal current-prefix-arg '(4))))
(goto-line (- line display-line-numbers-offset))
(choose-completion)))
(defun my/completion-goto-line-define-keys (maps)
"Setup M-<number> key to select Nth candidate."
(dolist (map maps)
(dotimes (i 10)
(define-key map (read-kbd-macro (format "M-%d" i)) 'my/completion-goto-line))))
;; M-<number> to select Nth candidate.
(my/completion-goto-line-define-keys (list minibuffer-local-completion-map
completion-in-region-mode-map
completion-list-mode-map))
(defun my/completion-list-mode-hook-function ()
(setq-local mode-line-format nil
track-eol nil)
(display-line-numbers-mode +1)
(hl-line-mode -1)
(rainbow-mode +1)
(face-remap-add-relative 'line-number :background 'unspecified :foregound 'unspecified :inherit 'default)
(face-remap-add-relative 'line-number-current-line :background 'unspecified :foregound 'unspecified :inherit 'default))
(add-hook 'completion-list-mode-hook #'my/completion-list-mode-hook-function)
Completions buffer + aggressive-completion
补全非常丝滑。
分享下我的配置:
(use-package minibuffer
:init
(keymap-unset minibuffer-local-completion-map "SPC")
:bind
(:map completion-list-mode-map
("z" . switch-to-minibuffer))
:custom
(isearch-allow-scroll t)
;(enable-recursive-minibuffers t)
(minibuffer-depth-indicate-mode t)
(minibuffer-electric-default-mode t)
;; Don't insert completion at point into minibuffer
(minibuffer-completion-auto-choose nil)
;; One frame one minibuffer.
(minibuffer-follows-selected-frame nil)
(read-buffer-completion-ignore-case t)
(read-file-name-completion-ignore-case t)
(minibuffer-default-prompt-format " [%s]")
(minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
(resize-mini-windows t)
(completion-auto-help t)
(completion-show-help nil)
;(completion-show-inline-help nil)
(completion-cycle-threshold nil)
;; `t' `second-tab' `nil'
(completion-auto-select 'seond-tab)
(completions-detailed t)
;; Ignore cases when complete
(completion-ignore-case t)
;; vertical display
(completions-format 'one-column)
(completions-max-height 7)
(completions-sort #'completion:list-sort)
:config
;; Hide the mode line of the Completions buffers
(add-to-list 'display-buffer-alist
'("\\`\\*Completions\\*"
nil
(window-parameters (mode-line-format . none))))
(defun completion:list-sort (all)
"对 `Completions-buffer' 中的补全项进行排序"
(let ((hist (minibuffer-history-value)))
(thread-first all
(sort (lambda (c1 c2) (< (length c1) (length c2))))
(sort (lambda (c1 c2) (> (length (member c1 hist))
(length (member c2 hist)))))))))
(use-package all-the-icons-completion
:straight t
:hook (after-init-hook . all-the-icons-completion-mode))
(use-package aggressive-completion
:straight t
:bind
(:map aggressive-completion-minibuffer-map
("TAB" . completion:auto-select))
:hook
(after-init-hook . aggressive-completion-mode)
:config
(add-hook 'aggressive-completion-mode-hook #'completion:disable-auto-select)
(defun completion:disable-auto-select ()
;; 避免自动切换至 `Completions-buffer' 中的补全项
(setq completion-auto-select nil
;; 禁止 `minibuffer' 中的补全
completion-cycle-threshold nil))
(defun completion:auto-select ()
"`TAB' 键可切换至 `Completions-buffer' 中的补全项"
(interactive)
(let ((completion-auto-select t))
(minibuffer-complete))))
(use-package orderless
:straight t
:custom
(completion-styles '(orderless basic))
(completion-category-defaults nil)
(completion-category-overrides '((file (styles basic partial-completion)))))
能有个视频或者动图展示下有多丝滑就更好了
原生补全保姆级教程来了