diff options
Diffstat (limited to '')
| -rw-r--r-- | init.el | 133 | ||||
| -rw-r--r-- | org-msg-style.css | 42 |
2 files changed, 144 insertions, 31 deletions
@@ -162,13 +162,13 @@ :bind ((:prefix-map consult-commands :prefix-docstring "Consult mode quick commands" :prefix "C-c c" - ("c b" . 'consult-bookmark) - ("c f" . 'consult-ripgrep) - ("c l" . 'consult-focus-lines) - ("c o" . 'consult-outline) - ("c r l" . 'consult-register-load) - ("c r s" . 'consult-register-store) - ("c r w" . 'consult-register))) + ("b" . 'consult-bookmark) + ("f" . 'consult-ripgrep) + ("l" . 'consult-focus-lines) + ("o" . 'consult-outline) + ("r l" . 'consult-register-load) + ("r s" . 'consult-register-store) + ("r w" . 'consult-register))) :bind (("C-x b" . 'consult-buffer) ("M-g M-g" . 'consult-goto-line)) :hook (completion-list-mode . consult-preview-at-point-mode)) @@ -238,6 +238,9 @@ (before-save . lsp-format-buffer) (before-save . lsp-organize-imports))) +(use-package htmlize + :ensure t) + (use-package just-mode :ensure t) @@ -349,6 +352,8 @@ :bind (("C-c M" . mu4e) ("C-x m" . mu4e-compose-new)) :hook (mu4e-compose-mode . (lambda () (use-hard-newlines -1))) + :init + (setq mail-user-agent 'mu4e-user-agent) :config (defun my/email-to-display-name (email) "Derive a display name from EMAIL, e.g. jane.doe@x.com -> Jane Doe." @@ -356,7 +361,7 @@ (split-string (car (split-string email "@")) "[._-]") " ")) - (setq mu4e-compose-format-flowed t) + ;; (setq mu4e-compose-format-flowed t) ;; this handled by org-msg (setq message-citation-line-function 'message-insert-formatted-citation-line) (setq message-citation-line-format "On %a, %d %b %Y at %R, %f wrote:\n") @@ -466,7 +471,7 @@ (use-package org-ai :after password-store :ensure t - :bind (("C-c M-a h" . 'org-ai-prompt)) + :bind (("C-c o o" . 'org-ai-prompt)) :init (org-ai-global-mode) (setq org-ai-openai-api-token (password-store-get "openai.com/api.openai.com/apikey") @@ -480,26 +485,52 @@ (setq org-journal-file-format "%Y-%m.org") (setq org-journal-enable-agenda-integration nil)) +(use-package org-msg + :ensure t + :after (:all mu4e org) + :hook ((message-mode . org-msg-mode) + (mu4e-compose-mode . org-msg-mode) + (org-msg-edit-mode . my/org-msg-hexo-ish-css)) + :config + (defun my/org-msg-hexo-ish-css () + "Use a Hexo-ish CSS file for org-msg emails only." + (setq-local org-msg-enforce-css + (expand-file-name "org-msg-style.css" user-emacs-directory))) + + (setq org-msg-options "html-postamble:nil H:5 num:nil ^:{} toc:nil author:nil email:nil tex:dvipng" + org-msg-startup "hidestars indent inlineimages" + org-msg-greeting-fmt "\n" + org-msg-greeting-name-limit 3 + org-msg-default-alternatives '((new . (text html)) + (reply-to-html . (text html)) + (reply-to-text . (text))) + org-msg-convert-citation t + org-msg-signature "")) + (use-package org-mode :after (:all org-ai org-journal ob-restclient) :mode "\\.org$" :bind (:prefix-map org-commands :prefix-docstring "Org mode quick commands" :prefix "C-c o" - ("j o" . org-journal-open-current-journal-file) + ("j c" . org-journal-open-current-journal-file) ("j n" . org-journal-new-entry) - ("j s" . org-journal-new-scheduled-entry) - ("c i" . org-capture) + ("p n" . org-capture) + ;; open plan.org + ("p o" . (lambda () (interactive) + (find-file (expand-file-name "planner/plan.org" org-dir)))) + ;; bulk archive + ("p a" . (lambda () (interactive) + (org-map-entries #'org-archive-subtree "/DONE|CANCELLED" 'file))) ("a" . org-agenda)) :hook ((org-mode . hl-todo-mode) (org-mode . olivetti-mode) (org-mode . org-ai-mode) - (org-mode . org-indent-mode)) + (org-mode . org-indent-mode) + (after-save . my/org-git-autocommit-after-save)) :init - (setq org-gtd-dir (expand-file-name "gtd/" org-dir)) - (org-babel-do-load-languages 'org-babel-load-languages '((emacs-lisp . t) @@ -511,27 +542,74 @@ (setq org-ai-image-directory (expand-file-name "org-ai-images/" org-dir)) + (defun my/org-git-autocommit-after-save () + "Auto-commit the current file if it lives under ~/.org/." + (when (and buffer-file-name + (not (file-remote-p buffer-file-name)) + (string-prefix-p + (file-name-as-directory (expand-file-name "~/.org/")) + (expand-file-name buffer-file-name))) + (let* ((default-directory (expand-file-name "~/.org/")) + (rel (file-relative-name buffer-file-name default-directory)) + (msg (format "autocommit on save [%s]" rel))) + (call-process "git" nil nil nil "add" "--" rel) + (call-process "git" nil nil nil "commit" "-m" msg "--" rel)))) + + (defun my/org-agenda-workspace-files () + "Return all plan.org files under ~/workspace, skipping common generated dirs." + (let ((root (expand-file-name "~/workspace"))) + (seq-filter + (lambda (f) + (not (string-match-p + (rx "/" (or ".git" "node_modules" ".direnv" ".venv" + "dist" "build" "target" ".cache") + "/") + f))) + (directory-files-recursively root "\\`plan\\.org\\'")))) + :custom - ;; GTD files - (org-default-notes-file (expand-file-name "gtd/inbox.org" org-dir)) - (org-agenda-files (list (expand-file-name "gtd/inbox.org" org-dir) - (expand-file-name "gtd/active.org" org-dir))) + (org-html-htmlize-output-type 'css) + + ;; Planner Files + (org-default-notes-file (expand-file-name "planner/plan.org" org-dir)) + (org-agenda-files + (cons (expand-file-name "planner/plan.org" org-dir) + (my/org-agenda-workspace-files))) ;; Capture templates (org-capture-templates - `(("i" "Inbox" entry (file+headline ,(expand-file-name "gtd/inbox.org" org-dir) "Inbox") + `(("t" "Todo" entry + (file+headline ,(expand-file-name "planner/plan.org" org-dir) "Inbox") "* TODO %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n" :empty-lines 1))) ;; Refile targets - (org-refile-targets `((,(expand-file-name "gtd/active.org" org-dir) :maxlevel . 2))) - (org-refile-use-outline-path 'file) + (org-refile-targets + `((,(expand-file-name "planner/plan.org" org-dir) :maxlevel . 2))) + (org-refile-use-outline-path t) (org-outline-path-complete-in-steps nil) (org-refile-allow-creating-parent-nodes 'confirm) ;; Archive location (year-based) - (org-archive-location (concat (expand-file-name "gtd/archive/" org-dir) - (format-time-string "%Y") ".org::")) + (org-archive-location + (concat (expand-file-name "planner/archive/" org-dir) + (format-time-string "%Y") ".org::")) + + ;; Planner states + (org-todo-keywords + '((sequence "TODO(t)" "NEXT(n)" "WAIT(w@)" "PROJECT(p)" "SOMEDAY(s)" + "|" "DONE(d!)" "CANCELLED(c@)"))) + + (org-agenda-custom-commands + '(("g" "GTD" + ((agenda "" ((org-agenda-span 7))) + (todo "NEXT" ((org-agenda-overriding-header "Next Actions"))) + (todo "WAIT" ((org-agenda-overriding-header "Waiting For"))) + (todo "PROJECT" ((org-agenda-overriding-header "Projects"))) + (todo "SOMEDAY" ((org-agenda-overriding-header "Someday / Maybe"))))))) + + ;; Babel + (org-confirm-babel-evaluate nil) ;; Display settings (org-auto-align-tags t) @@ -542,13 +620,6 @@ (org-num-face nil) (org-level-color-stars-only nil) - ;; Todo keywords - (org-todo-keywords - '((sequence "BACKLOG(b)" "BLOCKED(l)" "TODO(t)" "IN_PROGRESS(i)" "|" "DONE(d)" "CANCELLED(c)"))) - - ;; Babel - (org-confirm-babel-evaluate nil) - :custom-face (org-level-1 ((t (:family "Roboto" :height 120)))) (org-level-2 ((t (:family "Roboto" :height 110)))) diff --git a/org-msg-style.css b/org-msg-style.css new file mode 100644 index 0000000..1f5aba6 --- /dev/null +++ b/org-msg-style.css @@ -0,0 +1,42 @@ +pre.src, pre.example { + display: block; + overflow-x: auto; + padding: 0.75em; + border-radius: 6px; + + /* pick light or dark */ + background: #2d2d2d; + color: #cccccc; + + line-height: 1.4; +} + +/* Inline code/verbatim */ +code, .org-verbatim, .org-code { + background: rgba(127,127,127,0.15); + padding: 0.1em 0.25em; + border-radius: 4px; +} + +/* htmlize/org faces -> CSS classes (approx theme mapping) */ +.org-string, .org-doc { + color: #7ec699; +} + +.org-comment { + color: #999999; + font-style: italic; +} + +.org-keyword, .org-type, .org-builtin { + color: #cc99cd; + font-weight: 600; +} + +.org-function-name { + color: #6699cc; +} + +.org-variable-name { + color: #f99157; +} |
