From 30d4f2070d5a022a1bb6f43f939d292b2cfe17c0 Mon Sep 17 00:00:00 2001 From: JSDurand Date: Sun, 11 Oct 2026 15:33:12 +0800 Subject: eshell: add claude session sources in "j", and ghostel * eshell-conf.el (eshell/j): Now directories of claude sessions are also included as candidates. (eshell-visual-commands): Add claude to the list of visual commands. ("~/scripts/claude/claude-session.el"): The code claude wrote to retrieve claude session data. (#'eshell/cs): Manage claude sessions, i.e. like listing, jumping, and deleting them. ("CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN"): Add this environmental variable to make sure claude spits everything to ghostel so that I can scroll and see everything. ("ghostel/lisp"): Load ghostel. (btm): Use ghostel to run btm instead of vterm used previously. (global-map): Add a binding for ghostel, just in case. (eshell-mode-hook): Use ghostel to run visual commands. --- eshell-conf.el | 123 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 103 insertions(+), 20 deletions(-) (limited to 'eshell-conf.el') diff --git a/eshell-conf.el b/eshell-conf.el index 216b003..1013383 100644 --- a/eshell-conf.el +++ b/eshell-conf.el @@ -247,11 +247,16 @@ See `eshell-j' for the actual functionality and for the format of ARGS." (eshell-eval-using-options "j" args - '((?r "recent" 'exclusive use-recent-p "Find in recent directories instead of symbolic links.") - (?a "all" nil use-recent-p "Find both in recent directories and in symbolic links.") + '((?r "recent" exclusive use-recent-p + "Find in recent directories instead of symbolic links.") + (?a "all" nil use-recent-p + "Find in recent directories, \ +symbolic links, and in claude session directories.") + (?s "session" nil use-session-p + "Find in directories of Claude sessions.") (?h "help" nil nil "Print this help message.") - :usage "[-hra] [short-cut]") - (eshell-j args use-recent-p))) + :usage "[-hras] [short-cut]") + (eshell-j args use-recent-p use-session-p))) ;;;###autoload (defun eshell/mark (&rest args) @@ -339,7 +344,7 @@ supposed to leave the global state alone as well. "The directory that stores links to other directories.") ;;;###autoload -(defun eshell-j (&optional short-cut use-recent-p) +(defun eshell-j (&optional short-cut use-recent-p use-session-p) "Jump to SHORT-CUT. Where this jumps to is determined by the symbolic links in the directory `eshell-mark-directory'. If USE-RECENT-P is non-nil, then @@ -347,8 +352,15 @@ also include recent directories in the list of candidates. Moreover, if USE-RECENT-P is 'exclusive, then only list the recent directories as candidates, unless there are no recent directories, in which case it falls back to use the marks as the -candidates." - (let* ((mark-directory eshell-mark-directory) +candidates. + +If USE-SESSION-P and USE-RECENT-P are non-nil, then also include the +claude session directories in the list of candidates. + +If USE-RECENT-P is non-nil and USE-RECENT-P is nil, only the claude +session directories are in the list of candidates." + (let* ((all-p (eq use-recent-p t)) + (mark-directory eshell-mark-directory) (short-cut (eshell-flatten-and-stringify short-cut)) (links (delq nil (mapcar @@ -396,7 +408,7 @@ candidates." candidates :test #'string= ;; In Haskell this woule be a simple function composition. - :key (function (lambda (ls) (file-truename (cdr ls)))))) + :key (lambda (ls) (file-truename (cdr ls))))) ;; Delete non-matching ones (candidates (delq @@ -404,21 +416,60 @@ candidates." (mapcar (lambda (cand) (cond ((string-match-p short-cut (cdr cand)) cand))) - candidates)))) + candidates))) + ;; also include session candidates if required + (sessions + (cond + ((or all-p use-session-p) (claude-session-candidates)))) + ;; filter sessions + (sessions + (delq + nil + (mapcar + (lambda (session) + (cond + ((string-match-p short-cut (car session)) session))) + sessions))) + ;; merging + (candidates + (cond + (use-recent-p (append candidates sessions)) + (use-session-p sessions) + (candidates)))) (cond ((null candidates) (user-error "No candidates matching %s found" short-cut)) - ((null (cdr candidates)) - ;; Only one candidate - (eshell/cd (file-truename (cdar candidates)))) - ((eshell/cd (file-truename - (cdr - (assoc - (let ((completion-regexp-list - (cons short-cut completion-regexp-list))) - (completing-read - "Choose a link: " candidates nil t)) - candidates #'string=)))))))) + ((let ((dirs-of-cands + (durand-eshell-delete-dups + candidates + :key (lambda (cand) + (directory-file-name + (file-truename (cdr cand)))) + :test #'string=))) + (null (cdr dirs-of-cands))) + ;; Only one directory candidate + (let ((eshell-last-arguments + (cons (file-truename (cdar candidates)) nil))) + (eshell/cd (car eshell-last-arguments)))) + ((let ((eshell-last-arguments + (cons + (file-truename + (cdr + (assoc + (let ((candidates + (delq + nil + (mapcar + (lambda (cand) + (cond + ((string-match-p short-cut (car cand)) + cand))) + candidates)))) + (completing-read + "Choose a link: " candidates nil t)) + candidates #'string=))) + nil))) + (eshell/cd (car eshell-last-arguments))))))) ;;; Custom ls @@ -812,6 +863,9 @@ For example, \"...\" expands into \"../..\"." (add-to-list 'eshell-visual-commands "btm" nil #'string=) +(add-to-list 'eshell-visual-commands + "claude" nil #'string=) + (add-to-list 'eshell-visual-subcommands (list "git" "log" "diff" "show" "help")) @@ -1080,5 +1134,34 @@ command." ((setq continue-loop nil))))) (while (pcomplete-here (gv-complete-files finding-dir))))) +;;;; Claude session + +(load-file "~/scripts/claude/claude-session.el") + +(defalias #'eshell/cs #'eshell/claude-sessions + "Use the function written by claude to list claude code sessions.") + +(setenv "CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN" "1") + +;;;; Ghostel + +(use-package "ghostel/lisp" 'ghostel) + +(use-package "ghostel/lisp" 'ghostel-eshell) + +(defun btm () + "Run the command \"bpm\" in a ghostel buffer." + (interactive) + (ghostel) + (with-current-buffer ghostel-buffer-name + (modeline-toggle)) + (sit-for 0.5) + (ghostel-send-string "btm") + (ghostel-send-key "return")) + +(define-key global-map [?\H-t] #'ghostel) + +(add-hook 'eshell-mode-hook #'ghostel-eshell-visual-command-mode) + (provide 'eshell-conf) ;;; eshell-conf.el ends here -- cgit v1.2.3-18-g5258