From 06942cd010dd71aa3a95cee09cb15a0849003f53 Mon Sep 17 00:00:00 2001 From: Daniel Gomez Date: Sat, 13 Jul 2019 15:02:05 -0400 Subject: [PATCH] Add file with possibly relevant Org configuration from my init --- org-init.el | 587 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 587 insertions(+) create mode 100644 org-init.el diff --git a/org-init.el b/org-init.el new file mode 100644 index 0000000..e8ab452 --- /dev/null +++ b/org-init.el @@ -0,0 +1,587 @@ +;; Possibly relevant configuration for org-thesis + +;;;;;;;;;;;;;; +;; Straight ;; +;;;;;;;;;;;;;; +;; Straight.el is a functional package manager for Emacs. It server as +;; a replacement for the native package.el + +(setq-default straight-repository-branch "develop") + +;; Bootstrap the package manager, straight.el. +(defvar bootstrap-version) +(let ((bootstrap-file + (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory)) + (bootstrap-version 5)) + (unless (file-exists-p bootstrap-file) + (with-current-buffer + (url-retrieve-synchronously + "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el" + 'silent 'inhibit-cookies) + (goto-char (point-max)) + (eval-print-last-sexp))) + (load bootstrap-file nil 'nomessage)) + +(defun straight-reload-init () + "Reload init.el." + (interactive) + (straight-transaction + (straight-mark-transaction-as-init) + (message "Reloading init.el...") + (load user-init-file nil 'nomessage) + (message "Reloading init.el... done."))) + +;;;;;;;;;;;;;;;;; +;; use-package ;; +;;;;;;;;;;;;;;;;; + +;; Use-package is a declarative package configurator. +;; We need to set some configurations before "requiring" use-package, so that it +;; integrates better with imenu and this init file. +(setq-default use-package-enable-imenu-support t + use-package-form-regexp-eval + `(concat ,(eval-when-compile + (concat "^\\s-*(" + (regexp-opt '("use-package" "use-feature" "require") t) + "\\s-+\\(")) + (or (bound-and-true-p lisp-mode-symbol-regexp) + "\\(?:\\sw\\|\\s_\\|\\\\.\\)+") "\\)")) + +;; Call straight-use-package to bootstrap use-package so we can use it. +(straight-use-package 'use-package) + +(defmacro use-feature (name &rest args) + "Like `use-package', but with `straight-use-package-by-default' disabled." + (declare (indent defun)) + `(use-package ,name + :straight nil + ,@args)) + +;; When configuring a feature with `use-package', also tell +;; straight.el to install a package of the same name, unless otherwise +;; specified using the `:straight' keyword. +(setq-default straight-use-package-by-default t) + +;; Tell `use-package' to always load features lazily unless told +;; otherwise. It's nicer to have this kind of thing be deterministic: +;; if `:demand' is present, the loading is eager; otherwise, the +;; loading is lazy. See +;; https://github.com/jwiegley/use-package#notes-about-lazy-loading. +(setq-default use-package-always-defer t) + +;;;;;;;;;;;;;; +;; Org Mode ;; +;;;;;;;;;;;;;; + +;; Our real configuration for Org comes much later. Doing this now +;; means that if any packages that are installed in the meantime +;; depend on Org, they will not accidentally cause the Emacs-provided +;; (outdated and duplicated) version of Org to be loaded before the +;; real one is registered. +(use-package org-plus-contrib) +;; Here we guarantee that org mode gets loaded properly. + +(use-feature org + ;; See an inspirational Org config here: https://github.com/novoid/dot-emacs/blob/master/config.org + :config + (setq-default org-catch-invisible-edits 'smart + org-special-ctrl-a/e t + org-image-actual-width '(400) + org-return-follows-link t + org-list-allow-alphabetical t + ;; Aesthetics + org-blank-before-new-entry '((heading . t) (plain-list-item . nil)) + org-fontify-quote-and-verse-blocks t + org-hide-macro-markers nil + org-fontify-whole-heading-line t + org-fontify-done-headline t + org-hide-emphasis-markers nil + org-highlight-latex-and-related '(latex) + ;; Image display + org-image-actual-width '(400) + ;; Agenda + org-deadline-warning-days 40 + org-deadline-past-days 21) + + (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) + (add-to-list 'org-structure-template-alist '("sh" . "src sh")) + (add-to-list 'org-structure-template-alist '("py" . "src python")) + (add-to-list 'org-structure-template-alist '("j" . "src jupyter-python")) + + ;; After inserting an org template, also open a line. + (defun org-structure-template-and-open-line (orig-func &rest args) + (apply orig-func args) + (unless mark-active + (open-line 1))) + + (advice-add 'org-insert-structure-template + :around #'org-structure-template-and-open-line) + + (defun scimax/org-return (&optional ignore) + "Add new list item, heading or table row with RET. +A double return on an empty element deletes it. +Use a prefix arg to get regular RET. " + (interactive "P") + (if ignore + (org-return) + (cond + ((eq 'line-break (car (org-element-context))) + (org-return-indent)) + ;; Open links like usual, unless point is at the end of a line. + ;; and if at beginning of line, just press enter. + ((or (and (eq 'link (car (org-element-context))) (not (eolp))) + (bolp)) + (org-return)) + ;; checkboxes too + ((org-at-item-checkbox-p) + (if (org-element-property :contents-begin + (org-element-context)) + ;; we have content so add a new checkbox + (org-insert-todo-heading nil) + ;; no content so delete it + (setf (buffer-substring (line-beginning-position) (point)) "") + (org-return))) + ;; lists end with two blank lines, so we need to make sure we are also not + ;; at the beginning of a line to avoid a loop where a new entry gets + ;; created with only one blank line. + ((org-in-item-p) + (if (save-excursion + (beginning-of-line) (org-element-property :contents-begin (org-element-context))) + (org-insert-item) + (beginning-of-line) + (delete-region (line-beginning-position) (line-end-position)) + (org-return))) + ;; org-heading + ((org-at-heading-p) + (if (not (string= "" (org-element-property :title (org-element-context)))) + (progn + ;; Go to end of subtree suggested by Pablo GG on Disqus post. + (org-end-of-subtree) + (org-insert-heading-respect-content) + (outline-show-entry)) + ;; The heading was empty, so we delete it + (beginning-of-line) + (setf (buffer-substring + (line-beginning-position) (line-end-position)) ""))) + ;; tables + ((org-at-table-p) + (if (-any? + (lambda (x) (not (string= "" x))) + (nth + (- (org-table-current-dline) 1) + (remove 'hline (org-table-to-lisp)))) + (org-return) + ;; empty row + (beginning-of-line) + (setf (buffer-substring + (line-beginning-position) (line-end-position)) "") + (org-return))) + ;; fall-through case + (t + (org-return))))) + + (defmacro unpackaged/def-org-maybe-surround (&rest keys) + "Define and bind interactive commands for each of KEYS that surround the region or insert text. + Commands are bound in `org-mode-map' to each of KEYS. If the + region is active, commands surround it with the key character, + otherwise call `org-self-insert-command'." + `(progn + ,@(cl-loop for key in keys + for name = (intern (concat "unpackaged/org-maybe-surround-" key)) + for docstring = (format "If region is active, surround it with \"%s\", otherwise call `org-self-insert-command'." key) + collect `(defun ,name () + ,docstring + (interactive) + (if (region-active-p) + (let ((beg (region-beginning)) + (end (region-end))) + (save-excursion + (goto-char end) + (insert ,key) + (goto-char beg) + (insert ,key))) + (call-interactively #'org-self-insert-command))) + collect `(define-key org-mode-map (kbd ,key) #',name)))) + + (unpackaged/def-org-maybe-surround "~" "=" "*" "/" "+" "$") + + (defun org-summary-todo (n-done n-not-done) + "Switch entry to DONE when all subentries are done, to TODO otherwise." + (let (org-log-done org-log-states) ; turn off logging + (org-todo (if (= n-not-done 0) "DONE" "TODO")))) + + :hook ((org-after-todo-statistics . org-summary-todo) + (org-mode . visual-line-mode) + (org-mode . visual-fill-column-mode) + (org-mode . flycheck-mode) + ;; (org-mode . flyspell-mode) ; Flyspell-mode bug when used with company. Activate only when necessary. + (org-mode . (lambda () + (push '("#+begin_src" . "λ") prettify-symbols-alist) + (push '("#+end_src" . "λ") prettify-symbols-alist) + (push '("#+begin_example" . "⁈") prettify-symbols-alist) + (push '("#+end_example" . "⁈") prettify-symbols-alist) + (push '("#+begin_quote" . "“") prettify-symbols-alist) + (push '("#+end_quote" . "”") prettify-symbols-alist) + (push '("#+begin_export" . "->") prettify-symbols-alist) + (push '("#+end_export" . "<-") prettify-symbols-alist) + (push '("jupyter-python" . "") prettify-symbols-alist) + (push '("#+RESULTS:" . "=") prettify-symbols-alist) + (push '(":results" . "=") prettify-symbols-alist) + (push '(":dir" . "") prettify-symbols-alist) + (push '(":session" . "@") prettify-symbols-alist) + (setq line-spacing 4) + (prettify-symbols-mode)))) + + :bind (:map org-mode-map + ("RET" . scimax/org-return))) + +(use-feature org-src + :after org + :demand t + :config + (setq-default org-edit-src-content-indentation 0 + org-src-preserve-indentation t + org-src-fontify-natively t)) + +(use-feature ob + :after org + :demand t + :config + (setq-default org-confirm-babel-evaluate nil + org-confirm-elisp-link-function nil + org-confirm-shell-link-function nil) + + (dolist (language '((org . t) + (python . t) + (matlab . t) + (shell . t) + (latex . t))) + (add-to-list 'org-babel-load-languages language)) + (org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages) + + :hook (org-babel-after-execute . org-display-inline-images)) + +(use-feature ox + :after org + :demand t + :config + ;; This is so that we are not queried if bind-keywords are safe when we set + ;; org-export-allow-bind to t. + (put 'org-export-allow-bind-keywords 'safe-local-variable #'booleanp) + (setq org-export-with-sub-superscripts '{} + org-export-coding-system 'utf-8 + org-html-checkbox-type 'html)) + +;; Once I reach feature parity with my old Spacemacs setup I should +;; make these configurations into a dedicated module. +(use-feature ox-latex + :after ox + :demand t + :init (setq org-latex-pdf-process + '("latexmk -pdflatex='pdflatex -shell-escape -interaction nonstopmode' -pdf -bibtex -f %f")) + :config + + ;; Sometimes it's good to locally override these two. + (put 'org-latex-title-command 'safe-local-variable #'stringp) + (put 'org-latex-toc-command 'safe-local-variable #'stringp) + + ;; Need to let ox know about ipython and jupyter + (add-to-list 'org-latex-minted-langs '(ipython "python")) + (add-to-list 'org-babel-tangle-lang-exts '("ipython" . "py")) + (add-to-list 'org-latex-minted-langs '(jupyter-python "python")) + (add-to-list 'org-babel-tangle-lang-exts '("jupyter-python" . "py")) + + ;; Mimore class is a latex class for writing articles. + (add-to-list 'org-latex-classes + '("mimore" + "\\documentclass{mimore} + [NO-DEFAULT-PACKAGES] + [PACKAGES] + [EXTRA]" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) + + ;; Mimosis is a class I used to write my Ph.D. thesis. + (add-to-list 'org-latex-classes + '("mimosis" + "\\documentclass{mimosis} + [NO-DEFAULT-PACKAGES] + [PACKAGES] + [EXTRA] +\\newcommand{\\mboxparagraph}[1]{\\paragraph{#1}\\mbox{}\\\\} +\\newcommand{\\mboxsubparagraph}[1]{\\subparagraph{#1}\\mbox{}\\\\}" + ("\\chapter{%s}" . "\\chapter*{%s}") + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\mboxparagraph{%s}" . "\\mboxparagraph*{%s}") + ("\\mboxsubparagraph{%s}" . "\\mboxsubparagraph*{%s}"))) + + ;; Elsarticle is Elsevier class for publications. + (add-to-list 'org-latex-classes + '("elsarticle" + "\\documentclass{elsarticle} + [NO-DEFAULT-PACKAGES] + [PACKAGES] + [EXTRA]" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) + + (setq org-latex-prefer-user-labels t)) + +;; Feature `ox-extra' is a library from the org-plus-contrib package. +;; It adds extra keywords and tagging functionality for org export. +(use-feature ox-extra + ;; Demand so that ignore headlines is always active. + :demand t + :after ox + ;; The ignore-headlines allows Org to understand the tag :ignore: and simply + ;; remove tagged headings on export, but leave their content in. + ;; See my blog post about writing thesis with org mode here: + ;; https://write.as/dani/writing-a-phd-thesis-with-org-mode + :config (ox-extras-activate '(ignore-headlines))) + +;; Feature `org-compat' is a adapter layer so that org can communicate with other Emacs +;; built-in packages. +(use-feature org-compat + :demand t + :after org + :config (setq org-imenu-depth 3)) + +;; Org-keys adds speed keys when cursor is at the beginning of a heading +(use-feature org-keys + :demand t + :after org + :config (setq org-use-speed-commands t + org-speed-commands-user '(("S" . org-store-link)))) + +;; Package `ob-async' allows executing ob commands asynchronously. +(use-package ob-async + :disabled t + :after ob + :config + ;; Jupyter defines its own async that conflicts with ob-async. + (setq ob-async-no-async-languages-alist '("jupyter-python" "jupyter-julia"))) + +;; The `ox-word' library uses pandoc to export Org files to Microsoft Word via +;; LaTeX. It is currently a part of Kitchin's awesome Scimax project. +(use-package ox-word + :after (:all org-ref ox) + :demand t + :straight (ox-word :type git + :host github + :repo "jkitchin/scimax" + :files ("ox-word.el"))) + +;; The `org-ref' package adds functionality to manage, insert and navigate +;; citations (and other references as well, such as equations) within Org mode. +(use-package org-ref + :after org + :demand t ;; Ensure that it loads so that links work immediately. + :config + (setq org-ref-default-bibliography '("~/project/org-thesis/thesis/thesis.bib") + org-ref-get-pdf-filename-function 'org-ref-get-pdf-filename-helm-bibtex + bibtex-completion-pdf-field "file" + org-ref-default-citation-link "parencite") + + (defun org-ref-grep-pdf (&optional _candidate) + "Search pdf files of marked CANDIDATEs." + (interactive) + (let ((keys (helm-marked-candidates)) + (get-pdf-function org-ref-get-pdf-filename-function)) + (helm-do-pdfgrep-1 + (-remove (lambda (pdf) + (string= pdf "")) + (mapcar (lambda (key) + (funcall get-pdf-function key)) + keys))))) + + (defun org-ref-open-pdf-at-point-in-emacs () + "Open the pdf for bibtex key under point if it exists." + (interactive) + (let* ((results (org-ref-get-bibtex-key-and-file)) + (key (car results)) + (pdf-file (funcall org-ref-get-pdf-filename-function key))) + (if (file-exists-p pdf-file) + (find-file-other-window pdf-file) + (message "no pdf found for %s" key)))) + + (defun org-ref-open-in-scihub () + "Open the bibtex entry at point in a browser using the url field or doi field. +Not for real use, just here for demonstration purposes." + (interactive) + (let ((doi (org-ref-get-doi-at-point))) + (when doi + (if (string-match "^http" doi) + (browse-url doi) + (browse-url (format "http://sci-hub.se/%s" doi))) + (message "No url or doi found")))) + + (helm-add-action-to-source "Grep PDF" 'org-ref-grep-pdf helm-source-bibtex 1) + + ;; The following makes it possible to grep pdfs from the org-ref Helm + ;; selection interface with C-s. + (setq helm-bibtex-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "C-s") (lambda () (interactive) + (helm-run-after-exit 'org-ref-grep-pdf))) + map)) + (push `(keymap . ,helm-bibtex-map) helm-source-bibtex) + + (setq org-ref-helm-user-candidates + '(("Open in Sci-hub" . org-ref-open-in-scihub) + ("Open in Emacs" . org-ref-open-pdf-at-point-in-emacs)))) + +(use-package org-brain + :init + (setq org-brain-path "~/org/knowledge") + (defun org-brain-insert-resource-icon (link) + "Insert an icon, based on content of org-mode LINK." + (insert (format "%s " + (cond ((string-prefix-p "http" link) + (cond ((string-match "wikipedia\\.org" link) + (all-the-icons-faicon "wikipedia-w")) + ((string-match "github\\.com" link) + (all-the-icons-octicon "mark-github")) + ((string-match "vimeo\\.com" link) + (all-the-icons-faicon "vimeo")) + ((string-match "youtube\\.com" link) + (all-the-icons-faicon "youtube")) + ((string-match "imdb\\.com" link) + (all-the-icons-material "movie")) + (t + (all-the-icons-faicon "globe")))) + ((string-prefix-p "brain:" link) + (all-the-icons-fileicon "brain")) + ((string-prefix-p "cite:" link) + (all-the-icons-material "book")) + ((string-prefix-p "parencite:" link) + (all-the-icons-material "book")) + (t + (all-the-icons-icon-for-file link)))))) + + :config + (setq org-id-track-globally t) + (setq org-id-locations-file "~/.emacs.d/.org-id-locations") + (setq org-brain-visualize-default-choices 'all) + (setq org-brain-title-max-length 100) + + (defun org-brain-open-org-noter (entry) + "Open `org-noter' on the ENTRY. +If run interactively, get ENTRY from context." + (interactive (list (org-brain-entry-at-pt))) + (org-with-point-at (org-brain-entry-marker entry) + (org-noter))) + + :commands org-brain-visualize + + :bind (:map org-brain-visualize-mode-map + ("C-c n" . org-brain-open-org-noter)) + + :hook + (org-brain-visualize-mode . visual-line-mode) + (org-brain-after-resource-button-functions . org-brain-insert-resource-icon)) + +(use-package org-cliplink + :defer 5 + :after org) + +(use-package org-noter + :after org + :commands org-noter + :config (setq org-noter-default-notes-file-names nil + ;; org-noter-always-create-frame nil + org-noter-notes-search-path '("~/org/Research-Notes") + org-noter-separate-notes-from-heading t)) + +;; Feature org-protocol is a part of org-plus-contrib. +(use-feature org-protocol + :demand 5 + :after org + :init + (defun transform-square-brackets-to-round-ones(string-to-transform) + "Transforms [ into ( and ] into ), other chars left unchanged." + (concat + (mapcar #'(lambda (c) (if (equal c ?\[) ?\( (if (equal c ?\]) ?\) c))) string-to-transform))) + :config + (setq org-capture-templates '(("t" "Todo [inbox]" entry + (file+headline "~/gtd/inbox.org" "Tasks") + "* TODO %i%?") + ("T" "Tickler" entry + (file+headline "~/gtd/tickler.org" "Tickler") + "* %i%? \n %U") + ("p" "Protocol" entry + (file+headline "~/gtd/inbox.org" "Inbox") + "* %^{Title}\nSource: [[%:link]] %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n %?") + ("L" "Protocol Link" entry + (file+headline "~/gtd/inbox.org" "Inbox") + "* %? [[%:link][%(transform-square-brackets-to-round-ones \"%:description\")]] %U\n"))) + + (setq org-refile-targets '(("~/gtd/gtd.org" :maxlevel . 3) + ("~/gtd/someday.org" :level . 1) + ("~/gtd/readings.org" :maxlevel . 1) + ("~/gtd/random.org" :maxlevel . 1) + ("~/gtd/learning.org" :level . 1) + ("~/gtd/tickler.org" :maxlevel . 2))) + + (setq org-agenda-files '("~/gtd/inbox.org" + "~/gtd/gtd.org" + "~/gtd/tickler.org"))) + +;; Package org-download allows drag and drop of images directly into Emacs org-mode. +(use-package org-download + :after org + :demand t + + :commands (org-download-enable + org-download-yank + org-download-screenshot) + + :config + (setq-default org-download-image-dir "./img") + (setq org-download-screenshot-method "screencapture -i %s") + + :hook ((org-mode dired-mode) . org-download-enable)) + +;;;;;;;;;;; +;; Latex ;; +;;;;;;;;;;; + +(use-package auctex) +(use-feature tex + :config + (setq-default TeX-auto-save t + TeX-PDF-mode t + Tex-show-compilation nil + TeX-parse-self t) + :hook ((LaTeX-mode . visual-line-mode) + (LaTeX-mode . (lambda () + (add-to-list + 'TeX-command-list + '("XeLaTeX" "%`xelatex%(mode)%' %t" TeX-run-TeX nil t)))))) + +(use-feature tex-buf + :config + (setq TeX-save-query nil)) + +(use-package company-auctex + :demand t + :after (:all company tex) + :config + (company-auctex-init)) + +(use-package scimax-latex + :straight (scimax-latex :type git + :host github + :repo "jkitchin/scimax" + :files ("scimax-latex.el")) + :commands (scimax-latex-setup + kpsewhich + texdoc))