diff options
Diffstat (limited to 'lisp/ss-org.el')
| -rw-r--r-- | lisp/ss-org.el | 306 |
1 files changed, 0 insertions, 306 deletions
diff --git a/lisp/ss-org.el b/lisp/ss-org.el deleted file mode 100644 index fc8fc9b..0000000 --- a/lisp/ss-org.el +++ /dev/null @@ -1,306 +0,0 @@ -;;; ss-org.el --- Base Org configuration -*- lexical-binding: t; -*- - -;;; Commentary: - -;; Shared Org setup and note-opening helpers. - -;;; Code: - -(require 'org) -(require 'ss-core) - -(defvar ss-navigation-back-stack nil - "Stack of older locations for `ss-jump-back'.") - -(defvar ss-navigation-forward-stack nil - "Stack of newer locations for `ss-jump-forward'.") - -(defvar ss-navigation--inhibit-recording nil - "When non-nil, suppress navigation history recording.") - -(defun ss-navigation--current-location () - "Return the current location as a marker-backed plist." - (unless (minibufferp (current-buffer)) - (list :marker (copy-marker (point-marker)) - :window-start - (when (window-live-p (selected-window)) - (copy-marker (window-start (selected-window))))))) - -(defun ss-navigation--location-valid-p (location) - "Return non-nil when LOCATION still points to a live buffer position." - (when-let ((marker (plist-get location :marker))) - (and (markerp marker) - (marker-buffer marker) - (marker-position marker)))) - -(defun ss-navigation--same-location-p (left right) - "Return non-nil when LEFT and RIGHT identify the same buffer position." - (and (ss-navigation--location-valid-p left) - (ss-navigation--location-valid-p right) - (eq (marker-buffer (plist-get left :marker)) - (marker-buffer (plist-get right :marker))) - (= (marker-position (plist-get left :marker)) - (marker-position (plist-get right :marker))))) - -(defun ss-navigation--prune-stack (stack) - "Return STACK with dead or duplicate locations removed." - (let (pruned previous) - (dolist (location stack (nreverse pruned)) - (when (and (ss-navigation--location-valid-p location) - (not (ss-navigation--same-location-p location previous))) - (push location pruned) - (setq previous location))))) - -(defun ss-navigation--push-location (stack-symbol location &optional clear-forward) - "Push LOCATION onto STACK-SYMBOL unless it duplicates the top entry. -When CLEAR-FORWARD is non-nil, reset `ss-navigation-forward-stack'." - (when (ss-navigation--location-valid-p location) - (set stack-symbol (ss-navigation--prune-stack (symbol-value stack-symbol))) - (unless (ss-navigation--same-location-p location (car (symbol-value stack-symbol))) - (set stack-symbol (cons location (symbol-value stack-symbol)))) - (when clear-forward - (setq ss-navigation-forward-stack nil)) - t)) - -(defun ss-navigation-push-current-location () - "Push the current location onto the back stack. -This is for significant navigation points only and clears forward history." - (interactive) - (ss-navigation--push-location - 'ss-navigation-back-stack - (ss-navigation--current-location) - 'clear-forward)) - -(defun ss-navigation--restore-location (location) - "Restore LOCATION, returning non-nil when successful." - (when (ss-navigation--location-valid-p location) - (let* ((marker (plist-get location :marker)) - (buffer (marker-buffer marker)) - (window-start (plist-get location :window-start))) - (switch-to-buffer buffer) - (goto-char marker) - (when (and (markerp window-start) - (eq (marker-buffer window-start) buffer) - (window-live-p (selected-window))) - (set-window-start (selected-window) - (marker-position window-start) - t)) - t))) - -(defun ss-navigation--jump-from-stack (stack-symbol target-symbol) - "Restore the next location from STACK-SYMBOL and push current onto TARGET-SYMBOL." - (set stack-symbol (ss-navigation--prune-stack (symbol-value stack-symbol))) - (when-let ((target (car (symbol-value stack-symbol)))) - (let ((current (ss-navigation--current-location))) - (set stack-symbol (cdr (symbol-value stack-symbol))) - (when (ss-navigation--location-valid-p current) - (ss-navigation--push-location target-symbol current)) - (let ((ss-navigation--inhibit-recording t)) - (ss-navigation--restore-location target))))) - -(defun ss-navigation--jump-via-command (command) - "Use COMMAND as a mark-ring fallback jump, recording forward history." - (when (fboundp command) - (let ((before (ss-navigation--current-location)) - after) - (let ((ss-navigation--inhibit-recording t)) - (condition-case nil - (call-interactively command) - (error nil))) - (setq after (ss-navigation--current-location)) - (when (and (ss-navigation--location-valid-p before) - (ss-navigation--location-valid-p after) - (not (ss-navigation--same-location-p before after))) - (ss-navigation--push-location 'ss-navigation-forward-stack before) - t)))) - -(defun ss-jump-back () - "Move backward through navigation history." - (interactive) - (or (ss-navigation--jump-from-stack - 'ss-navigation-back-stack - 'ss-navigation-forward-stack) - (ss-navigation--jump-via-command 'pop-global-mark) - (ss-navigation--jump-via-command 'pop-to-mark-command) - (progn - (message "No back location available") - nil))) - -(defun ss-jump-forward () - "Move forward through navigation history." - (interactive) - (or (ss-navigation--jump-from-stack - 'ss-navigation-forward-stack - 'ss-navigation-back-stack) - (progn - (message "No forward location available") - nil))) - -(defun ss-navigation--record-jump (original &rest args) - "Record the pre-jump location around ORIGINAL with ARGS." - (if ss-navigation--inhibit-recording - (apply original args) - (let ((before (ss-navigation--current-location)) - result) - (setq result (apply original args)) - (let ((after (ss-navigation--current-location))) - (when (and (ss-navigation--location-valid-p before) - (ss-navigation--location-valid-p after) - (not (ss-navigation--same-location-p before after))) - (ss-navigation--push-location - 'ss-navigation-back-stack - before - 'clear-forward))) - result))) - -(defun ss-navigation--advise-command (command) - "Wrap COMMAND so significant jumps record navigation history." - (unless (advice-member-p #'ss-navigation--record-jump command) - (advice-add command :around #'ss-navigation--record-jump))) - -(defun ss-navigation-setup () - "Install navigation history advice for note-related jump commands." - (dolist (command '(ss-open-journal - ss-open-journal-today-session - ss-open-journal-full - ss-open-moc)) - (ss-navigation--advise-command command)) - (with-eval-after-load 'org - (ss-navigation--advise-command 'org-open-at-point)) - (with-eval-after-load 'org-agenda - (dolist (command '(org-agenda-goto - org-agenda-switch-to - org-agenda-open-link)) - (ss-navigation--advise-command command))) - (with-eval-after-load 'denote - (ss-navigation--advise-command 'denote-open-or-create)) - (with-eval-after-load 'ss-crm - (dolist (command '(ss-crm-find - ss-crm-open - ss-crm-overview)) - (ss-navigation--advise-command command)))) - -(defvar ss-journal-session-mode-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-c C-c") #'ss-journal-session-save-and-dismiss) - (define-key map (kbd "C-c C-k") #'ss-journal-session-dismiss) - map) - "Keymap for focused journal editing sessions.") - -(defconst ss-journal-session-header-line - "Journal session: C-c C-c save and dismiss, C-c C-k dismiss" - "Header line shown during focused journal editing sessions.") - -(define-minor-mode ss-journal-session-mode - "Minor mode for focused journal editing sessions." - :lighter " Journal-Session" - :keymap ss-journal-session-mode-map - (if ss-journal-session-mode - (setq-local header-line-format ss-journal-session-header-line) - (kill-local-variable 'header-line-format))) - -(defun ss-journal-session-dismiss () - "End the focused journal session without saving automatically." - (interactive) - (widen) - (ss-journal-session-mode -1) - (quit-window nil (selected-window))) - -(defun ss-journal-session-save-and-dismiss () - "Save the journal buffer, then end the focused journal session." - (interactive) - (save-buffer) - (ss-journal-session-dismiss)) - -(defun ss-open-journal () - "Open today's journal entry in a focused session, creating it when needed." - (interactive) - (ss-open-journal-today-session)) - -(defun ss-open-journal-today-session () - "Open today's journal entry in a focused, dismissable session." - (interactive) - (find-file (ss-require-existing-file ss-journal-file)) - (widen) - (unless (fboundp 'ss-journal-goto-date) - (user-error "Journal date navigation is unavailable")) - (ss-journal-goto-date nil 'create) - (when (fboundp 'ss-journal-ensure-day-sections) - (ss-journal-ensure-day-sections)) - (org-fold-show-entry) - (org-fold-show-subtree) - (org-narrow-to-subtree) - (ss-journal-session-mode 1)) - -(defun ss-open-journal-full () - "Open `ss-journal-file' with the full buffer visible." - (interactive) - (find-file (ss-require-existing-file ss-journal-file)) - (widen)) - -(defun ss-open-moc () - "Open the central MOC note." - (interactive) - (find-file (ss-require-existing-file ss-moc-file))) - -(defun ss-org-refresh-agenda-files-for-refile (&rest _args) - "Refresh `org-agenda-files' before refile when agenda setup is available." - (when (fboundp 'ss-refresh-org-agenda-files) - (ss-refresh-org-agenda-files))) - -(defun ss-org-configure-refile () - "Configure Org refile to target any heading in `org-agenda-files'." - (setq org-refile-targets '((org-agenda-files :regexp . "^\\*+ ")) - org-refile-use-outline-path 'file - org-outline-path-complete-in-steps nil) - (unless (advice-member-p #'ss-org-refresh-agenda-files-for-refile #'org-refile) - (advice-add 'org-refile :before #'ss-org-refresh-agenda-files-for-refile))) - -(defun ss-org-setup () - "Initialize base Org configuration." - (use-package org - :ensure nil - :config - (setq org-directory ss-org-directory - org-catch-invisible-edits 'error - org-hide-emphasis-markers t - org-agenda-search-headline-for-time t - org-agenda-custom-commands - '( - ("d" "Daily Agenda" - ((agenda "") - (todo "CLARIFY" - ((org-agenda-overriding-header "Open Questions")))))) - org-todo-keywords - '((sequence "TODO(t)" "CLARIFY(c)" "WAIT(w@/!)" "|" - "DONE(d)" "CANCELLED(x@)")) - org-log-done 'note - org-log-into-drawer t) - (ss-org-configure-refile) - (add-hook 'org-mode-hook - (lambda () - (setq-local org-hide-emphasis-markers t) - (when (fboundp 'olivetti-mode) - (olivetti-mode 1)) - (font-lock-flush) - (font-lock-ensure)))) - - (use-package git-auto-commit-mode - :ensure t - :pin melpa - :commands (git-auto-commit-mode) - :init - (setq gac-shell-and - (if (string-match-p "fish\\'" shell-file-name) - " ; and " - " && "))) - - (add-hook 'emacs-startup-hook - (lambda () - (find-file (ss-require-existing-file ss-moc-file)))) - - (ss-navigation-setup)) - -(provide 'ss-org) - -;;; ss-org.el ends here |
