changelog shortlog graph tags branches changeset files revisions annotate raw help

Mercurial > core / emacs/lib/ulang.el

changeset 639: 32375ed43c74
parent: 6c0e4a44c082
child: 642b3b82b20d
author: Richard Westhaver <ellis@rwest.io>
date: Sun, 08 Sep 2024 12:24:33 -0400
permissions: -rw-r--r--
description: org-set-location
1 ;;; ulang.el --- ulang compliance lib -*- lexical-binding:t -*-
2 
3 ;; Copyright (C) 2023
4 
5 ;; Author: <ellis@zor>
6 ;; Keywords: comm
7 
8 ;; This program is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation, either version 3 of the License, or
11 ;; (at your option) any later version.
12 
13 ;; This program is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
17 
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20 
21 ;;; Commentary:
22 
23 ;;
24 
25 
26 ;;; Code:
27 (require 'org)
28 (require 'ox)
29 
30 (defgroup ulang nil
31  "CC Universal Language.")
32 
33 (defvar ulang-link-history nil)
34 (defvar ulang-file-history nil)
35 
36 ;; see org-special-properties
37 (defvar ulang-special-properties
38  '("VERSION"))
39 
40 ;;;###autoload
41 (defun dblock-insert-links (regexp)
42  "Create dblock to insert links matching REGEXP."
43  (interactive (list (read-regexp "Insert links matching: " nil ulang-link-history)))
44  (org-create-dblock (list :name "links"
45  :regexp regexp
46  :id-only nil))
47  (org-update-dblock))
48 
49 (org-dynamic-block-define "links" 'dblock-insert-links)
50 
51 ;; (org-export-translate-to-lang (list '("Table of Contents" "Index")) "ulang")
52 ;; (setq org-export-global-macros nil)
53 
54 ;; todo keywords
55 (setq org-stuck-projects '("+PROJECT/-DONE" ("NEXT") nil ""))
56 
57 (setq org-todo-keywords
58  '((sequence "TBD(0!)" "TODO(t!)" "NEXT(n!)" "WIP(i!)" "|" "DONE(d!)")
59  (sequence "HOLD(H@/!)" "WIP(!)" "|")
60  (sequence "WAIT(W@/!)" "WIP(!)" "|")
61  (sequence "RESEARCH(s!)" "WIP(!)" "REPORT(c!)" "|")
62  (sequence "OUTLINE(O!)" "DRAFT(M!)" "REVIEW(V!)" "|")
63  (sequence "FIXME(f!)" "WIP(!)" "TEST(T!)" "|")
64  (type "FIND(q!)" "READ(r@!)" "WATCH(A@!)" "HACK(h!)"
65  "CODE(c!)" "BENCH(b!)" "DEPLOY(D!)" "RUN(X!)"
66  "REFILE(w!)" "LOG(L!)" "GOTO(g!)" "|")
67  (type "PROJECT(p!)" "PRODUCT(P!)" "SPRINT(S!)" "RELEASE(R!)" "|")
68  (sequence "|" "DONE(d!)" "NOPE(x@!)")))
69 
70 (setq org-todo-keyword-faces
71  '(("PROJECT" . (:foreground "lightseagreen" :weight bold))
72  ("PRODUCT" . (:foreground "olivedrab" :weight bold))
73  ("RELEASE" . (:foreground "maroon3" :weight bold))
74  ("RESEARCH" . (:foreground "maroon2" :weight bold))
75  ("HACK" . (:foreground "maroon3" :weight bold))
76  ("TBD" . (:foreground "brown" :weight bold))
77  ("CODE" . (:foreground "bisque" :weight bold :background "midnightblue"))
78  ("HOLD" . (:foreground "red1" :weight bold :background "yellow1"))
79  ("WAIT" . (:foreground "red4" :weight bold :background "yellow1"))
80  ("WIP" . (:foreground "darkorchid2" :weight bold))
81  ("NOPE" . (:foreground "hotpink" :weight bold :background "darkgreen"))))
82 
83 ;; link abbrevs
84 (setq org-link-abbrev-alist
85  '(("vc" . "https://vc.compiler.company/%s")
86  ("comp" . "https://compiler.company/%s")
87  ("cdn" . "https://cdn.compiler.company/%s")
88  ("packy" . "https://packy.compiler.company/%s")
89  ("yt" . "https://youtube.com/watch?v=%s")
90  ("wikipedia" . "https://en.wikipedia.org/wiki/%s")
91  ("reddit" . "https://reddit.com/%s")
92  ("hn" . "https://news.ycombinator.com/%s")
93  ("so" . "https://stackoverflow.com/%s")))
94 
95 ;;; IDs
96 (defun org-custom-id-get (&optional pom create prefix)
97  "Get the CUSTOM_ID property of the entry at point-or-marker POM.
98  If POM is nil, refer to the entry at point. If the entry does
99  not have an CUSTOM_ID, the function returns nil. However, when
100  CREATE is non nil, create a CUSTOM_ID if none is present
101  already. PREFIX will be passed through to `org-id-new'. In any
102  case, the CUSTOM_ID of the entry is returned."
103  (interactive)
104 (org-with-point-at pom
105  (let ((id (org-entry-get nil "CUSTOM_ID"))
106  ;; use CUSTOM_ID for links
107  (org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id))
108  (cond
109  ((and id (stringp id) (string-match "\\S-" id))
110  id)
111  (create
112  (setq id (org-id-new prefix))
113  (org-entry-put pom "CUSTOM_ID" id)
114  (org-id-add-location id (buffer-file-name (buffer-base-buffer)))
115  id)))))
116 
117 ;;;###autoload
118 (defun org-id-add-to-headlines-in-file ()
119  "Add ID properties to all headlines in the
120  current file which do not already have one."
121  (interactive)
122  (org-map-entries (lambda () (org-id-get (point) 'create))))
123 
124 (defun org-custom-id-add-to-headlines-in-file ()
125  "Add CUSTOM_ID properties to all headlines in the
126  current file which do not already have one."
127  (interactive)
128  (org-map-entries (lambda () (org-custom-id-get (point) 'create))))
129 
130 (defun org-id-add-to-headlines-in-files (&optional files)
131  (interactive)
132  (with-temp-buffer
133  (dolist (f (or files org-agenda-files))
134  (find-file f)
135  (org-id-add-to-headlines-in-file)
136  (save-buffer))))
137 
138 (defun org-id-add-to-headlines-in-directory (&optional dir)
139  (interactive)
140  (let ((dir (or dir org-directory)))
141  (org-id-add-to-headlines-in-files
142  (directory-files-recursively dir "[.]org$"))))
143 
144 (message "Initialized ULANG.")
145 
146 ;;; Commands
147 
148 ;; (org-property-inherit-p "LOCATION")
149 
150 ;; currently does not support locations with spaces.. need to walk
151 ;; ancestors ourselves to do so. for now only URIs and pathnames are
152 ;; supported.
153 (defun org-get-location (point)
154  "Get the value of property LOCATION at POINT."
155  (interactive "d")
156  (org-with-point-at point
157  (format "%s" (or (apply 'join-paths (string-split (org-entry-get-with-inheritance "LOCATION") " "))
158  (caadar (org-collect-keywords '("LOCATION") nil '("LOCATION")))))))
159 
160 (defun org-set-location (value)
161  "Set the value of property LOCATION. If point is before first heading
162 instead set or replace the location file keyword."
163  (interactive (list nil))
164  (let ((val (or value (org-read-property-value "LOCATION" nil nil))))
165  (if (org-before-first-heading-p)
166  (save-excursion
167  (beginning-of-buffer)
168  (let ((start (point)))
169  (when (re-search-forward (rx bol "#+LOCATION:" (+ space) (group (* (not space))) eol) nil t)
170  (setq start (match-beginning 0))
171  (goto-char start)
172  (delete-line))
173  (insert "#+LOCATION: " val "\n")))
174  (org-set-property "LOCATION" value))))
175 
176 (defun org-follow-location ()
177  "Open the location specified by the LOCATION property of the org heading
178 or file at point."
179  (interactive)
180  (let ((loc ))
181  (cond
182  ((string-match-p org-link-any-re loc) (org-link-open-from-string loc))
183  ;; TODO 2024-08-29: handle other location types (physical, etc)
184  (t (find-file loc t)))))
185 
186 (provide 'ulang)
187 ;;; ulang.el ends here