123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856 |
- ;;; Code:
- (require 'alert)
- (require 'org)
- (require 'appt)
- (require 'org-clock)
- (require 'org-habit)
- (require 'org-goto)
- (require 'org-depend)
- (require 'org-contacts)
- (require 'org-notify)
- (require 'org-mime nil 'noerror)
- (require 'org-crypt)
- (require 'org-protocol)
- (require 'org-projectile)
- (require 'org-annotate-file)
- (require 'gnus-icalendar)
- (require 'midnight)
- (require 'bookmark)
- (with-eval-after-load 'ox
- (require 'ox-rst)
- (require 'ox-hugo))
- ;; Vars
- (defvar-local distopico:org--directory (expand-file-name "~/Documents/org/"))
- (defvar-local distopico:org--agenda-files '("daily.org" "calendar.org" "notes.org" "life.org" "todo.org" "contacts.org"))
- (defvar-local distopico:org--special-categories '("Holiday" "Birthday" "Vacation"))
- (defvar-local distopico:org--icons (in-emacs-d "themes/icons/"))
- (defvar-local distopico:org--clock-default-effort "1:00")
- (defvar-local distopico::org--state-remove-trigger '("TODO" "HOLD"))
- (defvar distopico:org--appt-current nil)
- ;; Configuration
- (setq org-modules
- (append org-modules
- '(org-contacts
- org-habit
- org-toc
- org-notify
- ol-gnus
- ;;org-pomodoro
- org-depend
- org-mime
- org-crypt
- org-protocol
- org-projectile)))
- ;; General settings
- (setq org-directory distopico:org--directory
- org-startup-folded t
- org-log-done 'time
- org-log-into-drawer t
- org-auto-align-tags t
- org-support-shift-select t
- org-track-ordered-property-with-tag t
- org-src-fontify-natively t
- org-src-tab-acts-natively t
- org-yank-adjusted-subtrees t
- org-use-speed-commands t
- org-special-ctrl-k t
- org-special-ctrl-a/e t
- ;; org-startup-indented nil
- ;; org-hide-leading-stars nil
- org-src-preserve-indentation t
- org-reverse-note-order nil
- org-M-RET-may-split-line nil
- org-cycle-separator-lines 2
- org-blank-before-new-entry '((heading . auto) (plain-list-item . auto)) ;; TODO: check this if have problems with blank spaces
- org-tags-column -120
- org-refile-use-outline-path nil
- org-refile-allow-creating-parent-nodes 'confirm
- org-refile-targets '((org-agenda-files . (:maxlevel . 4)))
- org-goto-interface 'outline
- org-goto-max-level 10)
- ;; Contacts
- (setq org-contacts-files (list (expand-file-name "contacts.org" org-directory)))
- ;; Diary to Org
- (setq diary-file (concat org-directory "diary")
- org-agenda-diary-file (expand-file-name "calendar.org" org-directory))
- ;;Archive
- (setq org-archive-location (expand-file-name "archive/archive_%s::" org-directory))
- ;; General Notes
- (setq org-default-notes-file (expand-file-name "notes.org" org-directory))
- ;; Annotation
- (setq org-annotate-file-storage-file (expand-file-name "notes.org" org-directory)
- org-annotate-file-add-search t)
- ;; Workflow definition
- (setq org-use-fast-todo-selection t
- org-enforce-todo-dependencies t
- org-todo-keywords
- '((sequence "TODO(t)" "NEXT(n)" "STARTED(s!)" "|" "DONE(d!)")
- (sequence "HOLD(h)" "WAITING(w@/!)" "|" "CANCELED(c@/!)")
- (sequence "PROJECT(p!)" "|" "SOMEDAY(m)"))
- org-stuck-projects
- '("TODO=\"HOLD\"|TODO=\"PROJECT\"|@distopia/-DONE"
- ("TODO" "NEXT" "STARTED" "WAITING")
- nil "")
- org-todo-state-tags-triggers '(("CANCELLED" ("archive" . t)))
- org-clock-out-when-done '("HOLD" "WAITING" "CANCELLED" "DONE")
- org-todo-keyword-faces
- '(("TODO" . (:foreground "#df3800" :weight bold))
- ("STARTED" . (:foreground "#e0c625" :weight bold))
- ("NEXT" . (:foreground "DeepPink2" :weight bold))
- ("HOLD" . (:foreground "#b68800" :weight bold))
- ("WAITING" . (:foreground "#4d9694" :weight bold))
- ("CANCELED" . (:foreground "#566ea2" :weight bold))
- ("DONE" . (:foreground "#448c27" :weight bold))
- ("PROJECT" . (:foreground "orchid" :weight bold)))
- org-default-priority ?D
- org-lowest-priority ?E
- org-priority-faces
- '((?A . "#f01a0f")
- (?B . "#f0640f")
- (?C . "light sea green")
- (?D . "slate blue")))
- ;; Default tags
- (setq org-tag-persistent-alist
- '(("@work" . ?b)
- ("@home" . ?h)
- ("@bookmarks" . ?m)
- ("@writing" . ?w)
- ("@errands" . ?e)
- ("@haking" . ?c)
- ("@reading" . ?r)
- ("@laptop" . ?l)
- ("@pc" . ?p)
- ("@weekly" . ?W)
- ("@family" . ?f)))
- ;; Templates
- (setq org-capture-templates
- `(;; General todo task
- ("t" "Todo" entry
- (file+headline ,(concat org-directory "todo.org") "Backlog")
- "* TODO %?\n%A\n%i\n" :prepend t :clock-resume t :refile-targets ((nil :maxlevel . 1)))
- ;; Task with specific time
- ("T" "Tasks" entry
- (file+headline ,(concat org-directory "todo.org") "Various Tasks")
- "* TODO %^{Task}%?\n SCHEDULED: %^t\n")
- ;; Task with minimum effort
- ("q" "Quick task" item
- (file+headline ,(concat org-directory "todo.org") "Quick Task")
- "- [ ] %^{Task}" :immediate-finish t)
- ;; Web bookmark
- ("B" "Bookmark" item
- (file+function ,(concat org-directory "bookmarks.org") distopico:org-ask-headline-target)
- "- %a \n%?%:initial\n\n" :refile-targets ((nil :maxlevel . 2)))
- ;; Notes to remember with custom title
- ("n" "Note" entry
- (file+headline org-default-notes-file "General Notes")
- "* %^{Title}\n :PROPERTIES:\n:CREATED:%U\n:END:\n\n%i\n\n%a"
- :prepend t :empty-lines 1)
- ;; Note to remember without tittle
- ("Q" "Quick note" item
- (file+headline org-default-notes-file "Quick Notes"))
- ;; Some unexpected idea about a project
- ("i" "Idea" entry
- (file+headline org-default-notes-file "Idea")
- "* %^{Title}\n %i" :prepend t)
- ;; Manage contacts list
- ("c" "Contacts" entry
- (file+headline distopico:contacts-files "General")
- "* %(org-contacts-template-name)%?\n:PROPERTIES:\n:EMAIL: %(org-contacts-template-email)\n:NICKNAME: \n:END:\n"
- :refile-targets ((nil :maxlevel . 1)))
- ;; Organized my habits of day
- ("h" "Habit" entry
- (file+headline ,(concat org-directory "daily.org") "Habits")
- "* TODO %?\nSCHEDULED: %(format-time-string \"<%Y-%m-%d %h %H:%M .+1d/3d>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:CAPTURED: %U\n:END:"
- :clock-resume t)
- ;; Some real life tasks
- ("l" "Life Task" entry
- (file+headline ,(concat org-directory "life.org") "Life Tasks")
- "* TODO %?\n %i\n%a")
- ;; For my life
- ("b" "Stuff to buy" entry
- (file+headline ,(concat org-directory "life.org") "Stuff to buy")
- "* TODO %^{Title}%?\n" :prepend t)
- ;; Notes without specific space
- ("o" "Organizer" entry
- (file+function org-default-notes-file distopico:org-ask-headline-target)
- "** %?\n<%<%Y-%m-%d %a %T>>")
- ;; I haven't many events in my life
- ("e" "Event" entry
- (file+headline ,(concat org-directory "calendar.org") "Events")
- "* %^{Event}%? %^g\n%i\n%^T\n:PROPERTIES:\n:APPT_WARNTIME: %^{Wartime min/hour}\n:END:\n")
- ;; Some event in website
- ("E" "Event Link" entry
- (file+headline ,(concat org-directory "calendar.org") "Events")
- "* %^{Event}%? %^g\n%A\n%^T\n%i\n:PROPERTIES:\n:APPT_WARNTIME: %^{Wartime min/hour}\n:END:\n")
- ;; Remember response some email
- ("M" "Messages" entry
- (file+headline org-default-notes-file "Messages")
- "* NEXT Respond to %:fromaddress on %:subject\nSCHEDULED: %t\n CAPTURED: %U\n%a\n")))
- ;; Agenda
- (setq org-agenda-files (mapcar (lambda (x) (expand-file-name x org-directory)) distopico:org--agenda-files)
- org-agenda-window-setup 'only-window
- org-agenda-restore-windows-after-quit t
- org-agenda-skip-deadline-prewarning-if-scheduled t
- org-agenda-skip-timestamp-if-done t
- org-agenda-skip-deadline-if-done t
- org-agenda-skip-scheduled-if-done t
- org-agenda-insert-diary-extract-time t
- org-agenda-todo-list-sublevels t
- org-agenda-dim-blocked-tasks t
- ;; nil
- org-agenda-include-diary nil
- org-agenda-sticky nil
- org-agenda-remove-tags nil
- ;; Other
- org-agenda-tags-column -102
- org-agenda-span 2
- org-agenda-day-face-function 'distopico:org-agenda-day-face-special-function
- org-agenda-category-icon-alist
- `(("Emacs"
- ,(if window-system
- "~/.emacs.d/themes/icons/emacs.png"
- (list "ξ")) nil nil :ascent center)
- ("Holiday\\|Vacation"
- ,(if window-system
- "~/.emacs.d/themes/icons/holidays.png"
- (list "☀")) nil nil :ascent center)
- (".*" '(space . (:width (16)))))
- org-agenda-custom-commands
- '(("p" "Projects" tags "@distopia|PROJECT"
- ((org-agenda-dim-blocked-tasks t)
- (org-agenda-skip-scheduled-if-done nil)
- (org-agenda-skip-deadline-if-done nil)
- (org-agenda-todo-ignore-with-date nil)
- (org-agenda-todo-ignore-scheduled nil)
- (org-agenda-todo-ignore-deadlines nil)))
- ("N" "Next to do" tags-todo "next|NEXT|SCHEDULED=\".*\"")
- ("b" "Things to buy any time" tags-todo "+tobuy+SCHEDULED=\"\"")
- ("y" "Syadmin stuff to do" tags-todo "+sysadmin+SCHEDULED=\"\"")
- ("D" "Daily tasks:" tags "daily|CATEGORY=\"daily\"|STYLE=\"habit\"")))
- ;;Appointment
- (setq appt-audible nil
- appt-display-diary nil
- appt-display-mode-line t
- appt-display-format 'window
- appt-message-warning-time 16
- appt-display-interval 8
- appt-disp-window-function 'distopico:org-appt-disp-window-function
- appt-delete-window-function 'distopico:org-appt-delete-window-function)
- ;; Notify
- (setq org-notify-audible nil)
- (org-notify-add 'default
- '(:time "16m" :duration 20 :actions -notify)
- '(:time "2h" :actions -message)
- '(:time "3d" :actions -email))
- ;; Clocks
- (setq org-clock-auto-clock-resolution 'when-no-clock-is-running
- org-clock-clocktable-default-properties '(:maxlevel 3 :scope file)
- org-clock-history-length 20
- org-clock-in-resume t
- org-clock-in-switch-to-state 'distopico:clock-in-to-next
- org-clock-out-remove-zero-time-clocks t
- org-clock-into-drawer t
- org-clock-persist 'history
- org-clock-report-include-clocking-task t
- org-show-notification-handler 'distopico:show-notification-handler
- org-clock-persist-file (in-emacs-d ".cache/org-clock-save.el"))
- ;; Habits
- (setq org-habit-graph-column 60
- org-habit-show-done-always-green t)
- ;; mu4e
- (setq org-capture-templates-contexts
- '(("M" ((in-mode . "mu4e-headers-mode")
- (in-mode . "mu4e-view-mode")))))
- (setq gnus-icalendar-org-capture-file (concat org-directory "calendar.org")
- gnus-icalendar-org-capture-headline '("Personal"))
- ;; Org Projectile
- (setq org-projectile-projects-file (expand-file-name "todo.org" org-directory))
- (push (org-projectile-project-todo-entry) org-capture-templates)
- ;; (add-to-list 'org-capture-templates
- ;; (org-projectile:project-todo-entry "p" "* TODO %? %a" "Project Todo"))
- ;; Add export back-ends
- (dolist (source '(md gfm rst))
- (add-to-list 'org-export-backends source t))
- ;; Babel
- (org-babel-do-load-languages
- 'org-babel-load-languages
- '((emacs-lisp . t)
- (js . t)
- (css . t)
- (latex . t)
- (python . t)
- (shell . t)))
- ;; Crypt
- (org-crypt-use-before-save-magic)
- (setq org-tags-exclude-from-inheritance '("crypt")
- org-crypt-disable-auto-save t)
- ;; midnight
- (setq midnight-mode t)
- (remove-hook 'midnight-hook 'clean-buffer-list)
- ;; Custom map key
- (define-key org-mode-map (kbd "C-M-s-<return>") 'distopico:org-insert-todo-subheading)
- (define-key org-mode-map (kbd "C-M-<return>") 'distopico:org-insert-subheading)
- (define-key org-mode-map (kbd "M-s-<return>") 'distopico:org-insert-heading-for-next-day)
- (define-key org-mode-map (kbd "C-c k") 'org-cut-subtree)
- (define-key org-mode-map (kbd "C-c q") 'org-copy-subtree)
- (define-key org-mode-map (kbd "C-c y") 'org-paste-subtree)
- (define-key org-agenda-mode-map (kbd "C-<tab>") 'org-agenda-cycle-show)
- (define-key org-agenda-mode-map (kbd "M-d") 'distopico:org-agenda-done)
- (define-key org-agenda-mode-map (kbd "M-D") 'distopico:org-agenda-mark-done-and-add)
- (define-key org-agenda-mode-map (kbd "M-n") 'distopico:org-agenda-new)
- (define-key org-agenda-mode-map (kbd "M-y") 'org-agenda-todo-yesterday)
- (define-key org-agenda-mode-map (kbd "M-p") 'org-pomodoro)
- (define-key org-agenda-mode-map (kbd "M-q") 'org-agenda-quit)
- (define-key org-agenda-mode-map (kbd "C-q") 'bury-buffer)
- (define-key org-agenda-mode-map "q" 'bury-buffer)
- (define-key bookmark-bmenu-mode-map (kbd "a") 'distopico:org-show-annotations-bookmark)
- (add-to-list 'org-speed-commands '("n" distopico:org-show-next-heading-tidily))
- (add-to-list 'org-speed-commands '("p" distopico:org-show-previous-heading-tidily))
- ;; Update always at 9:30
- (run-at-time "9:30" nil 'distopico:org-show-agenda-appt)
- ;; Update org-agenda buffer each 10min/600sec
- (run-at-time nil 600 'distopico:org-agenda-redo-in-other-window)
- ;; Functions
- (with-no-warnings (defvar date))
- (defun distopico:org-lunar-phases ()
- "Show lunar phase in Agenda buffer."
- (let* ((phase-list (lunar-phase-list (nth 0 date) (nth 2 date)))
- (phase (cl-find-if (lambda (phase) (equal (car phase) date))
- phase-list)))
- (when phase
- (setq ret (concat (lunar-phase-name (nth 2 phase)) " "
- (substring (nth 1 phase) 0 5))))))
- (defun distopico:show-notification-handler (message)
- "Handler for `org-mode' notifications using `alert' mode.
- Display the `MESSAGE' as body notification.
- TODO: make this generic to replace `distopico:org-appt-disp-window-function'."
- (progn
- (alert message
- :title "Org-mode"
- :mode 'org-mode
- :severity 'normal
- :style 'notifications
- :category 'emacs
- :icon (concat distopico:org--icons "org-mode.png"))))
- (defun distopico:org-appt-disp-window-function (left time message)
- "Show notification on appointments based on `LEFT' `TIME' `MESSAGE'."
- (progn
- (add-to-list 'distopico:org--appt-current message)
- (alert message
- :title (concat "Appointment "
- (cond ((equal left "0") "now!")
- ((equal left "1") "in 1 minute!")
- (t (format "in %s minutes" left))))
- :mode 'org-mode
- :severity 'moderate
- :style 'notifications
- :category 'emacs
- :icon (concat distopico:org--icons "org-mode.png"))))
- (defun distopico:org-appt-delete-window-function ()
- "Delete appointment after show it."
- (if distopico:org--appt-current
- (setq distopico:org--appt-current
- (delete (nth 0 distopico:org--appt-current) distopico:org--appt-current))))
- (defun distopico:org-remove-redundant-tags ()
- "Remove redundant tags of headlines in current buffer.
- A tag is considered redundant if it is local to a headline and
- inherited by a parent headline.
- From https://github.com/thisirs/dotemacs/blob/master/init-org.el"
- (interactive)
- (when (eq major-mode 'org-mode)
- (save-excursion
- (org-map-entries
- (lambda ()
- (let ((alltags (split-string (or (org-entry-get (point) "ALLTAGS") "") ":"))
- local inherited tag)
- (dolist (tag alltags)
- (if (get-text-property 0 'inherited tag)
- (push tag inherited) (push tag local)))
- (dolist (tag local)
- (if (member tag inherited) (org-toggle-tag tag 'off)))))
- t nil))))
- (defun distopico:org-saveplace ()
- "Fix a problem with saveplace.el putting you back in a folded position."
- (when (outline-invisible-p)
- (save-excursion
- (outline-previous-visible-heading 1)
- (org-show-subtree))))
- (defun distopico:org-show-next-heading-tidily ()
- "Show next entry, keeping other entries closed."
- (if (save-excursion (end-of-line) (outline-invisible-p))
- (progn (org-show-entry) (show-children))
- (outline-next-heading)
- (unless (and (bolp) (org-on-heading-p))
- (org-up-heading-safe)
- (outline-hide-subtree)
- (org-cycle-show-empty-lines t)
- (message "Boundary reached"))
- (org-overview)
- (org-cycle-show-empty-lines t)
- (org-reveal t)
- (org-show-entry)
- (outline-show-children)
- (org-cycle-show-empty-lines t) ))
- (defun distopico:org-show-previous-heading-tidily ()
- "Show previous entry, keeping other entries closed."
- (let ((pos (point)))
- (outline-previous-heading)
- (unless (and (< (point) pos) (bolp) (org-on-heading-p))
- (goto-char pos)
- (outline-hide-subtree)
- (org-cycle-show-empty-lines t)
- (message "Boundary reached"))
- (org-overview)
- (org-cycle-show-empty-lines t)
- (org-reveal t)
- (org-show-entry)
- (outline-show-children)
- (org-cycle-show-empty-lines t) ))
- (defun distopico:org-insert-subheading (arg)
- "Insert a new subheading `ARG' and demote it same to `org-insert-subheading'.
- This also removes blank lines from level 1.
- Works for outline headings and for plain lists alike."
- (interactive "P")
- (org-insert-heading-respect-content arg)
- (let ((pos (point)))
- (let ((cur-level (org-current-level))
- (prev-level (org-get-previous-line-level)))
- (when (= prev-level 1)
- (forward-line -1)
- (delete-blank-lines)
- (goto-char (min (point) pos)))))
- (cond
- ((org-at-heading-p) (org-do-demote))
- ((org-at-item-p) (org-indent-item)))
- (end-of-line))
- (defun distopico:org-insert-todo-subheading (arg)
- "Insert a new subheading `ARG' with TODO keyword or checkbox and demote it.
- Same to `org-insert-subheading' but remove blank lines from level 1.
- Works for outline headings and for plain lists alike."
- (interactive "P")
- (org-insert-todo-heading-respect-content arg)
- (let ((pos (point)))
- (let ((cur-level (org-current-level))
- (prev-level (org-get-previous-line-level)))
- (when (= prev-level 1)
- (forward-line -1)
- (delete-blank-lines)
- (goto-char (min (point) pos)))))
- (cond
- ((org-at-heading-p) (org-do-demote))
- ((org-at-item-p) (org-indent-item)))
- (end-of-line))
- (defun distopico:org-insert-heading-for-next-day ()
- "Insert a same-level heading for the following day.
- from: http://pages.sachachua.com/.emacs.d/Sacha.html"
- (interactive)
- (let ((new-date
- (seconds-to-time
- (+ 86400.0
- (float-time
- (org-read-date nil 'to-time (elt (org-heading-components) 4)))))))
- (org-insert-heading-after-current)
- (insert (format-time-string "%Y-%m-%d\n" new-date))))
- (defun distopico:org-insert-trigger ()
- "Automatically insert chain-find-next trigger on NEXT state."
- (cond ((equal org-state "NEXT")
- (unless org-depend-doing-chain-find-next
- (org-set-property "TRIGGER" "chain-find-next(NEXT,from-current,priority-up,effort-down)")))
- ((member org-state distopico::org--state-remove-trigger)
- (save-excursion
- (org-show-entry)
- (org-delete-property "TRIGGER")))))
- (defun distopico:org-toggle-next-tag ()
- "Org possibly toggle next tag based on todo keyword."
- (save-excursion
- (org-back-to-heading)
- (let ((todo-is-next (equal (org-get-todo-state) "NEXT"))
- (next-in-tags (member "NEXT" (org-get-tags))))
- (if (or (and todo-is-next (not next-in-tags))
- (and (not todo-is-next) next-in-tags))
- (org-toggle-tag "next" 'on)
- (org-toggle-tag "next" 'off)))))
- (defun distopico:org:remove-empty-propert-drawers ()
- "Remove all empty property drawers in current file."
- (interactive)
- (unless (eq major-mode 'org-mode)
- (error "You need to turn on Org mode for this function"))
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward ":PROPERTIES:" nil t)
- (save-excursion
- (org-remove-empty-drawer-at (match-beginning 0))))))
- (defun distopico:org-add-default-effort ()
- "Add a default effort estimation."
- (unless (org-entry-get (point) "Effort")
- (org-set-property "Effort" distopico:org--clock-default-effort)))
- (defun distopico:org-agenda-redo-in-other-window ()
- "Call `org-agenda-redo' function even in the non-agenda buffer."
- (interactive)
- (let ((agenda-window (get-buffer-window org-agenda-buffer-name t)))
- (when agenda-window
- (with-selected-window agenda-window (org-agenda-redo)))))
- (defun distopico:org-show-agenda (&optional open-same-window)
- "Switch to the org agenda, or prompt for new one if one does not exist.
- optional `OPEN-SAME-WINDOW'"
- (interactive "P")
- (let ((agenda-buffer (get-buffer "*Org Agenda*")))
- (if agenda-buffer
- (if open-same-window
- (switch-to-buffer agenda-buffer)
- (switch-to-buffer-other-window agenda-buffer))
- (org-agenda-list))
- (tabbar-local-mode 1)))
- (defun distopico:org-show-agenda-appt ()
- "Update appt and show agenda."
- (interactive)
- (distopico:org-show-agenda))
- (defun distopico:org-agenda-done (&optional arg)
- "Mark current TODO as done optional `ARG' are unused.
- This change 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.
- from: http://pages.sachachua.com/.emacs.d/Sacha.html"
- (interactive "P")
- (org-agenda-todo "DONE"))
- (defun distopico:org-agenda-mark-done-and-add ()
- "Mark the current TODO as done and add another task after it.
- Creates it at the same level as the previous task, so it's better to use
- this with to-do items than with projects or headings.
- from: http://pages.sachachua.com/.emacs.d/Sacha.html"
- (interactive)
- (org-agenda-todo "DONE")
- (org-agenda-switch-to)
- (org-capture 0 "t"))
- (defun distopico:org-agenda-new ()
- "Create a new note or task at the current agenda item.
- Creates it at the same level as the previous task, so it's better to use
- this with to-do items than with projects or headings."
- (interactive)
- (org-agenda-switch-to)
- (org-capture 0))
- (defun distopico:org-agenda-day-face-special-function (date)
- "Compute DATE face for holidays/vacations/birthday."
- (unless (org-agenda-today-p date)
- (dolist (file (org-agenda-files nil 'ifmode))
- (let ((face
- (dolist (entry (org-agenda-get-day-entries file date))
- (let ((category (with-temp-buffer
- (insert entry)
- (org-get-category (point-min)))))
- (when (string-match
- (mapconcat 'downcase distopico:org--special-categories "\\|")
- category)
- (cl-return '(:foreground "PaleGreen")))))))
- (when face (cl-return face))))))
- (defun distopico:org-update-agenda-views ()
- "Update all org agenda buffers (if any)."
- (save-window-excursion
- (mapc
- (lambda (buf)
- (with-current-buffer buf
- (org-agenda-redo t)))
- (get-buffers-with-major-mode 'org-agenda-mode))))
- (defun distopico:remove-empty-drawer-on-clock-out ()
- "Delete clocking drawer if it is empty."
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward ":LOGBOOK:" nil t) ;
- (save-excursion
- (org-remove-empty-drawer-at (match-beginning 0))))
- (while (re-search-forward ":CLOCK:" nil t) ;
- (save-excursion
- (org-remove-empty-drawer-at (match-beginning 0))))))
- (defun distopico:clock-in-to-next (state) ;
- "Switch task from TODO `STATE' to NEXT when clocking in.
- Skips capture tasks and tasks with subtasks."
- (if (and (string-equal state "TODO")
- (not (or (string-equal "*Remember*" (buffer-name))
- (string-prefix-p "CAPTURE-" (buffer-name)))))
- (let ((subtree-end (save-excursion (org-end-of-subtree t)))
- (has-subtask nil))
- (save-excursion
- (forward-line 1)
- (while (and (not has-subtask)
- (< (point) subtree-end)
- (re-search-forward "^\*+ " subtree-end t))
- (when (member (org-get-todo-state) org-not-done-keywords)
- (setq has-subtask t))))
- (when (not has-subtask)
- "NEXT"))))
- (defun distopico:org-clock-in-set-state-to-started ()
- "Mark STARTED when clocked in."
- (save-excursion
- (catch 'exit
- (cond
- ((derived-mode-p 'org-agenda-mode)
- (let* ((marker (or (org-get-at-bol 'org-marker)
- (org-agenda-error)))
- (hdmarker (or (org-get-at-bol 'org-hd-marker) marker))
- (pos (marker-position marker))
- (col (current-column))
- newhead)
- (org-with-remote-undo (marker-buffer marker)
- (with-current-buffer (marker-buffer marker)
- (widen)
- (goto-char pos)
- (org-back-to-heading t)
- (if (org-get-todo-state)
- (org-todo "STARTED"))))))
- (t (if (org-get-todo-state)
- (org-todo "STARTED")))))))
- (defun distopico:org-inherited-no-file-tags ()
- "Preserves the logic of level one groupings."
- (let ((tags (org-entry-get nil "ALLTAGS" 'selective))
- (ltags (org-entry-get nil "TAGS")))
- (mapc (lambda (tag)
- (setq tags
- (replace-regexp-in-string (concat tag ":") "" tags)))
- (append org-file-tags (when ltags (split-string ltags ":" t))))
- (if (string= ":" tags) nil tags)))
- (defun distopico:org-ask-headline-target (&optional prompt targets)
- "Ask headline location, optional pass custom `PROMPT' text and `TARGETS'."
- (let* ((loc-prompt (or prompt "Headline"))
- (org-refile-targets (or targets '((nil :maxlevel . 2))))
- (hd (condition-case nil
- (car (org-refile-get-location loc-prompt nil t))
- (error (car org-refile-history)))))
- (goto-char (point-min))
- (outline-next-heading)
- (if (re-search-forward
- (format org-complex-heading-regexp-format (regexp-quote hd))
- nil t)
- (goto-char (point-at-bol))
- (goto-char (point-max)))))
- (defun distopico:org-show-annotations-bookmark ()
- "Opens the annotations window for the currently selected bookmark file."
- (interactive)
- (bookmark-bmenu-other-window)
- (org-annotate-file))
- (defun distopico:org-run-appt ()
- "Run org appointments."
- (interactive)
- (setq appt-time-msg-list nil)
- (when (not appt-timer)
- (appt-activate +1))
- (org-agenda-to-appt))
- (defun distopico:org-appt-add-hook-async ()
- (async-start
- `(lambda ()
- (require 'org-agenda)
- ,(add-hook 'after-init-hook
- `(lambda ()
- ,(distopico:org-run-appt)
- ))) 'ignore))
- (defun distopico:org-reset-appts ()
- "This also reverts all files, but it does update the appt list."
- (interactive)
- (setq appt-time-msg-list nil)
- (cl-flet ((yes-or-no-p (x) t))
- (org-revert-all-org-buffers))
- (org-agenda-to-appt))
- ;; Advice functions
- (defun distopico:org--capture-refile (orig-fun &rest args)
- "Advise or `org--capture-refile' to use `prepend' property.
- This wrap `ORIG-FUN' with it `ARGS' overwriting `org-reverse-note-order'."
- (let ((org-reverse-note-order (org-capture-get :prepend 'local)))
- (apply orig-fun args)))
- (defun distopico:org--capture-finalize (&optional stay-with-capture)
- "Advise capture-finalize to close the frame.
- See: `org-capture-finalize' for `STAY-WITH-CAPTURE' docs."
- (if (equal "emacs-capture" (frame-parameter nil 'name))
- (delete-frame)))
- (defun distopico:org--capture-kill ()
- "Advise capture-kill to close the frame."
- (if (equal "emacs-capture" (frame-parameter nil 'name))
- (delete-frame)))
- (defadvice org-archive-subtree (around distopico:org-archive-subtree-low-level activate)
- "Preserve top level headings when archiving to a file."
- ;; TODO: migrate to new advice
- (let ((tags (distopico:org-inherited-no-file-tags))
- (afile (car (org-archive--compute-location
- (or (org-entry-get nil "ARCHIVE" 'inherit) org-archive-location))))
- (org-archive-location
- (if (save-excursion (org-back-to-heading)
- (> (org-outline-level) 1))
- (concat (car (split-string org-archive-location "::"))
- "::* "
- (car (org-get-outline-path)))
- org-archive-location)))
- ad-do-it
- (when (and (not current-prefix-arg)
- (not (use-region-p)))
- (with-current-buffer (find-file-noselect afile)
- (save-excursion
- (while (org-up-heading-safe))
- (org-set-tags-to tags))))))
- (advice-add #'org-capture-refile :around 'distopico:org--capture-refile)
- (advice-add #'org-capture-finalize :after 'distopico:org--capture-finalize)
- (advice-add #'org-capture-kill :after 'distopico:org--capture-kill)
- ;; Hooks
- (defun distopico:org-init-hook ()
- "Hook for set up `org-mode' on init."
- ;; Org mime messages to HTML
- (when (fboundp 'org-mime-org-buffer-htmlize)
- (local-set-key (kbd "C-c M-o") 'org-mime-org-buffer-htmlize))
- ;; (distopico:org-saveplace) TODO: check if already need it
- ;; Try when enable org-indent-mode again
- ;; (aggressive-indent-mode)
- ;; TODO enable for blogging, no enabled by default because
- ;; with tags indented does not look good, maybe disable tags
- ;; indentation is one option.
- ;; (visual-line-mode +1)
- (flyspell-mode +1)
- (add-hook 'completion-at-point-functions 'pcomplete-completions-at-point nil 'make-it-local)
- (add-hook 'before-save-hook 'distopico:org-before-save-hook nil 'make-it-local)
- (add-hook 'after-save-hook 'distopico:org-after-save-hook nil 'make-it-local))
- (defun distopico:org-after-save-hook ()
- "Hook for after save in `org-mode'."
- (when (eq major-mode 'org-mode)
- (distopico:org-run-appt)
- (distopico:org:remove-empty-propert-drawers)
- (org-save-all-org-buffers)
- (message (concat "Wrote " (buffer-file-name)))))
- (defun distopico:org-before-save-hook ()
- "Hook for before save in `org-mode'."
- (when (eq major-mode 'org-mode)
- (and buffer-file-name
- (file-exists-p buffer-file-name)
- (distopico:org-remove-redundant-tags))
- (org-align-tags t)
- (org-update-all-dblocks)))
- (defun distopico:org-capture-mode-hook ()
- "Hook for `org-capture-mode'."
- (flyspell-mode +1)
- ;; Capture to be the only window when used as a popup.
- (if (equal "emacs-capture" (frame-parameter nil 'name))
- (delete-other-windows)))
- (defun distopico:org-capture-before-finalize-hook ()
- "Hook for capture before finalized in`org-mode'."
- (org-align-tags))
- (defun distopico:org-capture-after-finalize-hook ()
- "Hook for capture after finalized in`org-mode'."
- (if (equal "emacs-capture" (frame-parameter nil 'name))
- (delete-frame))
- (distopico:org-update-agenda-views))
- (defun distopico:org-init-load-hook ()
- "Hook when Emacs load."
- (distopico:org-run-appt)
- (org-notify-start))
- (defun distopico:org-after-todo-state-change-hook ()
- "Hook after a todo state change happens."
- (distopico:org-toggle-next-tag)
- (distopico:org-insert-trigger))
- ;; Hooks
- (add-hook 'org-mode-hook 'distopico:org-init-hook)
- (add-hook 'org-after-todo-state-change-hook #'distopico:org-after-todo-state-change-hook 'append)
- (add-hook 'midnight-hook 'distopico:org-show-agenda-appt 'append)
- (add-hook 'distopico:after-init-load-hook #'distopico:org-init-load-hook)
- (with-eval-after-load 'org-capture
- (add-hook 'org-capture-mode-hook #'distopico:org-capture-mode-hook 'append)
- (add-hook 'org-capture-before-finalize-hook #'distopico:org-capture-before-finalize-hook 'append)
- (add-hook 'org-capture-after-finalize-hook #'distopico:org-capture-after-finalize-hook 'append))
- (with-eval-after-load 'org-clock
- (org-clock-persistence-insinuate)
- (add-hook 'org-clock-in-hook
- (lambda ()
- (pomodoro)
- (add-hook 'pomodoro-break-finished-hook 'org-clock-in-last)
- (add-hook 'pomodoro-finished-hook 'org-clock-out)
- (distopico:org-clock-in-set-state-to-started)) 'append)
- (add-hook 'org-clock-out-hook
- (lambda ()
- (distopico:remove-empty-drawer-on-clock-out)) 'append)
- (add-hook 'org-clock-cancel-hook
- (lambda ()
- (pomodoro-stop)
- (remove-hook 'pomodoro-break-finished-hook 'org-clock-in-last)
- (remove-hook 'pomodoro-finished-hook 'org-clock-out)
- (distopico:remove-empty-drawer-on-clock-out)) 'append))
- (provide 'conf-org)
- ;;; conf-org.el ends here
|