{ config, lib, pkgs, ... }: with lib; mkIf (elem "emacs::org" config.machine.pkgs) { programs.emacs.init.usePackage.org = { enable = true; package = epkgs: [ epkgs.org epkgs.org-plus-contrib ]; mode = [ ''("\\.org\\'" . org-mode)'' ]; command = [ "org-mode" ]; hook = [ "(org-mode . (lambda () (org-indent-mode)))" '' (org-mode . (lambda () ;; Automatic line-wrapping in org-mode ;;(auto-fill-mode 1) (setq completion-at-point-functions '(org-completion-symbols ora-cap-filesystem)))) '' '' (org-mode . (lambda () "Beautify Org Checkbox Symbol" (push '("[ ]" . "☐" ) prettify-symbols-alist) (push '("[X]" . "☑" ) prettify-symbols-alist) (push '("[-]" . "❍" ) prettify-symbols-alist) (prettify-symbols-mode))) '' ] ++ optional (elem "emacs::flyspell" config.machine.pkgs) "(org-mode . (lambda () (flyspell-mode)))"; bind = { "C-c a" = "org-agenda"; }; bindLocal = { org-mode-map = { "M-" = "org-metaup"; "M-" = "org-metadown"; "M-." = "org-open-at-point"; "M-," = "org-mark-ring-goto"; "M-S-" = "org-insert-todo-heading-respect-content"; "M-" = "org-meta-return"; "M-p" = "org-previous-visible-heading"; "M-n" = "org-next-visible-heading"; } // (optionalAttrs (elem "emacs::company" config.machine.pkgs) { "" = "company-pcomplete"; }); }; config = '' ;; Insead of "..." show "…" when there's hidden folded content ;; org-prettify (defface org-checkbox-done-text '((t (:foreground "#71696A" :strike-through t))) "Face for the text part of a checked org-mode checkbox.") (font-lock-add-keywords 'org-mode `(("^[ \t]*\\(?:[-+*]\\|[0-9]+[).]\\)[ \t]+\\(\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[\\(?:X\\|\\([0-9]+\\)/\\2\\)\\][^\n]*\n\\)" 1 'org-checkbox-done-text prepend)) 'append) ;; Some characters to choose from: …, ⤵, ▼, ↴, ⬎, ⤷, and ⋱ (setq org-ellipsis " ▼") ;; get nice looking tables (only for non org-tables; rarely used) (setq table-cell-horizontal-chars "\u2501") (setq table-cell-vertical-char ?\u2503) (setq table-cell-intersection-char ?\u254B) (setq org-directory "~/Documents/org/") ;; Show headings up to level 2 by default when opening an org files (setq org-startup-folded 'content) ;; Show inline images by default (setq org-startup-with-inline-images t) ;; Add more levels to headlines that get displayed with imenu (setq org-imenu-depth 5) ;; Enter key follows links (= C-c C-o) (setq org-return-follows-link t) ;; Don't remove links after inserting (setq org-keep-stored-link-after-insertion t) (setq org-tag-alist (quote ((:startgroup) ("WAITING" . ?w) ("HOLD" . ?h) ("CANCELLED" . ?c) ("NOTE" . ?n) (:endgroup) ("PERSONAL" . ?P) ("WORK" . ?W) ("ATOMX" . ?A) ("E5" . ?E) ("HOGASO" . ?H) ("ORG" . ?o) ("crypt" . ?C) ("FLAGGED" . ??)))) ;; Allow setting single tags without the menu (setq org-fast-tag-selection-single-key (quote expert)) (setq org-archive-mark-done nil) (setq org-archive-location "%s_archive::* Archived Tasks") ;; C-RET, C-S-RET insert new heading after current task content (setq org-insert-heading-respect-content nil) ;; Show a little bit more when using sparse-trees (setq org-show-following-heading t) (setq org-show-hierarchy-above t) (setq org-show-siblings (quote ((default)))) ;; don't show * / = etc (setq org-hide-emphasis-markers t) ;; leave highlights in sparse tree after edit. C-c C-c removes highlights (setq org-remove-highlights-with-change nil) ;; M-RET should not split the lines (setq org-M-RET-may-split-line '((default . nil))) (setq org-special-ctrl-a/e t) (setq org-special-ctrl-k t) (setq org-yank-adjusted-subtrees t) ;; Show org entities as UTF-8 characters (e.g. \sum as ∑) (setq org-pretty-entities t) ;; But Don't print "bar" as subscript in "foo_bar" (setq org-pretty-entities-include-sub-superscripts nil) ;; And also don't display ^ or _ as super/subscripts (setq org-use-sub-superscripts nil) ;; undone TODO entries will block switching the parent to DONE (setq org-enforce-todo-dependencies t) (setq org-use-fast-todo-selection t) (setq org-todo-keywords (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)") (sequence "WAITING(w@/!)" "HOLD(h@/!)" "|" "CANCELLED(c@/!)" "PHONE" "MEETING")))) (setq org-todo-keyword-faces (quote (("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) ("MEETING" :foreground "forest green" :weight bold) ("PHONE" :foreground "forest green" :weight bold)))) ;; Auto completion for symbols in org-mode ;; https://oremacs.com/2017/10/04/completion-at-point/ (defun org-completion-symbols () (when (looking-back "[`~=][a-zA-Z]+" nil) (let (cands) (save-match-data (save-excursion (goto-char (point-min)) (while (re-search-forward "[`~=]\\([a-zA-Z.\\-_]+\\)[`~=]" nil t) (cl-pushnew (match-string-no-properties 0) cands :test 'equal)) cands)) (when cands (list (match-beginning 0) (match-end 0) cands))))) (defun ora-cap-filesystem () (let (path) (when (setq path (ffap-string-at-point)) (when (string-match "\\`file:\\(.*\\)\\'" path) (setq path (match-string 1 path))) (let ((compl (all-completions path #'read-file-name-internal))) (when compl (let* ((str (car compl)) (offset (let ((i 0) (len (length str))) (while (and (< i len) (equal (get-text-property i 'face str) 'completions-common-part)) (cl-incf i)) i))) (list (- (point) offset) (point) compl))))))) ''; }; programs.emacs.init.usePackage.ob = { enable = true; package = epkgs: [ epkgs.ob-ipython epkgs.ob-rust epkgs.ob-diagrams ]; defer = true; init = '' (add-hook 'org-babel-after-execute-hook 'org-display-inline-images 'append) ''; config = '' (setq org-confirm-babel-evaluate nil) ; don't prompt me to confirm everytime I want to evaluate a block (defun org-babel-restart-session-to-point (&optional arg) "Restart session up to the src-block in the current point. Goes to beginning of buffer and executes each code block with `org-babel-execute-src-block' that has the same language and session as the current block. ARG has same meaning as in `org-babel-execute-src-block'." (interactive "P") (unless (org-in-src-block-p) (error "You must be in a src-block to run this command")) (let* ((current-point (point-marker)) (info (org-babel-get-src-block-info)) (lang (nth 0 info)) (params (nth 2 info)) (session (cdr (assoc :session params)))) (save-excursion (goto-char (point-min)) (while (re-search-forward org-babel-src-block-regexp nil t) ;; goto start of block (goto-char (match-beginning 0)) (let* ((this-info (org-babel-get-src-block-info)) (this-lang (nth 0 this-info)) (this-params (nth 2 this-info)) (this-session (cdr (assoc :session this-params)))) (when (and (< (point) (marker-position current-point)) (string= lang this-lang) (src-block-in-session-p session)) (org-babel-execute-src-block arg))) ;; move forward so we can find the next block (forward-line))))) (defun org-babel-kill-session () "Kill session for current code block." (interactive) (unless (org-in-src-block-p) (error "You must be in a src-block to run this command")) (save-window-excursion (org-babel-switch-to-session) (kill-buffer))) (defun org-babel-remove-result-buffer () "Remove results from every code block in buffer." (interactive) (save-excursion (goto-char (point-min)) (while (re-search-forward org-babel-src-block-regexp nil t) (org-babel-remove-result)))) ;; this adds a "new language" in babel that gets exported as js in html ;; https://www.reddit.com/r/orgmode/comments/5bi6ku/tip_for_exporting_javascript_source_block_to/ (add-to-list 'org-src-lang-modes '("inline-js" . javascript)) (defvar org-babel-default-header-args:inline-js '((:results . "html") (:exports . "results"))) (defun org-babel-execute:inline-js (body _params) (format "" body)) ;; Path when plantuml is installed from AUR (package `plantuml') (setq org-plantuml-jar-path "/opt/plantuml/plantuml.jar") ;; add all languages to org mode (org-babel-do-load-languages 'org-babel-load-languages '((C . t) ;;(R . t) (asymptote) (awk) (calc . t) (clojure . t) (comint) (css) (ditaa . t) (dot . t) (emacs-lisp . t) (fortran) (gnuplot . t) (haskell) (io) (java) (js . t) (latex) (ledger . t) (lilypond) (lisp) (lua . t) (matlab) (maxima) (mscgen) (ocaml) (octave . t) (org . t) (perl) (picolisp) (plantuml . t) (python . t) ;; (ipython . t) ;; (restclient . t) (ref) (ruby) (sass) (scala) (scheme) (screen) (shell . t) (shen) (snippet) (sql . t) (sqlite . t))) ''; }; programs.emacs.init.usePackage.org-src = { enable = true; package = epkgs: null; defer = true; init = ''(put 'org-src-preserve-indentation 'safe-local-variable 'booleanp)''; config = '' (setq org-src-window-setup 'current-window) (setq org-src-fontify-natively t) ; syntax highlighting for source code blocks ;; Tab should do indent in code blocks ;; I think I hate this function (causes scroll on TAB (setq org-src-tab-acts-natively t) ;; ?Fix weird scrolling ;; Don't remove (or add) any extra whitespace (setq org-src-preserve-indentation nil) (setq org-edit-src-content-indentation 0) ;;; Some helper function to manage org-babel sessions (defun src-block-in-session-p (&optional name) "Return if src-block is in a session of NAME. NAME may be nil for unnamed sessions." (let* ((info (org-babel-get-src-block-info)) ;;(lang (nth 0 info)) ;;(body (nth 1 info)) (params (nth 2 info)) (session (cdr (assoc :session params)))) (cond ;; unnamed session, both name and session are nil ((and (null session) (null name)) t) ;; Matching name and session ((and (stringp name) (stringp session) (string= name session)) t) ;; no match (t nil)))) ;; dot == graphviz-dot (add-to-list 'org-src-lang-modes '("dot" . graphviz-dot)) ;; Add 'conf-mode' to org-babel (add-to-list 'org-src-lang-modes '("ini" . conf)) (add-to-list 'org-src-lang-modes '("conf" . conf)) ''; }; programs.emacs.init.usePackage.org-tempo = { enable = true; package = null; }; programs.emacs.init.usePackage.ox = { enable = true; package = null; defer = true; command = []; config = '' ;; Use html5 as org export and use new tags (setq org-html-doctype "html5") (setq org-html-html5-fancy t) ;; Don't add html footer to export (setq org-html-postamble nil) ;; Don't export ^ or _ as super/subscripts (setq org-export-with-sub-superscripts nil) ''; }; programs.emacs.init.usePackage.ox-gfm = { enable = true; after = [ "ox" ]; }; programs.emacs.init.usePackage.ox-rst = { enable = true; after = [ "ox" ]; }; programs.emacs.init.usePackage.ox-md = { enable = true; package = null; after = [ "ox" ]; }; programs.emacs.init.usePackage.org-bullets = { enable = true; hook = [ "(org-mode . org-bullets-mode)" ]; }; programs.emacs.init.usePackage.org-crypt = { enable = true; package = epkgs: null; after = [ "org" ]; hook = [ "(org-mode . (lambda () (add-hook 'before-save-hook 'org-encrypt-entries nil t)))" ]; command = [ "org-decrypt-entry" "org-encrypt-entry" ]; bindLocal = { org-mode-map = { "C-c d" = "org-decrypt-entry"; "C-c e" = "org-encrypt-entry"; };}; config = '' (setq org-tags-exclude-from-inheritance (quote ("crypt"))) ;; GPG key to use for encryption (load-file "~/.emacs.d/org-crypt-key.el") ;; don't ask to disable auto-save (setq org-crypt-disable-auto-save "encrypt") ''; }; programs.emacs.init.usePackage.org-drill = { enable = true; }; }