diff --git a/dotfiles/emacs.d/.gitignore b/dotfiles/emacs.d/.gitignore
index 365b0a7a..6e4822f0 100644
--- a/dotfiles/emacs.d/.gitignore
+++ b/dotfiles/emacs.d/.gitignore
@@ -30,7 +30,7 @@ jabber-avatar-cache
kat-mode.el
org-caldav-*
org-caldav-backup.org
-org-config.el
+org-config*.el
org-gcal/
persp-confs/
places
diff --git a/dotfiles/emacs.d/README.org b/dotfiles/emacs.d/README.org
index 99499167..1c62a3a7 100644
--- a/dotfiles/emacs.d/README.org
+++ b/dotfiles/emacs.d/README.org
@@ -595,15 +595,6 @@ For composing functions with an apply so that they can be used with the ~:around
,@body
(- (float-time) ,start))))
#+END_SRC
-** Add Files to ~org-agenda-files~
-#+BEGIN_SRC emacs-lisp
-(defun imalison:add-to-org-agenda-files (incoming-files)
- (setq org-agenda-files
- (delete-dups
- (cl-loop for filepath in (append org-agenda-files incoming-files)
- when (and filepath (file-exists-p (file-truename filepath)))
- collect (file-truename filepath)))))
-#+END_SRC
** Get String From File
#+BEGIN_SRC emacs-lisp
(defun imalison:get-string-from-file (file-path)
@@ -2993,946 +2984,11 @@ The following is taken from [[https://github.com/syl20bnr/spacemacs/blob/a650877
#+end_src
** Document
*** org
-**** config
-#+BEGIN_SRC emacs-lisp :tangle org-config.el
-(defvar imalison:org-dir "~/org")
-(defvar imalison:shared-org-dir "~/katnivan")
-(defvar imalison:org-whoami "Ivan Malison")
-(defvar imalison:org-people (list "Ivan Malison" "Kat Huang"))
-(defvar imalison:org-default-initial-state "TODO")
-(use-package org
- :defer 1
- :commands (org-mode org org-mobile-push org-mobile-pull org-agenda)
- :mode ("\\.org\\'" . org-mode)
- :bind (("C-c c" . org-capture)
- :map org-mode-map
- (("C-e" . end-of-visual-line)
- ("C-c n t" . org-insert-todo-heading)
- ("C-c n s" . org-insert-todo-subheading)
- ("C-c n h" . org-insert-habit)
- ("C-c n m" . org-make-habit)
- ("C-c n l" . org-store-link)
- ("C-c n i" . org-insert-link)
- ("C-c C-t" . org-todo)
- ("C-c C-S-t" . org-todo-force-notes)
- ("M-." . elisp-slime-nav-find-elisp-thing-at-point)))
- :custom
- ((org-startup-indented nil)
- (org-startup-folded t)
- (org-fold-catch-invisible-edits 'show)
- (org-edit-src-content-indentation 0)
- (org-src-preserve-indentation t)
- (org-refile-targets '((org-agenda-files . (:maxlevel . 2))
- (org-agenda-files . (:level . 0))))
- (org-refile-use-outline-path 'file)
- (org-refile-allow-creating-parent-nodes t)
- (org-outline-path-complete-in-steps nil)
- (org-log-into-drawer t)
- (org-log-reschedule t)
- (org-log-redeadline t)
- (org-treat-insert-todo-heading-as-state-change t)
- (org-lowest-priority 69) ;; The character E
- (org-enforce-todo-dependencies t)
- (org-deadline-warning-days 0)
- (org-default-priority ?C)
- (org-agenda-skip-scheduled-if-done t)
- (org-agenda-skip-deadline-if-done t)
- (org-agenda-window-setup 'other-window)
- (org-imenu-depth 10)
- (org-agenda-timegrid-use-ampm 1)
- (org-todo-repeat-to-state "TODO")
- (org-agenda-span 10)
- (org-habit-show-all-today t)
- (org-agenda-start-day "-0d"))
- :preface
- (progn
- (require 'cl-lib)
- (defun imalison:maybe-symbol-name (arg)
- (if (symbolp arg)
- (symbol-name arg)
- arg))
-
- (defun imalison:set-display-custom-times ()
- (setq org-display-custom-times nil))
-
- (setq org-goto-interface 'outline-path-completion
- org-goto-max-level 10
- org-export-headline-levels 3)
- (add-hook 'org-mode-hook 'imalison:disable-linum-mode)
- (add-hook 'org-mode-hook (lambda () (setq org-todo-key-trigger t)))
- (add-hook 'org-mode-hook 'imalison:set-display-custom-times)
- (add-hook 'org-agenda-mode-hook 'imalison:disable-linum-mode)
- (add-hook 'org-agenda-mode-hook 'imalison:set-display-custom-times)
- (add-hook 'org-agenda-mode-hook 'imalison:disable-linum-mode)
-
- (defmacro imalison:def-agenda-pred (&rest forms)
- `(lambda ()
- (unless ,@forms
- (or (outline-next-heading)
- (point-max)))))
-
- (defun imalison:org-known-assignees ()
- imalison:org-people)
-
- (cl-defun imalison:set-assignee (&key assignee (override t))
- (interactive)
- (let ((chosen-assignee (if (called-interactively-p 'interactive)
- (completing-read "Choose assignee: "
- (imalison:org-known-assignees)
- nil t)
- (or assignee imalison:org-whoami))))
- (when (or override (not (org-entry-get nil "ASSIGNEE")))
- (org-set-property "ASSIGNEE" chosen-assignee))))
-
- (defun imalison:assign-to-self-if-unassigned ()
- (interactive)
- (imalison:set-assignee :assignee imalison:org-whoami :override nil))
-
- (defun imalison:shared-org-file-p ()
- (string-prefix-p (file-truename imalison:shared-org-dir)
- (file-truename default-directory)))
-
- (require 'org-habit)
- (when (not (fboundp 'org-is-habit-p))
- (defun org-is-habit-p ()
- (string-equal (org-entry-get nil "STYLE") "habit")))
-
- (defun imalison:habit-or-repeating-heading ()
- (org-is-habit-p))
-
- (defun imalison:shared-non-habit-p ()
- (and (not (imalison:habit-or-repeating-heading))
- (imalison:shared-org-file-p)))
-
- (defvar imalison:auto-assign-to-self-predicates
- (list 'imalison:shared-non-habit-p))
-
- (defun imalison:auto-assign-to-self-when ()
- (cl-loop for pred in imalison:auto-assign-to-self-predicates
- when (funcall pred)
- return t
- finally return nil))
-
- (defun imalison:maybe-auto-assign-to-self (&rest args)
- (when (imalison:auto-assign-to-self-when)
- (imalison:assign-to-self-if-unassigned)))
-
- (advice-add 'org-schedule :after 'imalison:maybe-auto-assign-to-self)
-
- (cl-defun imalison:assigned-to-me (&key (include-unassigned t))
- (let ((assignee (org-entry-get nil "ASSIGNEE")))
- (or (string-equal assignee imalison:org-whoami)
- (and include-unassigned (null assignee)))))
-
- (defalias 'imalison:assigned-to-me-agenda-pred
- (imalison:def-agenda-pred
- (imalison:assigned-to-me)))
-
- (cl-defun imalison:org-time-condition-met-p (&key (property "CREATED") (days 30) (future nil))
- (let* ((property-value (org-entry-get (point) property))
- (comparison-time
- (if future
- (time-add (current-time) (days-to-time days))
- (time-subtract (current-time) (days-to-time days))))
- (formatted-time-string (format-time-string "<%Y-%m-%d %H:%M>" comparison-time))
- (compare-time (org-time-string-to-time formatted-time-string))
- (node-time (when property-value (org-time-string-to-time property-value))))
- (when node-time
- (if future
- (time-less-p node-time compare-time)
- (time-less-p compare-time node-time)))))
-
- (defun org-archive-if (condition-function)
- (if (funcall condition-function)
- (let ((next-point-marker
- (save-excursion (org-forward-heading-same-level 1) (point-marker))))
- (org-archive-subtree)
- (setq org-map-continue-from (marker-position next-point-marker)))))
-
- (defun org-archive-if-completed ()
- (interactive)
- (org-archive-if 'org-entry-is-done-p))
-
- (defun org-archive-completed-in-buffer ()
- (interactive)
- (org-map-entries 'org-archive-if-completed))
-
- (defun org-archive-all-in-buffer ()
- (interactive)
- (org-map-entries 'org-archive-subtree))
-
- (cl-defun imalison:make-org-template (&key (content "%?"))
- (with-temp-buffer
- (org-mode)
- (insert content)
- (org-set-property "CREATED"
- (with-temp-buffer
- (org-insert-time-stamp
- (org-current-effective-time) t t)))
- (buffer-substring-no-properties (point-min) (point-max))))
-
- (defun imalison:make-org-template-from-file (filename)
- (imalison:make-org-template (imalison:get-string-from-file filename)))
-
- (cl-defun imalison:make-org-todo-template
- (&key (content "%?") (creation-state imalison:org-default-initial-state))
- (with-temp-buffer
- (org-mode)
- (org-insert-heading)
- (insert content)
- (org-todo creation-state)
- (org-set-property "CREATED"
- (with-temp-buffer
- (org-insert-time-stamp
- (org-current-effective-time) t t)))
- (remove-hook 'post-command-hook 'org-add-log-note)
- (let ((org-log-note-purpose 'state)
- (org-log-note-return-to (point-marker))
- (org-log-note-marker (progn (goto-char (org-log-beginning t))
- (point-marker)))
- (org-log-note-state creation-state))
- (org-add-log-note))
- (buffer-substring-no-properties (point-min) (point-max))))
-
- (defun org-todo-force-notes ()
- (interactive)
- (let ((org-todo-log-states
- (mapcar (lambda (state)
- (list state 'note 'time))
- (apply 'append org-todo-sets))))
- (cond ((eq major-mode 'org-mode) (org-todo))
- ((eq major-mode 'org-agenda-mode) (org-agenda-todo)))))
-
- (defun org-make-habit ()
- (interactive)
- (org-set-property "STYLE" "habit"))
-
- (defun org-insert-habit ()
- (interactive)
- (org-insert-todo-heading nil)
- (org-make-habit))
-
- (defun org-todo-at-date (date)
- (interactive (list (org-time-string-to-time (org-read-date))))
- (cl-flet ((org-current-effective-time (&rest r) date)
- (org-today (&rest r) (time-to-days date)))
- (cond ((eq major-mode 'org-mode) (org-todo))
- ((eq major-mode 'org-agenda-mode) (org-agenda-todo)))))
-
- (defun imalison:make-org-linked-todo-template ()
- (imalison:make-org-todo-template "[#C] %? %A"))
-
- (defun org-cmp-creation-times (a b)
- (let ((a-created (get-date-created-from-agenda-entry a))
- (b-created (get-date-created-from-agenda-entry b)))
- (imalison:compare-int-list a-created b-created)))
-
- (defun org-agenda-done (&optional arg)
- "Mark current TODO as done.
- This changes the line at point, all other lines in the agenda referring to
- the same tree node, and the headline of the tree node in the Org-mode file."
- (interactive "P")
- (org-agenda-todo "DONE")))
- :config
- (progn
- (setq org-global-properties
- '(quote (("Effort_ALL" . "0:15 0:30 0:45 1:00 2:00 3:00 4:00 5:00 6:00 0:00")
- ("STYLE_ALL" . "habit"))))
- ;; Record changes to todo states
- (setq org-todo-keywords
- '((sequence "INBOX(i!)" "TODO(t!)" "NEXT(n!)" "STARTED(s!)" "WAIT(w!)"
- "BACKLOG(b!)" "|" "DONE(d!)" "HANDLED(h!)" "EXPIRED(e!)"
- "CANCELED(c!)")))
-
- (setq org-columns-default-format
- "%80ITEM(Task) %10Effort(Effort){:} %10CLOCKSUM")
-
- (add-to-list 'org-show-context-detail '(org-goto . lineage))
-
- (add-to-list
- 'org-src-lang-modes '("plantuml" . plantuml))
-
- (add-hook 'org-mode-hook 'imalison:load-babel-languages)
- (defun imalison:load-babel-languages ()
- (let* ((loaded-ob (or (require 'ob-sh nil t) (require 'ob-shell nil t)))
- (ob-shell-name
- (when loaded-ob
- (intern (substring-no-properties (imalison:maybe-symbol-name loaded-ob) 3))))
- (added-modes (when ob-shell-name `((,ob-shell-name . t)))))
- (org-babel-do-load-languages
- 'org-babel-load-languages
- `((python . t)
- (ruby . t)
- (octave . t)
- (plantuml . t)
- (js . t)
- ,@added-modes))))
-
- (use-package ob-typescript
- :config
- (progn
- (org-babel-do-load-languages
- 'org-babel-load-languages '((typescript . t)))))
-
- (use-package ob-mermaid
- :config
- (org-babel-do-load-languages
- 'org-babel-load-languages '((mermaid . t))))
-
- (when nil
- ;; Enable appointment notifications.
- (defadvice org-agenda-to-appt (before wickedcool activate)
- "Clear the appt-time-msg-list."
- (setq appt-time-msg-list nil))
- (appt-activate)
- (defun org-agenda-to-appt-no-message ()
- (shut-up (org-agenda-to-appt)))
- (run-at-time "00:00" 60 'org-agenda-to-appt-no-message))
-
-
- ;; Override the key definition for org-exit
- ;; TODO why does this cause an error
- ;; (define-key org-agenda-mode-map "x" #'org-agenda-done)
-
- ;; org-mode add-ons
- (use-package org-present
- :commands org-present)
-
- (use-package org-pomodoro
- :disabled t)
-
- ;; variable configuration
- (add-to-list 'org-modules 'org-habit)
- (add-to-list 'org-modules 'org-expiry)
-
- (setq org-src-fontify-natively t)
- (setq org-habit-graph-column 50)
- (setq org-habit-show-habits-only-for-today t)
-
- ;; My priority system:
-
- ;; A - Absolutely MUST, at all costs, be completed by the provided
- ;; due date. TODO: implement some type of extreme nagging
- ;; system that alerts in an intrusive way for overdue A
- ;; priority tasks.
-
- ;; B - Should be given immediate attention if the due date is any
- ;; time in the next two days. Failure to meet due date would
- ;; be bad but not catastrophic.
-
- ;; C - The highest priority to which tasks for which failure to
- ;; complete on time would not have considerable significant
- ;; consequences. There is still significant reason to prefer
- ;; the completion of these tasks sooner rather than later.
-
- ;; D - Failure to complete within a few days (or ever) of any
- ;; deadline would be completely okay. As such, any deadline
- ;; present on such a task is necessarily self imposed. Still
- ;; probably worth doing
-
- ;; E - Potentially not even worth doing at all, but worth taking a
- ;; note about in case it comes up again, or becomes more
- ;; interesting later.
-
- ;; F - Almost certainly not worth attempting in the immediate future.
- ;; Just brain dump.
-
- ;; Priorities are somewhat contextual within each category. Things
- ;; in the gtd or work categories are generally regarded as much
- ;; more important than things with the same priority from the
- ;; dotfiles category.
-
- ;; Items without deadlines or scheduled times of a given priority
- ;; can be regarded as less important than items that DO have
- ;; deadlines of that same priority.
-
-
- (define-key mode-specific-map [?a] 'org-agenda)
- (unbind-key "C-j" org-mode-map)
-
- (use-package org-bullets
- :commands org-bullets-mode
- :preface
- (add-hook 'org-mode-hook
- (lambda () (org-bullets-mode 1))))
-
- (use-package org-ehtml
- :disabled t
- :config
- (progn
- (setq org-ehtml-allow-agenda t)
- (setq org-ehtml-editable-headlines t)
- (setq org-ehtml-everything-editable t)))
-
- ;; Agenda setup.
- (defvar imalison:org-gtd-file
- (imalison:join-paths imalison:org-dir "gtd.org"))
- (defvar imalison:org-habits-file
- (imalison:join-paths imalison:org-dir "habits.org"))
- (defvar imalison:org-calendar-file
- (imalison:join-paths imalison:org-dir "calendar.org"))
- (defvar imalison:org-inbox-file
- (imalison:join-paths imalison:org-dir "inbox.org"))
- (defvar imalison:shared-org-gtd-file
- (imalison:join-paths imalison:shared-org-dir "shared_gtd.org"))
- (defvar imalison:shared-habits-file
- (imalison:join-paths imalison:shared-org-dir "shared_habits.org"))
- (defvar imalison:shared-calendar-file
- (imalison:join-paths imalison:shared-org-dir "shared_calendar.org"))
- (defvar imalison:shared-shopping-file
- (imalison:join-paths imalison:shared-org-dir "shared_shopping.org"))
-
-
- (defvar imalison:orgzly-files
- (list (imalison:join-paths imalison:shared-org-dir "kat_orgzly.org")
- (imalison:join-paths imalison:shared-org-dir "ivan_orgzly.org")
- (imalison:join-paths imalison:org-dir "orgzly.org")))
-
- (unless (boundp 'org-capture-templates)
- (defvar org-capture-templates nil))
-
- (defvar imalison:created-property-string "
-:PROPERTIES:
-:CREATED: %U
-:END:")
-
- (imalison:add-to-org-agenda-files
- (nconc (list imalison:org-gtd-file imalison:org-habits-file
- imalison:org-calendar-file imalison:org-inbox-file
- imalison:shared-org-gtd-file imalison:shared-habits-file
- imalison:shared-calendar-file imalison:shared-shopping-file)
- imalison:orgzly-files))
-
- (add-to-list 'org-capture-templates
- `("t" "GTD Todo (Linked)" entry (file ,imalison:org-gtd-file)
- (function imalison:make-org-linked-todo-template)))
-
- (add-to-list 'org-capture-templates
- `("g" "GTD Todo" entry (file ,imalison:org-gtd-file)
- (function imalison:make-org-todo-template)))
-
- (add-to-list 'org-capture-templates
- `("s" "Shared GTD Todo" entry (file ,imalison:shared-org-gtd-file)
- (function imalison:make-org-todo-template)))
-
- (add-to-list 'org-capture-templates
- `("y" "Calendar entry (Linked)" entry
- (file ,imalison:org-calendar-file)
- ,(format "%s%s\n%s" "* %? %A" imalison:created-property-string "%^T")))
-
- (add-to-list 'org-capture-templates
- `("c" "Calendar entry" entry
- (file ,imalison:org-calendar-file)
- ,(format "%s\n%s\n%s" "* %?" imalison:created-property-string "%^T")))
-
- (add-to-list 'org-capture-templates
- `("z" "Shopping Todo" entry (file ,imalison:shared-shopping-file)
- (function (lambda (&rest args) (imalison:make-org-todo-template :creation-state "TODO")))))
-
- (add-to-list 'org-capture-templates
- `("h" "Habit" entry (file ,imalison:org-habits-file)
- "* TODO
-SCHEDULED: %^t
-:PROPERTIES:
-:CREATED: %U
-:STYLE: habit
-:END:"))
-
-
- (defun org-get-priority-at-point ()
- (save-excursion
- (beginning-of-line)
- (org-back-to-heading t)
- (when (looking-at org-priority-regexp)
- (let ((ms (match-string 2)))
- (org-priority-to-value ms)))))
-
- (defmacro imalison:def-agenda-priority-pred (priority)
- `(imalison:def-agenda-pred
- (>= (org-get-priority-at-point) ,priority)))
-
- (require 'org-agenda)
- (when (fboundp 'org-agenda-transient)
- (bind-key "C-c a" 'org-agenda-transient))
-
- (let ((this-week-high-priority
- ;; The < in the following line has behavior that is opposite
- ;; to what one might expect.
- `(tags-todo
- "+PRIORITY<\"C\""
- ((org-agenda-overriding-header "Upcoming high priority tasks:")
- (org-agenda-skip-function
- ,(imalison:def-agenda-pred
- (or
- (imalison:org-time-condition-met-p
- :property "DEADLINE" :days 7 :future t)
- (imalison:org-time-condition-met-p
- :property "SCHEDULED" :days 7 :future t)))))))
- (due-today
- `(alltodo
- ""
- ((org-agenda-overriding-header "Due today:")
- (org-agenda-skip-function
- ,(imalison:def-agenda-pred
- (or
- (imalison:org-time-condition-met-p
- :property "DEADLINE" :days 0 :future t)
- (imalison:org-time-condition-met-p
- :property "SCHEDULED" :days 0 :future t)))))))
- (recently-created
- `(alltodo
- ""
- ((org-agenda-overriding-header "Recently Created:")
- (org-agenda-skip-function
- ,(imalison:def-agenda-pred
- (imalison:org-time-condition-met-p :days 10)))
- (org-agenda-cmp-user-defined 'org-cmp-creation-times)
- (org-agenda-sorting-strategy '(user-defined-down)))))
- (next '(todo "NEXT"))
- (started '(todo "STARTED"))
- (inbox '(todo "INBOX"))
- (missing-deadline
- '(tags-todo "-DEADLINE={.}/!"
- ((org-agenda-overriding-header
- "These don't have deadlines:"))))
- (missing-priority
- '(tags-todo "-PRIORITY={.}/!"
- ((org-agenda-overriding-header
- "These don't have priorities:")))))
-
- (setq org-agenda-custom-commands
- `(("M" "Main agenda view"
- ((agenda ""
- ((org-agenda-overriding-header "Agenda:")
- (org-agenda-ndays 5)
- (org-deadline-warning-days 0)
- (org-agenda-skip-function 'imalison:assigned-to-me-agenda-pred)))
- ,due-today
- ,next
- ,inbox
- ,this-week-high-priority
- ,recently-created)
- nil nil)
- ,(cons "A" (cons "High priority upcoming" this-week-high-priority))
- ,(cons "d" (cons "Overdue tasks and due today" due-today))
- ,(cons "r" (cons "Recently created" recently-created))
- ("h" "A, B priority:" tags-todo "+PRIORITY<\"C\""
- ((org-agenda-overriding-header
- "High Priority:")))
- ("c" "At least priority C:" tags-todo "+PRIORITY<\"D\""
- ((org-agenda-overriding-header
- "At least priority C:"))))))
-
- (require 'org-agenda)
- (when (fboundp 'org-agenda-transient)
- (bind-key "C-c a" 'org-agenda-transient))
-
- ;; What follows is a description of the significance of each of
- ;; the values available in `org-todo-keywords'. All headings with
- ;; one of these keywords deal with the concept of the completion
- ;; of some task or collection of tasks to bring about a particular
- ;; state of affairs. In some cases, the actual tasks involved may
- ;; not be known at the time of task creation.
-
- ;; Incomplete States:
-
- ;; IDEA - This TODO exists in only the most abstract sense: it is
- ;; an imagined state of affairs that requires tasks that are
- ;; either not yet known, or have not thoroughly been considered.
-
- ;; RESEARCH - This TODO needs to be investigated further before
- ;; action can be taken to achieve the desired outcome. It is not
- ;; known how much time and effort will be consumed in the actual
- ;; completion of the task.
-
- ;; TODO - The scope and work involved in this TODO are well
- ;; understood, but for some reason or another, it is not something
- ;; that should be attempted in the immediate future. Typically
- ;; this is because the task is not considered a top priority, but
- ;; it may also be for some other reason.
-
- ;; NEXT - This TODO is immediately actionable and should be
- ;; started in the immediate future.
-
- ;; STARTED - Work on this TODO has already started, further work
- ;; is immediately actionable.
-
- ;; WAIT - The work involved in this TODO is well understood, but
- ;; it is blocked for the time being.
-
- ;; BACKLOG - While technically actionable, this task is not only
- ;; not worth pursuing in the immediate future, but the foreseable
- ;; future. It exists as a task mostly as a note/reminder, in case
- ;; it becomes higher priority in the future.
-
- ;; Complete States:
-
- ;; DONE - This TODO has been completed exactly as imagined.
-
- ;; HANDLED - This TODO was completed in spirit, though not by the
- ;; means that were originally imagined/outlined in the TODO.
-
- ;; EXPIRED - The owner of this TODO failed to take action on it
- ;; within the appropriate time period, and there is now no point in
- ;; attempting it.
-
- ;; CANCELED - For whatever reason, this TODO should no longer be
- ;; attempted. This TODO is typically used in contrast to the
- ;; EXPIRED TODO to indicate that the owner is not necessarily to
- ;; blame.
- ))
-#+END_SRC
-**** Load org-config.el
-I put some org-mode specific configs in a separate file so that they can be used
-separately. This means that I need to load this file in init.el.
+My org-mode configuration now lives in its own file org-config.org.
#+BEGIN_SRC emacs-lisp
-(load-file (concat (file-name-directory load-file-name) "org-config.el"))
+(org-babel-load-file
+ (concat (file-name-directory load-file-name) "org-config.org"))
#+END_SRC
-**** Use frames
-#+BEGIN_SRC emacs-lisp
-(use-package org
- :config
- (progn
- (setq org-src-window-setup 'current-window)
- (when frame-mode
- (progn
- (setcdr (assoc 'file org-link-frame-setup) 'find-file-other-frame)))))
-#+END_SRC
-**** Disable yasnippet in org-mode
-#+BEGIN_SRC emacs-lisp
-(use-package org
- :straight nil
- :config
- (progn
- (defun imalison:disable-yas ()
- (yas-minor-mode -1))
- (add-hook 'org-mode-hook 'imalison:disable-yas)))
-#+END_SRC
-**** Set Background Color of Source Blocks for Export
-This was taken from [[http://emacs.stackexchange.com/questions/3374/set-the-background-of-org-exported-code-blocks-according-to-theme][here]].
-#+BEGIN_SRC emacs-lisp :tangle org-config.el
-(use-package org
- :config
- (progn
- (defun imalison:org-inline-css-hook (exporter)
- "Insert custom inline css to automatically set the
-background of code to whatever theme I'm using's background"
- (when (eq exporter 'html)
- (let* ((my-pre-bg (face-background 'default))
- (my-pre-fg (face-foreground 'default)))
- (setq
- org-html-head-extra
- (concat
- org-html-head-extra
- (format "\n"
- my-pre-bg my-pre-fg))))))
-
- (add-hook 'org-export-before-processing-hook 'imalison:org-inline-css-hook)))
-#+END_SRC
-**** Use my own default naming scheme for org-headings
-First we define a function that will generate a sanitized version of the heading
-as its link target.
-#+BEGIN_SRC emacs-lisp :tangle org-config.el
-(defun imalison:org-get-raw-value (item)
- (when (listp item)
- (let* ((property-list (cadr item)))
- (when property-list (plist-get property-list :raw-value)))))
-
-(defun imalison:sanitize-name (name)
- (replace-regexp-in-string "[^[:alpha:]]" "" (s-downcase name)))
-
-(defun imalison:generate-name (datum cache)
- (let ((raw-value (imalison:org-get-raw-value datum)))
- (if raw-value
- (imalison:sanitize-name raw-value)
- ;; This is the default implementation from org
- (let ((type (org-element-type datum)))
- (format "org%s%d"
- (if type
- (replace-regexp-in-string "-" "" (symbol-name type))
- "secondarystring")
- (incf (gethash type cache 0)))))))
-#+END_SRC
-
-This function replaces the default naming scheme with a call to
-~imalison:generate-name~, and uses a slightly different uniquify approach.
-#+BEGIN_SRC emacs-lisp :tangle org-config.el
-(use-package ox
- :defer t
- :straight nil
- :config
- (defun org-export-get-reference (datum info)
- "Return a unique reference for DATUM, as a string.
-DATUM is either an element or an object. INFO is the current
-export state, as a plist. Returned reference consists of
-alphanumeric characters only."
- (let ((type (org-element-type datum))
- (cache (or (plist-get info :internal-references)
- (let ((h (make-hash-table :test #'eq)))
- (plist-put info :internal-references h)
- h)))
- (reverse-cache (or (plist-get info :taken-internal-references)
- (let ((h (make-hash-table :test 'equal)))
- (plist-put info :taken-internal-references h)
- h))))
- (or (gethash datum cache)
- (let* ((name (imalison:generate-name datum cache))
- (number (+ 1 (gethash name reverse-cache -1)))
- (new-name (format "%s%s" name (if (< 0 number) number ""))))
- (puthash name number reverse-cache)
- (puthash datum new-name cache)
- new-name)))))
-#+END_SRC
-**** Add link icons in headings that lead to themselves
-#+BEGIN_SRC emacs-lisp :tangle org-config.el
-(use-package ox-html
- :commands (org-html-export-as-html org-html-export-as-html)
- :straight nil
- :preface
- (progn
- (defvar imalison:link-svg-html
- "")
- (defvar imalison:current-html-headline)
- (defun imalison:set-current-html-headline (headline &rest args)
- (setq imalison:current-html-headline headline))
- (defun imalison:clear-current-html-headline (&rest args)
- (setq imalison:current-html-headline nil))
- (defun imalison:org-html-format-heading-function (todo todo-type priority text tags info)
- (let* ((reference (when imalison:current-html-headline
- (org-export-get-reference imalison:current-html-headline info)))
- ;; Don't do anything special if the current headline is not set
- (new-text (if reference
- (format "%s %s" text reference imalison:link-svg-html)
- text)))
- (org-html-format-headline-default-function
- todo todo-type priority new-text tags info))))
- :config
- (progn
- ;; This is set before and cleared afterwards, so that we know when we are
- ;; generating the text for the headline itself and when we are not.
- (advice-add 'org-html-headline :before 'imalison:set-current-html-headline)
- (advice-add 'org-html-headline :after 'imalison:clear-current-html-headline)
- (setq org-html-format-headline-function
- 'imalison:org-html-format-heading-function)))
-#+END_SRC
-**** Allow with query params in image extentions
-#+BEGIN_SRC emacs-lisp :tangle org-config.el
-(use-package ox-html
- :defer t
- :straight nil
- :config
- (setq org-html-inline-image-rules
- '(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\(\\?.*?\\)?\\'")
-
- ("http" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\(\\?.*?\\)?\\'")
- ("https" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\(\\?.*?\\)?\\'"))))
-#+END_SRC
-**** Use org-tempo to allow inserting templates using e.g. = (org-get-priority-at-point) ,priority)))
+
+(cl-defun imalison:org-time-condition-met-p (&key (property "CREATED") (days 30) (future nil))
+ (let* ((property-value (org-entry-get (point) property))
+ (comparison-time
+ (if future
+ (time-add (current-time) (days-to-time days))
+ (time-subtract (current-time) (days-to-time days))))
+ (formatted-time-string (format-time-string "<%Y-%m-%d %H:%M>" comparison-time))
+ (compare-time (org-time-string-to-time formatted-time-string))
+ (node-time (when property-value (org-time-string-to-time property-value))))
+ (when node-time
+ (if future
+ (time-less-p node-time compare-time)
+ (time-less-p compare-time node-time)))))
+
+(defun org-cmp-creation-times (a b)
+ (let ((a-created (get-date-created-from-agenda-entry a))
+ (b-created (get-date-created-from-agenda-entry b)))
+ (imalison:compare-int-list a-created b-created)))
+#+end_src
+*** Transient support
+#+begin_src emacs-lisp :tangle org-config-config.el
+(when (fboundp 'org-agenda-transient)
+ (bind-key "C-c a" 'org-agenda-transient))
+#+end_src
+*** Agenda Commands (Views)
+#+begin_src emacs-lisp :tangle org-config-config.el
+(let ((this-week-high-priority
+ ;; The < in the following line has behavior that is opposite
+ ;; to what one might expect.
+ `(tags-todo
+ "+PRIORITY<\"C\""
+ ((org-agenda-overriding-header "Upcoming high priority tasks:")
+ (org-agenda-skip-function
+ ,(imalison:def-agenda-pred
+ (or
+ (imalison:org-time-condition-met-p
+ :property "DEADLINE" :days 7 :future t)
+ (imalison:org-time-condition-met-p
+ :property "SCHEDULED" :days 7 :future t)))))))
+ (due-today
+ `(alltodo
+ ""
+ ((org-agenda-overriding-header "Due today:")
+ (org-agenda-skip-function
+ ,(imalison:def-agenda-pred
+ (or
+ (imalison:org-time-condition-met-p
+ :property "DEADLINE" :days 0 :future t)
+ (imalison:org-time-condition-met-p
+ :property "SCHEDULED" :days 0 :future t)))))))
+ (recently-created
+ `(alltodo
+ ""
+ ((org-agenda-overriding-header "Recently Created:")
+ (org-agenda-skip-function
+ ,(imalison:def-agenda-pred
+ (imalison:org-time-condition-met-p :days 10)))
+ (org-agenda-cmp-user-defined 'org-cmp-creation-times)
+ (org-agenda-sorting-strategy '(user-defined-down)))))
+ (next '(todo "NEXT"))
+ (started '(todo "STARTED"))
+ (inbox '(todo "INBOX"))
+ (missing-deadline
+ '(tags-todo "-DEADLINE={.}/!"
+ ((org-agenda-overriding-header
+ "These don't have deadlines:"))))
+ (missing-priority
+ '(tags-todo "-PRIORITY={.}/!"
+ ((org-agenda-overriding-header
+ "These don't have priorities:")))))
+
+ (setq org-agenda-custom-commands
+ `(("M" "Main agenda view"
+ ((agenda ""
+ ((org-agenda-overriding-header "Agenda:")
+ (org-agenda-ndays 5)
+ (org-deadline-warning-days 0)
+ (org-agenda-skip-function 'imalison:assigned-to-me-agenda-pred)))
+ ,due-today
+ ,next
+ ,inbox
+ ,this-week-high-priority
+ ,recently-created)
+ nil nil)
+ ,(cons "A" (cons "High priority upcoming" this-week-high-priority))
+ ,(cons "d" (cons "Overdue tasks and due today" due-today))
+ ,(cons "r" (cons "Recently created" recently-created))
+ ("h" "A, B priority:" tags-todo "+PRIORITY<\"C\""
+ ((org-agenda-overriding-header
+ "High Priority:")))
+ ("c" "At least priority C:" tags-todo "+PRIORITY<\"D\""
+ ((org-agenda-overriding-header
+ "At least priority C:"))))))
+#+end_src
+** Archive
+#+begin_src emacs-lisp :tangle org-config-config.el
+(defun org-archive-if (condition-function)
+ (if (funcall condition-function)
+ (let ((next-point-marker
+ (save-excursion (org-forward-heading-same-level 1) (point-marker))))
+ (org-archive-subtree)
+ (setq org-map-continue-from (marker-position next-point-marker)))))
+
+(defun org-archive-if-completed ()
+ (interactive)
+ (org-archive-if 'org-entry-is-done-p))
+
+(defun org-archive-completed-in-buffer ()
+ (interactive)
+ (org-map-entries 'org-archive-if-completed))
+
+(defun org-archive-all-in-buffer ()
+ (interactive)
+ (org-map-entries 'org-archive-subtree))
+#+end_src
+** Capture
+*** Helper Functions
+#+begin_src emacs-lisp :tangle org-config-config.el
+(cl-defun imalison:make-org-template (&key (content "%?"))
+ (with-temp-buffer
+ (org-mode)
+ (insert content)
+ (org-set-property "CREATED"
+ (with-temp-buffer
+ (org-insert-time-stamp
+ (org-current-effective-time) t t)))
+ (buffer-substring-no-properties (point-min) (point-max))))
+
+(defun imalison:make-org-template-from-file (filename)
+ (imalison:make-org-template (imalison:get-string-from-file filename)))
+
+(cl-defun imalison:make-org-todo-template
+ (&key (content "%?") (creation-state imalison:org-default-initial-state))
+ (with-temp-buffer
+ (org-mode)
+ (org-insert-heading)
+ (insert content)
+ (org-todo creation-state)
+ (org-set-property "CREATED"
+ (with-temp-buffer
+ (org-insert-time-stamp
+ (org-current-effective-time) t t)))
+ (remove-hook 'post-command-hook 'org-add-log-note)
+ (let ((org-log-note-purpose 'state)
+ (org-log-note-return-to (point-marker))
+ (org-log-note-marker (progn (goto-char (org-log-beginning t))
+ (point-marker)))
+ (org-log-note-state creation-state))
+ (org-add-log-note))
+ (buffer-substring-no-properties (point-min) (point-max))))
+
+(defun imalison:make-org-linked-todo-template ()
+ (imalison:make-org-todo-template "[#C] %? %A"))
+#+end_src
+*** Templates
+#+begin_src emacs-lisp :tangle org-config-config.el
+(use-package org-capture
+ :straight nil
+ :config
+ (add-to-list 'org-capture-templates
+ `("t" "GTD Todo (Linked)" entry (file ,imalison:org-gtd-file)
+ (function imalison:make-org-linked-todo-template)))
+
+ (add-to-list 'org-capture-templates
+ `("g" "GTD Todo" entry (file ,imalison:org-gtd-file)
+ (function imalison:make-org-todo-template)))
+
+ (add-to-list 'org-capture-templates
+ `("s" "Shared GTD Todo" entry (file ,imalison:shared-org-gtd-file)
+ (function imalison:make-org-todo-template)))
+
+ (add-to-list 'org-capture-templates
+ `("y" "Calendar entry (Linked)" entry
+ (file ,imalison:org-calendar-file)
+ ,(format "%s%s\n%s" "* %? %A" imalison:created-property-string "%^T")))
+
+ (add-to-list 'org-capture-templates
+ `("c" "Calendar entry" entry
+ (file ,imalison:org-calendar-file)
+ ,(format "%s\n%s\n%s" "* %?" imalison:created-property-string "%^T")))
+
+ (add-to-list 'org-capture-templates
+ `("z" "Shopping Todo" entry (file ,imalison:shared-shopping-file)
+ (function (lambda (&rest args) (imalison:make-org-todo-template :creation-state "TODO")))))
+
+ (add-to-list 'org-capture-templates
+ `("h" "Habit" entry (file ,imalison:org-habits-file)
+ "* TODO
+SCHEDULED: %^t
+:PROPERTIES:
+:CREATED: %U
+:STYLE: habit
+:END:")))
+#+end_src
+** Babel
+#+begin_src emacs-lisp :tangle org-config-config.el
+(add-hook 'org-mode-hook 'imalison:load-babel-languages)
+(defun imalison:load-babel-languages ()
+ (let* ((loaded-ob (or (require 'ob-sh nil t) (require 'ob-shell nil t)))
+ (ob-shell-name
+ (when loaded-ob
+ (intern (substring-no-properties (imalison:maybe-symbol-name loaded-ob) 3))))
+ (added-modes (when ob-shell-name `((,ob-shell-name . t)))))
+ (org-babel-do-load-languages
+ 'org-babel-load-languages
+ `((python . t)
+ (ruby . t)
+ (octave . t)
+ (plantuml . t)
+ (js . t)
+ ,@added-modes))))
+
+(use-package ob-typescript
+ :config
+ (progn
+ (org-babel-do-load-languages
+ 'org-babel-load-languages '((typescript . t)))))
+
+(use-package ob-mermaid
+ :config
+ (org-babel-do-load-languages
+ 'org-babel-load-languages '((mermaid . t))))
+#+end_src
+** frame-mode handling
+Note that this does not go into org-config-config.el. This is on purpose
+#+begin_src emacs-lisp
+(use-package org
+ :after frame-mode
+ :config
+ (progn
+ (defun imalison:org-frame-mode-hook ()
+ (setq org-src-window-setup 'current-window)
+ (when frame-mode
+ (progn
+ (setcdr (assoc 'file org-link-frame-setup) 'find-file-other-frame))))
+ (add-hook 'frame-mode-hook 'imalison:org-frame-mode-hook)))
+#+end_src
+** Disable yasnippet in org-mode
+#+BEGIN_SRC emacs-lisp
+(use-package org
+ :straight nil
+ :config
+ (progn
+ (defun imalison:disable-yas ()
+ (yas-minor-mode -1))
+ (add-hook 'org-mode-hook 'imalison:disable-yas)))
+#+END_SRC
+** Set Background Color of Source Blocks for Export
+This was taken from [[http://emacs.stackexchange.com/questions/3374/set-the-background-of-org-exported-code-blocks-according-to-theme][here]].
+#+BEGIN_SRC emacs-lisp
+(use-package org
+ :config
+ (progn
+ (defun imalison:org-inline-css-hook (exporter)
+ "Insert custom inline css to automatically set the
+background of code to whatever theme I'm using's background"
+ (when (eq exporter 'html)
+ (let* ((my-pre-bg (face-background 'default))
+ (my-pre-fg (face-foreground 'default)))
+ (setq
+ org-html-head-extra
+ (concat
+ org-html-head-extra
+ (format "\n"
+ my-pre-bg my-pre-fg))))))
+
+ (add-hook 'org-export-before-processing-hook 'imalison:org-inline-css-hook)))
+#+END_SRC
+** Use my own default naming scheme for org-headings
+First we define a function that will generate a sanitized version of the heading
+as its link target.
+#+BEGIN_SRC emacs-lisp
+(defun imalison:org-get-raw-value (item)
+ (when (listp item)
+ (let* ((property-list (cadr item)))
+ (when property-list (plist-get property-list :raw-value)))))
+
+(defun imalison:sanitize-name (name)
+ (replace-regexp-in-string "[^[:alpha:]]" "" (s-downcase name)))
+
+(defun imalison:generate-name (datum cache)
+ (let ((raw-value (imalison:org-get-raw-value datum)))
+ (if raw-value
+ (imalison:sanitize-name raw-value)
+ ;; This is the default implementation from org
+ (let ((type (org-element-type datum)))
+ (format "org%s%d"
+ (if type
+ (replace-regexp-in-string "-" "" (symbol-name type))
+ "secondarystring")
+ (incf (gethash type cache 0)))))))
+#+END_SRC
+
+This function replaces the default naming scheme with a call to
+~imalison:generate-name~, and uses a slightly different uniquify approach.
+#+BEGIN_SRC emacs-lisp
+(use-package ox
+ :defer t
+ :straight nil
+ :config
+ (defun org-export-get-reference (datum info)
+ "Return a unique reference for DATUM, as a string.
+DATUM is either an element or an object. INFO is the current
+export state, as a plist. Returned reference consists of
+alphanumeric characters only."
+ (let ((type (org-element-type datum))
+ (cache (or (plist-get info :internal-references)
+ (let ((h (make-hash-table :test #'eq)))
+ (plist-put info :internal-references h)
+ h)))
+ (reverse-cache (or (plist-get info :taken-internal-references)
+ (let ((h (make-hash-table :test 'equal)))
+ (plist-put info :taken-internal-references h)
+ h))))
+ (or (gethash datum cache)
+ (let* ((name (imalison:generate-name datum cache))
+ (number (+ 1 (gethash name reverse-cache -1)))
+ (new-name (format "%s%s" name (if (< 0 number) number ""))))
+ (puthash name number reverse-cache)
+ (puthash datum new-name cache)
+ new-name)))))
+#+END_SRC
+** Add link icons in headings that lead to themselves
+#+BEGIN_SRC emacs-lisp
+(use-package ox-html
+ :commands (org-html-export-as-html org-html-export-as-html)
+ :straight nil
+ :preface
+ (progn
+ (defvar imalison:link-svg-html
+ "")
+ (defvar imalison:current-html-headline)
+ (defun imalison:set-current-html-headline (headline &rest args)
+ (setq imalison:current-html-headline headline))
+ (defun imalison:clear-current-html-headline (&rest args)
+ (setq imalison:current-html-headline nil))
+ (defun imalison:org-html-format-heading-function (todo todo-type priority text tags info)
+ (let* ((reference (when imalison:current-html-headline
+ (org-export-get-reference imalison:current-html-headline info)))
+ ;; Don't do anything special if the current headline is not set
+ (new-text (if reference
+ (format "%s %s" text reference imalison:link-svg-html)
+ text)))
+ (org-html-format-headline-default-function
+ todo todo-type priority new-text tags info))))
+ :config
+ (progn
+ ;; This is set before and cleared afterwards, so that we know when we are
+ ;; generating the text for the headline itself and when we are not.
+ (advice-add 'org-html-headline :before 'imalison:set-current-html-headline)
+ (advice-add 'org-html-headline :after 'imalison:clear-current-html-headline)
+ (setq org-html-format-headline-function
+ 'imalison:org-html-format-heading-function)))
+#+END_SRC
+** Allow with query params in image extentions
+#+BEGIN_SRC emacs-lisp
+(use-package ox-html
+ :defer t
+ :straight nil
+ :config
+ (setq org-html-inline-image-rules
+ '(("file" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\(\\?.*?\\)?\\'")
+
+ ("http" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\(\\?.*?\\)?\\'")
+ ("https" . "\\.\\(jpeg\\|jpg\\|png\\|gif\\|svg\\)\\(\\?.*?\\)?\\'"))))
+#+END_SRC
+** Use org-tempo to allow inserting templates using e.g.