mirror of
https://github.com/SqrtMinusOne/eshell-atuin.git
synced 2025-12-11 04:43:02 +03:00
eshell-atuin: history works
This commit is contained in:
parent
5043d8b879
commit
1ccac4b746
1 changed files with 125 additions and 17 deletions
142
eshell-atuin.el
142
eshell-atuin.el
|
|
@ -5,7 +5,7 @@
|
||||||
;; Author: Korytov Pavel <thexcloud@gmail.com>
|
;; Author: Korytov Pavel <thexcloud@gmail.com>
|
||||||
;; Maintainer: Korytov Pavel <thexcloud@gmail.com>
|
;; Maintainer: Korytov Pavel <thexcloud@gmail.com>
|
||||||
;; Version: 0.2.0
|
;; Version: 0.2.0
|
||||||
;; Package-Requires: ((emacs "27.1"))
|
;; Package-Requires: ((emacs "27.1") (compat "29.1.4.1"))
|
||||||
;; Homepage: https://github.com/SqrtMinusOne/eshell-atuin.el
|
;; Homepage: https://github.com/SqrtMinusOne/eshell-atuin.el
|
||||||
;; Published-At: 2024-03-08
|
;; Published-At: 2024-03-08
|
||||||
|
|
||||||
|
|
@ -29,6 +29,8 @@
|
||||||
;; TODO
|
;; TODO
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
(require 'avl-tree)
|
||||||
|
(require 'compat)
|
||||||
(require 'eshell)
|
(require 'eshell)
|
||||||
|
|
||||||
(defgroup eshell-atuin ()
|
(defgroup eshell-atuin ()
|
||||||
|
|
@ -41,6 +43,49 @@
|
||||||
:group 'eshell-atuin
|
:group 'eshell-atuin
|
||||||
:type 'file)
|
:type 'file)
|
||||||
|
|
||||||
|
(defcustom eshell-atuin-search-fields '(time duration command)
|
||||||
|
"List of fields to retrive from atuin.
|
||||||
|
|
||||||
|
Be sure to keep \"time\" and \"command\" here, otherwise the package
|
||||||
|
will not work."
|
||||||
|
:group 'eshell-atuin
|
||||||
|
:type '(repeat
|
||||||
|
(choice
|
||||||
|
(const time)
|
||||||
|
(const exit)
|
||||||
|
(const duration)
|
||||||
|
(const command)
|
||||||
|
(const directory)
|
||||||
|
(const user)
|
||||||
|
(const host)
|
||||||
|
(const relativetime))))
|
||||||
|
|
||||||
|
(defcustom eshell-atuin-history-format "%c"
|
||||||
|
"How to format history items.
|
||||||
|
|
||||||
|
See `format-spec' on the general syntax. Available flags and
|
||||||
|
corresponding search fields from `eshell-atuin-search-fields':
|
||||||
|
- %t - time
|
||||||
|
- %e - exit
|
||||||
|
- %d - duration
|
||||||
|
- %c - command
|
||||||
|
- %i - directory
|
||||||
|
- %u - user
|
||||||
|
- %h - host
|
||||||
|
- %r - relativetime"
|
||||||
|
:group 'eshell-atuin
|
||||||
|
:type 'file)
|
||||||
|
|
||||||
|
(defcustom eshell-atuin-search-options '("--exit" "0")
|
||||||
|
"Additional options for \\='atuin search\\='.
|
||||||
|
|
||||||
|
See \\='atuin help search\\=' for the kind of things you may want to
|
||||||
|
include here. Some examples:
|
||||||
|
- \\='(\"--exit\" \"0\") to filter out non-zero exit codes.
|
||||||
|
- \\='(\"--exclude-cwd\" \"/some/dir\")"
|
||||||
|
:group 'eshell-atuin
|
||||||
|
:type '(repeat string))
|
||||||
|
|
||||||
(defvar-local eshell-atuin--history-id nil
|
(defvar-local eshell-atuin--history-id nil
|
||||||
"ID of the current atuin history command.")
|
"ID of the current atuin history command.")
|
||||||
|
|
||||||
|
|
@ -76,14 +121,12 @@
|
||||||
(list
|
(list
|
||||||
"--duration"
|
"--duration"
|
||||||
(prog1
|
(prog1
|
||||||
(concat (number-to-string
|
(thread-first eshell-atuin--last-command-start
|
||||||
(round
|
(time-since)
|
||||||
(*
|
(float-time)
|
||||||
1000000000 ; nanoseconds
|
(* 1000000000)
|
||||||
(float-time
|
(round)
|
||||||
(time-subtract
|
(number-to-string))
|
||||||
(current-time)
|
|
||||||
eshell-atuin--last-command-start))))))
|
|
||||||
(setq eshell-atuin--last-command-start nil))))
|
(setq eshell-atuin--last-command-start nil))))
|
||||||
,eshell-atuin--history-id))
|
,eshell-atuin--history-id))
|
||||||
(buf (generate-new-buffer "*atuin-output*"))
|
(buf (generate-new-buffer "*atuin-output*"))
|
||||||
|
|
@ -122,19 +165,84 @@
|
||||||
(advice-remove #'eshell-send-input #'eshell-atuin--pre-exec)
|
(advice-remove #'eshell-send-input #'eshell-atuin--pre-exec)
|
||||||
(remove-hook 'eshell-post-command-hook #'eshell-atuin--post-exec))))
|
(remove-hook 'eshell-post-command-hook #'eshell-atuin--post-exec))))
|
||||||
|
|
||||||
(defun eshell-atuin--get-history ()
|
(defun eshell-atuin--compare (a b)
|
||||||
|
(string-lessp
|
||||||
|
(alist-get 'time a)
|
||||||
|
(alist-get 'time b)))
|
||||||
|
|
||||||
|
(defvar eshell-atuin--history-cache (avl-tree-create #'eshell-atuin--compare)
|
||||||
|
"TODO.")
|
||||||
|
|
||||||
|
(defvar eshell-atuin--history-last-update nil
|
||||||
|
"TODO.")
|
||||||
|
|
||||||
|
(defun eshell-atuin--create-format-flag ()
|
||||||
|
(mapconcat
|
||||||
|
(lambda (item)
|
||||||
|
(format "{%s}" item))
|
||||||
|
eshell-atuin-search-fields
|
||||||
|
"\\t"))
|
||||||
|
|
||||||
|
(defun eshell-atuin--parse-history-line (line)
|
||||||
|
(cl-loop for field in eshell-atuin-search-fields
|
||||||
|
for value in (string-split line "\t")
|
||||||
|
collect (cons field value)))
|
||||||
|
|
||||||
|
(defun eshell-atuin--history-list ()
|
||||||
(with-temp-buffer
|
(with-temp-buffer
|
||||||
(let ((ret (call-process
|
(let* ((proc-args `("search" "-f" ,(eshell-atuin--create-format-flag)
|
||||||
eshell-atuin-executable nil t nil
|
,@(when eshell-atuin--history-last-update
|
||||||
"history" "list" "-f" "")))
|
(list "--after"
|
||||||
(unless (= 0 ret)
|
(thread-last
|
||||||
|
eshell-atuin--history-last-update
|
||||||
|
(time-since)
|
||||||
|
(float-time)
|
||||||
|
(round)
|
||||||
|
(format "%s seconds ago"))))
|
||||||
|
,@eshell-atuin-search-options))
|
||||||
|
(ret (apply #'call-process eshell-atuin-executable
|
||||||
|
nil t nil proc-args))
|
||||||
|
(commands (make-hash-table :test #'equal)))
|
||||||
|
(unless (or (= 0 ret) (= 1 ret))
|
||||||
(error "`atuin history list' retured %s: %s" ret (buffer-string)))
|
(error "`atuin history list' retured %s: %s" ret (buffer-string)))
|
||||||
(buffer-substring-no-properties
|
(goto-char (point-min))
|
||||||
(point-min) (point-max)))))
|
(cl-loop while (not (eobp))
|
||||||
|
for line = (buffer-substring-no-properties
|
||||||
|
(line-beginning-position)
|
||||||
|
(line-end-position))
|
||||||
|
for datum = (eshell-atuin--parse-history-line line)
|
||||||
|
if (alist-get 'command datum) collect datum
|
||||||
|
do (forward-line 1)))))
|
||||||
|
|
||||||
|
(defun eshell-atuin--history-update ()
|
||||||
|
(cl-loop for line in (eshell-atuin--history-list)
|
||||||
|
do (avl-tree-enter eshell-atuin--history-cache line))
|
||||||
|
(setq eshell-atuin--history-last-update (current-time)))
|
||||||
|
|
||||||
|
(defun eshell-atuin--history-collection ()
|
||||||
|
(avl-tree-mapf
|
||||||
|
(lambda (e)
|
||||||
|
(cons
|
||||||
|
(format-spec eshell-atuin-history-format
|
||||||
|
`((?t . ,(alist-get 'time e))
|
||||||
|
(?e . ,(alist-get 'exit e))
|
||||||
|
(?d . ,(alist-get 'duration e))
|
||||||
|
(?c . ,(alist-get 'command e))
|
||||||
|
(?i . ,(alist-get 'directory e))
|
||||||
|
(?h . ,(alist-get 'host e))
|
||||||
|
(?r . ,(alist-get 'relativetime e))))
|
||||||
|
(alist-get 'command e)))
|
||||||
|
#'cons
|
||||||
|
eshell-atuin--history-cache))
|
||||||
|
|
||||||
(defun eshell-atuin-history ()
|
(defun eshell-atuin-history ()
|
||||||
(interactive)
|
(interactive)
|
||||||
)
|
(let* ((commands (eshell-atuin--history-collection))
|
||||||
|
(input (eshell-atuin--get-input))
|
||||||
|
(compl (completing-read "History: " commands nil t input)))
|
||||||
|
(eshell-bol)
|
||||||
|
(delete-region (point) (line-end-position))
|
||||||
|
(insert compl)))
|
||||||
|
|
||||||
(provide 'eshell-atuin)
|
(provide 'eshell-atuin)
|
||||||
;;; eshell-atuin.el ends here
|
;;; eshell-atuin.el ends here
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue