(require 'fcuny-vars) (use-package dash :ensure t) (defvar org-directory (expand-file-name "~/Documents/notebooks")) (defvar org-default-tasks-file (concat org-directory "/tasks.org")) (defvar org-default-journal-file (concat org-directory "/journal.org")) (defvar org-default-notes-file (concat org-directory "/notes.org")) (defvar org-default-work-tasks-file (concat org-directory "/work-tasks.org")) (defvar org-default-work-journal-file (concat org-directory "/work-journal.org")) (defvar org-default-work-notes-file (concat org-directory "/work-notes.org")) (defvar org-default-inbox-file (concat org-directory "/inbox.org")) (use-package org :after (dash) :ensure t :hook ((org-mode . (lambda () (setq fill-column 120))) (org-mode . turn-on-auto-fill) (org-mode . org-indent-mode) (org-capture-mode-hook . delete-other-windows) (org-mode . org-hide-block-all)) :bind (("C-c c" . org-capture) ("C-c a" . org-agenda) ("C-c o" . hydra-org-menu/body)) :config (progn () (org-babel-do-load-languages 'org-babel-load-languages '((shell . t) (python . t) (emacs-lisp . t)))) (defhydra hydra-org-menu (:hint nil) " ^go to ^ ^action ^ ^-------------------^ ^---------------^ _g i_: go to inbox _s_: save files _g p_: go to personal _g w_: go to work _g n_: go to notes " ("g i" (find-file-other-window org-default-inbox-file)) ("g p" (find-file-other-window org-default-tasks-file)) ("g w" (find-file-other-window org-default-work-tasks-file)) ("g n" (find-file-other-windw org-default-work-notes-file)) ("s" (org-save-all-org-buffers))) :custom ;; cosmetic (org-pretty-entities t) (org-startup-indented nil) ;; (org-log-done 'time) ;; look (org-agenda-window-setup 'current-window) ;; priorities (org-priority-start-cycle-with-default nil) ;; Start one over/under default value. (org-lowest-priority ?D) (org-default-priority ?D) ;; Ensures unset tasks have low priority. ;; how to manage tasks (org-todo-keywords '((sequence "TODO(t)" "STARTED(s)" "DELEGATED(D)" "|" "DONE(d)") (sequence "SOMEDAY" "|" "CANCELED(c)"))) ;; agenda related (calendar-week-start-day 1) ;; org-mode uses calendar for the date picker, and I want this to start on Monday (org-agenda-start-on-weekday 1) ;; this is specific to org-agenda (org-agenda-files `(,org-default-tasks-file ,org-default-work-tasks-file)) (org-agenda-custom-commands (quote (("h" "Hotlist (what's important and due soon)" ((tags-todo "DEADLINE<\"<+0d>\"" ((org-agenda-overriding-header "OVERDUE"))) (tags-todo "DEADLINE>=\"<+0d>\"+DEADLINE<=\"<+1w>\"" ((org-agenda-overriding-header "DUE IN NEXT 7 DAYS"))) (tags-todo "DEADLINE=\"\"+PRIORITY={A}|DEADLINE>\"<+1w>\"+PRIORITY={A}" ((org-agenda-overriding-header "HIGH PRIORITY")))) ((org-agenda-todo-ignore-scheduled 'future) (org-agenda-sorting-strategy '(deadline-up)))) ("w" . "Work...") ("wf" "Work Today" ((tags-todo "DEADLINE=\"<+0d>\"" ((org-agenda-overriding-header "Due today") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline)) (org-agenda-sorting-strategy '(priority-down)))) (tags-todo "DEADLINE<\"<+0d>\"" ((org-agenda-overriding-header "Overdue") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline)) (org-agenda-sorting-strategy '(priority-down)))) (tags-todo "TODO={STARTED}" ((org-agenda-overriding-header "Started") (org-agenda-sorting-strategy '(priority-down)))) (agenda "" ((org-agenda-entry-types '(:scheduled)) (org-agenda-overriding-header "Scheduled") (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) (org-agenda-sorting-strategy '(priority-down time-down)) (org-agenda-span 'day) (org-agenda-start-on-weekday nil) (org-agenda-time-grid nil))) (tags "TODO={MEETING}+CREATED>\"<-7d>\"" ((org-agenda-overriding-header "Recent meetings (last 7 days)"))) (tags "TODO={NOTE}+CREATED>\"<-7d>\"" ((org-agenda-overriding-header "Recent notes (last 7 days)")))) ((org-agenda-files `(,org-default-work-tasks-file)) (org-agenda-sorting-strategy '(deadline-up)))) ("wp" "For 1:1" ((tags "people&TODO={TODO\\|STARTED}" ((org-agenda-overriding-header "Tasks for 1:1"))) ((org-agenda-files `(,org-default-work-tasks-file))))) ("wt" "Triage unscheduled tasks" ((tags "work&TODO<>\"\"&TODO<>{DONE\\|CANCELED\\|NOTE\\|MEETING\\|PROJECT}" ((org-agenda-overriding-header "Unscheduled tasks: ") (org-agenda-skip-function (quote (org-agenda-skip-entry-if (quote scheduled) (quote deadline) (quote timestamp) (quote regexp) "\\* \\(SOMEDAY\\)"))) (org-agenda-sorting-strategy (quote (category-up))) (org-agenda-prefix-format "%-11c%5(fcuny/org-todo-age) ")))) ((org-agenda-files `(,org-default-tasks-file ,org-default-work-tasks-file)))) ("wP" "Work project" ((tags "TODO={PROJECT}" ((org-agenda-overriding-header "All work projects")))) ((org-agenda-files `(,org-default-work-tasks-file)))) ("ws" "Someday tasks" ((tags-todo "TODO={SOMEDAY}" ((org-agenda-overriding-header "NO DUE DATE / SOMEDAY") (org-agenda-skip-function '(org-agenda-skip-entry-if 'deadline))))) ((org-agenda-files `(,org-default-work-tasks-file)))) ("p" . "Personal ...") ("pt" "Personal Today" ((tags-todo "DEADLINE=\"<+0d>\"" ((org-agenda-overriding-header "Due today") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline)) (org-agenda-sorting-strategy '(priority-down)))) (tags-todo "DEADLINE<\"<+0d>\"" ((org-agenda-overriding-header "Overdue") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline)) (org-agenda-sorting-strategy '(priority-down)))) (tags-todo "TODO={STARTED}" ((org-agenda-overriding-header "Started") (org-agenda-sorting-strategy '(priority-down)))) (tags "TODO={NOTE}+CREATED>\"<-7d>\"" ((org-agenda-overriding-header "Recent notes (last 7 days)"))) (agenda "" ((org-agenda-entry-types '(:scheduled)) (org-agenda-overriding-header "Scheduled") (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) (org-agenda-sorting-strategy '(priority-down time-down)) (org-agenda-span 'day) (org-agenda-start-on-weekday nil) (org-agenda-time-grid nil)))) ((org-agenda-files `(,org-default-tasks-file ,org-default-notes-file)) (org-agenda-sorting-strategy '(deadline-up))))))) ;; org babel related ;; prevent the conversion of spaces into tabs (necessary for Python code exports) (org-src-fontify-natively t) (org-src-preserve-indentation t) (org-edit-src-content-indentation t) ;; behavior ;; I want to follow links on RET (org-return-follows-link t) (org-enforce-todo-dependencies t) (org-export-with-toc nil) (org-export-with-section-numbers nil) ;; A few abbreviations I use regularly (org-link-abbrev-alist '(("src" . "~/workspace/%s") ("jira" . "https://jira.twitter.biz/browse/%s") ("ph" . "https://phabricator.twitter.biz/%s") ("go" . "http://go/%s"))) ;; entries (org-blank-before-new-entry (quote ((heading . nil) (plain-list-item . nil)))) ;; see https://github.com/abo-abo/swiper/issues/986 (org-goto-interface 'outline-path-completion) ;; refile and capture (org-refile-use-outline-path 'file) (org-outline-path-complete-in-steps nil) (org-refile-allow-creating-parent-nodes 'confirm) (org-refile-targets (quote ((org-default-tasks-file :level . 0) (org-default-work-tasks-file :level . 0) (org-default-notes-file :level . 0) (org-default-work-notes-file :level . 0)))) (org-reverse-note-order t) (org-capture-templates `(("t" "Add task" entry (file ,org-default-inbox-file) "* TODO %?\n:PROPERTIES:\n:ID: %(shell-command-to-string \"uuidgen\"):CREATED: %U\n:END:\n") ("n" "Note" entry (file ,org-default-inbox-file) "* %?\n:PROPERTIES:\n:ID: %(shell-command-to-string \"uuidgen\"):CREATED: %U\n:END:\n") ("j" "Journal" entry (file+olp+datetree ,org-default-journal-file) "* %?\n:PROPERTIES:\n:ID: %(shell-command-to-string \"uuidgen\"):CREATED: %U\n:END:\n" :tree-type month) ("m" "Meeting notes" entry (file ,org-default-inbox-file) "* %? %^g:meeting:\n:PROPERTIES:\n:ID: %(shell-command-to-string \"uuidgen\"):CREATED: %U\n:END:\n") ("i" "Interview notes" entry (file ,org-default-inbox-file) (file ,(concat fcuny/path-emacs-etc "/interview.org"))) ("J" "Work Journal" entry (file+olp+datetree ,org-default-work-journal-file) "* %?\n:PROPERTIES:\n:ID: %(shell-command-to-string \"uuidgen\"):CREATED: %U\n:END:\n" :tree-type month)))) (use-package htmlize :ensure t) (use-package orgit :ensure t) (defun fcuny/org-todo-age-time (&optional pos) (let ((stamp (org-entry-get (or pos (point)) "CREATED" t))) (when stamp (time-subtract (current-time) (org-time-string-to-time (org-entry-get (or pos (point)) "CREATED" t)))))) (defun fcuny/org-todo-age (&optional pos) (let ((days (time-to-number-of-days (fcuny/org-todo-age-time pos)))) (cond ((< days 1) "today") ((< days 7) (format "%dd" days)) ((< days 30) (format "%.1fw" (/ days 7.0))) ((< days 358) (format "%.1fM" (/ days 30.0))) (t (format "%.1fY" (/ days 365.0)))))) (defun fcuny/org-refile-to-datetree (&optional file) "Refile current subtree to a datetree in FILE corresponding to it's timestamp. The current time is used if the entry has no timestamp. If FILE is nil, refile in the current file." (interactive) (require 'org-datetree) (let* ((file (cond (file (find-file-noselect file)) (t (current-buffer)))) (datetree-date (or (org-entry-get nil "CREATED" t) (org-read-date t nil "now"))) (date (org-date-to-gregorian datetree-date))) (org-refile nil nil (list nil (buffer-file-name file) nil (with-current-buffer file (save-excursion (org-datetree-find-date-create date) (point))))))) (defun fcuny/org-refile-to-work-journal () "Refile current subtree to a datetree in work journal corresponding to it's timestamp. The current time is used if the entry has no timestamp." (interactive) (fcuny/org-refile-to-datetree org-default-work-journal-file)) (defun fcuny/org-subtree-region () "Return a list of the start and end of a subtree." (save-excursion (list (progn (org-back-to-heading) (point)) (progn (org-end-of-subtree) (point))))) (defun fcuny/org-refile-directly (file-dest) "Move the current subtree to the end of FILE-DEST. If SHOW-AFTER is non-nil, show the destination window, otherwise, this destination buffer is not shown." (interactive "fDestination: ") (defun dump-it (file contents) (find-file-other-window file-dest) (goto-char (point-max)) (insert "\n" contents)) (save-excursion (let* ((region (fcuny/org-subtree-region)) (contents (buffer-substring (first region) (second region)))) (apply 'kill-region region) (save-window-excursion (dump-it file-dest contents))))) (defun fcuny/org-refile-to-task () "Refile (move) the current Org subtree to `org-default-tasks-file'." (interactive) (fcuny/org-refile-directly org-default-tasks-file)) (defun fcuny/org-refile-to-personal () "Refile (move) the current Org subtree to `org-default-personal-file'." (interactive) (fcuny/org-refile-directly org-default-personal-file)) (defun fcuny/org-refile-to-notes () "Refile (move) the current Org subtree to `org-default-notes-file'." (interactive) (fcuny/org-refile-directly org-default-notes-file)) (defun fcuny/org-refile-to-work () "Refile (move) the current Org subtree to `org-default-work-file'." (interactive) (fcuny/org-refile-directly org-default-work-file)) (provide 'fcuny-org)