|
|
@ -818,7 +818,17 @@ If the property is already set, replace its value." |
|
|
|
; (add-hook 'org-mode-hook 'org-indent-mode) |
|
|
|
:bind (:map org-mode-map ("S-<right>" . org-shiftright) |
|
|
|
("S-<left>" . org-shiftleft)) |
|
|
|
|
|
|
|
:init |
|
|
|
(defun my--org-agenda-files-set () |
|
|
|
"Sets default agenda files. |
|
|
|
Necessary when updating roam agenda todos." |
|
|
|
(setq org-agenda-files (list (concat MY--PATH_ORG_FILES "notes.org") |
|
|
|
(concat MY--PATH_ORG_FILES "projects.org") |
|
|
|
(concat MY--PATH_ORG_FILES "tasks.org"))) |
|
|
|
(when *sys/linux* |
|
|
|
(nconc org-agenda-files |
|
|
|
(directory-files-recursively MY--PATH_ORG_FILES_MOBILE "\\.org$")))) |
|
|
|
(my--org-agenda-files-set) |
|
|
|
:config |
|
|
|
(defun my--org-company () |
|
|
|
(set (make-local-variable 'company-backends) |
|
|
@ -829,14 +839,7 @@ If the property is already set, replace its value." |
|
|
|
org-habit |
|
|
|
org-tempo ;; easy templates |
|
|
|
))) |
|
|
|
(setq org-default-notes-file (concat MY--PATH_ORG_FILES "notes.org") |
|
|
|
org-agenda-files (list (concat MY--PATH_ORG_FILES "notes.org") |
|
|
|
(concat MY--PATH_ORG_FILES "projects.org") |
|
|
|
(concat MY--PATH_ORG_FILES "tasks.org"))) |
|
|
|
|
|
|
|
(when *sys/linux* |
|
|
|
(nconc org-agenda-files |
|
|
|
(directory-files-recursively MY--PATH_ORG_FILES_MOBILE "\\.org$"))) |
|
|
|
(setq org-default-notes-file (concat MY--PATH_ORG_FILES "notes.org")) |
|
|
|
(setq org-id-locations-file (concat MY--PATH_USER_LOCAL ".org-id-locations") |
|
|
|
org-log-into-drawer "LOGBOOK") |
|
|
|
|
|
|
@ -1066,7 +1069,118 @@ org-roam-db-sync |
|
|
|
:after org |
|
|
|
:init |
|
|
|
(setq org-roam-v2-ack t) |
|
|
|
|
|
|
|
(defun my--project-p () |
|
|
|
"Return non-nil if current buffer has any todo entry. |
|
|
|
|
|
|
|
TODO entries marked as done are ignored, meaning this function |
|
|
|
returns nil if current buffer contains only completed tasks." |
|
|
|
(seq-find |
|
|
|
(lambda (type) |
|
|
|
(eq type 'todo)) |
|
|
|
(org-element-map |
|
|
|
(org-element-parse-buffer 'headline) |
|
|
|
'headline |
|
|
|
(lambda (h) |
|
|
|
(org-element-property :todo-type h))))) |
|
|
|
|
|
|
|
(defun my--project-update-tag () |
|
|
|
"Update PROJECT tag in the current buffer." |
|
|
|
(when (and (not (active-minibuffer-window)) |
|
|
|
(my--buffer-roam-note-p)) |
|
|
|
(save-excursion |
|
|
|
(goto-char (point-min)) |
|
|
|
(let* ((tags (my--buffer-tags-get)) |
|
|
|
(original-tags tags)) |
|
|
|
(if (my--project-p) |
|
|
|
(setq tags (cons "project" tags)) |
|
|
|
(setq tags (remove "project" tags))) |
|
|
|
|
|
|
|
;;cleanup duplicates |
|
|
|
(when (or (seq-difference tags original-tags) |
|
|
|
(seq-difference original-tags tags)) |
|
|
|
(apply #'my--buffer-tags-set tags)))))) |
|
|
|
|
|
|
|
(defun my--buffer-tags-get () |
|
|
|
"Return filetags value in current buffer." |
|
|
|
(my--buffer-prop-get-list "filetags" "[ :]")) |
|
|
|
|
|
|
|
(defun my--buffer-tags-set (&rest tags) |
|
|
|
"Set TAGS in current buffer. |
|
|
|
If filetags value is already set, replace it." |
|
|
|
(if tags |
|
|
|
(my--buffer-prop-set |
|
|
|
"filetags" (concat ":" (string-join tags ":") ":")) |
|
|
|
(my--buffer-prop-remove "filetags"))) |
|
|
|
|
|
|
|
(defun my--buffer-tags-add (tag) |
|
|
|
"Add a TAG to filetags in current buffer." |
|
|
|
(let* ((tags (my--buffer-tags-get)) |
|
|
|
(tags (append tags (list tag)))) |
|
|
|
(apply #'my--buffer-tags-set tags))) |
|
|
|
|
|
|
|
(defun my--buffer-tags-remove (tag) |
|
|
|
"Remove a TAG from filetags in current buffer." |
|
|
|
(let* ((tags (my--buffer-tags-get)) |
|
|
|
(tags (delete tag tags))) |
|
|
|
(apply #'my--buffer-tags-set tags))) |
|
|
|
|
|
|
|
(defun my--buffer-prop-set (name value) |
|
|
|
"Set a file property called NAME to VALUE in buffer file. |
|
|
|
If the property is already set, replace its value." |
|
|
|
(setq name (downcase name)) |
|
|
|
(org-with-point-at 1 |
|
|
|
(let ((case-fold-search t)) |
|
|
|
(if (re-search-forward (concat "^#\\+" name ":\\(.*\\)") |
|
|
|
(point-max) t) |
|
|
|
(replace-match (concat "#+" name ": " value) 'fixedcase) |
|
|
|
(while (and (not (eobp)) |
|
|
|
(looking-at "^[#:]")) |
|
|
|
(if (save-excursion (end-of-line) (eobp)) |
|
|
|
(progn |
|
|
|
(end-of-line) |
|
|
|
(insert "\n")) |
|
|
|
(forward-line) |
|
|
|
(beginning-of-line))) |
|
|
|
(insert "#+" name ": " value "\n"))))) |
|
|
|
(defun my--buffer-prop-set-list (name values &optional separators) |
|
|
|
"Set a file property called NAME to VALUES in current buffer. |
|
|
|
VALUES are quoted and combined into single string using |
|
|
|
`combine-and-quote-strings'. |
|
|
|
If SEPARATORS is non-nil, it should be a regular expression |
|
|
|
matching text that separates, but is not part of, the substrings. |
|
|
|
If nil it defaults to `split-string-and-unquote', normally |
|
|
|
\"[ \f\t\n\r\v]+\", and OMIT-NULLS is forced to t. |
|
|
|
If the property is already set, replace its value." |
|
|
|
(my--buffer-prop-set |
|
|
|
name (combine-and-quote-strings values separators))) |
|
|
|
|
|
|
|
(defun my--buffer-prop-get (name) |
|
|
|
"Get a buffer property called NAME as a string." |
|
|
|
(org-with-point-at 1 |
|
|
|
(when (re-search-forward (concat "^#\\+" name ": \\(.*\\)") |
|
|
|
(point-max) t) |
|
|
|
(buffer-substring-no-properties |
|
|
|
(match-beginning 1) |
|
|
|
(match-end 1))))) |
|
|
|
|
|
|
|
(defun my--buffer-prop-get-list (name &optional separators) |
|
|
|
"Get a buffer property NAME as a list using SEPARATORS. |
|
|
|
If SEPARATORS is non-nil, it should be a regular expression |
|
|
|
matching text that separates, but is not part of, the substrings. |
|
|
|
If nil it defaults to `split-string-default-separators', normally |
|
|
|
\"[ \f\t\n\r\v]+\", and OMIT-NULLS is forced to t." |
|
|
|
(let ((value (my--buffer-prop-get name))) |
|
|
|
(when (and value (not (string-empty-p value))) |
|
|
|
(split-string-and-unquote value separators)))) |
|
|
|
|
|
|
|
(defun my--buffer-prop-remove (name) |
|
|
|
"Remove a buffer property called NAME." |
|
|
|
(org-with-point-at 1 |
|
|
|
(when (re-search-forward (concat "\\(^#\\+" name ":.*\n?\\)") |
|
|
|
(point-max) t) |
|
|
|
(replace-match "")))) |
|
|
|
|
|
|
|
(defun my--buffer-roam-note-p () |
|
|
|
"Return non-nil if the currently visited buffer is a note." |
|
|
|
(and buffer-file-name |
|
|
@ -1085,11 +1199,18 @@ org-roam-db-sync |
|
|
|
(org-roam-node-list)))) |
|
|
|
|
|
|
|
(defun my/org-roam-refresh-agenda-list () |
|
|
|
"Add all org roam files with #+filetags: Project" |
|
|
|
"Add all org roam files with #+filetags: project" |
|
|
|
(interactive) |
|
|
|
(my--org-agenda-files-set) |
|
|
|
(nconc org-agenda-files |
|
|
|
(my--org-roam-list-notes-by-tag "Project")) |
|
|
|
(my--org-roam-list-notes-by-tag "project")) |
|
|
|
(setq org-agenda-files (delete-dups org-agenda-files))) |
|
|
|
|
|
|
|
(add-hook 'find-file-hook #'my--project-update-tag) |
|
|
|
(add-hook 'before-save-hook #'my--project-update-tag) |
|
|
|
|
|
|
|
(advice-add 'org-agenda :before #'my/org-roam-refresh-agenda-list) |
|
|
|
(advice-add 'org-todo-list :before #'my/org-roam-refresh-agenda-list) |
|
|
|
:config |
|
|
|
(require 'org-roam-dailies) ;; ensure the keymap is available |
|
|
|
(org-roam-db-autosync-mode) |
|
|
|