Commit 3a0a211ab645

Vincent Demeester <vincent@sbr.pm>
2020-01-31 13:12:33
emacs.org: move setup-org.el
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
1 parent 28d8a05
Changed files (2)
lisp/setup-org.el
@@ -1,7 +1,4 @@
-;;; setup-org.el --- setup org-mode -*- lexical-binding: t; -*-
-;;; Commentary:
-;;; Code:
-
+;;; -*- lexical-binding: t; -*-
 (defvar org-directory "~/desktop/org/")
 (defvar site-directory "~/desktop/sites/")
 
@@ -550,9 +547,3 @@ activation of `org-tree-slide-mode'."
   :after magit)
 
 (provide 'setup-org)
-;;; setup-org.el ends here
-
-;; Local Variables:
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
emacs.org
@@ -341,6 +341,561 @@
   (provide 'setup-browser)
 #+end_src
 
+** ~setup-org.el~
+
+#+begin_src emacs-lisp :tangle lisp/setup-org.el
+  ;;; -*- lexical-binding: t; -*-
+  (defvar org-directory "~/desktop/org/")
+  (defvar site-directory "~/desktop/sites/")
+
+  (defvar org-default-projects-dir (concat org-directory "projects") "Primary tasks directory.")
+  (defvar org-default-technical-dir (concat org-directory "technical") "Directory of shareable, technical notes.")
+  (defvar org-default-personal-dir (concat org-directory "personal") "Directory of un-shareable, personal notes.")
+  (defvar org-default-completed-dir (concat org-directory "projects/completed") "Directory of completed project files.")
+  (defvar org-default-inbox-file (concat org-directory "projects/inbox.org") "New stuff collected in this file.")
+  (defvar org-default-incubate-file (concat org-directory "projects/incubate.org") "Ideas simmering on back burner.")
+  (defvar org-default-notes-file (concat org-directory "personal/notes.org") "Non-actionable, personal notes.")
+  (defvar org-default-media-file (concat org-directory "projects/media.org") "Links to other things to check out.")
+  (defvar org-default-journal-file (concat org-directory "personal/journal.org") "Journaling stuff.")
+
+  (set-register ?i `(file . ,org-default-inbox-file))
+  (set-register ?I `(file . ,org-default-incubate-file))
+  (set-register ?j `(file . ,org-default-journal-file))
+  (set-register ?m `(file . ,org-default-media-file))
+
+  (defvar org-default-publish-technical (concat site-directory "sbr.pm/technical"))
+
+  ;; Use `org-mode' instead of `lisp-interaction-mode' for scratch buffer
+  (setq
+   inhibit-startup-message t            ; don't show the startup message
+   inhibit-startup-screen t             ; … or screen
+   initial-scratch-message nil          ; empty scratch buffer
+   initial-major-mode 'org-mode  ; org-mode by default
+   )
+
+  (use-package s)
+
+  (use-package org
+    :defer t
+    :mode (("\\.org$" . org-mode))
+    :commands (org-capture org-agenda)
+    :ensure org-plus-contrib
+    :hook (org-mode . vde/org-mode-hook)
+    :bind (("C-c o c" . org-capture)
+           ("C-c o l" . org-store-link)
+           ("C-c o r r" . org-refile)
+           ("C-c o r a" . org-agenda-refile)
+           ("C-c o a" . org-agenda)
+           ("<f12>" . org-agenda)
+           ("<f11>" . org-clock-goto))
+    :config
+    (use-package find-lisp)
+    (setq org-modules '(org-crypt
+                        org-docview
+                        org-habit
+                        org-id
+                        org-info
+                        org-irc
+                        org-protocol
+                        org-man
+                        org-git-link
+                        org-notmuch))
+    (setq org-todo-keywords
+          '((sequence "TODO(t)" "NEXT(n)" "STARTED(s)" "|" "DONE(d!)" "CANCELED(c@/!)")
+            (sequence "WAITING(w@/!)" "SOMEDAY(s)" "|" "CANCELED(c@/!)")
+            (sequence "IDEA(i)" "|" "CANCELED(c@/!)")))
+    (setq org-todo-state-tags-triggers '(
+                                         ("CANCELLED" ("CANCELLED" . t))
+                                         ("WAITING" ("WAITING" . t))
+                                         (done ("WAITING"))
+                                         ("TODO" ("WAITING") ("CANCELLED"))
+                                         ("NEXT" ("WAITING") ("CANCELLED"))
+                                         ("DONE" ("WAITING") ("CANCELLED"))))
+    (setq org-blank-before-new-entry '((heading . t)
+                                       (plain-list-item . nil)))
+
+    (setq org-habit-show-habits-only-for-today nil)
+    (setq org-habit-graph-column 80)
+    (setq org-agenda-files (list org-default-projects-dir))
+    (setq org-agenda-file-regexp "^[a-z0-9-_]+.org")
+
+    (setq org-agenda-include-diary t)
+    (setq org-use-property-inheritance t)
+
+    (setq org-enforce-todo-dependencies t)
+
+    (setq org-refile-use-outline-path 'file
+          org-outline-path-complete-in-steps nil
+          org-refile-allow-creating-parent-nodes 'confirm)
+
+    (setq org-refile-targets (append '((org-default-media-file :level . 1)
+                                       (org-default-inbox-file :level . 0))
+                                     (->>
+                                      (directory-files org-default-projects-dir nil ".org")
+                                      (-remove-item (file-name-base org-default-media-file))
+                                      (--remove (s-starts-with? "." it))
+                                      (--map (format "%s/%s" org-default-projects-dir it))
+                                      (--map `(,it :level . 1)))))
+
+    (setq org-indirect-buffer-display 'dedicated-frame)
+    (setq org-use-speed-commands t)
+
+    (setq org-log-done (quote time))
+    (setq org-log-redeadline (quote time))
+    (setq org-log-reschedule (quote time))
+    (setq org-log-into-drawer t)
+
+    (setq org-fontify-whole-heading-line t)
+    (setq org-src-fontify-natively t)
+    (setq org-src-tab-acts-natively t)
+
+    (setq org-pretty-entities t)
+    (setq org-insert-heading-respect-content t)
+    (setq org-ellipsis " …")
+
+    (setq org-agenda-window-setup (quote current-window))
+    (setq org-special-ctrl-a/e t)
+    (setq org-special-ctrl-k t)
+    (setq org-yank-adjusted-subtrees t)
+
+    (setcar (nthcdr 4 org-emphasis-regexp-components) 10)
+
+    (setq org-tag-alist (quote (("linux") ("nixos") ("emacs") ("org")
+                                ("openshift") ("redhat") ("tektoncd") ("kubernetes") ("knative" ) ("docker")
+                                ("docs") ("code") ("review")
+                                (:startgroup . nil)
+                                ("@home" . ?h) ("@work" . ?w) ("@errand" . ?e) ("@health" . ?l)
+                                (:endgroup . nil)
+                                (:startgroup . nil)
+                                ("@link" . ?i) ("@read" . ?r) ("@project" . ?p)
+                                (:endgroup . nil)
+                                )))
+    (setq org-agenda-skip-scheduled-if-done nil)
+
+    (use-package org-super-agenda
+      :config (org-super-agenda-mode))
+
+    (setq org-agenda-span 'day
+          org-agenda-compact-blocks t
+          org-super-agenda-header-separator "")
+    (setq org-agenda-sticky t)
+    (setq org-agenda-custom-commands
+          `(("n" "Personal agenda"
+             ((agenda "")
+              (tags-todo "+TODO=\"NEXT\""
+                         ((org-agenda-overriding-header "Next items")))
+              (tags-todo "@work-goals"
+                         ((org-agenda-skip-function '(org-agenda-skip-if nil '(scheduled deadline)))
+                          (org-agenda-overriding-header "Work")))
+              (tags-todo "@home-goals"
+                         ((org-agenda-skip-function '(org-agenda-skip-if nil '(scheduled deadline)))
+                          (org-agenda-overriding-header "Home"))))
+             ((org-super-agenda-groups
+               '((:name "Important" :priority "A")
+                 (:name "Done" :log closed)
+                 (:name "Scheduled" :time-grid t)
+                 (:name "Work" :tag "@work")
+                 (:name "Perso" :tag "@home")
+                 (:habit t))))
+             (org-agenda-list))))
+
+    (defun vde/is-project-p ()
+      "Any task with a todo keyword 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 has-subtask))))
+
+    (defun vde/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
+          (vde/find-project-task)
+          (if (equal (point) task)
+              nil
+            t))))
+
+    (defun vde/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 vde/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 vde/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)))
+
+    ;; Set default column view headings: Task Effort Clock_Summary
+    (setq org-columns-default-format "%80ITEM(Task) %TODO %3PRIORITY %10Effort(Effort){:} %10CLOCKSUM")
+
+    (setq org-global-properties (quote (("Effort_ALL" . "0:15 0:30 0:45 1:00 2:00 3:00 4:00 5:00 6:00 0:00")
+                                        ("STYLE_ALL" . "habit"))))
+
+    (org-clock-persistence-insinuate)
+    ;; Show lot of clocking history so it's easy to pick items off the C-F11 list
+    (setq org-clock-history-length 23)
+    ;; Change tasks to STARTED when clocking in
+    (setq org-clock-in-switch-to-state 'vde/clock-in-to-started)
+    ;; Clock out when moving task to a done state
+    (setq org-clock-out-when-done t)
+    ;; Save the running clock and all clock history when exiting Emacs, load it on startup
+    (setq org-clock-persist t)
+
+    (defun vde/clock-in-to-started (kw)
+      "Switch a task from TODO to STARTED when clocking in.
+  Skips capture tasks, projects, and subprojects.
+  Switch projects and subprojects from STARTED back to TODO"
+      (when (not (and (boundp 'org-capture-mode) org-capture-mode))
+        (cond
+         ((and (member (org-get-todo-state) (list "TODO"))
+               (vde/is-task-p))
+          "STARTED")
+         ((and (member (org-get-todo-state) (list "STARTED"))
+               (vde/is-project-p))
+          "TODO"))))
+
+    (defvar org-capture-templates (list))
+    (setq org-protocol-default-template-key "l")
+
+    ;; images
+    (setq org-image-actual-width nil
+          org-startup-with-inline-images t)
+
+    ;; Tasks (-> inbox)
+    (add-to-list 'org-capture-templates
+                 `("t" "Task Entry" entry
+                   (file ,org-default-inbox-file)
+                   "* %?\n:PROPERTIES:\n:CREATED:%U\n:END:\n\n%i\n\nFrom: %a"
+                   :empty-lines 1))
+    (add-to-list 'org-capture-templates
+                 `("r" "PR Review" entry
+                   (file ,org-default-inbox-file)
+                   "* TODO review gh:%^{issue} :review:\n:PROPERTIES:\n:CREATED:%U\n:END:\n\n%i\n%?\nFrom: %a"
+                   :empty-lines 1))
+    (add-to-list 'org-capture-templates
+                 `("l" "Link" entry
+                   (file ,org-default-inbox-file)
+                   "* %a\n%U\n%?\n%i"
+                   :empty-lines 1))
+    (add-to-list 'org-capture-templates
+                 '("n" "Thought or Note"  entry
+                   (file org-default-notes-file)
+                   "* %?\n\n  %i\n\n  See: %a" :empty-lines 1))
+
+    ;; Journal
+    (add-to-list 'org-capture-templates
+                 `("j" "Journal entry" entry
+                   (file+datetree ,org-default-journal-file)
+                   "* %^{title}\n%U\n%?\n%i\nFrom: %a"
+                   :empty-lines 1 :clock-in t :clock-resume t))
+    (add-to-list 'org-capture-templates
+                 `("w" "Worklog (journal) entry" entry
+                   (file+datetree ,org-default-journal-file)
+                   "* worklog :@work:log:\n%U\n** Today\n%?\n** Next (later today, tomorrow)\n"))
+    (add-to-list 'org-capture-templates
+                 `("e" "Weekly review" entry
+                   (file+datetree,org-default-journal-file)
+                   "* weekly review :weekly:review:\n%U
+
+  - [ ] review [[file:../projects/inbox.org][~inbox.org~]]
+    Clean the file by either
+    - refiling it to ~incubate.org~
+    - removing it / archiving it
+  - [ ] review [[file:../projects/incubate.org][~incubate.org~]]
+    - Is something worth becoming a project
+    - Is something not worth thinking about anymore ?
+  - [ ] empty mail inbox (and create task if needed)
+    - [ ] work
+    - [ ] perso
+  - [ ] Review next week ~F12 n w f~
+  - [ ] review ~org-mode~ workflow
+    - *what works, what doesn't ?*
+    - *is there task / stuck projects ?*
+    - *enhancement possible ?*
+  - [ ] export previous agenda (somewhere)"
+                   :clock-in t :clock-resume t))
+
+    ;; Olds, most likely to remove
+    (add-to-list 'org-capture-templates
+                 `("b" "Blog post" entry
+                   (file+headline "~/src/github.com/vdemeester/blog/content-org/posts.org" "Blog Ideas")
+                   "* %?\n:PROPERTIES:\n:END:\n"))
+    (add-to-list 'org-capture-templates
+                 `("bl" "Blog link post" entry
+                   (file+olp "~/src/github.com/vdemeester/blog/content-org/links.org" "Link")
+                   "* %a\n%?\n%i"))
+
+    (setq org-ditaa-jar-path "/home/vincent/.nix-profile/lib/ditaa.jar") ;; FIXME(vdemeester) remove /home/vincent
+    ;; org-babel
+    (org-babel-do-load-languages
+     'org-babel-load-languages
+     '((css . t)
+       (dot . t)
+       (ditaa . t)
+       (emacs-lisp . t)
+       (go . t)
+       (gnuplot . t)
+       (http . t)
+       (js . t)
+       ;;(ledger . t)
+       (latex . t)
+       (python . t)
+       ;;(rust . t)
+       (shell . t)
+       ;;(typescript . t)
+       ))
+
+    (setq org-latex-listings t)
+
+    (setq org-list-demote-modify-bullet
+          '(("+" . "-") ("-" . "+")))
+
+    (add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" ":END:"))
+    (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" "#\\+END_SRC"))
+    (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_EXAMPLE" "#\\+END_EXAMPLE"))
+
+    ;; org-links
+    ;; from http://endlessparentheses.com/use-org-mode-links-for-absolutely-anything.html
+    (org-link-set-parameters "tag"
+                             :follow #'endless/follow-tag-link)
+    (defun endless/follow-tag-link (tag)
+      "Display a list of TODO headlines with tag TAG.
+  With prefix argument, also display headlines without a TODO keyword."
+      (org-tags-view (null current-prefix-arg) tag))
+
+    (org-link-set-parameters "grep"
+                             :follow #'vde/follow-grep-link
+                             :face '(:foreground "DarkRed" :underline t))
+    (defun vde/follow-grep-link (regexp)
+      "Run `rgrep' with REGEXP and FOLDER as argument,
+  like this : [[grep:REGEXP:FOLDER]]."
+      (setq expressions (split-string regexp ":"))
+      (setq exp (nth 0 expressions))
+      (grep-compute-defaults)
+      (if (= (length expressions) 1)
+          (progn
+            (rgrep exp "*" (expand-file-name "./")))
+        (progn
+          (setq folder (nth 1 expressions))
+          (rgrep exp "*" (expand-file-name folder))))
+      )
+
+    (org-link-set-parameters "rg"
+                             :follow #'vde/follow-rg-link
+                             :face '(:foreground "DarkGreen" :underline t))
+    (defun vde/follow-rg-link (regexp)
+      "Run `ripgrep-regexp` with REXEP and FOLDER as argument,
+  like this : [[pt:REGEXP:FOLDER]]"
+      (setq expressions (split-string regexp ":"))
+      (setq exp (nth 0 expressions))
+      (if (= (length expressions) 1)
+          (progn
+            (ripgrep-regexp exp (expand-file-name "./")))
+        (progn
+          (setq folder (nth 1 expressions))
+          (ripgrep-regexp exp (file-name-as-directory (expand-file-name folder)))))
+      )
+
+    (org-link-set-parameters "gh"
+                             :follow #'vde/follow-gh-link
+                             :export #'vde/org-gh-export
+                             :face '(:foreground "DimGrey" :underline t))
+    (defun vde/org-gh-export (link description format)
+      "Export a github page link from Org files."
+      (let ((path (vde/gh-get-url link))
+            (desc (or description link)))
+        (cond
+         ((eq format 'html) (format "<a hrefl=\"_blank\" href=\"%s\">%s</a>" path desc))
+         ((eq format 'latex) (format "\\href{%s}{%s}" path desc))
+         ((eq format 'texinfo) (format "@uref{%s,%s}" path desc))
+         ((eq format 'ascii) (format "%s (%s)" desc path))
+         (t path))))
+    (defun vde/follow-gh-link (issue)
+      "Browse github issue/pr specified"
+      (browse-url (vde/gh-get-url issue)))
+
+    (defun vde/gh-get-url (path)
+      "Translate org-mode link `gh:foo/bar#1' to github url."
+      (setq expressions (split-string path "#"))
+      (setq project (nth 0 expressions))
+      (setq issue (nth 1 expressions))
+      (format "https://github.com/%s/issues/%s" project issue))
+
+    (org-link-set-parameters
+     "org"
+     :complete (lambda () (+org-link-read-file "org" org-directory))
+     :follow   (lambda (link) (find-file (expand-file-name link org-directory)))
+     :face     (lambda (link)
+                 (if (file-exists-p (expand-file-name link org-directory))
+                     'org-link
+                   'error)))
+    (defun +org-link-read-file (key dir)
+      (let ((file (read-file-name (format "%s: " (capitalize key)) dir)))
+        (format "%s:%s"
+                key
+                (file-relative-name file dir))))
+    )
+
+  (defun vde/org-mode-hook ()
+    "Org-mode hook"
+    (setq show-trailing-whitespace t)
+    (when (not (eq major-mode 'org-agenda-mode))
+      (setq fill-column 90)
+      (auto-revert-mode)
+      (auto-fill-mode)
+      (flyspell-mode)
+      (org-indent-mode)
+      (smartparens-mode)))
+
+  (use-package org-id
+    :after org
+    :custom
+    (org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)
+    :config
+    (defun eos/org-custom-id-get (&optional pom create prefix)
+      "Get the CUSTOM_ID property of the entry at point-or-marker POM.
+     If POM is nil, refer to the entry at point. If the entry does
+     not have an CUSTOM_ID, the function returns nil. However, when
+     CREATE is non nil, create a CUSTOM_ID if none is present
+     already. PREFIX will be passed through to `org-id-new'. In any
+     case, the CUSTOM_ID of the entry is returned."
+      (interactive)
+      (org-with-point-at pom
+        (let ((id (org-entry-get nil "CUSTOM_ID")))
+          (cond
+           ((and id (stringp id) (string-match "\\S-" id))
+            id)
+           (create
+            (setq id (org-id-new (concat prefix "h")))
+            (org-entry-put pom "CUSTOM_ID" id)
+            (org-id-add-location id (buffer-file-name (buffer-base-buffer)))
+            id)))))
+
+    (defun eos/org-add-ids-to-headlines-in-file ()
+      "Add CUSTOM_ID properties to all headlines in the
+     current file which do not already have one."
+      (interactive)
+      (org-map-entries (lambda ()
+                         (eos/org-custom-id-get (point) 'create)))))
+
+  (use-package ob-go
+    :after (org))
+  (use-package ob-async
+    :after (org))
+  (use-package ob-http
+    :after (org))
+
+  (use-package org-crypt
+    :after (org)
+    :config
+    (org-crypt-use-before-save-magic)
+    (setq org-tags-exclude-from-inheritance (quote ("crypt"))))
+
+  (use-package smartparens-org
+    :after org-mode)
+
+  (use-package ox-publish
+    :config
+    (setq org-html-coding-system 'utf-8-unix))
+  (use-package ox-slack
+    :after ox)
+  (use-package ox-hugo
+    :after ox
+    :commands (org-hugo-slug)
+    :bind (:map vde-mode-map
+                ("C-c G" . org-hugo-export-wim-to-md))
+    :config
+    (use-package ox-hugo-auto-export))
+
+  (use-package org-notify
+    :after org
+    :config
+    (org-notify-start))
+
+  (use-package org-capture-pop-frame)
+
+  (use-package darkroom
+    :custom
+    (darkroom-text-scale-increase 2))
+  (use-package org-tree-slide
+    :after (org darkroom)
+    :custom
+    (org-tree-slide-breadcrumbs nil)
+    (org-tree-slide-header nil)
+    (org-tree-slide-slide-in-effect nil)
+    (org-tree-slide-heading-emphasis nil)
+    (org-tree-slide-cursor-init t)
+    (org-tree-slide-modeline-display nil)
+    (org-tree-slide-skip-done nil)
+    (org-tree-slide-skip-comments t)
+    (org-tree-slide-fold-subtrees-skipped t)
+    (org-tree-slide-skip-outline-level 8)
+    (org-tree-slide-never-touch-face t)
+    :config
+    (defun prot/org-presentation ()
+      "Specifies conditions that should apply locally upon
+  activation of `org-tree-slide-mode'."
+      (if (eq darkroom-tentative-mode nil)
+          (progn
+            (darkroom-tentative-mode 1)
+            (org-indent-mode 1)
+            (set-frame-font "Hack-14" t t)
+            (setq cursor-type '(bar . 1)))
+        (darkroom-tentative-mode -1)
+        (org-indent-mode -1)
+        (prot/fonts-per-monitor)
+        (setq cursor-type 'box)))
+    :bind (("<f8>" . org-tree-slide-mode)
+           :map org-tree-slide-mode-map
+           ("<C-right>" . org-tree-slide-move-next-tree)
+           ("<C-left>" . org-tree-slide-move-previous-tree))
+    :hook (org-tree-slide-mode . prot/org-presentation))
+
+  (use-package orgit
+    :after magit)
+
+  (provide 'setup-org)
+#+end_src
+
+
 ** ~setup-style.el~
 
 #+begin_src emacs-lisp :tangle lisp/setup-style.el