feat: add SPC p L to remove a linked session from project

Parse .hermes-sessions, show menu of linked sessions, prompt
for confirmation, then regenerate the file without the entry.
This commit is contained in:
2026-07-18 18:57:36 -04:00
parent 6c420a60dc
commit 7d853c39c2
2 changed files with 110 additions and 2 deletions

View File

@@ -2209,10 +2209,64 @@ If SESSION-ID is empty, show a menu of recent sessions to browse."
(gortium/hermes--rename-session session-id (format "[%s] %s" name title))
(gortium/hermes-append-session sfile session-id title)
(message "Session %s linked to project %s as \"%s\"" session-id name title)))
;; -------------------------------------------------------------------
;; Remove a linked session from project
;; -------------------------------------------------------------------
;;;###autoload
(defun gortium/hermes-remove-session ()
"Remove a Hermes session from the current project's .hermes-sessions."
(interactive)
(pcase-let ((`(,root ,sfile ,_name) (gortium/hermes--project-info)))
(if (not (file-exists-p sfile))
(user-error "No .hermes-sessions in %s" root)
(let (sessions current)
(with-temp-buffer
(insert-file-contents sfile)
(while (not (eobp))
(forward-line 1)
(cond
((looking-at "^\\*\\* \\([^—]+\\) — \\(.+\\)$")
(setq current (list :date (string-trim (match-string 1))
:title (match-string 2)
:id nil)))
((and current (looking-at "^:HERMES_SESSION: \\(.+\\)$"))
(plist-put current :id (match-string 1))
(push current sessions)
(setq current nil)))))
(if (null sessions)
(message "No Hermes sessions recorded for this project.")
(let* ((items (mapcar (lambda (s)
(format "%s — %s"
(plist-get s :date)
(plist-get s :title)))
sessions))
(choice (completing-read "Remove Hermes session: " items nil t))
(idx (cl-position choice items :test #'string=))
(target (nth idx sessions)))
(when (y-or-p-n (format "Remove \"%s\"? " (plist-get target :title)))
(let ((kept (cl-remove-if
(lambda (s)
(string= (plist-get s :id) (plist-get target :id)))
sessions)))
(with-temp-buffer
(insert "# -*- mode: org -*-\n"
"#+TITLE: Sessions — " _name "\n\n* Sessions\n\n")
(dolist (s (nreverse kept))
(insert (format "** %s — %s\n:PROPERTIES:\n:HERMES_SESSION: %s\n:END:\n[[hermes:%s][Resume — %s]]\n\n"
(plist-get s :date)
(plist-get s :title)
(plist-get s :id)
(plist-get s :id)
(plist-get s :title))))
(write-region (point-min) (point-max) sfile nil 'silent)
(message "Session removed from project."))))))))))
(map! :leader
:desc "New Hermes session" "p h" #'gortium/hermes-start
:desc "Resume Hermes session" "p H" #'gortium/hermes-resume
:desc "Link session to project" "p l" #'gortium/hermes-link-session)
:desc "Link session to project" "p l" #'gortium/hermes-link-session
:desc "Remove session from project" "p L" #'gortium/hermes-remove-session)
#+end_src
* Tramp

View File

@@ -1405,10 +1405,64 @@ If SESSION-ID is empty, show a menu of recent sessions to browse."
(gortium/hermes--rename-session session-id (format "[%s] %s" name title))
(gortium/hermes-append-session sfile session-id title)
(message "Session %s linked to project %s as \"%s\"" session-id name title)))
;; -------------------------------------------------------------------
;; Remove a linked session from project
;; -------------------------------------------------------------------
;;;###autoload
(defun gortium/hermes-remove-session ()
"Remove a Hermes session from the current project's .hermes-sessions."
(interactive)
(pcase-let ((`(,root ,sfile ,_name) (gortium/hermes--project-info)))
(if (not (file-exists-p sfile))
(user-error "No .hermes-sessions in %s" root)
(let (sessions current)
(with-temp-buffer
(insert-file-contents sfile)
(while (not (eobp))
(forward-line 1)
(cond
((looking-at "^\\*\\* \\([^—]+\\) — \\(.+\\)$")
(setq current (list :date (string-trim (match-string 1))
:title (match-string 2)
:id nil)))
((and current (looking-at "^:HERMES_SESSION: \\(.+\\)$"))
(plist-put current :id (match-string 1))
(push current sessions)
(setq current nil)))))
(if (null sessions)
(message "No Hermes sessions recorded for this project.")
(let* ((items (mapcar (lambda (s)
(format "%s — %s"
(plist-get s :date)
(plist-get s :title)))
sessions))
(choice (completing-read "Remove Hermes session: " items nil t))
(idx (cl-position choice items :test #'string=))
(target (nth idx sessions)))
(when (y-or-p-n (format "Remove \"%s\"? " (plist-get target :title)))
(let ((kept (cl-remove-if
(lambda (s)
(string= (plist-get s :id) (plist-get target :id)))
sessions)))
(with-temp-buffer
(insert "# -*- mode: org -*-\n"
"#+TITLE: Sessions — " _name "\n\n* Sessions\n\n")
(dolist (s (nreverse kept))
(insert (format "** %s — %s\n:PROPERTIES:\n:HERMES_SESSION: %s\n:END:\n[[hermes:%s][Resume — %s]]\n\n"
(plist-get s :date)
(plist-get s :title)
(plist-get s :id)
(plist-get s :id)
(plist-get s :title))))
(write-region (point-min) (point-max) sfile nil 'silent)
(message "Session removed from project."))))))))))
(map! :leader
:desc "New Hermes session" "p h" #'gortium/hermes-start
:desc "Resume Hermes session" "p H" #'gortium/hermes-resume
:desc "Link session to project" "p l" #'gortium/hermes-link-session)
:desc "Link session to project" "p l" #'gortium/hermes-link-session
:desc "Remove session from project" "p L" #'gortium/hermes-remove-session)
;; set `tramp-direct-async-process' locally in all ssh connections
(connection-local-set-profile-variables