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.