mirror of
https://github.com/pestctrl/emacs-config.git
synced 2026-02-16 16:24:18 +00:00
276 lines
11 KiB
EmacsLisp
276 lines
11 KiB
EmacsLisp
;;; org-process.el --- Some useful functions cutting down big piles of stuff in org mode -*- lexical-binding: t -*-
|
|
|
|
;; Copyright (C) 2019 Benson Chu
|
|
|
|
;; Author: Benson Chu <bensonchu457@gmail.com>
|
|
;; Created: <2019-12-05 Thu>
|
|
|
|
;; This file is not part of GNU Emacs.
|
|
|
|
;; This program is free software: you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
;; (at your option) any later version.
|
|
|
|
;; This program 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 General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
;;; Commentary:
|
|
|
|
;; These functions help me slash a huge subtree that is ungodly awful to handle.
|
|
;; It helps me quickly sort through a huge subtree that has received no attention
|
|
;; for a while. Quick way to jump-start the cleaning process.
|
|
|
|
;;; Code:
|
|
|
|
(require 'cl)
|
|
(require 'org)
|
|
(require 'org-loop)
|
|
|
|
;; Utilities that will help with the rest of the code.
|
|
|
|
(defun get-random-uuid ()
|
|
(replace-regexp-in-string "\n$" ""
|
|
(shell-command-to-string "uuidgen")))
|
|
|
|
(defun op/refile-to-location (file headline)
|
|
(let ((pos (save-excursion
|
|
(find-file file)
|
|
(org-find-exact-headline-in-buffer headline))))
|
|
(org-refile nil nil (list headline file nil pos))))
|
|
|
|
(defun op/refile-to-point (file point)
|
|
(org-refile nil nil (list nil file nil point)))
|
|
|
|
(defun op/lenient-y-or-n-p (prompt)
|
|
"Prompt a `y-or-n-p' with prompt `PROMPT', but allow for actions to be taken in X-windows."
|
|
(save-excursion
|
|
(let ((query-replace-map (copy-keymap query-replace-map)))
|
|
(define-key query-replace-map [t] 'skip)
|
|
(y-or-n-p prompt))))
|
|
|
|
|
|
;; Actual user functions
|
|
|
|
(defun process-youtube-headline ()
|
|
(interactive)
|
|
(op/org-add-tag "watch")
|
|
(save-window-excursion
|
|
(save-excursion
|
|
(if (op/lenient-y-or-n-p "Educational?")
|
|
(progn (org-todo)
|
|
(op/org-add-tag
|
|
(if (op/lenient-y-or-n-p "short?")
|
|
"short"
|
|
"long"))
|
|
(op/org-add-tag "grow")
|
|
(op/refile-to-location (my/agenda-file "sandbox.org")
|
|
"Educational Youtube Videos"))
|
|
(org-todo "TODO")
|
|
(op/org-add-tag "rest")
|
|
(op/refile-to-location (my/agenda-file "eternal.org")
|
|
"Entertaining YouTube Videos")))))
|
|
|
|
(defun op/insert-category-heading (point heading-name)
|
|
(let* ((uuid (get-random-uuid))
|
|
(new-heading (concat heading-name
|
|
": "
|
|
uuid))
|
|
(condition (= point (point))))
|
|
(prog1
|
|
(save-excursion
|
|
(goto-char point)
|
|
(org-insert-heading)
|
|
(insert new-heading)
|
|
(my/org-add-tag "sorting")
|
|
(beginning-of-line)
|
|
(forward-char)
|
|
(point-marker))
|
|
(when condition
|
|
(outline-next-heading)))))
|
|
|
|
;; (defun op/refile-quick-sort ()
|
|
;; (interactive)
|
|
;; (find-file (my/agenda-file "refile.org"))
|
|
;; (goto-char (point-min))
|
|
;; (outline-next-heading)
|
|
;; (let* ((youtube-marker (op/insert-category-heading "Youtube Videos"))
|
|
;; (reddit-marker (op/insert-category-heading "Reddit Things")))
|
|
;; (while
|
|
;; (progn
|
|
;; (org-copy-subtree)
|
|
;; (let ((tree-string (current-kill 0)))
|
|
;; (cond ((or (string-match-p "Watch \"" tree-string)
|
|
;; (string-match-p "youtube\.com/" tree-string)
|
|
;; (string-match-p "youtu\.be/" tree-string))
|
|
;; (op/refile-to-point (buffer-file-name) youtube-marker))
|
|
;; ((or (string-match-p "reddit\.com" tree-string)
|
|
;; (string-match-p "redd\.it" tree-string))
|
|
;; (op/refile-to-point (buffer-file-name) reddit-marker))
|
|
;; (t (outline-next-heading))))))))
|
|
|
|
(defun op/refile-quick-sort ()
|
|
(interactive)
|
|
(goto-char (point-min))
|
|
(let ((beg (ol/get-bot-marker)))
|
|
(outline-next-heading)
|
|
(let* ((other-marker (op/insert-category-heading beg "Other"))
|
|
(youtube-marker (op/insert-category-heading beg "Youtube Videos"))
|
|
(reddit-marker (op/insert-category-heading beg "Reddit Things")))
|
|
(olsb/children
|
|
(org-copy-subtree)
|
|
(let ((tree-string (current-kill 0)))
|
|
(cond ((and (member "sorting" (org-get-tags-at (point)))
|
|
(let ((heading-text (org-get-heading)))
|
|
(not (remove-if-not (lambda (regex)
|
|
(string-match-p regex heading-text))
|
|
'("Reddit Things: " "Youtube Videos: " "Other: ")))))
|
|
nil)
|
|
((or (string-match-p "Watch \"" tree-string)
|
|
(string-match-p "youtube\.com/" tree-string)
|
|
(string-match-p "youtu\.be/" tree-string))
|
|
(op/refile-to-point (buffer-file-name) youtube-marker))
|
|
((or (string-match-p "reddit\.com" tree-string)
|
|
(string-match-p "redd\.it" tree-string))
|
|
(op/refile-to-point (buffer-file-name) reddit-marker))
|
|
(t
|
|
(op/refile-to-point (buffer-file-name) other-marker)))))
|
|
(dolist (regex '("Reddit Things: " "Youtube Videos: " "Other: "))
|
|
(goto-char (point-min))
|
|
(when (search-forward (concat "** " regex))
|
|
(my/org-delete-promote))))))
|
|
|
|
(defun op/org-sort-subtree ()
|
|
(interactive)
|
|
(let ((db '((1-undecided . nil)))
|
|
(beg (ol/get-bot-marker))
|
|
(path (org-get-outline-path t)))
|
|
(org-set-tags (delete "sorting" (org-get-tags nil t)))
|
|
(ols/children
|
|
(if (member "sorting" (org-get-tags (point) t))
|
|
(let* ((heading (org-get-heading t t t t))
|
|
(index-of (string-match-p ":" heading))
|
|
(category (intern (substring heading 0 index-of))))
|
|
(forward-char)
|
|
(setf (alist-get category db)
|
|
(point-marker))
|
|
nil)
|
|
(let* ((category-name (ivy-completing-read "Category? " (sort (mapcar #'car db) #'ivy-string<)))
|
|
(category (intern category-name))
|
|
(entry (assoc category db)))
|
|
(unless entry ;; New category!
|
|
(let ((refile-location (op/insert-category-heading beg category-name)))
|
|
(setf (alist-get category db)
|
|
refile-location)))
|
|
(when-let (location (alist-get category db))
|
|
(op/refile-to-point (buffer-file-name) location)))))))
|
|
|
|
(use-exwm
|
|
:config
|
|
(require 'fireorg)
|
|
|
|
(defun op/youtube-loop ()
|
|
(interactive)
|
|
(let ((ff (get-buffer "fireorg")))
|
|
(if (null ff)
|
|
(progn
|
|
(fireorg/make-fireorg-window)
|
|
(run-with-timer 4 nil 'op/youtube-loop))
|
|
(let ((org (find-file-noselect (my/agenda-file "refile.org"))))
|
|
(fireorg/setup org ff
|
|
;; Goto youtube node
|
|
(beginning-of-buffer)
|
|
(search-forward "Youtube Videos: ")
|
|
(org-back-to-heading)
|
|
;; Loop through the children
|
|
(ol/children
|
|
(fireorg/open-link ff
|
|
(when (op/lenient-y-or-n-p "Refile this one?")
|
|
(process-youtube-headline)
|
|
(org-get-last-sibling)))))))))
|
|
|
|
(defun op/get-rid-of-entertaining-youtube-videos ()
|
|
(interactive)
|
|
(let ((ff (get-buffer "fireorg")))
|
|
(if (null ff)
|
|
(progn
|
|
(fireorg/make-fireorg-window)
|
|
(run-with-timer 4 nil 'op/get-rid-of-entertaining-youtube-videos))
|
|
(let ((org (find-file-noselect (my/agenda-file "refile.org"))))
|
|
(fireorg/setup org ff
|
|
(beginning-of-buffer)
|
|
(search-forward "Youtube Videos: ")
|
|
(org-back-to-heading)
|
|
|
|
(ol/children
|
|
(fireorg/open-link ff
|
|
(when (not (op/lenient-y-or-n-p "Educational?"))
|
|
(save-excursion
|
|
(save-window-excursion
|
|
(op/org-add-tag "watch")
|
|
(org-todo "TODO")
|
|
(op/org-add-tag "rest")
|
|
(op/refile-to-location (my/agenda-file "eternal.org")
|
|
"Entertaining YouTube Videos")))
|
|
(org-get-last-sibling)))))))))
|
|
|
|
(defun fireorg/org-sort-subtree (org)
|
|
(interactive (list (current-buffer)))
|
|
(let ((ff (get-buffer "fireorg")))
|
|
(if (null ff)
|
|
(progn
|
|
(fireorg/make-fireorg-window)
|
|
(run-with-timer 4 nil 'fireorg/org-sort-subtree org))
|
|
(fireorg/setup org ff
|
|
(let ((db '((1-undecided . nil)))
|
|
(beg (ol/get-bot-marker))
|
|
(path (org-get-outline-path t)))
|
|
(org-set-tags (delete "sorting" (org-get-tags nil t)))
|
|
(ols/children
|
|
(if (member "sorting" (org-get-tags))
|
|
(let* ((heading (org-get-heading t t t t))
|
|
(index-of (string-match-p ":" heading))
|
|
(category (intern (substring heading 0 index-of))))
|
|
(forward-char)
|
|
(setf (alist-get category db)
|
|
(point-marker))
|
|
nil)
|
|
(fireorg/open-link ff
|
|
(let* ((category-name (completing-read "Category? " (sort (mapcar #'car db) #'ivy-string<)))
|
|
(category (intern category-name))
|
|
(entry (assoc category db)))
|
|
(unless entry ;; New category!
|
|
(let ((refile-location (op/insert-category-heading beg category-name)))
|
|
(setf (alist-get category db)
|
|
refile-location)))
|
|
(prog1 (when-let (location (alist-get category db))
|
|
(op/refile-to-point (buffer-file-name) location))
|
|
(recenter))))))))))))
|
|
|
|
;; (defun op/open-loop ()
|
|
;; (interactive)
|
|
;; (let* ((ff-buffer (or (get-buffer "fireorg")
|
|
;; (ivy-read "Firefox Buffer: " #'internal-complete-buffer
|
|
;; :keymap ivy-switch-buffer-map
|
|
;; :preselect (buffer-name (other-buffer (current-buffer)))
|
|
;; :matcher #'ivy--switch-buffer-matcher)))
|
|
;; (id (with-current-buffer ff-buffer exwm--id)))
|
|
;; (while t
|
|
;; (let ((url (->> (org-offer-links-in-entry (current-buffer) (point) 0)
|
|
;; (car)
|
|
;; (get-text-property 0 'htmlize-link)
|
|
;; (cadr))))
|
|
;; (start-process-shell-command "refile-open" nil (format "firefox -P youtube \"%s\"" url))
|
|
;; (switch-window)
|
|
;; (op/lenient-y-or-n-p "Next")
|
|
;; (switch-window))
|
|
;; (org-end-of-subtree t t)
|
|
;; (exwm-background/exwm-input--fake-key-to-window id ?\C-w))))
|
|
|
|
(provide 'org-process)
|
|
;; org-process.el ends here
|