summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.el76
-rw-r--r--config.org76
2 files changed, 144 insertions, 8 deletions
diff --git a/config.el b/config.el
index 580039a..0ef30ef 100644
--- a/config.el
+++ b/config.el
@@ -1468,6 +1468,70 @@ Skips capture tasks and projects."
(defun my/org-capture-meeting-to-journal ()
(my/org-capture-to-journal "\n* Meeting: "))
+(defcustom my/org-capture-project-notes-file "notes.org"
+ "File name for source notes captured at the current project root."
+ :type 'string
+ :group 'org-capture)
+
+(defcustom my/org-capture-source-language-alist
+ '((c-mode . "C")
+ (c-ts-mode . "C")
+ (c++-mode . "C++")
+ (c++-ts-mode . "C++")
+ (emacs-lisp-mode . "emacs-lisp")
+ (js-mode . "js")
+ (js-ts-mode . "js")
+ (shell-mode . "shell")
+ (sh-mode . "shell"))
+ "Exceptional major-mode to Org source language mappings used by project captures.
+Modes not listed here are inferred from `org-src-lang-modes' or their mode name."
+ :type '(alist :key-type symbol :value-type string)
+ :group 'org-capture)
+
+(defun my/org-capture-original-buffer ()
+ "Return the live buffer from which the current capture was invoked."
+ (let ((buffer (org-capture-get :original-buffer)))
+ (unless (buffer-live-p buffer)
+ (user-error "The source buffer for this capture is no longer available"))
+ buffer))
+
+(defun my/org-capture-project-notes-path ()
+ "Return the project-root notes file for the current capture."
+ (with-current-buffer (my/org-capture-original-buffer)
+ (let ((root (or (and (fboundp 'projectile-project-root)
+ (ignore-errors (projectile-project-root)))
+ (when-let* ((project (project-current nil default-directory)))
+ (project-root project)))))
+ (unless root
+ (user-error "Cannot capture source note outside a recognized project"))
+ (expand-file-name my/org-capture-project-notes-file root))))
+
+(defun my/org-capture-source-language ()
+ "Return the Org source language for the current capture's source buffer."
+ (with-current-buffer (my/org-capture-original-buffer)
+ (or (alist-get major-mode my/org-capture-source-language-alist)
+ (cl-loop for (language . mode) in org-src-lang-modes
+ for mode-function = (intern (format "%s-mode" mode))
+ when (derived-mode-p mode-function)
+ return (format "%s" language))
+ (string-remove-suffix
+ "-mode"
+ (string-remove-suffix "-ts-mode" (symbol-name major-mode))))))
+
+(defun my/org-capture-source-link ()
+ "Return a file link to the first source line of the current capture."
+ (with-current-buffer (my/org-capture-original-buffer)
+ (unless buffer-file-name
+ (user-error "Cannot link a capture from a buffer without a file"))
+ (let* ((position (if (and (org-capture-get :initial) (mark t))
+ (min (point) (mark t))
+ (point)))
+ (line (line-number-at-pos position t))
+ (file (abbreviate-file-name buffer-file-name)))
+ (org-link-make-string
+ (format "file:%s::%d" file line)
+ (format "%s:%d" (file-name-nondirectory file) line)))))
+
(defun my/org-capture-task-to-journal ()
(let* ((context (read-string "Task: "))
(todo-state (completing-read "TODO state: "
@@ -1512,7 +1576,11 @@ Skips capture tasks and projects."
"" :immediate-finish t :jump-to-captured t)
("m" "Meeting" plain
(function my/org-capture-meeting-to-journal)
- "" :immediate-finish nil :jump-to-captured t))))
+ "" :immediate-finish nil :jump-to-captured t)
+ ("p" "Project source TODO" entry
+ (file+headline my/org-capture-project-notes-path "Inbox")
+ "* TODO %?\n\n#+begin_src %(my/org-capture-source-language)\n%i\n#+end_src\n\n%(my/org-capture-source-link)"
+ :prepend t :empty-lines 1))))
(use-package org-super-agenda
:ensure t
@@ -4436,7 +4504,7 @@ locally. Note: entries no longer present on the server are lost."
(setq browse-url-browser-function 'eww-browse-url
browse-url-secondary-browser-function 'browse-url-generic
- browse-url-generic-program "qutebrowser")
+ browse-url-generic-program "helium-browser")
(defun my/browse-url-no-frame-guard (orig url &rest args)
"Around-advice for `browse-url' that resolves and calls the handler
@@ -4966,7 +5034,7 @@ opening another file in same project does not re-notify."
:ensure nil
:commands (rsync-ui rsync-ui-dired))
-(defun rlr/org-export-html-to-browser ()
+(defun my/org-export-html-to-browser ()
"Export the current Org buffer to a temporary HTML file in the system temp directory, open it, and then delete it when Emacs is killed."
(interactive)
(unless (derived-mode-p 'org-mode)
@@ -4982,7 +5050,7 @@ opening another file in same project does not re-notify."
(lambda () (ignore-errors (delete-file tmp))))
(funcall browse-url-secondary-browser-function
(browse-url-file-url tmp))))
-(defvar rlr/org-preview-css "
+(defvar my/org-preview-css "
<style>
:root { color-scheme: light dark; }
body {
diff --git a/config.org b/config.org
index 682fdf6..d664e72 100644
--- a/config.org
+++ b/config.org
@@ -1726,6 +1726,70 @@ Skips capture tasks and projects."
*** org-capture combined with denote
#+begin_src emacs-lisp
+(defcustom my/org-capture-project-notes-file "notes.org"
+ "File name for source notes captured at the current project root."
+ :type 'string
+ :group 'org-capture)
+
+(defcustom my/org-capture-source-language-alist
+ '((c-mode . "C")
+ (c-ts-mode . "C")
+ (c++-mode . "C++")
+ (c++-ts-mode . "C++")
+ (emacs-lisp-mode . "emacs-lisp")
+ (js-mode . "js")
+ (js-ts-mode . "js")
+ (shell-mode . "shell")
+ (sh-mode . "shell"))
+ "Exceptional major-mode to Org source language mappings used by project captures.
+Modes not listed here are inferred from `org-src-lang-modes' or their mode name."
+ :type '(alist :key-type symbol :value-type string)
+ :group 'org-capture)
+
+(defun my/org-capture-original-buffer ()
+ "Return the live buffer from which the current capture was invoked."
+ (let ((buffer (org-capture-get :original-buffer)))
+ (unless (buffer-live-p buffer)
+ (user-error "The source buffer for this capture is no longer available"))
+ buffer))
+
+(defun my/org-capture-project-notes-path ()
+ "Return the project-root notes file for the current capture."
+ (with-current-buffer (my/org-capture-original-buffer)
+ (let ((root (or (and (fboundp 'projectile-project-root)
+ (ignore-errors (projectile-project-root)))
+ (when-let* ((project (project-current nil default-directory)))
+ (project-root project)))))
+ (unless root
+ (user-error "Cannot capture source note outside a recognized project"))
+ (expand-file-name my/org-capture-project-notes-file root))))
+
+(defun my/org-capture-source-language ()
+ "Return the Org source language for the current capture's source buffer."
+ (with-current-buffer (my/org-capture-original-buffer)
+ (or (alist-get major-mode my/org-capture-source-language-alist)
+ (cl-loop for (language . mode) in org-src-lang-modes
+ for mode-function = (intern (format "%s-mode" mode))
+ when (derived-mode-p mode-function)
+ return (format "%s" language))
+ (string-remove-suffix
+ "-mode"
+ (string-remove-suffix "-ts-mode" (symbol-name major-mode))))))
+
+(defun my/org-capture-source-link ()
+ "Return a file link to the first source line of the current capture."
+ (with-current-buffer (my/org-capture-original-buffer)
+ (unless buffer-file-name
+ (user-error "Cannot link a capture from a buffer without a file"))
+ (let* ((position (if (and (org-capture-get :initial) (mark t))
+ (min (point) (mark t))
+ (point)))
+ (line (line-number-at-pos position t))
+ (file (abbreviate-file-name buffer-file-name)))
+ (org-link-make-string
+ (format "file:%s::%d" file line)
+ (format "%s:%d" (file-name-nondirectory file) line)))))
+
(defun my/org-capture-task-to-journal ()
(let* ((context (read-string "Task: "))
(todo-state (completing-read "TODO state: "
@@ -1770,7 +1834,11 @@ Skips capture tasks and projects."
"" :immediate-finish t :jump-to-captured t)
("m" "Meeting" plain
(function my/org-capture-meeting-to-journal)
- "" :immediate-finish nil :jump-to-captured t))))
+ "" :immediate-finish nil :jump-to-captured t)
+ ("p" "Project source TODO" entry
+ (file+headline my/org-capture-project-notes-path "Inbox")
+ "* TODO %?\n\n#+begin_src %(my/org-capture-source-language)\n%i\n#+end_src\n\n%(my/org-capture-source-link)"
+ :prepend t :empty-lines 1))))
#+end_src
** org-super-agenda
@@ -5320,7 +5388,7 @@ locally. Note: entries no longer present on the server are lost."
#+begin_src emacs-lisp
(setq browse-url-browser-function 'eww-browse-url
browse-url-secondary-browser-function 'browse-url-generic
- browse-url-generic-program "qutebrowser")
+ browse-url-generic-program "helium-browser")
#+end_src
** browse-url no-frame guard
@@ -5951,7 +6019,7 @@ Privileged ZFS operations stay non-interactive by default. Unlocking runs authen
* exp
#+begin_src emacs-lisp
-(defun rlr/org-export-html-to-browser ()
+(defun my/org-export-html-to-browser ()
"Export the current Org buffer to a temporary HTML file in the system temp directory, open it, and then delete it when Emacs is killed."
(interactive)
(unless (derived-mode-p 'org-mode)
@@ -5967,7 +6035,7 @@ Privileged ZFS operations stay non-interactive by default. Unlocking runs authen
(lambda () (ignore-errors (delete-file tmp))))
(funcall browse-url-secondary-browser-function
(browse-url-file-url tmp))))
-(defvar rlr/org-preview-css "
+(defvar my/org-preview-css "
<style>
:root { color-scheme: light dark; }
body {