sqrtminusone / eshell-atuin Goto Github PK
View Code? Open in Web Editor NEWeshell ❤️ atuin
License: GNU General Public License v3.0
eshell ❤️ atuin
License: GNU General Public License v3.0
If eshell-atuin-mode
is run from a directory with a buffer-local process-environment
, then ATUIN_SESSION
does not get set globally and eshell-atuin
never tries to reinitialize it. This can happen when using a package such as envrc, for example.
Currently I work around the problem by initializing eshell-atuin
in a temporary buffer:
(with-temp-buffer
(eshell-atuin-mode))
But another solution might be to store ATUIN_SESSION
in a lisp variable and wrap each call to atuin
in with-environment-variables
.
With eshell-atuin-mode
turned on, running any command causes the following error:
Debugger entered--Lisp error: (error "‘atuin history end’ returned 2: error: unexpected argument '--duration' found\n\n tip: to pass '--duration' as a value, use '-- --duration'\n\nUsage: atuin history end <ID|--exit <EXIT>>\n\nFor more information, try '--help'.\n")
(error "`atuin history end' returned %s: %s" 2 "error: unexpected argument '--duration' found\n\n tip: to pass '--duration' as a value, use '-- --duration'\n\nUsage: atuin history end <ID|--exit <EXIT>>\n\nFor more information, try '--help'.\n")
(if (= (process-exit-status process) 0) nil (error "`atuin history end' returned %s: %s" (process-exit-status process) (save-current-buffer (set-buffer buf) (buffer-string))))
(unwind-protect (if (= (process-exit-status process) 0) nil (error "`atuin history end' returned %s: %s" (process-exit-status process) (save-current-buffer (set-buffer buf) (buffer-string)))) (kill-buffer buf))
(progn (unwind-protect (if (= (process-exit-status process) 0) nil (error "`atuin history end' returned %s: %s" (process-exit-status process) (save-current-buffer (set-buffer buf) (buffer-string)))) (kill-buffer buf)))
(if (eq (process-status process) 'exit) (progn (unwind-protect (if (= (process-exit-status process) 0) nil (error "`atuin history end' returned %s: %s" (process-exit-status process) (save-current-buffer (set-buffer buf) (buffer-string)))) (kill-buffer buf))))
((closure ((buf . #<buffer *atuin-output*>)) (process _msg) (if (eq (process-status process) 'exit) (progn (unwind-protect (if (= (process-exit-status process) 0) nil (error "`atuin history end' returned %s: %s" (process-exit-status process) (save-current-buffer ... ...))) (kill-buffer buf))))) #<process atuin-history-stop> "exited abnormally with code 2\n")
The error is from eshell-atuin--post-exec
, and is caused by atuin history end
not understanding the --duration
argument.
Here is the output of atuin history end --help
:
~ ❯ atuin history end --help
Finishes a new command in the history (adds time, exit code)
Usage: atuin history end --exit <EXIT> <ID>
Arguments:
<ID>
Options:
-e, --exit <EXIT>
-h, --help Print help
There appears to be no --duration
option.
I don't see --duration
mentioned in the atuin docs either, so I'm not sure what's going on.
My atuin version:
~ ❯ atuin --version
atuin 17.0.1
I tried to include directories in the history format:
(setopt eshell-atuin-search-fields '(time duration command directory)
eshell-atuin-history-format "%-80c %t + %i")
but ran into the following error:
Debugger entered--Lisp error: (error "Invalid format character: ‘%i’")
(error "Invalid format character: `%%%c'" 105)
(format-spec "%-80c %t + %i" ((116 . "2024-02-26 07:43:55") (101) (100 . "90ms") (99 . "for archive in *.zip; do") (105) (104) (114)))
(let* ((p (if (and nil (not (eq nil 'eq))) (assoc 'formatted-value e nil) (assq 'formatted-value e))) (v (format-spec eshell-atuin-history-format (list (cons 116 (alist-get 'time e)) (cons 101 (alist-get 'exit e)) (cons 100 (alist-get 'duration e)) (cons 99 (alist-get 'command e)) (cons 105 (alist-get 'directory e)) (cons 104 (alist-get 'host e)) (cons 114 (alist-get 'relativetime e)))))) (progn (if p (setcdr p v) (setq e (cons (setq p (cons 'formatted-value v)) e))) v))
(progn (let* ((p (if (and nil (not (eq nil ...))) (assoc 'formatted-value e nil) (assq 'formatted-value e))) (v (format-spec eshell-atuin-history-format (list (cons 116 (alist-get ... e)) (cons 101 (alist-get ... e)) (cons 100 (alist-get ... e)) (cons 99 (alist-get ... e)) (cons 105 (alist-get ... e)) (cons 104 (alist-get ... e)) (cons 114 (alist-get ... e)))))) (progn (if p (setcdr p v) (setq e (cons (setq p (cons ... v)) e))) v)))
(if (alist-get 'command e) (progn (let* ((p (if (and nil (not ...)) (assoc 'formatted-value e nil) (assq 'formatted-value e))) (v (format-spec eshell-atuin-history-format (list (cons 116 ...) (cons 101 ...) (cons 100 ...) (cons 99 ...) (cons 105 ...) (cons 104 ...) (cons 114 ...))))) (progn (if p (setcdr p v) (setq e (cons (setq p ...) e))) v))))
(let ((e (let* ((--cl-var-- eshell-atuin-search-fields) (field nil) (--cl-var-- (string-split line "\11")) (value nil) (--cl-var-- nil)) (while (and (consp --cl-var--) (progn (setq field ...) (consp --cl-var--))) (setq value (car --cl-var--)) (setq --cl-var-- (cons (cons field value) --cl-var--)) (setq --cl-var-- (cdr --cl-var--)) (setq --cl-var-- (cdr --cl-var--))) (nreverse --cl-var--)))) (if (alist-get 'command e) (progn (let* ((p (if (and nil ...) (assoc ... e nil) (assq ... e))) (v (format-spec eshell-atuin-history-format (list ... ... ... ... ... ... ...)))) (progn (if p (setcdr p v) (setq e (cons ... e))) v)))) e)
(eshell-atuin--parse-history-line "2024-02-26 07:43:55\1190ms\11for archive in *.zip; do")
(eshell-atuin--history-update)
(eshell-atuin-history)
(funcall-interactively eshell-atuin-history)
(command-execute eshell-atuin-history)
I narrowed it down to the following:
(let ((e '((time . "2024-02-26 07:43:55")
(duration . "90ms")
(command . "for archive in *.zip; do"))))
(format-spec eshell-atuin-history-format ; "%-80c %t + %i"
`((?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)))))
;; => Fails with the above error
The alist e here is what's constructed on atuin's output for the failing string. The problem is that atuin does not return a directory for the first line of the above multiline bash for
loop. The format-spec
fails since ?i
is mapped to nil
via (alist-get 'directory e)
.
I was able to solve it by specifying a delete
option when using format-spec, which removes missing specifiers. This version is fine:
(let ((e '((time . "2024-02-26 07:43:55")
(duration . "90ms")
(command . "for archive in *.zip; do"))))
(format-spec eshell-atuin-history-format ; "%-80c %t + %i"
`((?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)))
'delete))
Another way to fix it would be to make alist-get
return a non-nil default, as in (alist-get 'directory e "")
. This is probably the better solution when you have a history format with missing entries in the middle, like %-80c %-40i %t
, since format-spec
will remove the whole specifier (%-40i
in this case) and misalign the result.
@SqrtMinusOne Thanks for writing eshell-atuin. Incidentally, I was trying to write the exact same functionality this week, but using a dynamic completion table (and thus no cache). It wasn't going well, now I don't need to bother!
While we're here, thanks for your emacs-i3-integration code as well! I've been using it for quite some time now.
I did have an issue to report, but I'll do it separately -- feel free to close this one.
It seems that eshell-atuin-history
uses the default atuin mode (in my case 'directory'). Is there a way to use the other modes?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.