在 Linux 下,eshell-autojump 会进行区分大小写的匹配,我觉得这很麻烦。我试图通过建议 eshell/j 使用总是返回 t 的 eshell-under-windows-p 来规避这个问题,但令我懊恼的是在 eshell/j 中调用的 eshell-under-windows-p 是不受 cl-letf 的影响。我修改了我的 eshell/j 来给我一些调试信息:
;; Modified eshell/j inside eshell-autojump.el to this
(defun eshell/j (&rest args) ; all but first ignored
"Jump to a directory you often cd to.
This compares the argument with the list of directories you usually jump to.
Without an argument, list the ten most common directories.
With a positive integer argument, list the n most common directories.
Otherwise, call `eshell/cd' with the result."
(setq args (eshell-flatten-list args))
(let ((path (car args))
(candidates (eshell-autojump-candidates))
(case-fold-search (eshell-under-windows-p))
result)
(when (not path)
(setq path 10))
(message "case-fold-search = %S" case-fold-search)
(message "eshell-under-windows-p returns %s from inside eshell/j" (eshell-under-windows-p))
(if (and (integerp path) (> path 0))
(progn
(let ((n (nthcdr (1- path) candidates)))
(when n
(setcdr n nil)))
(eshell-lisp-command (mapconcat 'identity candidates "\n")))
(while (and candidates (not result))
(if (string-match path (car candidates))
(setq result (car candidates))
(setq candidates (cdr candidates))))
(eshell/cd result))))
我的 init.el 添加了建议,试图通过欺骗它认为我们在 Windows 上来尝试使 eshell/j 无大小写:
;; Added to init.el
(require 'eshell-autojump)
(advice-add 'eshell/j :around
(lambda (orig-fun &rest xs)
(cl-letf (((symbol-function 'eshell-under-windows-p) (lambda () t)))
(progn (message "eshell-under-windows-p returns %s from lambda" (eshell-under-windows-p)) (apply orig-fun xs)))))
但是当我尝试跳转到 eshell 时,我在 Messages 缓冲区中得到的只是:
;; I get in *Messages*
eshell-under-windows-p returns t from lambda
case-fold-search = nil
eshell-under-windows-p returns nil from inside eshell/j
我对 elisp 的菜鸟知识不足以解决这里可能的范围界定问题。谁能解码为什么从 eshell/j 调用时 eshell-under-window-p 不受影响?
我找到了答案。 cl-letf 不适用于字节编译函数。由于 eshell-autojump 是一个软件包,它在安装时会进行字节编译,并且 cl-letf 不能用于修改其内部行为。
最后我成功地通过以下方式欺骗 eshell/j 使其不区分大小写:
(defun my/eshell-j-case-insensitive (orig-fun &rest args)
"Advice function to make `eshell/j' case-insensitive."
(let ((original-system-type system-type))
(unwind-protect
(progn
(setq system-type 'windows-nt) ; Temporarily set system-type to Windows
(apply orig-fun args))
(setq system-type original-system-type)))) ; Restore the original system-type
(advice-add 'eshell/j :around #'my/eshell-j-case-insensitive)