my-emacs-d/lisp/gpolonkai/org-utils.el

176 lines
6.5 KiB
EmacsLisp
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; 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 languages 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