From 9a07d3aacce17cb7ccaf489c53b5cb12d1f5da9f Mon Sep 17 00:00:00 2001 From: Aaron LI Date: Mon, 13 Mar 2017 22:00:29 +0800 Subject: spacemacs: Change 'aly' -> 'my' --- _spacemacs.d/config/aly-mu4e-config.el | 353 ----------------------------- _spacemacs.d/config/aly-org-config.el | 286 ----------------------- _spacemacs.d/config/aly-org-helpers.el | 399 --------------------------------- _spacemacs.d/config/my-mu4e.el | 353 +++++++++++++++++++++++++++++ _spacemacs.d/config/my-org-helpers.el | 399 +++++++++++++++++++++++++++++++++ _spacemacs.d/config/my-org.el | 286 +++++++++++++++++++++++ _spacemacs.d/init.el | 4 +- 7 files changed, 1040 insertions(+), 1040 deletions(-) delete mode 100644 _spacemacs.d/config/aly-mu4e-config.el delete mode 100644 _spacemacs.d/config/aly-org-config.el delete mode 100644 _spacemacs.d/config/aly-org-helpers.el create mode 100644 _spacemacs.d/config/my-mu4e.el create mode 100644 _spacemacs.d/config/my-org-helpers.el create mode 100644 _spacemacs.d/config/my-org.el diff --git a/_spacemacs.d/config/aly-mu4e-config.el b/_spacemacs.d/config/aly-mu4e-config.el deleted file mode 100644 index d5d31a8..0000000 --- a/_spacemacs.d/config/aly-mu4e-config.el +++ /dev/null @@ -1,353 +0,0 @@ -;;; aly-mu4e-config.el --- mu4e (mu for Emacs) configurations -;; -*- mode: emacs-lisp -*- -;; vim: set ts=8 sw=2 tw=0 fenc=utf-8 ft=lisp: -;; -;; Aaron LI -;; Created: 2016-02-21 -;; Updated: 2016-09-03 -;; - -;;; Commentary: -;; mu4e (mu for Emacs) configurations for spacemacs. -;; mu (maildir indexer/searcher): https://github.com/djcb/mu -;; - -;;; Code: - -;; maildir location -(setq mu4e-maildir "~/mail") - -;; turn on debug: log debug information to the *mu4e-log* buffer -(setq mu4e-debug t) - -(with-eval-after-load 'mu4e - ;; speed up indexing - (setq mu4e-index-cleanup nil) ; don't do a full cleanup check - (setq mu4e-index-lazy-check t) ; don't consider up-to-date directories - - ;; multiple email accounts: contexts (require mu4e >= 0.9.16) - (setq mu4e-contexts - `( ,(make-mu4e-context - :name "Outlook-aly" - :enter-func (lambda () - (mu4e-message "Switched to context: outlook-aly")) - ;; `leave-func' not defined - ;; `match-func' is invoked just before `mu4e-compose-pre-hook' - :match-func (lambda (msg) - (when msg - (mu4e-message-contact-field-matches msg - :to "aaronly.me@outlook.com"))) - :vars '((user-mail-address . "aaronly.me@outlook.com") - (user-full-name . "Aaron LI") - (mu4e-sent-folder . "/outlook-aly/sent") - (mu4e-drafts-folder . "/outlook-aly/drafts") - (mu4e-trash-folder . "/outlook-aly/trash") - (mu4e-refile-folder . "/outlook-aly/archive") - (mu4e-compose-signature . "Aly") - (mu4e-sent-messages-behavior . delete))) - ,(make-mu4e-context - :name "Gmail-aly" - :enter-func (lambda () - (mu4e-message "Switched to context: gmail-aly")) - ;; `leave-func' not defined - :match-func (lambda (msg) - (when msg - (mu4e-message-contact-field-matches msg - :to "aaronly.me@gmail.com"))) - :vars '((user-mail-address . "aaronly.me@gmail.com") - (user-full-name . "Aaron LI") - ;; special folders - (mu4e-sent-folder . "/sent") - (mu4e-drafts-folder . "/gmail-aly/drafts") - (mu4e-trash-folder . "/gmail-aly/trash") - (mu4e-refile-folder . "/gmail-aly/archive") - (mu4e-compose-signature . "Aly") - ;; do NOT save message to 'sent-folder' - (mu4e-sent-messages-behavior . delete))) - ,(make-mu4e-context - :name "outlook-li" - :enter-func (lambda () - (mu4e-message "Switched to context: outlook-li")) - ;; `leave-func' not defined - :match-func (lambda (msg) - (when msg - (mu4e-message-contact-field-matches msg - :to '("liweitianux@live.com" - "liweitianux@outlook.com")))) - :vars '((user-mail-address . "liweitianux@live.com") - (user-full-name . "Weitian LI") - (mu4e-sent-folder . "/outlook-li/sent") - (mu4e-drafts-folder . "/outlook-li/drafts") - (mu4e-trash-folder . "/outlook-li/trash") - (mu4e-refile-folder . "/outlook-li/archive") - (mu4e-compose-signature . "Weitian") - (mu4e-sent-messages-behavior . delete))) - ,(make-mu4e-context - :name "gmail-li" - :enter-func (lambda () - (mu4e-message "Switched to context: gmail-li")) - ;; `leave-func' not defined - :match-func (lambda (msg) - (when msg - (mu4e-message-contact-field-matches msg - :to "liweitianux@gmail.com"))) - :vars '((user-mail-address . "liweitianux@gmail.com") - (user-full-name . "Weitian LI") - (mu4e-sent-folder . "/sent") - (mu4e-drafts-folder . "/gmail-li/drafts") - (mu4e-trash-folder . "/gmail-li/trash") - (mu4e-refile-folder . "/gmail-li/archive") - (mu4e-compose-signature . "Weitian") - (mu4e-sent-messages-behavior . delete))) - ,(make-mu4e-context - :name "sjtu" - :enter-func (lambda () - (mu4e-message "Switched to context: sjtu")) - ;; `leave-func' not defined - :match-func (lambda (msg) - (when msg - (mu4e-message-contact-field-matches msg - :to "liweitianux@sjtu.edu.cn"))) - :vars '((user-mail-address . "liweitianux@sjtu.edu.cn") - (user-full-name . "Weitian LI") - (mu4e-sent-folder . "/sjtu/sent") - (mu4e-drafts-folder . "/sjtu/drafts") - (mu4e-trash-folder . "/sjtu/trash") - (mu4e-refile-folder . "/sjtu/archive") - (mu4e-compose-signature . - (concat "Weitian LI\n" - "Shanghai Jiao Tong University")) - ;; copy message to sent folder - (mu4e-sent-messages-behavior . sent))) - ,(make-mu4e-context - :name "autistici" - :enter-func (lambda () - (mu4e-message "Switched to context: autistici")) - ;; `leave-func' not defined - :match-func (lambda (msg) - (when msg - (mu4e-message-contact-field-matches msg - :to "liweitianux@autistici.org"))) - :vars '((user-mail-address . "liweitianux@autistici.org") - (user-full-name . "Weitian LI") - (mu4e-sent-folder . "/autistici/sent") - (mu4e-drafts-folder . "/autistici/drafts") - (mu4e-trash-folder . "/autistici/trash") - (mu4e-refile-folder . "/autistici/archive") - (mu4e-compose-signature . "Weitian") - ;; copy message to sent folder - (mu4e-sent-messages-behavior . sent))) - ,(make-mu4e-context - :name "foxmail" - :enter-func (lambda () - (mu4e-message "Switched to context: foxmail")) - ;; `leave-func' not defined - :match-func (lambda (msg) - (when msg - (mu4e-message-contact-field-matches msg - :to '("liweitianux@foxmail.com" - "527922216@qq.com")))) - :vars '((user-mail-address . "liweitianux@foxmail.com") - (user-full-name . "Weitian LI") - (mu4e-sent-folder . "/foxmail/sent") - (mu4e-drafts-folder . "/foxmail/drafts") - (mu4e-trash-folder . "/foxmail/trash") - (mu4e-refile-folder . "/foxmail/archive") - (mu4e-compose-signature . "Weitian") - (mu4e-sent-messages-behavior . delete))))) - - ;; start with the first (default) context - ;; default: `ask-if-none' (ask when there's no context yet, and none match) - (setq mu4e-context-policy 'pick-first) - ;; compose with the current context if no context matches - ;; default: `ask' - ;(setq mu4e-compose-context-policy nil) - - ;; auto construct addresses list by extracting addresses from contexts - (setq mu4e-user-mail-address-list - (delq nil - (mapcar (lambda (context) - (when (mu4e-context-vars context) - (cdr (assq 'user-mail-address - (mu4e-context-vars context))))) - mu4e-contexts))) - - ;; send mail using `msmtp' - (setq message-send-mail-function 'message-send-mail-with-sendmail - message-sendmail-f-is-evil t - ;; choose the account according to the `From' header - message-sendmail-extra-arguments '("--read-envelope-from") - sendmail-program "msmtp") - - ;; allow for fetch mail and update index using 'U' in the main view - (setq mu4e-get-mail-command "mbsync -a") - ;; get mail and update index periodically in the background (unit: seconds) - (setq mu4e-update-interval 900) - - ;; frequent mail folders, with shortcuts - ;; NOTE: do not use shortcut `o' as it is used for `[o]ther' - ;(setq mu4e-maildir-shortcuts - ; '(("/important" . ?i) - ; ("/archive" . ?a) - ; ("/gmail-aly/archive" . ?G) - ; ("/gmail-li/archive" . ?g) - ; ("/outlook-aly/inbox" . ?l) - ; ("/outlook-li/inbox" . ?L) - ; ("/sjtu/inbox" . ?s))) - - ;; do not keep message buffers around - (setq message-kill-buffer-on-exit t) - - ;; enable inline images - (setq mu4e-view-show-images t) - ;; use imagemagick if available - (when (fboundp 'imagemagick-register-types) - (imagemagick-register-types)) - - ;; display rich-text messages - (require 'mu4e-contrib) - ;; use `shr' html renderer; reqiure emacs >= 24.4 - (require 'shr) - (setq mu4e-html2text-command 'mu4e-shr2text) - (add-hook 'mu4e-view-mode-hook - (lambda () - ;; try to emulate some of the `eww' key-bindings - (local-set-key (kbd "") 'shr-next-link) - (local-set-key (kbd "") 'shr-previous-link))) - ;; change the luminosity form dark theme - (setq shr-color-visible-luminance-min 70) - - ;; customize bookmarks - (setq mu4e-bookmarks - '(("flag:unread AND NOT flag:trashed" "Unread messages" ?u) - ("date:today..now" "Today's messages" ?T) - ("date:7d..now" "Last 7 days" ?w) - ("date:1m..now" "Last month" ?m) - ("flag:flagged" "Flagged messages" ?f) - ("tag:todo OR tag:task" "TODO / Task" ?t) - ("tag:work" "Work" ?W) - ("tag:astro" "Astro" ?a) - ("tag:arxiv OR from:arxiv.org" "arXiv" ?x) - ("tag:SMS" "SMS" ?S) - ("flag:trashed OR tag:\\\\Trash" "Deleted" ?d) - ("mime:image/*" "Messages with images" ?p))) - - ;; headers list appearance - (setq mu4e-headers-date-format "%Y-%m-%d %H:%M" - mu4e-headers-fields '((:date . 18) ;; also :human-date - (:flags . 5) - (:from-or-to . 22) - (:subject . nil))) ;; also :thread-subject - - ;; header fields to be shown in the view buffer - (add-to-list 'mu4e-view-fields :size t) - (add-to-list 'mu4e-view-fields :user-agent t) - - ;; use fancy non-ascii characters in various places - ;(setq mu4e-use-fancy-chars t) - - ;; show full addresses instead of just names when view message - (setq mu4e-view-show-addresses t) - - ;; also include messages related to the searched messages - (setq mu4e-headers-include-related t) - ;; exclude the duplicate messages with the same `Message-ID' - ;(setq mu4e-headers-skip-duplicates t) - - ;; compose messages in a separate frame - (setq mu4e-compose-in-new-frame t) - - ;; confirm before sending - (add-hook 'message-send-hook - (lambda () - (unless (yes-or-no-p "Sure you want to send this?") - (signal 'quit nil)))) - - ;; custom actions - ;; retag action - (setq mu4e-action-tags-header "X-Keywords") - (add-to-list 'mu4e-headers-actions - '("tRetag message" . mu4e-action-retag-message) t) - (add-to-list 'mu4e-view-actions - '("tRetag message" . mu4e-action-retag-message) t) - ;; view in browser - (add-to-list 'mu4e-view-actions - '("bView in browser" . mu4e-action-view-in-browser) t) - ;; search for messages by the sender of the opened message - (defun search-for-sender (msg) - "Search for messages sent by the sender of the message at point." - (mu4e-headers-search - (concat "from:" (cdar (mu4e-message-field msg :from))))) - (add-to-list 'mu4e-view-actions - '("xSearch for sender" . search-for-sender) t) - - ;; set `mu4e' as emacs' default email program - (setq mail-user-agent 'mu4e-user-agent) - - ;; END: with-eval-after-load 'mu4e - ) - - -;;; Key bindings for Evil -;; Credits: -;; https://github.com/philc/emacs-config - .emacs.d/elisp/mu4e-mode-personal.el - -(dolist (mode '(mu4e-mode - mu4e-main-mode - mu4e-headers-mode - mu4e-view-mode - mu4e-compose-mode)) - (evil-set-initial-state mode 'normal)) - -(with-eval-after-load 'mu4e - (evil-make-overriding-map mu4e-main-mode-map 'normal t) - (evil-define-key 'normal mu4e-main-mode-map - "J" 'mu4e~headers-jump-to-maildir - "j" 'evil-next-line - "k" 'evil-previous-line) - (evil-make-overriding-map mu4e-headers-mode-map 'normal t) - (evil-define-key 'normal mu4e-headers-mode-map - "gg" 'evil-goto-first-line - "J" 'mu4e~headers-jump-to-maildir - "j" 'mu4e-headers-next - "k" 'mu4e-headers-prev - "]" 'mu4e-headers-next-unread - "[" 'mu4e-headers-prev-unread - "C" 'mu4e-compose-new - "E" 'mu4e-compose-edit - "F" 'mu4e-compose-forward - "R" 'mu4e-compose-reply) - (evil-leader/set-key-for-mode 'mu4e-headers-mode - "u" '(lambda () (interactive) (mu4e-update-mail-and-index t))) - ;; - (evil-make-overriding-map mu4e-view-mode-map 'normal t) - (evil-define-key 'normal mu4e-view-mode-map - "gg" 'evil-goto-first-line - "j" 'evil-next-line - "k" 'evil-previous-line - "\C-j" 'mu4e-view-headers-next - "\C-k" 'mu4e-view-headers-prev - "\C-]" 'mu4e-view-headers-next-unread - "\C-[" 'mu4e-view-headers-prev-unread - "C" 'mu4e-compose-new - "E" 'mu4e-compose-edit - "F" 'mu4e-compose-forward - "R" 'mu4e-compose-reply) - (evil-leader/set-key-for-mode 'mu4e-view-mode - "u" '(lambda () (interactive) (mu4e-update-mail-and-index t)) - "x" '(lambda () (interactive) (helm-M-x)) - "s" 'mu4e-view-raw-message) - ;; - (evil-make-overriding-map mu4e-compose-mode-map 'normal t) - (evil-leader/set-key-for-mode 'mu4e-compose-mode - "," 'message-send-and-exit - "c" 'message-send-and-exit - "d" 'message-dont-send - "k" 'mu4e-message-kill-buffer - "a" 'mml-attach-file) - ) ;; with-eval-after-load 'mu4e - - -(provide 'aly-mu4e-config) - -;;; aly-mu4e-config.el ends here diff --git a/_spacemacs.d/config/aly-org-config.el b/_spacemacs.d/config/aly-org-config.el deleted file mode 100644 index 0fb46f5..0000000 --- a/_spacemacs.d/config/aly-org-config.el +++ /dev/null @@ -1,286 +0,0 @@ -;;; aly-org-config.el --- Custom Configurations for Org Mode -;; -*- mode: emacs-lisp -*- -;; vim: set ts=8 sw=2 tw=0 fenc=utf-8 ft=lisp: -;; -;; Aaron LI -;; Created: 2016-05-31 -;; - -;;; Commentary: -;; Custom configurations for Emacs Org mode -;; -;; [1] Spacemacs: Org layer -;; https://github.com/syl20bnr/spacemacs/blob/master/layers/org/README.org -;; [2] Norang: Org Mode (by Bernt Hansen) -;; http://doc.norang.ca/org-mode.html -;; - -;;; Code: - -;; Default task to clock in whenever the clock normally stops -(defvar aly/organization-task-id "bb7f1326-bda4-11e6-a30d-185e0f33a428") - -;; Allow single character alphabetical bullets -;; Need to be set before `org.el' is loaded -(setq org-list-allow-alphabetical t) - -;; NOTE: -;; Spacemacs use the `org' from the ELPA instead of the one shipped with -;; Emacs. Therefore, any `org'-related code should NOT be loaded before -;; `dotspacemacs/user-config'. -(with-eval-after-load 'org - (require 'org-habit) - (require 'org-clock) - (require 'ox-latex) - - ;; Load custom helper functions for Org - (require 'aly-org-helpers) - - ;; Default location to look for Org files - (setq org-directory '("~/org")) - ;; Directories of files / files to be used for agenda display - (setq org-agenda-files '("~/org")) - ;; Default file for storing notes, also the fallback file for capture - (setq org-default-notes-file "~/org/refile.org") - - ;; TODO state keywords and face settings - (setq org-todo-keywords - '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") - (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" - "CANCELLED(c@/!)" "MAIL" "PHONE" "MEETING"))) - ;(setq org-todo-keyword-faces - ; '(("TODO" :foreground "red" :weight bold) - ; ("NEXT" :foreground "blue" :weight bold) - ; ("DONE" :foreground "forest green" :weight bold) - ; ("WAITING" :foreground "orange" :weight bold) - ; ("HOLD" :foreground "magenta" :weight bold) - ; ("CANCELLED" :foreground "forest green" :weight bold) - ; ("MAIL" :foreground "forest green" :weight bold) - ; ("PHONE" :foreground "forest green" :weight bold) - ; ("MEETING" :foreground "forest green" :weight bold))) - ;; Automatically assign tags on state changes - (setq org-todo-state-tags-triggers - '(("CANCELLED" ("CANCELLED" . t)) ;; add "CANCELLED" tag - ("WAITING" ("WAITING" . t)) ;; add "WAITING" tag - ("HOLD" ("WAITING") ("HOLD" . t)) - (done ("WAITING") ("HOLD")) ;; remove "WAITING" and "HOLD" tags - ("TODO" ("WAITING") ("CANCELLED") ("HOLD")) - ("TODO" ("WAITING") ("CANCELLED") ("HOLD")) - ("DONE" ("WAITING") ("CANCELLED") ("HOLD")))) - - ;; Allow to select a state while bypass the associated logging - (setq org-treat-S-cursor-todo-selection-as-state-change nil) - - ;; Capture templates - (setq org-capture-templates - '(("t" "Task" entry (file "") - "* TODO %?\n%U\n%a\n" :clock-in t :clock-resume t) - ("n" "Note" entry (file "") - "* %? :NOTE:\n%U\n%a\n" :clock-in t :clock-resume t) - ("d" "Diary" entry (file+datetree "diary.org") - "* %?\n%U\n" :clock-in t :clock-resume t) - ("p" "Phone Call" entry (file "") - "* PHONE %? :PHONE:\n%U" :clock-in t :clock-resume t) - ("m" "Meeting" entry (file "") - "* MEETING with %? :MEETING:\n%U" :clock-in t :clock-resume t) - ("h" "Habit" entry (file "") - "* NEXT %?\n%U\n%a\nSCHEDULED: %(format-time-string \"%<<%Y-%m-%d %a .+1d/3d>>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:END:\n") - )) - - ;; Remove empty `LOGBOOK' drawers on clock out - (add-hook 'org-clock-out-hook 'aly/remove-empty-drawer-on-clock-out 'append) - - ;; More handy shortcuts - (global-set-key (kbd "") 'org-agenda) - - ;; Exclude `DONE' state tasks from refile targets - (setq org-refile-target-verify-function 'aly/verify-refile-target) - - ;; Do not dim blocked tasks - (setq org-agenda-dim-blocked-tasks nil) - ;; Compact the block agenda view - (setq org-agenda-compact-blocks t) - ;; Custom agenda command definitions - (setq org-agenda-custom-commands - '(("N" "Notes" tags "NOTE" - ((org-agenda-overriding-header "Notes") - (org-tags-match-list-sublevels t))) - ("h" "Habits" tags-todo "STYLE=\"habit\"" - ((org-agenda-overriding-header "Habits") - (org-agenda-sorting-strategy - '(todo-state-down effort-up category-keep)))) - (" " "Agenda" - ((agenda "" nil) - (tags "REFILE" - ((org-agenda-overriding-header "Tasks to Refile") - (org-tags-match-list-sublevels nil))) - (tags-todo "-CANCELLED/!" - ((org-agenda-overriding-header "Stuck Projects") - (org-agenda-skip-function 'aly/skip-non-stuck-projects) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-HOLD-CANCELLED/!" - ((org-agenda-overriding-header "Projects") - (org-agenda-skip-function 'aly/skip-non-projects) - (org-tags-match-list-sublevels 'indented) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-CANCELLED/!NEXT" - ((org-agenda-overriding-header - (concat "Project Next Tasks" - (if aly/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'aly/skip-projects-and-habits-and-single-tasks) - (org-tags-match-list-sublevels t) - (org-agenda-todo-ignore-scheduled aly/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-deadlines aly/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-with-date aly/hide-scheduled-and-waiting-next-tasks) - (org-agenda-sorting-strategy - '(todo-state-down effort-up category-keep)))) - (tags-todo "-REFILE-CANCELLED-WAITING-HOLD/!" - ((org-agenda-overriding-header - (concat "Project Subtasks" - (if aly/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'aly/skip-non-project-tasks) - (org-agenda-todo-ignore-scheduled aly/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-deadlines aly/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-with-date aly/hide-scheduled-and-waiting-next-tasks) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-REFILE-CANCELLED-WAITING-HOLD/!" - ((org-agenda-overriding-header - (concat "Standalone Tasks" - (if aly/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'aly/skip-project-tasks) - (org-agenda-todo-ignore-scheduled aly/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-deadlines aly/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-with-date aly/hide-scheduled-and-waiting-next-tasks) - (org-agenda-sorting-strategy - '(category-keep)))) - (tags-todo "-CANCELLED+WAITING|HOLD/!" - ((org-agenda-overriding-header - (concat "Waiting and Postponed Tasks" - (if aly/hide-scheduled-and-waiting-next-tasks - "" - " (including WAITING and SCHEDULED tasks)"))) - (org-agenda-skip-function 'aly/skip-non-tasks) - (org-tags-match-list-sublevels nil) - (org-agenda-todo-ignore-scheduled aly/hide-scheduled-and-waiting-next-tasks) - (org-agenda-todo-ignore-deadlines aly/hide-scheduled-and-waiting-next-tasks))) - (tags "-REFILE/" - ((org-agenda-overriding-header "Tasks to Archive") - (org-agenda-skip-function 'aly/skip-non-archivable-tasks) - (org-tags-match-list-sublevels nil)))) - nil))) - - (defun aly/org-auto-exclude-function (tag) - "Automatic task exclusion in the agenda with `/ RET'" - (and (cond - ((string= tag "hold") t) ; exclude "HOLD" tasks - ) - (concat "-" tag))) - (setq org-agenda-auto-exclude-function 'aly/org-auto-exclude-function) - - ;; Clocking - ;; - ;; Resume clocking task when Emacs is restarted - (org-clock-persistence-insinuate) - ;; Save the running clock and all clock history when exiting Emacs, - ;; and load it on startup - (setq org-clock-persist t) - ;; Do not prompt to resume an active clock - (setq org-clock-persist-query-resume nil) - ;; Enable auto clock resolution for finding open clocks - (setq org-clock-auto-clock-resolution 'when-no-clock-is-running) - ;; Show lot of clocking history so it's easy to pick items off the list - (setq org-clock-history-length 23) - ;; Resume clocking task on clock-in if the clock is open - (setq org-clock-in-resume t) - ;; Change tasks to `NEXT' when clocking in - (setq org-clock-in-switch-to-state 'aly/clock-in-to-next) - ;; Separate drawers for clocking and logs - (setq org-drawers '("PROPERTIES" "LOGBOOK")) - ;; Save clock data and state changes and notes in the `LOGBOOK' drawer - (setq org-clock-into-drawer t) - ;; Remove clocked tasks with 0:00 duration - (setq org-clock-out-remove-zero-time-clocks t) - ;; Clock out when moving task to a done state - (setq org-clock-out-when-done t) - (add-hook 'org-clock-out-hook 'aly/clock-out-maybe 'append) - ;; Use discrete minute intervals (no rounding) increments for time editing - (setq org-time-stamp-rounding-minutes '(1 1)) - - ;; Agenda clock report parameters - (setq org-agenda-clockreport-parameter-plist - '(:link t :maxlevel 5 :fileskip0 t :compact t :narrow 80)) - ;; Set default column view headings: Task Effort ClockSummary - (setq org-columns-default-format - "%80ITEM(task) %10Effort(Effort){:} %10CLOCKSUM") - ;; Global `Effort' estimate values, - ;; and global `STYLE' property values for completion - (setq org-global-properties - '(("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"))) - ;; Agenda log mode items to display (closed and state changes by default) - (setq org-agenda-log-mode-items '(closed state)) - - ;; Tags with fast selection keys - (setq org-tag-alist - '((:startgroup) - ("@office" . ?o) - ("@home" . ?H) - ("@dorm" . ?d) - (:endgroup) - ("WAITING" . ?w) - ("HOLD" . ?h) - ("PERSONAL" . ?P) - ("WORK" . ?W) - ("ORG" . ?O) - ("ASTRO" . ?a) - ("NOTE" . ?n) - ("CANCELLED" . ?c) - ("FLAGGED" . ??))) - ;; Allow setting single tags without the menu - (setq org-fast-tag-selection-single-key (quote expert)) - ;; For tag searches ignore tasks with scheduled and deadline dates - (setq org-agenda-tags-todo-honor-ignore-options t) - - ;; Any task with a subtask using a todo keyword is a project. - ;; Projects are "stuck" if they have no subtask with a `NEXT' todo keyword. - - ;; Only show today's agenda by default - (setq org-agenda-span 'day) - ;; Disable the default stuck projects agenda view - (setq org-stuck-projects '("" nil nil "")) - - ;; Archive - (setq org-archive-mark-done nil) - (setq org-archive-location "%s_archive::* Archived Tasks") - - ;; Enable in-using Babel languages - (org-babel-do-load-languages - 'org-babel-load-languages - '((emacs-lisp . t) - (sh . t) - (python . t) - (ditaa . t) - )) - - ;; Set the bullet symbols for `org-bullets' - (setq org-bullets-bullet-list '("♠" "♥" "♣" "♦")) ;; "SHoCkeD" ordering - - ;; Set the path to the `ditaa' program - (setq org-ditaa-jar-path "~/.spacemacs.d/local/ditaa/ditaa.jar") - - ;; END: Org-mode configurations - ) - - -(provide 'aly-org-config) - -;;; aly-org-config.el ends here diff --git a/_spacemacs.d/config/aly-org-helpers.el b/_spacemacs.d/config/aly-org-helpers.el deleted file mode 100644 index 3254c79..0000000 --- a/_spacemacs.d/config/aly-org-helpers.el +++ /dev/null @@ -1,399 +0,0 @@ -;;; aly-org-helpers.el --- Custom Helper Functions for Org Mode -;; -*- mode: emacs-lisp -*- -;; vim: set ts=8 sw=2 tw=0 fenc=utf-8 ft=lisp: -;; -;; Aaron LI -;; Created: 2016-12-07 -;; - -;;; Commentary: -;; Custom helper functions for Org mode -;; -;; [1] Norang: Org Mode (by Bernt Hansen) -;; http://doc.norang.ca/org-mode.html -;; - -;;; Code: - - -(defun aly/verify-refile-target () - "Exclude todo keywords with a done state from refile targets" - (not (member (nth 2 (org-heading-components)) org-done-keywords))) - -(defun aly/remove-empty-drawer-on-clock-out () - "Remove empty `LOGBOOK' drawers on clock out" - (interactive) - (save-excursion - (beginning-of-line 0) - (org-remove-empty-drawer-at "LOGBOOK" (point)))) - -(defun aly/find-project-task () - "Move point to the parent (project) task if any" - (save-restriction - (widen) - (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) - (while (org-up-heading-safe) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq parent-task (point)))) - (goto-char parent-task) - parent-task))) - -(defun aly/is-project-p () - "Any task with a subtask using a todo keyword" - (save-restriction - (widen) - (let ((has-subtask) - (subtree-end (save-excursion (org-end-of-subtree t))) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (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-todo-keywords-1) - (setq has-subtask t)))) - (and is-a-task has-subtask)))) - -(defun aly/is-project-subtree-p () - "Any task with a todo keyword that is in a project subtree. -Callers of this function already widen the buffer view." - (let ((task (save-excursion (org-back-to-heading 'invisible-ok) - (point)))) - (save-excursion - (aly/find-project-task) - (if (equal (point) task) - nil - t)))) - -(defun aly/is-task-p () - "Any task with a todo keyword and no subtask" - (save-restriction - (widen) - (let ((has-subtask) - (subtree-end (save-excursion (org-end-of-subtree t))) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (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-todo-keywords-1) - (setq has-subtask t)))) - (and is-a-task (not has-subtask))))) - -(defun aly/is-subproject-p () - "Any task which is a subtask of another project" - (let ((is-subproject) - (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) - (save-excursion - (while (and (not is-subproject) (org-up-heading-safe)) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq is-subproject t)))) - (and is-a-task is-subproject))) - -(defun aly/list-sublevels-for-projects-indented () - "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. - This is normally used by skipping functions where this variable is already local to the agenda." - (if (marker-buffer org-agenda-restrict-begin) - (setq org-tags-match-list-sublevels 'indented) - (setq org-tags-match-list-sublevels nil)) - nil) - -(defun aly/list-sublevels-for-projects () - "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. - This is normally used by skipping functions where this variable is already local to the agenda." - (if (marker-buffer org-agenda-restrict-begin) - (setq org-tags-match-list-sublevels t) - (setq org-tags-match-list-sublevels nil)) - nil) - -(defvar aly/hide-scheduled-and-waiting-next-tasks t) - -(defun aly/toggle-next-task-display () - (interactive) - (setq aly/hide-scheduled-and-waiting-next-tasks (not aly/hide-scheduled-and-waiting-next-tasks)) - (when (equal major-mode 'org-agenda-mode) - (org-agenda-redo)) - (message "%s WAITING and SCHEDULED NEXT Tasks" (if aly/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) - -(defun aly/skip-stuck-projects () - "Skip trees that are not stuck projects" - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (if (aly/is-project-p) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - (save-excursion - (forward-line 1) - (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) - (unless (member "WAITING" (org-get-tags-at)) - (setq has-next t)))) - (if has-next - nil - next-headline)) ; a stuck project, has subtasks but no next task - nil)))) - -(defun aly/skip-non-stuck-projects () - "Skip trees that are not stuck projects" - ;; (aly/list-sublevels-for-projects-indented) - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (if (aly/is-project-p) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (has-next )) - (save-excursion - (forward-line 1) - (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) - (unless (member "WAITING" (org-get-tags-at)) - (setq has-next t)))) - (if has-next - next-headline - nil)) ; a stuck project, has subtasks but no next task - next-headline)))) - -(defun aly/skip-non-projects () - "Skip trees that are not projects" - ;; (aly/list-sublevels-for-projects-indented) - (if (save-excursion (aly/skip-non-stuck-projects)) - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((aly/is-project-p) - nil) - ((and (aly/is-project-subtree-p) (not (aly/is-task-p))) - nil) - (t - subtree-end)))) - (save-excursion (org-end-of-subtree t)))) - -(defun aly/skip-non-tasks () - "Show non-project tasks. -Skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((aly/is-task-p) - nil) - (t - next-headline))))) - -(defun aly/skip-project-trees-and-habits () - "Skip trees that are projects" - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((aly/is-project-p) - subtree-end) - ((org-is-habit-p) - subtree-end) - (t - nil))))) - -(defun aly/skip-projects-and-habits-and-single-tasks () - "Skip trees that are projects, tasks that are habits, single non-project tasks" - (save-restriction - (widen) - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((org-is-habit-p) - next-headline) - ((and aly/hide-scheduled-and-waiting-next-tasks - (member "WAITING" (org-get-tags-at))) - next-headline) - ((aly/is-project-p) - next-headline) - ((and (aly/is-task-p) (not (aly/is-project-subtree-p))) - next-headline) - (t - nil))))) - -(defun aly/skip-project-tasks-maybe () - "Show tasks related to the current restriction. -When restricted to a project, skip project and sub project tasks, habits, NEXT tasks, and loose tasks. -When not restricted, skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (next-headline (save-excursion (or (outline-next-heading) (point-max)))) - (limit-to-project (marker-buffer org-agenda-restrict-begin))) - (cond - ((aly/is-project-p) - next-headline) - ((org-is-habit-p) - subtree-end) - ((and (not limit-to-project) - (aly/is-project-subtree-p)) - subtree-end) - ((and limit-to-project - (aly/is-project-subtree-p) - (member (org-get-todo-state) (list "NEXT"))) - subtree-end) - (t - nil))))) - -(defun aly/skip-project-tasks () - "Show non-project tasks. -Skip project and sub-project tasks, habits, and project related tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((aly/is-project-p) - subtree-end) - ((org-is-habit-p) - subtree-end) - ((aly/is-project-subtree-p) - subtree-end) - (t - nil))))) - -(defun aly/skip-non-project-tasks () - "Show project tasks. -Skip project and sub-project tasks, habits, and loose non-project tasks." - (save-restriction - (widen) - (let* ((subtree-end (save-excursion (org-end-of-subtree t))) - (next-headline (save-excursion (or (outline-next-heading) (point-max))))) - (cond - ((aly/is-project-p) - next-headline) - ((org-is-habit-p) - subtree-end) - ((and (aly/is-project-subtree-p) - (member (org-get-todo-state) (list "NEXT"))) - subtree-end) - ((not (aly/is-project-subtree-p)) - subtree-end) - (t - nil))))) - -(defun aly/skip-projects-and-habits () - "Skip trees that are projects and tasks that are habits" - (save-restriction - (widen) - (let ((subtree-end (save-excursion (org-end-of-subtree t)))) - (cond - ((aly/is-project-p) - subtree-end) - ((org-is-habit-p) - subtree-end) - (t - nil))))) - -(defun aly/skip-non-subprojects () - "Skip trees that are not projects" - (let ((next-headline (save-excursion (outline-next-heading)))) - (if (aly/is-subproject-p) - nil - next-headline))) - -(setq aly/keep-clock-running nil) - -(defun aly/clock-in-to-next (kw) - "Switch a task from TODO to NEXT when clocking in. -Skips capture tasks, projects, and subprojects. -Switch projects and subprojects from NEXT back to TODO" - (when (not (and (boundp 'org-capture-mode) org-capture-mode)) - (cond - ((and (member (org-get-todo-state) (list "TODO")) - (aly/is-task-p)) - "NEXT") - ((and (member (org-get-todo-state) (list "NEXT")) - (aly/is-project-p)) - "TODO")))) - -(defun aly/punch-in (arg) - "Start continuous clocking and set the default task to the -selected task. If no task is selected set the Organization task -as the default task." - (interactive "p") - (setq aly/keep-clock-running t) - (if (equal major-mode 'org-agenda-mode) - ;; We are in the agenda - (let* ((marker (org-get-at-bol 'org-hd-marker)) - (tags (org-with-point-at marker (org-get-tags-at)))) - (if (and (eq arg 4) tags) - (org-agenda-clock-in '(16)) - (aly/clock-in-organization-task-as-default))) - ;; We are NOT in the agenda - (save-restriction - (widen) - ; Find the tags on the current task - (if (and (equal major-mode 'org-mode) - (not (org-before-first-heading-p)) - (eq arg 4)) - (org-clock-in '(16)) - (aly/clock-in-organization-task-as-default))))) - -(defun aly/punch-out () - (interactive) - (setq aly/keep-clock-running nil) - (when (org-clock-is-active) - (org-clock-out)) - (org-agenda-remove-restriction-lock)) - -(defun aly/clock-in-default-task () - (save-excursion - (org-with-point-at org-clock-default-task - (org-clock-in)))) - -(defun aly/clock-in-parent-task () - "Move point to the parent (project) task if any and clock in" - (let ((parent-task)) - (save-excursion - (save-restriction - (widen) - (while (and (not parent-task) (org-up-heading-safe)) - (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) - (setq parent-task (point)))) - (if parent-task - (org-with-point-at parent-task - (org-clock-in)) - (when aly/keep-clock-running - (aly/clock-in-default-task))))))) - -(defun aly/clock-in-organization-task-as-default () - (interactive) - (org-with-point-at (org-id-find aly/organization-task-id 'marker) - (org-clock-in '(16)))) - -(defun aly/clock-out-maybe () - (when (and aly/keep-clock-running - (not org-clock-clocking-in) - (marker-buffer org-clock-default-task) - (not org-clock-resolving-clocks-due-to-idleness)) - (aly/clock-in-parent-task))) - - -(defun aly/skip-non-archivable-tasks () - "Skip trees that are not available for archiving" - (save-restriction - (widen) - ;; Consider only tasks with done todo headings as archivable candidates - (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))) - (subtree-end (save-excursion (org-end-of-subtree t)))) - (if (member (org-get-todo-state) org-todo-keywords-1) - (if (member (org-get-todo-state) org-done-keywords) - (let* ((daynr (string-to-int (format-time-string "%d" (current-time)))) - (a-month-ago (* 60 60 24 (+ daynr 1))) - (last-month (format-time-string "%Y-%m-" (time-subtract (current-time) (seconds-to-time a-month-ago)))) - (this-month (format-time-string "%Y-%m-" (current-time))) - (subtree-is-current (save-excursion - (forward-line 1) - (and (< (point) subtree-end) - (re-search-forward (concat last-month "\\|" this-month) subtree-end t))))) - (if subtree-is-current - subtree-end ; Has a date in this month or last month, skip it - nil)) ; available to archive - (or subtree-end (point-max))) - next-headline)))) - - -(provide 'aly-org-helpers) - -;;; aly-org-helpers.el ends here diff --git a/_spacemacs.d/config/my-mu4e.el b/_spacemacs.d/config/my-mu4e.el new file mode 100644 index 0000000..6aa2f0d --- /dev/null +++ b/_spacemacs.d/config/my-mu4e.el @@ -0,0 +1,353 @@ +;;; my-mu4e.el --- mu4e (mu for Emacs) configurations +;; -*- mode: emacs-lisp -*- +;; vim: set ts=8 sw=2 tw=0 fenc=utf-8 ft=lisp: +;; +;; Aaron LI +;; Created: 2016-02-21 +;; Updated: 2016-09-03 +;; + +;;; Commentary: +;; mu4e (mu for Emacs) configurations for spacemacs. +;; mu (maildir indexer/searcher): https://github.com/djcb/mu +;; + +;;; Code: + +;; maildir location +(setq mu4e-maildir "~/mail") + +;; turn on debug: log debug information to the *mu4e-log* buffer +(setq mu4e-debug t) + +(with-eval-after-load 'mu4e + ;; speed up indexing + (setq mu4e-index-cleanup nil) ; don't do a full cleanup check + (setq mu4e-index-lazy-check t) ; don't consider up-to-date directories + + ;; multiple email accounts: contexts (require mu4e >= 0.9.16) + (setq mu4e-contexts + `( ,(make-mu4e-context + :name "Outlook-aly" + :enter-func (lambda () + (mu4e-message "Switched to context: outlook-aly")) + ;; `leave-func' not defined + ;; `match-func' is invoked just before `mu4e-compose-pre-hook' + :match-func (lambda (msg) + (when msg + (mu4e-message-contact-field-matches msg + :to "aaronly.me@outlook.com"))) + :vars '((user-mail-address . "aaronly.me@outlook.com") + (user-full-name . "Aaron LI") + (mu4e-sent-folder . "/outlook-aly/sent") + (mu4e-drafts-folder . "/outlook-aly/drafts") + (mu4e-trash-folder . "/outlook-aly/trash") + (mu4e-refile-folder . "/outlook-aly/archive") + (mu4e-compose-signature . "Aly") + (mu4e-sent-messages-behavior . delete))) + ,(make-mu4e-context + :name "Gmail-aly" + :enter-func (lambda () + (mu4e-message "Switched to context: gmail-aly")) + ;; `leave-func' not defined + :match-func (lambda (msg) + (when msg + (mu4e-message-contact-field-matches msg + :to "aaronly.me@gmail.com"))) + :vars '((user-mail-address . "aaronly.me@gmail.com") + (user-full-name . "Aaron LI") + ;; special folders + (mu4e-sent-folder . "/sent") + (mu4e-drafts-folder . "/gmail-aly/drafts") + (mu4e-trash-folder . "/gmail-aly/trash") + (mu4e-refile-folder . "/gmail-aly/archive") + (mu4e-compose-signature . "Aly") + ;; do NOT save message to 'sent-folder' + (mu4e-sent-messages-behavior . delete))) + ,(make-mu4e-context + :name "outlook-li" + :enter-func (lambda () + (mu4e-message "Switched to context: outlook-li")) + ;; `leave-func' not defined + :match-func (lambda (msg) + (when msg + (mu4e-message-contact-field-matches msg + :to '("liweitianux@live.com" + "liweitianux@outlook.com")))) + :vars '((user-mail-address . "liweitianux@live.com") + (user-full-name . "Weitian LI") + (mu4e-sent-folder . "/outlook-li/sent") + (mu4e-drafts-folder . "/outlook-li/drafts") + (mu4e-trash-folder . "/outlook-li/trash") + (mu4e-refile-folder . "/outlook-li/archive") + (mu4e-compose-signature . "Weitian") + (mu4e-sent-messages-behavior . delete))) + ,(make-mu4e-context + :name "gmail-li" + :enter-func (lambda () + (mu4e-message "Switched to context: gmail-li")) + ;; `leave-func' not defined + :match-func (lambda (msg) + (when msg + (mu4e-message-contact-field-matches msg + :to "liweitianux@gmail.com"))) + :vars '((user-mail-address . "liweitianux@gmail.com") + (user-full-name . "Weitian LI") + (mu4e-sent-folder . "/sent") + (mu4e-drafts-folder . "/gmail-li/drafts") + (mu4e-trash-folder . "/gmail-li/trash") + (mu4e-refile-folder . "/gmail-li/archive") + (mu4e-compose-signature . "Weitian") + (mu4e-sent-messages-behavior . delete))) + ,(make-mu4e-context + :name "sjtu" + :enter-func (lambda () + (mu4e-message "Switched to context: sjtu")) + ;; `leave-func' not defined + :match-func (lambda (msg) + (when msg + (mu4e-message-contact-field-matches msg + :to "liweitianux@sjtu.edu.cn"))) + :vars '((user-mail-address . "liweitianux@sjtu.edu.cn") + (user-full-name . "Weitian LI") + (mu4e-sent-folder . "/sjtu/sent") + (mu4e-drafts-folder . "/sjtu/drafts") + (mu4e-trash-folder . "/sjtu/trash") + (mu4e-refile-folder . "/sjtu/archive") + (mu4e-compose-signature . + (concat "Weitian LI\n" + "Shanghai Jiao Tong University")) + ;; copy message to sent folder + (mu4e-sent-messages-behavior . sent))) + ,(make-mu4e-context + :name "autistici" + :enter-func (lambda () + (mu4e-message "Switched to context: autistici")) + ;; `leave-func' not defined + :match-func (lambda (msg) + (when msg + (mu4e-message-contact-field-matches msg + :to "liweitianux@autistici.org"))) + :vars '((user-mail-address . "liweitianux@autistici.org") + (user-full-name . "Weitian LI") + (mu4e-sent-folder . "/autistici/sent") + (mu4e-drafts-folder . "/autistici/drafts") + (mu4e-trash-folder . "/autistici/trash") + (mu4e-refile-folder . "/autistici/archive") + (mu4e-compose-signature . "Weitian") + ;; copy message to sent folder + (mu4e-sent-messages-behavior . sent))) + ,(make-mu4e-context + :name "foxmail" + :enter-func (lambda () + (mu4e-message "Switched to context: foxmail")) + ;; `leave-func' not defined + :match-func (lambda (msg) + (when msg + (mu4e-message-contact-field-matches msg + :to '("liweitianux@foxmail.com" + "527922216@qq.com")))) + :vars '((user-mail-address . "liweitianux@foxmail.com") + (user-full-name . "Weitian LI") + (mu4e-sent-folder . "/foxmail/sent") + (mu4e-drafts-folder . "/foxmail/drafts") + (mu4e-trash-folder . "/foxmail/trash") + (mu4e-refile-folder . "/foxmail/archive") + (mu4e-compose-signature . "Weitian") + (mu4e-sent-messages-behavior . delete))))) + + ;; start with the first (default) context + ;; default: `ask-if-none' (ask when there's no context yet, and none match) + (setq mu4e-context-policy 'pick-first) + ;; compose with the current context if no context matches + ;; default: `ask' + ;(setq mu4e-compose-context-policy nil) + + ;; auto construct addresses list by extracting addresses from contexts + (setq mu4e-user-mail-address-list + (delq nil + (mapcar (lambda (context) + (when (mu4e-context-vars context) + (cdr (assq 'user-mail-address + (mu4e-context-vars context))))) + mu4e-contexts))) + + ;; send mail using `msmtp' + (setq message-send-mail-function 'message-send-mail-with-sendmail + message-sendmail-f-is-evil t + ;; choose the account according to the `From' header + message-sendmail-extra-arguments '("--read-envelope-from") + sendmail-program "msmtp") + + ;; allow for fetch mail and update index using 'U' in the main view + (setq mu4e-get-mail-command "mbsync -a") + ;; get mail and update index periodically in the background (unit: seconds) + (setq mu4e-update-interval 900) + + ;; frequent mail folders, with shortcuts + ;; NOTE: do not use shortcut `o' as it is used for `[o]ther' + ;(setq mu4e-maildir-shortcuts + ; '(("/important" . ?i) + ; ("/archive" . ?a) + ; ("/gmail-aly/archive" . ?G) + ; ("/gmail-li/archive" . ?g) + ; ("/outlook-aly/inbox" . ?l) + ; ("/outlook-li/inbox" . ?L) + ; ("/sjtu/inbox" . ?s))) + + ;; do not keep message buffers around + (setq message-kill-buffer-on-exit t) + + ;; enable inline images + (setq mu4e-view-show-images t) + ;; use imagemagick if available + (when (fboundp 'imagemagick-register-types) + (imagemagick-register-types)) + + ;; display rich-text messages + (require 'mu4e-contrib) + ;; use `shr' html renderer; reqiure emacs >= 24.4 + (require 'shr) + (setq mu4e-html2text-command 'mu4e-shr2text) + (add-hook 'mu4e-view-mode-hook + (lambda () + ;; try to emulate some of the `eww' key-bindings + (local-set-key (kbd "") 'shr-next-link) + (local-set-key (kbd "") 'shr-previous-link))) + ;; change the luminosity form dark theme + (setq shr-color-visible-luminance-min 70) + + ;; customize bookmarks + (setq mu4e-bookmarks + '(("flag:unread AND NOT flag:trashed" "Unread messages" ?u) + ("date:today..now" "Today's messages" ?T) + ("date:7d..now" "Last 7 days" ?w) + ("date:1m..now" "Last month" ?m) + ("flag:flagged" "Flagged messages" ?f) + ("tag:todo OR tag:task" "TODO / Task" ?t) + ("tag:work" "Work" ?W) + ("tag:astro" "Astro" ?a) + ("tag:arxiv OR from:arxiv.org" "arXiv" ?x) + ("tag:SMS" "SMS" ?S) + ("flag:trashed OR tag:\\\\Trash" "Deleted" ?d) + ("mime:image/*" "Messages with images" ?p))) + + ;; headers list appearance + (setq mu4e-headers-date-format "%Y-%m-%d %H:%M" + mu4e-headers-fields '((:date . 18) ;; also :human-date + (:flags . 5) + (:from-or-to . 22) + (:subject . nil))) ;; also :thread-subject + + ;; header fields to be shown in the view buffer + (add-to-list 'mu4e-view-fields :size t) + (add-to-list 'mu4e-view-fields :user-agent t) + + ;; use fancy non-ascii characters in various places + ;(setq mu4e-use-fancy-chars t) + + ;; show full addresses instead of just names when view message + (setq mu4e-view-show-addresses t) + + ;; also include messages related to the searched messages + (setq mu4e-headers-include-related t) + ;; exclude the duplicate messages with the same `Message-ID' + ;(setq mu4e-headers-skip-duplicates t) + + ;; compose messages in a separate frame + (setq mu4e-compose-in-new-frame t) + + ;; confirm before sending + (add-hook 'message-send-hook + (lambda () + (unless (yes-or-no-p "Sure you want to send this?") + (signal 'quit nil)))) + + ;; custom actions + ;; retag action + (setq mu4e-action-tags-header "X-Keywords") + (add-to-list 'mu4e-headers-actions + '("tRetag message" . mu4e-action-retag-message) t) + (add-to-list 'mu4e-view-actions + '("tRetag message" . mu4e-action-retag-message) t) + ;; view in browser + (add-to-list 'mu4e-view-actions + '("bView in browser" . mu4e-action-view-in-browser) t) + ;; search for messages by the sender of the opened message + (defun search-for-sender (msg) + "Search for messages sent by the sender of the message at point." + (mu4e-headers-search + (concat "from:" (cdar (mu4e-message-field msg :from))))) + (add-to-list 'mu4e-view-actions + '("xSearch for sender" . search-for-sender) t) + + ;; set `mu4e' as emacs' default email program + (setq mail-user-agent 'mu4e-user-agent) + + ;; END: with-eval-after-load 'mu4e + ) + + +;;; Key bindings for Evil +;; Credits: +;; https://github.com/philc/emacs-config - .emacs.d/elisp/mu4e-mode-personal.el + +(dolist (mode '(mu4e-mode + mu4e-main-mode + mu4e-headers-mode + mu4e-view-mode + mu4e-compose-mode)) + (evil-set-initial-state mode 'normal)) + +(with-eval-after-load 'mu4e + (evil-make-overriding-map mu4e-main-mode-map 'normal t) + (evil-define-key 'normal mu4e-main-mode-map + "J" 'mu4e~headers-jump-to-maildir + "j" 'evil-next-line + "k" 'evil-previous-line) + (evil-make-overriding-map mu4e-headers-mode-map 'normal t) + (evil-define-key 'normal mu4e-headers-mode-map + "gg" 'evil-goto-first-line + "J" 'mu4e~headers-jump-to-maildir + "j" 'mu4e-headers-next + "k" 'mu4e-headers-prev + "]" 'mu4e-headers-next-unread + "[" 'mu4e-headers-prev-unread + "C" 'mu4e-compose-new + "E" 'mu4e-compose-edit + "F" 'mu4e-compose-forward + "R" 'mu4e-compose-reply) + (evil-leader/set-key-for-mode 'mu4e-headers-mode + "u" '(lambda () (interactive) (mu4e-update-mail-and-index t))) + ;; + (evil-make-overriding-map mu4e-view-mode-map 'normal t) + (evil-define-key 'normal mu4e-view-mode-map + "gg" 'evil-goto-first-line + "j" 'evil-next-line + "k" 'evil-previous-line + "\C-j" 'mu4e-view-headers-next + "\C-k" 'mu4e-view-headers-prev + "\C-]" 'mu4e-view-headers-next-unread + "\C-[" 'mu4e-view-headers-prev-unread + "C" 'mu4e-compose-new + "E" 'mu4e-compose-edit + "F" 'mu4e-compose-forward + "R" 'mu4e-compose-reply) + (evil-leader/set-key-for-mode 'mu4e-view-mode + "u" '(lambda () (interactive) (mu4e-update-mail-and-index t)) + "x" '(lambda () (interactive) (helm-M-x)) + "s" 'mu4e-view-raw-message) + ;; + (evil-make-overriding-map mu4e-compose-mode-map 'normal t) + (evil-leader/set-key-for-mode 'mu4e-compose-mode + "," 'message-send-and-exit + "c" 'message-send-and-exit + "d" 'message-dont-send + "k" 'mu4e-message-kill-buffer + "a" 'mml-attach-file) + ) ;; with-eval-after-load 'mu4e + + +(provide 'my-mu4e) + +;;; my-mu4e.el ends here diff --git a/_spacemacs.d/config/my-org-helpers.el b/_spacemacs.d/config/my-org-helpers.el new file mode 100644 index 0000000..e3c30c1 --- /dev/null +++ b/_spacemacs.d/config/my-org-helpers.el @@ -0,0 +1,399 @@ +;;; my-org-helpers.el --- Custom Helper Functions for Org Mode +;; -*- mode: emacs-lisp -*- +;; vim: set ts=8 sw=2 tw=0 fenc=utf-8 ft=lisp: +;; +;; Aaron LI +;; Created: 2016-12-07 +;; + +;;; Commentary: +;; Custom helper functions for Org mode +;; +;; [1] Norang: Org Mode (by Bernt Hansen) +;; http://doc.norang.ca/org-mode.html +;; + +;;; Code: + + +(defun my/verify-refile-target () + "Exclude todo keywords with a done state from refile targets" + (not (member (nth 2 (org-heading-components)) org-done-keywords))) + +(defun my/remove-empty-drawer-on-clock-out () + "Remove empty `LOGBOOK' drawers on clock out" + (interactive) + (save-excursion + (beginning-of-line 0) + (org-remove-empty-drawer-at "LOGBOOK" (point)))) + +(defun my/find-project-task () + "Move point to the parent (project) task if any" + (save-restriction + (widen) + (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) + (while (org-up-heading-safe) + (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (setq parent-task (point)))) + (goto-char parent-task) + parent-task))) + +(defun my/is-project-p () + "Any task with a subtask using a todo keyword" + (save-restriction + (widen) + (let ((has-subtask) + (subtree-end (save-excursion (org-end-of-subtree t))) + (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) + (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-todo-keywords-1) + (setq has-subtask t)))) + (and is-a-task has-subtask)))) + +(defun my/is-project-subtree-p () + "Any task with a todo keyword that is in a project subtree. +Callers of this function already widen the buffer view." + (let ((task (save-excursion (org-back-to-heading 'invisible-ok) + (point)))) + (save-excursion + (my/find-project-task) + (if (equal (point) task) + nil + t)))) + +(defun my/is-task-p () + "Any task with a todo keyword and no subtask" + (save-restriction + (widen) + (let ((has-subtask) + (subtree-end (save-excursion (org-end-of-subtree t))) + (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) + (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-todo-keywords-1) + (setq has-subtask t)))) + (and is-a-task (not has-subtask))))) + +(defun my/is-subproject-p () + "Any task which is a subtask of another project" + (let ((is-subproject) + (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) + (save-excursion + (while (and (not is-subproject) (org-up-heading-safe)) + (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (setq is-subproject t)))) + (and is-a-task is-subproject))) + +(defun my/list-sublevels-for-projects-indented () + "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. + This is normally used by skipping functions where this variable is already local to the agenda." + (if (marker-buffer org-agenda-restrict-begin) + (setq org-tags-match-list-sublevels 'indented) + (setq org-tags-match-list-sublevels nil)) + nil) + +(defun my/list-sublevels-for-projects () + "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. + This is normally used by skipping functions where this variable is already local to the agenda." + (if (marker-buffer org-agenda-restrict-begin) + (setq org-tags-match-list-sublevels t) + (setq org-tags-match-list-sublevels nil)) + nil) + +(defvar my/hide-scheduled-and-waiting-next-tasks t) + +(defun my/toggle-next-task-display () + (interactive) + (setq my/hide-scheduled-and-waiting-next-tasks (not my/hide-scheduled-and-waiting-next-tasks)) + (when (equal major-mode 'org-agenda-mode) + (org-agenda-redo)) + (message "%s WAITING and SCHEDULED NEXT Tasks" (if my/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) + +(defun my/skip-stuck-projects () + "Skip trees that are not stuck projects" + (save-restriction + (widen) + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (if (my/is-project-p) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (has-next )) + (save-excursion + (forward-line 1) + (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) + (unless (member "WAITING" (org-get-tags-at)) + (setq has-next t)))) + (if has-next + nil + next-headline)) ; a stuck project, has subtasks but no next task + nil)))) + +(defun my/skip-non-stuck-projects () + "Skip trees that are not stuck projects" + ;; (my/list-sublevels-for-projects-indented) + (save-restriction + (widen) + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (if (my/is-project-p) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (has-next )) + (save-excursion + (forward-line 1) + (while (and (not has-next) (< (point) subtree-end) (re-search-forward "^\\*+ NEXT " subtree-end t)) + (unless (member "WAITING" (org-get-tags-at)) + (setq has-next t)))) + (if has-next + next-headline + nil)) ; a stuck project, has subtasks but no next task + next-headline)))) + +(defun my/skip-non-projects () + "Skip trees that are not projects" + ;; (my/list-sublevels-for-projects-indented) + (if (save-excursion (my/skip-non-stuck-projects)) + (save-restriction + (widen) + (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((my/is-project-p) + nil) + ((and (my/is-project-subtree-p) (not (my/is-task-p))) + nil) + (t + subtree-end)))) + (save-excursion (org-end-of-subtree t)))) + +(defun my/skip-non-tasks () + "Show non-project tasks. +Skip project and sub-project tasks, habits, and project related tasks." + (save-restriction + (widen) + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (cond + ((my/is-task-p) + nil) + (t + next-headline))))) + +(defun my/skip-project-trees-and-habits () + "Skip trees that are projects" + (save-restriction + (widen) + (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((my/is-project-p) + subtree-end) + ((org-is-habit-p) + subtree-end) + (t + nil))))) + +(defun my/skip-projects-and-habits-and-single-tasks () + "Skip trees that are projects, tasks that are habits, single non-project tasks" + (save-restriction + (widen) + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (cond + ((org-is-habit-p) + next-headline) + ((and my/hide-scheduled-and-waiting-next-tasks + (member "WAITING" (org-get-tags-at))) + next-headline) + ((my/is-project-p) + next-headline) + ((and (my/is-task-p) (not (my/is-project-subtree-p))) + next-headline) + (t + nil))))) + +(defun my/skip-project-tasks-maybe () + "Show tasks related to the current restriction. +When restricted to a project, skip project and sub project tasks, habits, NEXT tasks, and loose tasks. +When not restricted, skip project and sub-project tasks, habits, and project related tasks." + (save-restriction + (widen) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (next-headline (save-excursion (or (outline-next-heading) (point-max)))) + (limit-to-project (marker-buffer org-agenda-restrict-begin))) + (cond + ((my/is-project-p) + next-headline) + ((org-is-habit-p) + subtree-end) + ((and (not limit-to-project) + (my/is-project-subtree-p)) + subtree-end) + ((and limit-to-project + (my/is-project-subtree-p) + (member (org-get-todo-state) (list "NEXT"))) + subtree-end) + (t + nil))))) + +(defun my/skip-project-tasks () + "Show non-project tasks. +Skip project and sub-project tasks, habits, and project related tasks." + (save-restriction + (widen) + (let* ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((my/is-project-p) + subtree-end) + ((org-is-habit-p) + subtree-end) + ((my/is-project-subtree-p) + subtree-end) + (t + nil))))) + +(defun my/skip-non-project-tasks () + "Show project tasks. +Skip project and sub-project tasks, habits, and loose non-project tasks." + (save-restriction + (widen) + (let* ((subtree-end (save-excursion (org-end-of-subtree t))) + (next-headline (save-excursion (or (outline-next-heading) (point-max))))) + (cond + ((my/is-project-p) + next-headline) + ((org-is-habit-p) + subtree-end) + ((and (my/is-project-subtree-p) + (member (org-get-todo-state) (list "NEXT"))) + subtree-end) + ((not (my/is-project-subtree-p)) + subtree-end) + (t + nil))))) + +(defun my/skip-projects-and-habits () + "Skip trees that are projects and tasks that are habits" + (save-restriction + (widen) + (let ((subtree-end (save-excursion (org-end-of-subtree t)))) + (cond + ((my/is-project-p) + subtree-end) + ((org-is-habit-p) + subtree-end) + (t + nil))))) + +(defun my/skip-non-subprojects () + "Skip trees that are not projects" + (let ((next-headline (save-excursion (outline-next-heading)))) + (if (my/is-subproject-p) + nil + next-headline))) + +(setq my/keep-clock-running nil) + +(defun my/clock-in-to-next (kw) + "Switch a task from TODO to NEXT when clocking in. +Skips capture tasks, projects, and subprojects. +Switch projects and subprojects from NEXT back to TODO" + (when (not (and (boundp 'org-capture-mode) org-capture-mode)) + (cond + ((and (member (org-get-todo-state) (list "TODO")) + (my/is-task-p)) + "NEXT") + ((and (member (org-get-todo-state) (list "NEXT")) + (my/is-project-p)) + "TODO")))) + +(defun my/punch-in (arg) + "Start continuous clocking and set the default task to the +selected task. If no task is selected set the Organization task +as the default task." + (interactive "p") + (setq my/keep-clock-running t) + (if (equal major-mode 'org-agenda-mode) + ;; We are in the agenda + (let* ((marker (org-get-at-bol 'org-hd-marker)) + (tags (org-with-point-at marker (org-get-tags-at)))) + (if (and (eq arg 4) tags) + (org-agenda-clock-in '(16)) + (my/clock-in-organization-task-as-default))) + ;; We are NOT in the agenda + (save-restriction + (widen) + ; Find the tags on the current task + (if (and (equal major-mode 'org-mode) + (not (org-before-first-heading-p)) + (eq arg 4)) + (org-clock-in '(16)) + (my/clock-in-organization-task-as-default))))) + +(defun my/punch-out () + (interactive) + (setq my/keep-clock-running nil) + (when (org-clock-is-active) + (org-clock-out)) + (org-agenda-remove-restriction-lock)) + +(defun my/clock-in-default-task () + (save-excursion + (org-with-point-at org-clock-default-task + (org-clock-in)))) + +(defun my/clock-in-parent-task () + "Move point to the parent (project) task if any and clock in" + (let ((parent-task)) + (save-excursion + (save-restriction + (widen) + (while (and (not parent-task) (org-up-heading-safe)) + (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) + (setq parent-task (point)))) + (if parent-task + (org-with-point-at parent-task + (org-clock-in)) + (when my/keep-clock-running + (my/clock-in-default-task))))))) + +(defun my/clock-in-organization-task-as-default () + (interactive) + (org-with-point-at (org-id-find my/organization-task-id 'marker) + (org-clock-in '(16)))) + +(defun my/clock-out-maybe () + (when (and my/keep-clock-running + (not org-clock-clocking-in) + (marker-buffer org-clock-default-task) + (not org-clock-resolving-clocks-due-to-idleness)) + (my/clock-in-parent-task))) + + +(defun my/skip-non-archivable-tasks () + "Skip trees that are not available for archiving" + (save-restriction + (widen) + ;; Consider only tasks with done todo headings as archivable candidates + (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))) + (subtree-end (save-excursion (org-end-of-subtree t)))) + (if (member (org-get-todo-state) org-todo-keywords-1) + (if (member (org-get-todo-state) org-done-keywords) + (let* ((daynr (string-to-int (format-time-string "%d" (current-time)))) + (a-month-ago (* 60 60 24 (+ daynr 1))) + (last-month (format-time-string "%Y-%m-" (time-subtract (current-time) (seconds-to-time a-month-ago)))) + (this-month (format-time-string "%Y-%m-" (current-time))) + (subtree-is-current (save-excursion + (forward-line 1) + (and (< (point) subtree-end) + (re-search-forward (concat last-month "\\|" this-month) subtree-end t))))) + (if subtree-is-current + subtree-end ; Has a date in this month or last month, skip it + nil)) ; available to archive + (or subtree-end (point-max))) + next-headline)))) + + +(provide 'my-org-helpers) + +;;; my-org-helpers.el ends here diff --git a/_spacemacs.d/config/my-org.el b/_spacemacs.d/config/my-org.el new file mode 100644 index 0000000..f3bec12 --- /dev/null +++ b/_spacemacs.d/config/my-org.el @@ -0,0 +1,286 @@ +;;; my-org.el --- Custom Configurations for Org Mode +;; -*- mode: emacs-lisp -*- +;; vim: set ts=8 sw=2 tw=0 fenc=utf-8 ft=lisp: +;; +;; Aaron LI +;; Created: 2016-05-31 +;; + +;;; Commentary: +;; Custom configurations for Emacs Org mode +;; +;; [1] Spacemacs: Org layer +;; https://github.com/syl20bnr/spacemacs/blob/master/layers/org/README.org +;; [2] Norang: Org Mode (by Bernt Hansen) +;; http://doc.norang.ca/org-mode.html +;; + +;;; Code: + +;; Default task to clock in whenever the clock normally stops +(defvar my/organization-task-id "bb7f1326-bda4-11e6-a30d-185e0f33a428") + +;; Allow single character alphabetical bullets +;; Need to be set before `org.el' is loaded +(setq org-list-allow-alphabetical t) + +;; NOTE: +;; Spacemacs use the `org' from the ELPA instead of the one shipped with +;; Emacs. Therefore, any `org'-related code should NOT be loaded before +;; `dotspacemacs/user-config'. +(with-eval-after-load 'org + (require 'org-habit) + (require 'org-clock) + (require 'ox-latex) + + ;; Load custom helper functions for Org + (require 'my-org-helpers) + + ;; Default location to look for Org files + (setq org-directory '("~/org")) + ;; Directories of files / files to be used for agenda display + (setq org-agenda-files '("~/org")) + ;; Default file for storing notes, also the fallback file for capture + (setq org-default-notes-file "~/org/refile.org") + + ;; TODO state keywords and face settings + (setq org-todo-keywords + '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") + (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" + "CANCELLED(c@/!)" "MAIL" "PHONE" "MEETING"))) + ;(setq org-todo-keyword-faces + ; '(("TODO" :foreground "red" :weight bold) + ; ("NEXT" :foreground "blue" :weight bold) + ; ("DONE" :foreground "forest green" :weight bold) + ; ("WAITING" :foreground "orange" :weight bold) + ; ("HOLD" :foreground "magenta" :weight bold) + ; ("CANCELLED" :foreground "forest green" :weight bold) + ; ("MAIL" :foreground "forest green" :weight bold) + ; ("PHONE" :foreground "forest green" :weight bold) + ; ("MEETING" :foreground "forest green" :weight bold))) + ;; Automatically assign tags on state changes + (setq org-todo-state-tags-triggers + '(("CANCELLED" ("CANCELLED" . t)) ;; add "CANCELLED" tag + ("WAITING" ("WAITING" . t)) ;; add "WAITING" tag + ("HOLD" ("WAITING") ("HOLD" . t)) + (done ("WAITING") ("HOLD")) ;; remove "WAITING" and "HOLD" tags + ("TODO" ("WAITING") ("CANCELLED") ("HOLD")) + ("TODO" ("WAITING") ("CANCELLED") ("HOLD")) + ("DONE" ("WAITING") ("CANCELLED") ("HOLD")))) + + ;; Allow to select a state while bypass the associated logging + (setq org-treat-S-cursor-todo-selection-as-state-change nil) + + ;; Capture templates + (setq org-capture-templates + '(("t" "Task" entry (file "") + "* TODO %?\n%U\n%a\n" :clock-in t :clock-resume t) + ("n" "Note" entry (file "") + "* %? :NOTE:\n%U\n%a\n" :clock-in t :clock-resume t) + ("d" "Diary" entry (file+datetree "diary.org") + "* %?\n%U\n" :clock-in t :clock-resume t) + ("p" "Phone Call" entry (file "") + "* PHONE %? :PHONE:\n%U" :clock-in t :clock-resume t) + ("m" "Meeting" entry (file "") + "* MEETING with %? :MEETING:\n%U" :clock-in t :clock-resume t) + ("h" "Habit" entry (file "") + "* NEXT %?\n%U\n%a\nSCHEDULED: %(format-time-string \"%<<%Y-%m-%d %a .+1d/3d>>\")\n:PROPERTIES:\n:STYLE: habit\n:REPEAT_TO_STATE: NEXT\n:END:\n") + )) + + ;; Remove empty `LOGBOOK' drawers on clock out + (add-hook 'org-clock-out-hook 'my/remove-empty-drawer-on-clock-out 'append) + + ;; More handy shortcuts + (global-set-key (kbd "") 'org-agenda) + + ;; Exclude `DONE' state tasks from refile targets + (setq org-refile-target-verify-function 'my/verify-refile-target) + + ;; Do not dim blocked tasks + (setq org-agenda-dim-blocked-tasks nil) + ;; Compact the block agenda view + (setq org-agenda-compact-blocks t) + ;; Custom agenda command definitions + (setq org-agenda-custom-commands + '(("N" "Notes" tags "NOTE" + ((org-agenda-overriding-header "Notes") + (org-tags-match-list-sublevels t))) + ("h" "Habits" tags-todo "STYLE=\"habit\"" + ((org-agenda-overriding-header "Habits") + (org-agenda-sorting-strategy + '(todo-state-down effort-up category-keep)))) + (" " "Agenda" + ((agenda "" nil) + (tags "REFILE" + ((org-agenda-overriding-header "Tasks to Refile") + (org-tags-match-list-sublevels nil))) + (tags-todo "-CANCELLED/!" + ((org-agenda-overriding-header "Stuck Projects") + (org-agenda-skip-function 'my/skip-non-stuck-projects) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-HOLD-CANCELLED/!" + ((org-agenda-overriding-header "Projects") + (org-agenda-skip-function 'my/skip-non-projects) + (org-tags-match-list-sublevels 'indented) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-CANCELLED/!NEXT" + ((org-agenda-overriding-header + (concat "Project Next Tasks" + (if my/hide-scheduled-and-waiting-next-tasks + "" + " (including WAITING and SCHEDULED tasks)"))) + (org-agenda-skip-function 'my/skip-projects-and-habits-and-single-tasks) + (org-tags-match-list-sublevels t) + (org-agenda-todo-ignore-scheduled my/hide-scheduled-and-waiting-next-tasks) + (org-agenda-todo-ignore-deadlines my/hide-scheduled-and-waiting-next-tasks) + (org-agenda-todo-ignore-with-date my/hide-scheduled-and-waiting-next-tasks) + (org-agenda-sorting-strategy + '(todo-state-down effort-up category-keep)))) + (tags-todo "-REFILE-CANCELLED-WAITING-HOLD/!" + ((org-agenda-overriding-header + (concat "Project Subtasks" + (if my/hide-scheduled-and-waiting-next-tasks + "" + " (including WAITING and SCHEDULED tasks)"))) + (org-agenda-skip-function 'my/skip-non-project-tasks) + (org-agenda-todo-ignore-scheduled my/hide-scheduled-and-waiting-next-tasks) + (org-agenda-todo-ignore-deadlines my/hide-scheduled-and-waiting-next-tasks) + (org-agenda-todo-ignore-with-date my/hide-scheduled-and-waiting-next-tasks) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-REFILE-CANCELLED-WAITING-HOLD/!" + ((org-agenda-overriding-header + (concat "Standalone Tasks" + (if my/hide-scheduled-and-waiting-next-tasks + "" + " (including WAITING and SCHEDULED tasks)"))) + (org-agenda-skip-function 'my/skip-project-tasks) + (org-agenda-todo-ignore-scheduled my/hide-scheduled-and-waiting-next-tasks) + (org-agenda-todo-ignore-deadlines my/hide-scheduled-and-waiting-next-tasks) + (org-agenda-todo-ignore-with-date my/hide-scheduled-and-waiting-next-tasks) + (org-agenda-sorting-strategy + '(category-keep)))) + (tags-todo "-CANCELLED+WAITING|HOLD/!" + ((org-agenda-overriding-header + (concat "Waiting and Postponed Tasks" + (if my/hide-scheduled-and-waiting-next-tasks + "" + " (including WAITING and SCHEDULED tasks)"))) + (org-agenda-skip-function 'my/skip-non-tasks) + (org-tags-match-list-sublevels nil) + (org-agenda-todo-ignore-scheduled my/hide-scheduled-and-waiting-next-tasks) + (org-agenda-todo-ignore-deadlines my/hide-scheduled-and-waiting-next-tasks))) + (tags "-REFILE/" + ((org-agenda-overriding-header "Tasks to Archive") + (org-agenda-skip-function 'my/skip-non-archivable-tasks) + (org-tags-match-list-sublevels nil)))) + nil))) + + (defun my/org-auto-exclude-function (tag) + "Automatic task exclusion in the agenda with `/ RET'" + (and (cond + ((string= tag "hold") t) ; exclude "HOLD" tasks + ) + (concat "-" tag))) + (setq org-agenda-auto-exclude-function 'my/org-auto-exclude-function) + + ;; Clocking + ;; + ;; Resume clocking task when Emacs is restarted + (org-clock-persistence-insinuate) + ;; Save the running clock and all clock history when exiting Emacs, + ;; and load it on startup + (setq org-clock-persist t) + ;; Do not prompt to resume an active clock + (setq org-clock-persist-query-resume nil) + ;; Enable auto clock resolution for finding open clocks + (setq org-clock-auto-clock-resolution 'when-no-clock-is-running) + ;; Show lot of clocking history so it's easy to pick items off the list + (setq org-clock-history-length 23) + ;; Resume clocking task on clock-in if the clock is open + (setq org-clock-in-resume t) + ;; Change tasks to `NEXT' when clocking in + (setq org-clock-in-switch-to-state 'my/clock-in-to-next) + ;; Separate drawers for clocking and logs + (setq org-drawers '("PROPERTIES" "LOGBOOK")) + ;; Save clock data and state changes and notes in the `LOGBOOK' drawer + (setq org-clock-into-drawer t) + ;; Remove clocked tasks with 0:00 duration + (setq org-clock-out-remove-zero-time-clocks t) + ;; Clock out when moving task to a done state + (setq org-clock-out-when-done t) + (add-hook 'org-clock-out-hook 'my/clock-out-maybe 'append) + ;; Use discrete minute intervals (no rounding) increments for time editing + (setq org-time-stamp-rounding-minutes '(1 1)) + + ;; Agenda clock report parameters + (setq org-agenda-clockreport-parameter-plist + '(:link t :maxlevel 5 :fileskip0 t :compact t :narrow 80)) + ;; Set default column view headings: Task Effort ClockSummary + (setq org-columns-default-format + "%80ITEM(task) %10Effort(Effort){:} %10CLOCKSUM") + ;; Global `Effort' estimate values, + ;; and global `STYLE' property values for completion + (setq org-global-properties + '(("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"))) + ;; Agenda log mode items to display (closed and state changes by default) + (setq org-agenda-log-mode-items '(closed state)) + + ;; Tags with fast selection keys + (setq org-tag-alist + '((:startgroup) + ("@office" . ?o) + ("@home" . ?H) + ("@dorm" . ?d) + (:endgroup) + ("WAITING" . ?w) + ("HOLD" . ?h) + ("PERSONAL" . ?P) + ("WORK" . ?W) + ("ORG" . ?O) + ("ASTRO" . ?a) + ("NOTE" . ?n) + ("CANCELLED" . ?c) + ("FLAGGED" . ??))) + ;; Allow setting single tags without the menu + (setq org-fast-tag-selection-single-key (quote expert)) + ;; For tag searches ignore tasks with scheduled and deadline dates + (setq org-agenda-tags-todo-honor-ignore-options t) + + ;; Any task with a subtask using a todo keyword is a project. + ;; Projects are "stuck" if they have no subtask with a `NEXT' todo keyword. + + ;; Only show today's agenda by default + (setq org-agenda-span 'day) + ;; Disable the default stuck projects agenda view + (setq org-stuck-projects '("" nil nil "")) + + ;; Archive + (setq org-archive-mark-done nil) + (setq org-archive-location "%s_archive::* Archived Tasks") + + ;; Enable in-using Babel languages + (org-babel-do-load-languages + 'org-babel-load-languages + '((emacs-lisp . t) + (sh . t) + (python . t) + (ditaa . t) + )) + + ;; Set the bullet symbols for `org-bullets' + (setq org-bullets-bullet-list '("♠" "♥" "♣" "♦")) ;; "SHoCkeD" ordering + + ;; Set the path to the `ditaa' program + (setq org-ditaa-jar-path "~/.spacemacs.d/local/ditaa/ditaa.jar") + + ;; END: Org-mode configurations + ) + + +(provide 'my-org) + +;;; my-org.el ends here diff --git a/_spacemacs.d/init.el b/_spacemacs.d/init.el index 97583a1..9b3b791 100644 --- a/_spacemacs.d/init.el +++ b/_spacemacs.d/init.el @@ -485,8 +485,8 @@ ;; ;; Load custom configurations (push "~/.spacemacs.d/config" load-path) - (require 'aly-org-config) - (require 'aly-mu4e-config) + (require 'my-org) + (require 'my-mu4e) ;; ;; Set custom file location instead of using this file (setq custom-file "~/.spacemacs.d/custom.el") -- cgit v1.2.2