about summary refs log tree commit diff stats
path: root/lisp/acdw-eshell.el
blob: eedcc8b7ca645b0502c8b782b6221b0f28888697 (plain)
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
;;; acdw-eshell.el -*- lexical-binding: t; coding: utf-8-unix -*-

;; Author: Case Duckworth <(rot13-string "npqj@npqj.arg")>
;; Keywords: configuration
;; URL: https://tildegit.org/acdw/emacs

;; This file is NOT part of GNU Emacs.

;;; License:
;; Everyone is permitted to do whatever with this software, without
;; limitation.  This software comes without any warranty whatsoever,
;; but with two pieces of advice:
;; - Don't hurt yourself.
;; - Make good choices.

;;; Commentary:

;;; Code:

(require 'cl-lib)


;;; Eshell starting and quitting

(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))
      (eshell-life-is-too-much)
    (delete-forward-char arg)))

;;;###autoload
(defun eshell-pop-or-quit (&optional buffer-name)
  "Pop open an eshell buffer, or if in an eshell buffer, bury it."
  (interactive)
  (if (eq (current-buffer) (get-buffer (or buffer-name "*eshell*")))
      (eshell-life-is-too-much)
    (with-message "Starting eshell"
      (eshell))))


;;; 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)))

(add-hook 'eshell-mode-hook
          (lambda ()
            (add-hook 'eshell-post-command-hook
                      #'eshell-record-args nil t)
            (local-set-key (kbd "M-.") #'eshell-insert-prev-arg)))

;;;###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)))

(provide 'acdw-eshell)
;;; acdw-eshell.el ends here