From 5d89b6dd237ea73c9dad8ad991065b3e6d2ceda2 Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Thu, 29 May 2025 20:41:04 +0200 Subject: [PATCH] Move Org related functions from configuration.org to lisp/gpolonkai/org-utils.el --- configuration.org | 162 --------------------------------- init.el | 1 + lisp/gpolonkai/org-utils.el | 175 ++++++++++++++++++++++++++++++++++++ 3 files changed, 176 insertions(+), 162 deletions(-) create mode 100644 lisp/gpolonkai/org-utils.el diff --git a/configuration.org b/configuration.org index c8881f1..d09b354 100644 --- a/configuration.org +++ b/configuration.org @@ -2,168 +2,6 @@ This is a collection of functions and commands i wrote or stole from all around the internet. -** Org-mode related - -*** Wrapper around ~org-agenda~ to open my own custom list - -#+begin_src emacs-lisp -(defun gpolonkai/org-agenda-list (&optional arg) - (interactive "P") - (org-agenda arg "c")) -#+end_src - -*** Insert the current timestamp - -#+begin_src emacs-lisp -(defun gpolonkai/org-insert-current-timestamp (&optional arg) - "Insert the current timestamp" - (interactive "P") - (org-time-stamp '(16) arg)) -#+end_src - -*** Insert two spaces after certain marks - -#+begin_src emacs-lisp -(defcustom gpolonkai/org-dbl-space-punct-marks (list ?. ?! ?? ?…) - "Punctuation marks after which the space key should insert two space characters." - :type '(set character)) - -(defun gpolonkai/org-space-key (&optional arg) - "Insert two spaces after certain markers. - -ARG will be passed down verbatim to `self-insert-command'." - (interactive "p") - - (when (and - (not (org-in-block-p '("src"))) - (looking-back (rx-to-string `(any,@ gpolonkai/org-dbl-space-punct-marks)) nil)) - (call-interactively 'self-insert-command arg)) - (call-interactively 'self-insert-command arg)) -#+end_src - -*** Filter out tasks from the Org agenda if they have a specific priority - -The whole idea comes from [[https://blog.aaronbieber.com/2016/09/24/an-agenda-for-life-with-org-mode.html][here]] which i use almost verbatim, hence the ~air-~ prefix. - -#+begin_src emacs-lisp -(defun air-org-skip-subtree-if-priority (priority) - "Skip an agenda subtree if it has a priority of PRIORITY. - -PRIORITY may be one of the characters ?A, ?B, or ?C." - (let ((subtree-end (save-excursion (org-end-of-subtree t))) - (pri-value (* 1000 (- org-lowest-priority priority))) - (pri-current (org-get-priority (thing-at-point 'line t)))) - (if (= pri-value pri-current) - subtree-end - nil))) -#+end_src - -*** Filter out habits from the Org agenda - -#+begin_src emacs-lisp -(defun air-org-skip-subtree-if-habit () - "Skip an agenda entry if it has a STYLE property equal to \"habit\"." - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (if (string= (org-entry-get nil "STYLE") "habit") - subtree-end - nil))) -#+end_src - -*** Filter out entries from the Org agenda with a specific state - -#+begin_src emacs-lisp -(defun gpolonkai/org-skip-subtree-if-state (state) - "Skip an agenda entry if its state is STATE." - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (if (string= (org-get-todo-state) state) - subtree-end - nil))) -#+end_src - -*** Insert a heading with CREATED set to the current time - -This emulates how Orgzly work with my current settings. - -#+begin_src emacs-lisp -(defun gpolonkai/org-insert-heading-created (&optional arg) - (interactive "p") - (let* ((org-insert-heading-respect-content t) - (format-string (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]")) - (timestamp (format-time-string format-string (current-time)))) - (if (> arg 1) - (org-insert-subheading '(4)) - (org-insert-heading)) - (org-set-property "CREATED" timestamp))) -#+end_src - -*** Unfold everything during ~ediff~ sessions - -EDiff and Org-mode files don’t play nice together… - -From [[https://list.orgmode.org/loom.20130801T011342-572@post.gmane.org/][the org-mode mailing list]]. - -#+begin_src emacs-lisp -(defun f-ediff-org-showhide (buf command &rest cmdargs) - "If buffer BUF exists and in `org-mode', execute COMMAND with CMDARGS." - (when buf - (when (eq (buffer-local-value 'major-mode (get-buffer buf)) 'org-mode) - (save-excursion - (set-buffer buf) - (apply command cmdargs))))) - -(defun f-ediff-org-unfold-tree-element () - "Unfold tree at diff location." - (f-ediff-org-showhide ediff-buffer-A 'org-reveal) - (f-ediff-org-showhide ediff-buffer-B 'org-reveal) - (f-ediff-org-showhide ediff-buffer-C 'org-reveal)) - -(defun f-ediff-org-fold-tree () - "Fold tree back to top level." - (f-ediff-org-showhide ediff-buffer-A 'hide-sublevels 1) - (f-ediff-org-showhide ediff-buffer-B 'hide-sublevels 1) - (f-ediff-org-showhide ediff-buffer-C 'hide-sublevels 1)) -#+end_src - -*** Add code references to Org documents - -From the [[http://www.howardism.org/Technical/Emacs/capturing-content.html][Howardism blog]]. - -#+begin_src emacs-lisp -(defun ha/org-capture-fileref-snippet (f type headers func-name) - (let* ((code-snippet - (buffer-substring-no-properties (mark) (- (point) 1))) - (file-name (buffer-file-name)) - (file-base (file-name-nondirectory file-name)) - (line-number (line-number-at-pos (region-beginning))) - (initial-txt (if (null func-name) - (format "From [[file:%s::%s][%s]]:" - file-name line-number file-base) - (format "From ~%s~ (in [[file:%s::%s][%s]]):" - func-name file-name line-number - file-base)))) - (format " - %s - - ,#+begin_%s %s -%s - ,#+end_%s" initial-txt type headers code-snippet type))) - -(defun ha/org-capture-clip-snippet (f) - "Given a file, F, this captures the currently selected text -within an Org EXAMPLE block and a backlink to the file." - (with-current-buffer (find-buffer-visiting f) - (ha/org-capture-fileref-snippet f "example" "" nil))) - -(defun ha/org-capture-code-snippet (f) - "Given a file, F, this captures the currently selected text -within an Org SRC block with a language based on the current mode -and a backlink to the function and the file." - (with-current-buffer (find-buffer-visiting f) - (let ((org-src-mode (replace-regexp-in-string "-mode" "" (format "%s" major-mode))) - (func-name (which-function))) - (ha/org-capture-fileref-snippet f "src" org-src-mode func-name)))) -#+end_src - ** Text manipulation *** Fill or unfill a paragraph diff --git a/init.el b/init.el index 6b002c0..18da6d2 100644 --- a/init.el +++ b/init.el @@ -59,6 +59,7 @@ ;; Custom functions and commands (load "gpolonkai/utilities") (load "gpolonkai/windows") +(load "gpolonkai/org-utils") ;; I started moving my configuration to this Org file. It’s easier to document this way. (org-babel-load-file (expand-file-name "configuration.org" user-emacs-directory)) diff --git a/lisp/gpolonkai/org-utils.el b/lisp/gpolonkai/org-utils.el new file mode 100644 index 0000000..7a6c296 --- /dev/null +++ b/lisp/gpolonkai/org-utils.el @@ -0,0 +1,175 @@ +;;; gpolonkai/org-utils.el --- Org-mode related functions +;;; +;;; SPDX-License-Identifier: GPL-3.0-or-later +;;; Copyright © 2025 Gergely Polonkai +;;; This library is free software; you can redistribute it and/or +;;; modify it under the terms of the GNU Lesser General Public +;;; License as published by the Free Software Foundation; either +;;; version 3 of the License, or (at your option) any later version. +;;; +;;; This library is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;;; Lesser General Public License for more details. +;;; +;;; You should have received a copy of the GNU Lesser General Public +;;; License along with this library; if not, write to the +;;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;;; Boston, MA 02111-1307, USA. +;;; +;;; Commentary: +;;; +;;; Utility functions stolen from the Internet or written by me +;;; +;;; Code: + +(defun gpolonkai/org-agenda-list (&optional arg) + "Wrapper around `org-agenda' to open my custom list. + +ARG is passed verbatim to `org-agenda'." + (interactive "P") + (org-agenda arg "c")) + +(defun gpolonkai/org-insert-current-timestamp (&optional arg) + "Insert the current timestamp. + +ARG is passed verbatim to `org-time-stamp'." + (interactive "P") + (org-time-stamp '(16) arg)) + +(defcustom gpolonkai/org-dbl-space-punct-marks (list ?. ?! ?? ?…) + "Punctuation marks after which the space key should insert two space characters." + :type '(set character)) + +(defun gpolonkai/org-space-key (&optional arg) + "Insert two spaces after certain markers. + +ARG will be passed down verbatim to `self-insert-command'." + (interactive "p") + + (when (and + (not (org-in-block-p '("src"))) + (looking-back (rx-to-string `(any,@ gpolonkai/org-dbl-space-punct-marks)) nil)) + (call-interactively 'self-insert-command arg)) + (call-interactively 'self-insert-command arg)) + +;; The whole idea comes from https://blog.aaronbieber.com/2016/09/24/an-agenda-for-life-with-org-mode.html +;; which i use almost verbatim, hence the ~air-~ prefix. +(defun air-org-skip-subtree-if-priority (priority) + "Skip an agenda subtree if it has a priority of PRIORITY. + +PRIORITY may be one of the characters ?A, ?B, or ?C." + (let ((subtree-end (save-excursion (org-end-of-subtree t))) + (pri-value (* 1000 (- org-lowest-priority priority))) + (pri-current (org-get-priority (thing-at-point 'line t)))) + (if (= pri-value pri-current) + subtree-end + nil))) + +(defun air-org-skip-subtree-if-habit () + "Skip an agenda entry if it has a STYLE property equal to \"habit\"." + (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + (if (string= (org-entry-get nil "STYLE") "habit") + subtree-end + nil))) + +(defun gpolonkai/org-skip-subtree-if-state (state) + "Skip an agenda entry if its state is STATE." + (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + (if (string= (org-get-todo-state) state) + subtree-end + nil))) + +(defun gpolonkai/org-insert-heading-created (&optional arg) + "Insert a heading with the CREATED property set to the current time. + +This emulates how Orgzly works. + +If ARG is set, insert a subheading; otherwise insert a heading." + (interactive "p") + (let* ((org-insert-heading-respect-content t) + (format-string (concat "[" (substring (cdr org-time-stamp-formats) 1 -1) "]")) + (timestamp (format-time-string format-string (current-time)))) + (if (> arg 1) + (org-insert-subheading '(4)) + (org-insert-heading)) + (org-set-property "CREATED" timestamp))) + +;; The following functions, prefixed with `f-ediff', are from the org-mode mailing list (see archive +;; at https://list.orgmode.org/loom.20130801T011342-572@post.gmane.org/). + +(defun f-ediff-org-showhide (buf command &rest cmdargs) + "If buffer BUF exists and in `org-mode', execute COMMAND with CMDARGS." + (when buf + (when (eq (buffer-local-value 'major-mode (get-buffer buf)) 'org-mode) + (save-excursion + (set-buffer buf) + (apply command cmdargs))))) + +(defun f-ediff-org-unfold-tree-element () + "Unfold tree at diff location." + (f-ediff-org-showhide ediff-buffer-A 'org-reveal) + (f-ediff-org-showhide ediff-buffer-B 'org-reveal) + (f-ediff-org-showhide ediff-buffer-C 'org-reveal)) + +(defun f-ediff-org-fold-tree () + "Fold tree back to top level." + (f-ediff-org-showhide ediff-buffer-A 'hide-sublevels 1) + (f-ediff-org-showhide ediff-buffer-B 'hide-sublevels 1) + (f-ediff-org-showhide ediff-buffer-C 'hide-sublevels 1)) + +;; From the Howardism blog: http://www.howardism.org/Technical/Emacs/capturing-content.html + +(defun ha/org-capture-fileref-snippet (f type headers func-name) + "Capture a snippet from a file, with the filename and the location within. + +F is the name of the file the capture is coming from. + +TYPE is the type of the block to be inserted (e.g. \"src\"). + +HEADERS are the headers appended to the block's #begin line (usually starting +with the language’s mode). + +FUNC-NAME is the name of the function point is in, if any." + (let* ((code-snippet + (buffer-substring-no-properties (mark) (- (point) 1))) + (file-name (buffer-file-name)) + (file-base (file-name-nondirectory file-name)) + (line-number (line-number-at-pos (region-beginning))) + (initial-txt (if (null func-name) + (format "From [[file:%s::%s][%s]]:" + file-name line-number file-base) + (format "From ~%s~ (in [[file:%s::%s][%s]]):" + func-name file-name line-number + file-base)))) + (format " + %s + + ,#+begin_%s %s +%s + ,#+end_%s" initial-txt type headers code-snippet type))) + +(defun ha/org-capture-clip-snippet (f) + "Capture the selected text as an EXAMPLE block. + +The captured text also contains a backlink to the file. + +F is the file the capture is coming from." + (with-current-buffer (find-buffer-visiting f) + (ha/org-capture-fileref-snippet f "example" "" nil))) + +(defun ha/org-capture-code-snippet (f) + "Capture the selected text as an SRC block. + +The captured block will have the correct language set, and contains a backlink +to the file. + +F is the file the capture is coming from." + (with-current-buffer (find-buffer-visiting f) + (let ((org-src-mode (replace-regexp-in-string "-mode" "" (format "%s" major-mode))) + (func-name (which-function))) + (ha/org-capture-fileref-snippet f "src" org-src-mode func-name)))) + +(provide 'gpolonkai/org-utils) + +;;; org-utils.el ends here