diff --git a/doom/.config/doom/README.org b/doom/.config/doom/README.org index af80f95..1e51739 100644 --- a/doom/.config/doom/README.org +++ b/doom/.config/doom/README.org @@ -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 diff --git a/doom/.config/doom/config.el b/doom/.config/doom/config.el index 23d373f..f871f55 100644 --- a/doom/.config/doom/config.el +++ b/doom/.config/doom/config.el @@ -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