9

If I startup emacs 24.5.2 with emacs -Q and do M-x eshell, then run:

$ which rm
eshell/rm is a compiled Lisp function in `em-unix.el'

I get the eshell version. But if I C-h v eshell-prefer-lisp-functions I see the value is nil. Yet the documentation states:

If you would prefer to use the built-in commands instead of the external commands, set eshell-prefer-lisp-functions to t.

Is this a bug? I thought the docs might be backwards so I tried setting the variable to t, but the behavior stays the same, I continue getting the eshell implementation rather than the version in /bin.

Joseph Garvin
  • 2,061
  • 8
  • 21
  • I wonder if the problem is with `which`. If you do `rm --version`, what do you get? – zck Dec 21 '15 at 19:26
  • @zck I get what I would get from /bin/rm, *but* the whole reason I started investigating this is because I rm'd a large directory which caused all of emacs to freeze, indicating it's using the eshell version. I believe the eshell versions fallback to the system version when they encounter an unrecognized argument for compatibility sake, so I think the fact that it outputs the coreutils' rm version info is actually misleading, and it is using the eshell version. – Joseph Garvin Dec 21 '15 at 19:28
  • Well, that's confusing. Wish I could help more. – zck Dec 21 '15 at 19:48
  • Why not use direct command instead of relying on *prefer* settings? For example: `$ *rm filename`. Starting `*` will make `eshell` skip looking for built-in commands. This method is useful for bypassing built-in commands no matter what the *prefer* settings. – Emacs User Dec 27 '15 at 05:26

1 Answers1

4

Eshell always prefers Lisp functions. eshell-prefer-lisp-functions only affects the interpretation of *rm, not the interpretation of rm.

Source: the source code… From Emacs 24.3:

(defun eshell-plain-command (command args)
  (let* ((esym (eshell-find-alias-function command))
    …
    (if (and …
             (or esym eshell-prefer-lisp-functions
                 (not (eshell-search-path command))))
        (eshell-lisp-command sym args)
      (eshell-external-command command args))))

eshell-find-alias-function looks up a function under the eshell/ prefix. There's similar logic in eshell/which.

The variable's documentation is downright misleading, and the manual is rather misleading too. I guess the behavior is by design (after all, why would you define an eshell function if it's not to use it?), so it's a documentation bug.

To invoke the external utility, call /bin/rm, or, provided that you left eshell-prefer-lisp-functions set to nil, call *rm*. If you want rm to always invoke the external utility, you can define an alias: alias rm "rm $*" (thanks GDP2).

  • This is a bug report, not an answer. Delete the response or amend it with a workable solution. – Emacs User Dec 27 '15 at 17:05
  • 2
    Emacs User: What are you talking about? The question is "Why does eshell prefer lisp functions even when eshell-prefer-lisp-functions is nil?" and this is 100% an answer to that question. – phils Dec 28 '15 at 08:19
  • "The only way to make `rm` always invoke the external command is to ensure that there's no function called `eshell/rm`. (That, or of course advising or redefining some of Eshell's code.)" That's not the only way to make `rm` invoke the external command. As documented in the manual, you could make an alias which points `rm` to `*rm` (see also http://emacs.stackexchange.com/a/880/10761). – GDP2 Jul 19 '16 at 20:32
  • @Gilles No problem. – GDP2 Jul 19 '16 at 22:11