This makes Eshell’s
‘ls’ file names RET-able. Yay!
(eval-after-load "em-ls" '(progn (defun ted-eshell-ls-find-file-at-point (point) "RET on Eshell's `ls' output to open files." (interactive "d") (find-file (buffer-substring-no-properties (previous-single-property-change point 'help-echo) (next-single-property-change point 'help-echo)))) (defun pat-eshell-ls-find-file-at-mouse-click (event) "Middle click on Eshell's `ls' output to open files. From Patrick Anderson via the wiki." (interactive "e") (ted-eshell-ls-find-file-at-point (posn-point (event-end event)))) (let ((map (make-sparse-keymap))) (define-key map (kbd "RET") 'ted-eshell-ls-find-file-at-point) (define-key map (kbd "<return>") 'ted-eshell-ls-find-file-at-point) (define-key map (kbd "<mouse-2>") 'pat-eshell-ls-find-file-at-mouse-click) (defvar ted-eshell-ls-keymap map)) (defadvice eshell-ls-decorated-name (after ted-electrify-ls activate) "Eshell's `ls' now lets you click or RET on file names to open them." (add-text-properties 0 (length ad-return-value) (list 'help-echo "RET, mouse-2: visit this file" 'mouse-face 'highlight 'keymap ted-eshell-ls-keymap) ad-return-value) ad-return-value)))
At least on my setup (I tried on both Linux and W2k, running emacs 21), the function ted-eshell-ls-find-file does not work if point is before left-most character of file name. This is because the previous-single-property-change catches a point too far in the buffer and we get text we do not want to. The following modified function fixes this, but only for “short-listings” (that is, not ls -l). The solution is kinda ugly but it works:
(defun ted-eshell-ls-find-file () (interactive) (let ((fname (buffer-substring-no-properties (previous-single-property-change (point) 'help-echo) (next-single-property-change (point) 'help-echo)))) ;; Remove any leading whitespace, including newline that might ;; be fetched by buffer-substring-no-properties (setq fname (replace-regexp-in-string "^[ \t\n]*" "" fname)) ;; Same for trailing whitespace and newline (setq fname (replace-regexp-in-string "[ \t\n]*$" "" fname)) (cond ((equal "" fname) (message "No file name found at point")) (fname (find-file fname)))))
Now, if someone could fix it for long-listings too and describe how to bind the function to mouse-2 also, I would be one step closer to emacs-nirvana! – MathiasDahl
Here’s mouse-2 clickability. – PatrickAnderson
OK, I’ve cleaned up the code a bit. Only one user-visible change: middle-clicking on a file no longer moves point to that filename. I found that this more closely matched the behavior my fingers expect. – EdwardOConnor