加強 minibuffer 和預設的 find-file

如果你正在使用 helm 或 ido 的話就不用往下看了,這篇是給喜歡使用內建 find-file 的人看的。

我一直無法忍受 helm 和 ido-mode 的 find-file 設計,但又覺得他們有部份功能實在很方便,例如能夠按 DEL 直接刪回上個目錄的路徑,或者快速清空整個路徑再重新輸入等。這裡做了幾個符合自己需要的功能:

  1. 如果 minibuffer 中是個目錄的樣式,按 M-[DEL] 就可以往前刪到 parent dir
  2. 按一次 C-a 只是一般的 beginning-of-line ,但按第二次 C-a 的話:
    a. 如果是個路徑,會把~/或/以後的東西刪掉。
    b. 如果不是路徑,則整行刪掉。
  3. 以上行為都不會把刪過的東西存到 kill-ring,所以可以放心用力刪,而不用擔心會影響到目前的 kill-ring~ (這是對我來說最重要的一點,因為我很討厭每次在 minibuffer M-[DEL] 都會蓋過我的剪貼簿,而且 kill-ring 也會多一條沒用的檔案路徑)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
(defun minibuffer-beginning-of-line ()
"Pressing C-a once, this's just a normal `beginning-of-line'.
When pressing second time, and the string in minibuffer looks like a file path,
it will *delete* whole minibuffer except for ~/ or / in the beginning of
minibuffer."
(interactive)
(defvar minibuffer-point-beginning-of-line nil)
(if (eq minibuffer-point-beginning-of-line (point)) ;是否已經在 beginning-of-line
(if (or (equal "~/" (substring-no-properties (buffer-string) (1- (point)) (+ 1 (point))))
(equal "/" (substring-no-properties (buffer-string) (1- (point)) (point))))
(progn
(re-search-forward "/" nil :no-error)
(delete-region (point) (point-max)))
(delete-region (point) (point-max))) ;整個 string 看起來不是路徑就全部刪掉。
(progn (move-beginning-of-line 1) ;不在 beginning-of-line 的話
(setq minibuffer-point-beginning-of-line (point)))))

(defun minibuffer-backward-delete-word (arg)
"*Delete* word backward instead of kill it in minibuffer.
Besides, when the string in minibuffer looks like a file path, it will
delete backward until the parent directory."
(interactive "p")
(if (and (eq (point) (point-max)) ;如果在行尾,且整串看起來是個檔案路徑
(string-match "~*/\\([^/\n]+/\\)+$" (buffer-string)))
(progn (re-search-backward "/." nil :no-error)
(delete-region (1+ (point)) (point-max))
(end-of-line))
;; 下面這個只是一般的 backward delete word 而已
(delete-region (point) (progn (backward-word arg) (point)))))

(define-key minibuffer-local-completion-map (kbd "C-a") 'minibuffer-beginning-of-line)
(define-key minibuffer-local-completion-map (kbd "M-DEL") 'minibuffer-backward-delete-word)