127 lines
4.8 KiB
EmacsLisp
127 lines
4.8 KiB
EmacsLisp
;;; +eshell.el -*- lexical-binding: t; -*-
|
|
|
|
;;; Code:
|
|
|
|
;; https://karthinks.com/software/jumping-directories-in-eshell/
|
|
(defun eshell/z (&optional regexp)
|
|
"Navigate to a previously visited directory in eshell, or to
|
|
any directory proferred by `consult-dir'."
|
|
(let ((eshell-dirs (delete-dups
|
|
(mapcar 'abbreviate-file-name
|
|
(ring-elements eshell-last-dir-ring)))))
|
|
(cond
|
|
((and (not regexp) (featurep 'consult-dir))
|
|
(let* ((consult-dir--source-eshell `(:name "Eshell"
|
|
:narrow ?e
|
|
:category file
|
|
:face consult-file
|
|
:items ,eshell-dirs))
|
|
(consult-dir-sources (cons consult-dir--source-eshell
|
|
consult-dir-sources)))
|
|
(eshell/cd (substring-no-properties
|
|
(consult-dir--pick "Switch directory: ")))))
|
|
(t (eshell/cd (if regexp (eshell-find-previous-directory regexp)
|
|
(completing-read "cd: " eshell-dirs)))))))
|
|
|
|
;;; Start and quit
|
|
|
|
;; from https://old.reddit.com/r/emacs/comments/1zkj2d/advanced_usage_of_eshell/
|
|
(defun +eshell-here ()
|
|
"Go to eshell and set current directory to current buffer's."
|
|
;; consider: make a new eshell buffer when given a prefix argument.
|
|
(interactive)
|
|
(let ((dir (file-name-directory (or (buffer-file-name)
|
|
default-directory))))
|
|
(eshell)
|
|
(eshell/pushd ".")
|
|
(cd dir)
|
|
(goto-char (point-max))
|
|
(eshell-kill-input)
|
|
(eshell-send-input)
|
|
(setq-local scroll-margin 0)
|
|
(recenter 0)))
|
|
|
|
(defun +eshell-quit-or-delete-char (arg)
|
|
"Delete the character to the right, or quit eshell on an empty line."
|
|
(interactive "p")
|
|
(if (and (eolp) (looking-back eshell-prompt-regexp))
|
|
(progn (eshell-life-is-too-much)
|
|
(when (and (<= 1 (count-windows))
|
|
;; TODO: This is not what I want. What I really want is
|
|
;; for an eshell-only frame (i.e., called from a
|
|
;; keybind) to delete itself, but a regular Emacs frame
|
|
;; with Eshell inside to stick around. I think I'll
|
|
;; need to make a frame-local (?) variable for that to
|
|
;; work.
|
|
(> (length (frame-list)) 2)
|
|
server-process)
|
|
(delete-frame)))
|
|
(delete-forward-char arg)))
|
|
|
|
;;; Insert previous arguments
|
|
;; Record arguments
|
|
|
|
(defvar eshell-arg-history nil)
|
|
(defvar eshell-arg-history-index nil)
|
|
(add-to-list 'savehist-additional-variables 'eshell-arg-history)
|
|
|
|
(defun eshell-record-args (&rest _)
|
|
"Record unique arguments onto the front of `eshell-arg-history'."
|
|
(setq eshell-arg-history
|
|
(cl-loop with history = eshell-arg-history
|
|
for arg in (reverse eshell-last-arguments)
|
|
do (setq history (cons arg (remove arg history)))
|
|
finally return history)))
|
|
|
|
(defun eshell-insert-prev-arg ()
|
|
"Insert an argument from `eshell-arg-history' at point."
|
|
(interactive)
|
|
(if (eq last-command 'eshell-insert-prev-arg)
|
|
(progn
|
|
(let ((pos (point)))
|
|
(eshell-backward-argument 1)
|
|
(delete-region (point) pos))
|
|
(if-let ((text (nth eshell-arg-history-index
|
|
eshell-arg-history)))
|
|
(progn
|
|
(insert text)
|
|
(cl-incf eshell-arg-history-index))
|
|
(insert (cl-first eshell-arg-history))
|
|
(setq eshell-arg-history-index 1)))
|
|
(insert (cl-first eshell-arg-history))
|
|
(setq eshell-arg-history-index 1)))
|
|
|
|
;;;###autoload
|
|
(define-minor-mode eshell-arg-hist-mode
|
|
"Minor mode to enable argument history, like bash/zsh with M-."
|
|
:lighter "$."
|
|
:keymap (let ((map (make-sparse-keymap)))
|
|
(define-key map (kbd "M-.") #'eshell-insert-prev-arg)
|
|
map)
|
|
(if eshell-arg-hist-mode
|
|
(add-hook 'eshell-post-command-hook #'eshell-record-args nil t)
|
|
(remove-hook 'eshell-post-command-hook #'eshell-record-args t)))
|
|
|
|
;;;###autoload
|
|
(defmacro +eshell-eval-after-load (&rest forms)
|
|
"Execute FORMS after Eshell is loaded.
|
|
If Eshell is already loaded in the session, immediately execute
|
|
forms.
|
|
|
|
I wrote this because Eshell doesn't properly do loading or
|
|
something, it's really annoying to work with."
|
|
(declare (indent 0))
|
|
`(progn
|
|
(defun +eshell@setup ()
|
|
"Setup the Eshell session."
|
|
,@forms)
|
|
(when (featurep 'eshell)
|
|
`(dolist (buf (buffer-list))
|
|
(with-current-buffer buf
|
|
(when (derived-mode-p 'eshell-mode)
|
|
(+eshell@setup)))))
|
|
(add-hook 'eshell-mode-hook #'+eshell@setup)))
|
|
|
|
(provide '+eshell)
|
|
;;; +eshell.el ends here
|