This is my private DOOM emacs configuration. It is tangled from config.org
to config.el
and is exported to readme.org
with =,e O o= to render in the githup repo.
It is also rendered to HTML thanks to org-html-themes with =,e h h= .
NOTE: the code blocks in the sections marked with TODO are excluded from being tangled in my config.el
file.
(setq user-full-name "Luca Cambiaghi"
user-mail-address "luca.cambiaghi@me.com")
(setq-default
uniquify-buffer-name-style 'forward ; Uniquify buffer names
window-combination-resize t ; take new window space from all other windows (not just current)
x-stretch-cursor t) ; Stretch cursor to the glyph width
(setq undo-limit 80000000 ; Raise undo-limit to 80Mb
evil-want-fine-undo t ; By default while in insert all changes are one big blob. Be more granular
;; auto-save-default t ; Nobody likes to loose work, I certainly don't
inhibit-compacting-font-caches t) ; When there are lots of glyphs, keep them in memory
(delete-selection-mode 1) ; Replace selection when inserting text
;; (global-subword-mode 1) ; Iterate through CamelCase words
(setq +evil-want-o/O-to-continue-comments nil)
Let’s have general
auto-unbind keys:
(general-auto-unbind-keys)
We then remap some of the bindings (inspired by bindings.el).
(map! :leader
:desc "M-x" :n "SPC" #'counsel-M-x
:desc "ivy resume" :n ":" #'ivy-resume
:desc "Async shell command" :n "!" #'async-shell-command
:desc "Toggle eshell" :n "'" #'+eshell/toggle
:desc "Open dir in iTerm" :n "oi" #'+macos/open-in-iterm
(:desc "windows" :prefix "w"
:desc "popup raise" :n "p" #'+popup/raise)
(:desc "project" :prefix "p"
:desc "Eshell" :n "'" #'projectile-run-eshell
:desc "Terminal" :n "t" #'projectile-run-vterm ))
Add this keybinding because external keyboard inputs delta when pressing M-d
.
Bind command to restrict matches to highlighted region as RET
does not really work.
(define-key evil-normal-state-map (kbd "s-d") #'evil-multiedit-match-symbol-and-next)
(after! evil-multiedit
(setq evil-multiedit-follow-matches t)
(map! :v "zD" #'evil-multiedit-toggle-or-restrict-region))
(setq display-line-numbers-type nil)
Toggle big mode
with SPC t b
(setq doom-font (font-spec :family "Menlo" :size 16)
doom-big-font (font-spec :family "Menlo" :size 20))
(after! which-key
(setq which-key-idle-delay 0.5))
(defmacro modus-themes-format-sexp (sexp &rest objects)
`(eval (read (format ,(format "%S" sexp) ,@objects))))
(dolist (theme '("operandi" "vivendi"))
(modus-themes-format-sexp
(defun modus-%1$s-theme-load ()
(setq modus-%1$s-theme-slanted-constructs t
modus-%1$s-theme-bold-constructs t
modus-%1$s-theme-fringes 'subtle ; {nil,'subtle,'intense}
modus-%1$s-theme-mode-line '3d ; {nil,'3d,'moody}
modus-%1$s-theme-faint-syntax nil
modus-%1$s-theme-intense-hl-line nil
modus-%1$s-theme-intense-paren-match nil
modus-%1$s-theme-no-link-underline t
modus-%1$s-theme-no-mixed-fonts nil
modus-%1$s-theme-prompts nil ; {nil,'subtle,'intense}
modus-%1$s-theme-completions 'moderate ; {nil,'moderate,'opinionated}
modus-%1$s-theme-diffs nil ; {nil,'desaturated,'fg-only}
modus-%1$s-theme-org-blocks 'greyscale ; {nil,'greyscale,'rainbow}
modus-%1$s-theme-headings ; Read further below in the manual for this one
'((1 . line)
(t . rainbow-line-no-bold))
modus-%1$s-theme-variable-pitch-headings t
modus-%1$s-theme-scale-headings t
modus-%1$s-theme-scale-1 1.1
modus-%1$s-theme-scale-2 1.15
modus-%1$s-theme-scale-3 1.21
modus-%1$s-theme-scale-4 1.27
modus-%1$s-theme-scale-5 1.33)
(setq doom-theme 'modus-%1$s)
(doom/reload-theme))
theme))
(setq modus-operandi-theme-override-colors-alist
'(("bg-main" . "#fefcf4")
("bg-dim" . "#faf6ef")
("bg-alt" . "#f7efe5")
("bg-hl-line" . "#f4f0e3")
("bg-active" . "#e8dfd1")
("bg-inactive" . "#f6ece5")
("bg-region" . "#c6bab1")
("bg-header" . "#ede3e0")
("bg-tab-bar" . "#dcd3d3")
("bg-tab-active" . "#fdf6eb")
("bg-tab-inactive" . "#c8bab8")
("fg-unfocused" . "#55556f"))
modus-vivendi-theme-override-colors-alist
'(("bg-main" . "#100b17")
("bg-dim" . "#161129")
("bg-alt" . "#181732")
("bg-hl-line" . "#191628")
("bg-active" . "#282e46")
("bg-inactive" . "#1a1e39")
("bg-region" . "#393a53")
("bg-header" . "#202037")
("bg-tab-bar" . "#262b41")
("bg-tab-active" . "#120f18")
("bg-tab-inactive" . "#3a3a5a")
("fg-unfocused" . "#9a9aab"))
modus-operandi-theme-intense-paren-match t
modus-operandi-theme-distinct-org-blocks t)
;;Light for the day
(run-at-time "07:00" (* 60 60 24)
(lambda ()
(modus-operandi-theme-load)
;; (shell-command )
))
;; Dark for the night
(run-at-time "15:00" (* 60 60 24)
(lambda ()
(modus-vivendi-theme-load)))
(setq +doom-dashboard-banner-file
(expand-file-name "splash-images/black-hole2.png" doom-private-dir))
(after! centaur-tabs
(setq centaur-tabs-set-modified-marker t
centaur-tabs-modified-marker "M"
centaur-tabs-cycle-scope 'tabs
centaur-tabs-set-close-button nil)
(centaur-tabs-group-by-projectile-project))
note: insteadf of using SPC 0
, use SPC w h
to access its window. In general,
use those keys!
(after! winum
(map! (:when (featurep! :ui window-select)
:leader
:n "1" #'winum-select-window-1
:n "2" #'winum-select-window-2
:n "3" #'winum-select-window-3
)))
(setq +ligatures-extras-in-modes
'(not special-mode comint-mode eshell-mode term-mode vterm-mode python-mode))
;; (setq +ligatures-in-modes '(org-mode))
(after! doom-modeline
(setq doom-modeline-buffer-encoding nil)
(setq doom-modeline-env-enable-python nil))
(after! lsp-mode
(setq lsp-modeline-diagnostics-enable nil))
(after! doom-modeline
(setq display-time-default-load-average nil) ; don't show load average
(display-time-mode 1) ; Enable time in the mode-line
(display-battery-mode 1)) ; On laptops it's nice to know how much power you have
(setq evil-split-window-below t
evil-vsplit-window-right t)
After doom sync
you should run tree-sitter-install-grammars
(maybe?).
Disabled because of a bug with evil-multiedit
.
(use-package tree-sitter
:after python-mode
:defer t
:config
(require 'tree-sitter)
(require 'tree-sitter-langs)
(require 'tree-sitter-hl)
(add-hook 'python-mode-hook #'tree-sitter-hl-mode)
)
(use-package! centered-cursor-mode
:defer t
:config
(map! :leader
:desc "toggle centered cursor" :n "t-" (λ! () (interactive) (centered-cursor-mode 'toggle))
))
(defun my/startup-window-setup ()
"Called by emacs-startup-hook to set up my initial window configuration."
(split-window-right)
(other-window 1)
(find-file "~/txt/todo.org")
(other-window 1))
(add-hook 'emacs-startup-hook #'my-default-window-setup)
Need to disable centaur-tabs-mode
(defun my/enable-elegant ()
"Enable elegant-emacs theme"
(interactive)
(require 'elegance)
(require 'sanity)
;; (setq doom-theme 'elegance)
;; (add-hook! 'doom-load-theme-hook #'elegance-light)
;; (doom/reload-theme)
)
(use-package! selectrum
:commands (selectrum-mode)
:defer t
:config
(map! :map selectrum-minibuffer-map
:in "C-j" #'selectrum-next-candidate
))
(use-package! selectrum-prescient
:after selectrum
:defer t
:commands (prescient-persist-mode selectrum-prescient-mode))
(use-package! company-prescient
:commands (company-prescient-mode)
:defer t)
(use-package! marginalia
:commands (marginalia-mode))
(use-package! embark
:commands (marginalia-mode)
:config
(map! :map selectrum-minibuffer-map
:in "C-o" #'embark-act
)
)
(use-package consult
;; Replace bindings
;; :bind (("C-c o" . consult-outline)
;; ("C-x b" . consult-buffer)
;; ("M-g o" . consult-outline) ;; "M-s o" is a good alternative
;; ("M-g l" . consult-line) ;; "M-s l" is a good alternative
;; ("M-s m" . consult-multi-occur)
;; ("M-y" . consult-yank-pop)
;; :init
;; Replace functions (consult-multi-occur is a drop-in replacement)
;; (fset 'multi-occur #'consult-multi-occur)
:config
(map! :leader :desc "consult line" :n "ss" #'consult-line
:desc "M-x" :n "SPC" #'execute-extended-command
:desc "consult line" :n "ss" #'consult-line
)
;; Enable richer annotations during completion
;; Works only with selectrum as of now.
;; (consult-annotate-mode)
(consult-preview-mode) ;; Optionally enable previews
;; Enable richer annotations for M-x.
;; I have this disabled by default, since I don't want to be flooded with information.
;; Annotations are only enabled by default for the describe-* class of functions.
(add-to-list 'consult-annotate-commands
'(execute-extended-command . consult-annotate-symbol))
)
;; Projectile defaults to forcing icomplete instead of completing-read
(after! projectile
(setq projectile-completion-system 'default))
(add-hook! '(doom-first-input-hook)
(selectrum-mode +1)
(selectrum-prescient-mode +1)
(company-prescient-mode 1)
(prescient-persist-mode +1)
(marginalia-mode +1)
(selectrum-prescient-mode +1))
- Jump to current file with
SPC o -
- Hide details with
(
- Hide dotfiles with
H
- Mark with
m
, unmark withu
- Invert selection with
t
*
has some helpers for marking- First mark some files and then
K
to “hide” them - Open directory in right window with
S-RET
- When copying from left window, target will be right window
- Copy with
C
- Open subdir in buffer below with
I
- Open files with macos with
O
- View files with
go
and exit withq
(after! dired
(map! :map dired-mode-map
:n "h" #'dired-up-directory
:n "l" #'dired-find-file
)
(defun dired-open-by-macosx ()
"Opens a file in dired with the Mac OS X command 'open'."
(interactive)
(shell-command (concat "open " (shell-quote-argument (expand-file-name (dired-file-name-at-point))))))
(map! :map dired-mode-map
:n "O" #'dired-open-by-macosx
)
(use-package dired-hide-dotfiles
:hook (dired-mode . dired-hide-dotfiles-mode)
:config
(map! :map dired-mode-map
:n "H" #'dired-hide-dotfiles-mode
))
)
(after! magit
;; (magit-wip-mode)
(setq magit-repository-directories '(("~/git" . 2))
magit-save-repository-buffers nil
;; Don't restore the wconf after quitting magit
magit-inhibit-save-previous-winconf t
magit-log-arguments '("--graph" "--decorate" "--color")
;; magit-delete-by-moving-to-trash nil
git-commit-summary-max-length 120))
(after! company
(setq company-idle-delay 0
company-minimum-prefix-length 1
company-dabbrev-code-everywhere t
company-dabbrev-code-other-buffers 'all))
;; company-quickhelp-delay 0.4)
(after! company
(define-key! company-active-map
"TAB" nil
[tab] nil))
(after! company
(defvar company-mode/enable-yas t
"Enable yasnippet for all backends.")
(defun company-mode/backend-with-yas (backend)
(if (or (not company-mode/enable-yas) (and (listp backend) (member 'company-yasnippet backend)))
backend
(append (if (consp backend) backend (list backend))
'(:with company-yasnippet))))
(setq company-backends (mapcar #'company-mode/backend-with-yas company-backends)))
(after! org
(setq org-directory "~/Dropbox/org"
org-image-actual-width nil
+org-export-directory "~/Dropbox/org/export"
org-default-notes-file "~/Dropbox/org/personal/tasks/todo.org"
org-id-locations-file "~/Dropbox/org/.orgids"
;; org-agenda-files (directory-files-recursively "~/dropbox/org/" "\\.org$")
org-agenda-files '("~/dropbox/org/personal/tasks/birthdays.org" "~/dropbox/org/personal/tasks/todo.org" "~/dropbox/Notes/Test.inbox.org")
;; org-export-in-background t
org-catch-invisible-edits 'smart))
(after! org
(setq org-capture-templates
`(("b" "Blog" entry
(file+headline "personal/tasks/todo.org" "Blog")
,(concat "* WRITE %^{Title} %^g\n"
"SCHEDULED: %^t\n"
":PROPERTIES:\n"
":CAPTURED: %U\n:END:\n\n"
"%i%?"))
("i" "Inbox" entry
(file+headline "personal/tasks/todo.org" "Inbox")
,(concat "* %^{Title}\n"
":PROPERTIES:\n"
":CAPTURED: %U\n"
":END:\n\n"
"%i%l"))
("w" "Work" entry
(file+headline "personal/tasks/todo.org" "Work")
,(concat "* TODO [#A] %^{Title} :@work:\n"
"SCHEDULED: %^t\n"
":PROPERTIES:\n:CAPTURED: %U\n:END:\n\n"
"%i%?"))
("m" "Mail" entry
(file+headline "personal/tasks/todo.org" "Mail")
,(concat "* TODO [#B] %:subject :mail:\n"
"SCHEDULED: %t\n:"
"PROPERTIES:\n:CONTEXT: %a\n:END:\n\n"
"%i%?"))))
(add-to-list 'org-capture-templates
'("d" "New Diary Entry" entry(file+olp+datetree"~/Dropbox/org/personal/diary.org" "Daily Logs")
"* %^{thought for the day}
:PROPERTIES:
:CATEGORY: %^{category}
:SUBJECT: %^{subject}
:MOOD: %^{mood}
:END:
:RESOURCES:
:END:
\*What was one good thing you learned today?*:
- %^{whatilearnedtoday}
\*List one thing you could have done better*:
- %^{onethingdobetter}
\*Describe in your own words how your day was*:
- %?"))
(add-to-list 'org-capture-templates
'("u" "New URL Entry" entry(file+function "~/Dropbox/org/personal/dailies.org" org-reverse-datetree-goto-date-in-file)
"* [[%^{URL}][%^{Description}]] %^g %?")))
(after! org-superstar
(setq org-superstar-headline-bullets-list '("✖" "✚" "◆" "▶" "○")
org-ellipsis "▼"))
(set-popup-rule! "*org agenda*" :side 'right :size .40 :select t :vslot 2 :ttl 3)
(after! org
(require 'ox-ipynb))
(after! evil-org
(setq org-babel-clojure-backend 'cider))
Update to reveal 4 at some point. Install the toc-progress
plugin in the default org-re-reveal-root
.
(use-package! org-re-reveal
:after ox
:config
;; (setq org-re-reveal-root (expand-file-name "../../" (locate-library "dist/reveal.js" t))
;; org-re-reveal-revealjs-version "4")
(setq org-re-reveal-root "./reveal.js"
org-re-reveal-revealjs-version "3.8"
org-re-reveal-external-plugins '((progress . "{ src: '%s/plugin/toc-progress/toc-progress.js', async: true, callback: function() { toc_progress.initialize(); toc_progress.create();} }"))
))
(use-package ox-moderncv
:after org
:defer t
:load-path "/Users/luca/git/org-cv/"
:init (require 'ox-altacv))
;; :init (require 'ox-moderncv))
(after! latex
(setq org-latex-compiler "xelatex"))
(after! org
(defun html-body-id-filter (output backend info)
"Remove random ID attributes generated by Org."
(when (eq backend 'html)
(replace-regexp-in-string
" id=\"[[:alpha:]-]*org[[:alnum:]]\\{7\\}\""
""
output t)))
(add-to-list 'org-export-filter-final-output-functions 'html-body-id-filter))
(defun +remap-faces-at-start-present ()
(setq-local face-remapping-alist '((default (:height 2.0) variable-pitch)
(org-verbatim (:height 1.75) org-verbatim)
(org-block (:height 1.25) org-block)))
(hide-mode-line-mode 1)
(centaur-tabs-mode 0)
)
(defun +remap-faces-at-start-present-term ()
(interactive)
(setq-local face-remapping-alist '((default (:height 2.0) variable-pitch)
(org-verbatim (:height 1.75) org-verbatim)
(org-block (:height 1.25) org-block)))
)
(defun +remap-faces-at-stop-present ()
(setq-local face-remapping-alist '((default variable-pitch default)))
(hide-mode-line-mode 0)
(centaur-tabs-mode 1)
)
(after! org-tree-slide
(use-package! org-tree-slide
:commands org-tree-slide-mode
:hook ((org-tree-slide-play . (lambda () (+remap-faces-at-start-present)))
(org-tree-slide-stop . (lambda () (+remap-faces-at-stop-present))))
:config
(org-tree-slide-presentation-profile)
(setq org-tree-slide-skip-outline-level 0
org-tree-slide-modeline-display nil
org-tree-slide-slide-in-effect nil)
;; (remove-hook 'org-tree-slide-mode-hook #'+org-present-hide-blocks-h)
;; (remove-hook 'org-tree-slide-mode-hook #'+org-present-prettify-slide-h)
(remove-hook! 'org-tree-slide-mode-hook
#'+org-present-hide-blocks-h
#'+org-present-prettify-slide-h)
(map! :map org-tree-slide-mode-map
:n "C-j" #'org-tree-slide-move-next-tree
:n "C-k" #'org-tree-slide-move-previous-tree)
;; remove unnamed advice
(advice-mapc
(lambda (adv prop)
(advice-remove 'org-tree-slide--display-tree-with-narrow adv))
'org-tree-slide--display-tree-with-narrow))
)
(after! org
(map! :leader :n "t p" #'org-tree-slide-mode))
(use-package! org-tree-slide
:after org
:defer t
:commands org-tree-slide-mode
:hook ((org-tree-slide-play . (lambda () (+remap-faces-at-start-present)))
(org-tree-slide-stop . (lambda () (+remap-faces-at-stop-present))))
:config
(org-tree-slide-presentation-profile)
;; (org-tree-slide-simple-profile)
(setq ;; org-tree-slide-skip-outline-level 0
org-tree-slide-activate-message " "
org-tree-slide-deactivate-message " "
;; org-tree-slide-modeline-display nil
;; org-tree-slide-heading-emphasis t
org-tree-slide-slide-in-effect nil
;; text-scale-mode-amount 5
)
;; always toggle inline images
(add-hook 'org-tree-slide-mode-after-narrow-hook #'org-display-inline-images)
;; (defun +org-present-hide-blocks-h ()
;; "Hide org #+ constructs."
;; (save-excursion
;; (goto-char (point-min))
;; (while (re-search-forward "^[[:space:]]*\\(#\\+\\)\\(\\(?:BEGIN\\|END\\|ATTR\\)[^[:space:]]+\\).*" nil t)
;; (+org-present--make-invisible
;; (match-beginning 1)
;; (match-end 0)))))
;; (add-hook! 'org-tree-slide-mode-hook
;; #'+org-present-hide-blocks-h
;; #'+org-present-prettify-slide-h
;; )
(map! :map org-tree-slide-mode-map
:n "C-j" #'org-tree-slide-move-next-tree
:n "C-k" #'org-tree-slide-move-previous-tree)
(add-hook 'org-tree-slide-mode-hook #'evil-normalize-keymaps)
)
(after! ox
(add-to-list 'org-export-backends 'beamer))
(org-export-latex-classes
(quote
(("article" "\\documentclass[11pt]{article}"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
("linalg" "\\documentclass{article}
\\usepackage{linalgjh}
[DEFAULT-PACKAGES]
[EXTRA]
[PACKAGES]"
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
("\\paragraph{%s}" . "\\paragraph*{%s}")
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
("report" "\\documentclass[11pt]{report}"
("\\part{%s}" . "\\part*{%s}")
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
("book" "\\documentclass[11pt]{book}"
("\\part{%s}" . "\\part*{%s}")
("\\chapter{%s}" . "\\chapter*{%s}")
("\\section{%s}" . "\\section*{%s}")
("\\subsection{%s}" . "\\subsection*{%s}")
("\\subsubsection{%s}" . "\\subsubsection*{%s}"))
("beamer" "\\documentclass{beamer}" org-beamer-sectioning))))
(after! org
(setq org-html-style-fancy
(concat (f-read-text (expand-file-name "misc/org-export-header.html" doom-private-dir))
"<script>\n"
(f-read-text (expand-file-name "misc/pile-css-theme/main.js" doom-private-dir))
"</script>\n<style>\n"
(f-read-text (expand-file-name "misc/pile-css-theme/main.css" doom-private-dir))
"</style>")
org-html-style-plain org-html-style-default
org-html-style-default org-html-style-fancy
org-html-htmlize-output-type 'css
org-html-doctype "html5"
org-html-html5-fancy t))
For some reason jupyter-eval-buffer
does not work so we redefine it.
(after! python
(defun my/jupyter-eval-buffer ()
"Send the contents of BUFFER using `jupyter-current-client'."
(interactive)
(jupyter-eval-string (jupyter-load-file-code (buffer-file-name)))
))
Start a new REPL with =, ‘=.
If that does not work, call doom/reload-env
to refresh Emacs’ PATH.
(after! python
(defun my/jupyter-run-repl-or-pop-to-buffer-dwim ()
"If a buffer is already associated with a jupyter buffer,
then pop to it. Otherwise start a jupyter kernel."
(interactive)
(if (bound-and-true-p jupyter-current-client)
(jupyter-repl-pop-to-buffer)
(call-interactively #'jupyter-run-repl))))
;; (:when (featurep! :lang +jupyter)
(map! :after evil-org
:map evil-org-mode-map
:leader
:desc "tangle" :n "ct" #'org-babel-tangle
:localleader
:desc "Hydra" :n "," #'jupyter-org-hydra/body
:desc "Inspect at point" :n "?" #'jupyter-inspect-at-point
:desc "Execute and step" :n "RET" #'jupyter-org-execute-and-next-block
:desc "Delete code block" :n "x" #'jupyter-org-kill-block-and-results
:desc "New code block above" :n "+" #'jupyter-org-insert-src-block
:desc "New code block below" :n "=" (λ! () (interactive) (jupyter-org-insert-src-block t nil))
:desc "Merge code blocks" :n "m" #'jupyter-org-merge-blocks
;; :desc "Split code block" :n "-" #'jupyter-org-split-src-block
:desc "Split code block" :n "-" #'org-babel-demarcate-block
:desc "Fold results" :n "z" #'org-babel-hide-result-toggle
:map org-src-mode-map
:localleader
:desc "Exit edit" :n "'" #'org-edit-src-exit)
(map! :after python
:map python-mode-map
:localleader
(:desc "repl" :n "'" (λ! () (interactive) (my/jupyter-run-repl-or-pop-to-buffer-dwim))
:desc "eval" :prefix "e"
:desc "line or region" :n "e" #'jupyter-eval-line-or-region
:desc "defun" :n "d" #'jupyter-eval-defun
:desc "buffer" :n "b" (λ! () (interactive) (my/jupyter-eval-buffer)))
)
(set-popup-rule! "^\\*Org Src*" :side 'right :size .60 :select t :vslot 2 :ttl 3 :quit nil)
(set-popup-rule! "*jupyter-pager*" :side 'right :size .40 :select t :vslot 2 :ttl 3)
(set-popup-rule! "*jupyter-repl*" :side 'bottom :size .30 :vslot 2 :quit 'current :ttl 3)
(after! evil-org
(org-babel-lob-ingest "/Users/luca/git/experiments/literate/ml/rpy2.org"))
(Use =, e e=)
With g r
we can send code to the Jupyter REPL:
(after! ob-jupyter
(set-eval-handler! 'jupyter-repl-interaction-mode #'jupyter-eval-line-or-region))
On a python buffer, hit SPC o r
to start a jupyter kernel and associate the buffer with it.
You can send code to the REPL:
gr r
sends a line (or region)gr io
sends a symbol
(add-hook! python-mode
(set-repl-handler! 'python-mode #'my/jupyter-run-repl-or-pop-to-buffer-dwim))
Evaluate simple expressions to the right of the symbol with =, e e=
(after! ob-jupyter
(setq jupyter-eval-use-overlays t))
Important to load after evil-org
:
(after! evil-org
(setq org-babel-default-header-args:jupyter-python '((:async . "yes")
;; (:pandoc t)
(:kernel . "python3")))
(setq org-babel-default-header-args:jupyter-R '(;; (:pandoc t)
(:kernel . "ir"))))
(after! ob-jupyter
(cl-defmethod jupyter-org--insert-result (_req context result)
(let ((str
(org-element-interpret-data
(jupyter-org--wrap-result-maybe
context (if (jupyter-org--stream-result-p result)
(thread-last result
jupyter-org-strip-last-newline
jupyter-org-scalar)
result)))))
(if (< (length str) 100000)
(insert str)
(insert (format ": Result was too long! Length was %d" (length str)))))
(when (/= (point) (line-beginning-position))
;; Org objects such as file links do not have a newline added when
;; converting to their string representation by
;; `org-element-interpret-data' so insert one in these cases.
(insert "\n"))))
(defadvice! fixed-zmq-start-process (orig-fn &rest args)
:around #'zmq-start-process
(letf! (defun make-process (&rest plist)
(plist-put! plist :coding (plist-get plist :coding-system))
(plist-delete! plist :coding-system)
(apply make-process plist))
(apply orig-fn args)))
Found at emacs-jupyter/jupyter#160
(after! jupyter
;; * eldoc integration
(defun scimax-jupyter-signature ()
"Try to return a function signature for the thing at point."
(when (and (eql major-mode 'org-mode)
(string= (or (get-text-property (point) 'lang) "") "jupyter-python"))
(save-window-excursion
;;; Essentially copied from (jupyter-inspect-at-point).
(jupyter-org-with-src-block-client
(cl-destructuring-bind (code pos)
(jupyter-code-context 'inspect)
(jupyter-inspect code pos nil 0)))
(when (get-buffer "*Help*")
(with-current-buffer "*Help*"
(goto-char (point-min))
(prog1
(cond
((re-search-forward "Signature:" nil t 1)
(buffer-substring (line-beginning-position) (line-end-position)))
((re-search-forward "Docstring:" nil t 1)
(forward-line)
(buffer-substring (line-beginning-position) (line-end-position)))
(t
nil))
;; get rid of this so we don't accidentally show old results later
(with-current-buffer "*Help*"
(toggle-read-only)
(erase-buffer))))))))
(defun scimax-jupyter-eldoc-advice (orig-func &rest args)
"Advice function to get eldoc signatures in blocks in org-mode."
(or (scimax-jupyter-signature) (apply orig-func args)))
(defun scimax-jupyter-turn-on-eldoc ()
"Turn on eldoc signatures."
(interactive)
(advice-add 'org-eldoc-documentation-function :around #'scimax-jupyter-eldoc-advice))
( scimax-jupyter-turn-on-eldoc )
)
;; (map! :after org-evil
;; :map evil-org-mode-map
;; :n "M-<down>" nil
;; :n "M-j" nil
;; )
(defadvice! +ipython-use-virtualenv (orig-fn &rest args)
"Use the Python binary from the current virtual environment."
:around #'+python/open-repl
(if (getenv "VIRTUAL_ENV")
(let ((python-shell-interpreter (executable-find "ipython")))
(apply orig-fn args))
(apply orig-fn args)))
(setq python-shell-prompt-detect-failure-warning nil)
(set-popup-rule! "^\\*Python*" :side 'bottom :size .30)
(after! python
(setq python-shell-completion-native-enable nil))
(after! lsp-python-ms
(set-lsp-priority! 'pyright 1))
In case we get a wrong workspace root, we can delete it with lsp-workspace-folders-remove
(after! lsp-mode
(setq lsp-auto-guess-root nil))
(after! projectile
(setq projectile-project-root-files '("Dockerfile" "pyproject.toml" "project.clj")))
(setq read-process-output-max (* 1024 1024))
Lookup documentation with SPC c k
(set-popup-rule! "^\\*lsp-help" :side 'right :size .50 :select t :vslot 1)
(after! lsp-mode
(setq lsp-diagnostic-package :none))
(after! flycheck
(add-hook 'pyhon-mode-local-vars-hook
(lambda ()
(when (flycheck-may-enable-checker 'python-flake8)
(flycheck-select-checker 'python-flake8)))))
;; (setq flycheck-disabled-checkers 'lsp)
(after! lsp-mode
(setq lsp-eldoc-enable-hover nil
lsp-signature-auto-activate nil
;; lsp-enable-on-type-formatting nil
;; lsp-enable-symbol-highlighting nil
lsp-enable-file-watchers nil))
(after! lsp-mode
(setq lsp-restart 'ignore))
(when (featurep! +eglot)
(after! eglot
(add-to-list 'eglot-server-programs '(python-mode . ("pyright-langserver" "--stdio"))))
)
(after! python-pytest
(setq python-pytest-arguments '("--color" "--failed-first"))
(evil-set-initial-state 'python-pytest-mode 'normal))
(set-popup-rule! "^\\*pytest*" :side 'right :size .50)
(after! dap-mode
;; (setq dap-auto-show-output t)
(setq dap-output-window-max-height 50)
(setq dap-output-window-min-height 50)
(setq dap-auto-configure-features '(locals))
(setq dap-ui-buffer-configurations
`((,"*dap-ui-locals*" . ((side . right) (slot . 1) (window-width . 0.50))) ;; changed this to 0.50
(,"*dap-ui-repl*" . ((side . right) (slot . 1) (window-width . 0.50))) ;; added this! TODO enable when release on MELPA
(,"*dap-ui-expressions*" . ((side . right) (slot . 2) (window-width . 0.20)))
(,"*dap-ui-sessions*" . ((side . right) (slot . 3) (window-width . 0.20)))
(,"*dap-ui-breakpoints*" . ((side . left) (slot . 2) (window-width . , 0.20)))
(,"*debug-window*" . ((side . bottom) (slot . 3) (window-width . 0.20)))))
;; (set-popup-rule! "^\\*dap-debug-script*" :side 'bottom :size .30)
(defun my/window-visible (b-name)
"Return whether B-NAME is visible."
(-> (-compose 'buffer-name 'window-buffer)
(-map (window-list))
(-contains? b-name)))
(defun my/show-debug-windows (session)
"Show debug windows."
(let ((lsp--cur-workspace (dap--debug-session-workspace session)))
(save-excursion
(unless (my/window-visible dap-ui--repl-buffer)
(dap-ui-repl)))))
(add-hook 'dap-stopped-hook 'my/show-debug-windows)
(defun my/hide-debug-windows (session)
"Hide debug windows when all debug sessions are dead."
(unless (-filter 'dap--session-running (dap--get-sessions))
(and (get-buffer dap-ui--repl-buffer)
(kill-buffer dap-ui--repl-buffer)
(get-buffer dap-ui--debug-window-buffer)
(kill-buffer dap-ui--debug-window-buffer))))
(add-hook 'dap-terminated-hook 'my/hide-debug-windows)
)
;; (setq dap-auto-configure-features '(locals))
;; (after! dap-mode
;; (setq dap-overlays-use-overlays nil)
;; )
(remove-hook 'dap-mode-hook #'dap-tooltip-mode)
(remove-hook 'dap-ui-mode-hook #'dap-ui-controls-mode)
Templates accessible with =, d d=
(after! dap-python
(dap-register-debug-template "dap-debug-script"
(list :type "python"
:args []
:cwd "${workspaceFolder}"
;; :cwd (lsp-workspace-root)
;; :justMyCode :json-false
;; :debugOptions ["DebugStdLib" "ShowReturnValue" "RedirectOutput"]
;; :program nil ; (expand-file-name "~/git/blabla")
:request "launch"
;; :debugger 'ptvsd
:debugger 'debugpy
:name "dap-debug-script"))
(dap-register-debug-template "dap-debug-test-at-point"
(list :type "python-test-at-point"
:args ""
:justMyCode :json-false
;; :cwd "${workspaceFolder}"
:request "launch"
:module "pytest"
:debugger 'debugpy
:name "dap-debug-test-at-point"))
;; ("Python :: Run pytest (at point)" :type "python-test-at-point" :args "" :program nil :module "pytest" :request "launch" :name "Python :: Run pytest (at point)")
;; (dap-register-debug-template "Python :: Run pytest (at point), ptvsd"
;; (list :type "python-test-at-point"
;; :args ""
;; :module "pytest"
;; :request "launch"
;; :debugger 'ptvsd
;; :name "Python :: Run pytest (at point)"))
;; (dap-register-debug-template "Python :: Run pytest (at point), debugpy"
;; (list :type "python-test-at-point"
;; :args ["/Users/luca/git/wondercast/caf/test/customer_allocation/summarize_historical/summarize_historical_test.py::test_summarize"]
;; ;; :module "pytest"
;; :request "launch"
;; :debugger 'debugpy
;; :name "Python :: Run pytest (at point)"))
)
Standard debug test target, accessible with =, d t=
For pytest the command is
python -m ptvsd --wait --host localhost --port 62421 -m pytest /.../summarize_historical_test.py\:\:test_summarize
;; (after! dap-python
;; (require 'python-pytest)
;; (defun dap-python-test-method-at-point-debugpy ()
;; (interactive
;; (dap-debug
;; (list :type "python"
;; ;; :args []
;; ;; :args "py.test /Users/luca/git/wondercast/caf/test/customer_allocation/summarize_historical/summarize_historical_test.py"
;; :args (concat (buffer-file-name) ":" ":" (python-pytest--current-defun))
;; ;; :program (concat (buffer-file-name) ":" ":" (python-pytest--current-defun))
;; ;; :program "/Users/luca/git/wondercast/caf/test/customer_allocation/summarize_historical/summarize_historical_test.py"
;; ;; :module "pytest"
;; :debugger 'debugpy
;; :request "launch"
;; :name "dap-debug-test-function-debugpy"))))
;; (defun dap-python-test-method-at-point ()
;; (interactive
;; (dap-debug
;; (list :type "python"
;; :args ""
;; ;; :args []
;; :cwd (lsp-workspace-root)
;; :program (concat (buffer-file-name) ":" ":" (python-pytest--current-defun))
;; :module "pytest"
;; :debugger 'ptvsd
;; ;; :debugger 'debugpy
;; :request "launch"
;; :name "dap-debug-test-function")))))
(defadvice! +dap-python-poetry-executable-find-a (orig-fn &rest args)
"Use the Python binary from the current virtual environment."
:around #'dap-python--pyenv-executable-find
(if (getenv "VIRTUAL_ENV")
(executable-find (car args))
(apply orig-fn args)))
;; (after! dap-python
;; (defun dap-python--pyenv-executable-find (command)
;; (concat (getenv "VIRTUAL_ENV") "/bin/python")))
(map! :localleader
:map +dap-running-session-mode-map
"d" nil)
;; (map! :after dap-mode
;; :map dap-mode-map
;; :localleader "d" nil)
(map! :after dap-mode
:map python-mode-map
:localleader
;; "d" nil
(:desc "debug" :prefix "d"
:desc "Hydra" :n "h" #'dap-hydra
:desc "Run debug configuration" :n "d" #'dap-debug
:desc "dap-ui REPL" :n "r" #'dap-ui-repl
;; :desc "Debug test function" :n "t" #'dap-python-debug-test-at-point # TODO
:desc "Run last debug configuration" :n "l" #'dap-debug-last
:desc "Toggle breakpoint" :n "b" #'dap-breakpoint-toggle
:desc "dap continue" :n "c" #'dap-continue
:desc "dap next" :n "n" #'dap-next
:desc "Debug script" :n "s" #'dap-python-script
:desc "dap step in" :n "i" #'dap-step-in
:desc "dap eval at point" :n "e" #'dap-eval-thing-at-point
:desc "Disconnect" :n "q" #'dap-disconnect ))
(after! dap-mode
(setq dap-python-debugger 'debugpy))
(after! ein
(set-popup-rule! "^\\*ein" :ignore t))
Bindings, inspired by this.
(map! (:when (featurep! :tools ein)
(:map ein:notebook-mode-map
:nmvo doom-localleader-key nil ;; remove binding to local-leader
;; :desc "Execute" :ni "S-RET" #'ein:worksheet-execute-cell
:localleader
:desc "Show Hydra" :n "?" #'+ein/hydra/body
:desc "Execute and step" :n "RET" #'ein:worksheet-execute-cell-and-goto-next
:desc "Yank cell" :n "y" #'ein:worksheet-copy-cell
:desc "Paste cell" :n "p" #'ein:worksheet-yank-cell
:desc "Delete cell" :n "d" #'ein:worksheet-kill-cell
:desc "Insert cell below" :n "o" #'ein:worksheet-insert-cell-below
:desc "Insert cell above" :n "O" #'ein:worksheet-insert-cell-above
:desc "Next cell" :n "j" #'ein:worksheet-goto-next-input
:desc "Previous cell" :n "k" #'ein:worksheet-goto-prev-input
:desc "Save notebook" :n "fs" #'ein:notebook-save-notebook-command
)))
When SPC c k
fails, try searching in the docsets with SPC s k
.
Install docsets with dash-docs-install-docset
.
(set-popup-rule! "*eww*" :side 'right :size .50 :select t :vslot 2 :ttl 3)
(after! dash-docs
;; (setq dash-docs-docsets-path "/Users/luca/Library/Application Support/Dash/DocSets")
;; (setq counsel-dash-docsets-path "/Users/luca/Library/Application Support/Dash/DocSets")
;; (expand-file-name "~/Library/Application Support/Dash/DocSets")
;; (set-docsets! 'python-mode "NumPy" "Pandas" "scikit-learn"))
(setq counsel-dash-docsets '("Pandas" "scikit-learn"))
(setq dash-docs-docsets '("Pandas" "scikit-learn")))
(set-popup-rule! "*compilation*" :side 'right :size .50 :select t :vslot 2 :quit 'current)
(use-package elpy
:commands (elpy-enable)
:defer t
:init (elpy-enable)
:config
(elpy-enable)
(remove-hook 'elpy-modules 'elpy-module-pyvenv)
(remove-hook 'elpy-modules 'elpy-module-django)
(add-hook 'pyvenv-post-activate-hooks (lambda ()
(elpy-shell-kill)))
(setq elpy-modules (delq 'elpy-module-flymake elpy-modules))
(setq elpy-test-runner 'elpy-test-pytest-runner)
(setq elpy-test-compilation-function 'compile)
;; (defun append-pdb-arg (command)
;; (if (member "--pdb" command) command (append command '("--pdb"))))
;; (defun elpy-test-pdb (&optional test-whole-project)
;; "Run tests on the current test, or the whole project, with pdb support."
;; (interactive "P")
;; (let ((elpy-test-compilation-function 'pdb)
;; (elpy-test-pytest-runner-command (append-pdb-arg elpy-test-pytest-runner-command))
;; (elpy-test-nose-runner-command (append-pdb-arg elpy-test-nose-runner-command)))
;; (elpy-test test-whole-project)))
(setq python-shell-interpreter "ipython")
;; Have pytest capture sdtin
(setq elpy-test-pytest-runner-command '("py.test" "-s"))
;; Match on any appearance of a pdb or ipdb break point
(setq my-python-break-regexp "[i]?breakpoint()")
;; Use the new Emacs advice to search the current buffer for pdb/ipdb break points
;; only if the current buffer is derived from python-mode. Call compile with comint
;; arg t if found.
(defun my-compile-advice (args)
"Advises `compile' so it sets the argument COMINT to t
if breakpoints are present in `python-mode' files"
(when (derived-mode-p major-mode 'python-mode)
(save-excursion
(save-match-data
(goto-char (point-min))
(if (re-search-forward my-python-break-regexp (point-max) t)
;; set COMINT argument to `t'.
(let ((command (car args)))
(setq args (list command t)))))))
args)
(advice-add 'compile :filter-args #'my-compile-advice)
(map! :map elpy-mode-map
:localleader
:n "t" #'elpy-test
:n "z" #'elpy-shell-switch-to-shell
:n "," #'elpy-shell-send-region-or-buffer
:n "rr" #'elpy-refactor-rename
)
(set-company-backend! 'elpy-mode
'(elpy-company-backend :with company-files company-yasnippet)))
Disable popup for ESS:
(set-popup-rule! "^\\*R:" :ignore t)
(after! ess
(setq ess-eval-visibly 'nowait))
(after! ess
(setq ess-R-font-lock-keywords '((ess-R-fl-keyword:keywords . t)
(ess-R-fl-keyword:constants . t)
(ess-R-fl-keyword:modifiers . t)
(ess-R-fl-keyword:fun-defs . t)
(ess-R-fl-keyword:assign-ops . t)
(ess-R-fl-keyword:%op% . t)
(ess-fl-keyword:fun-calls . t)
(ess-fl-keyword:numbers . t)
(ess-fl-keyword:operators . t)
(ess-fl-keyword:delimiters . t)
(ess-fl-keyword:= . t)
(ess-R-fl-keyword:F&T . t))))
(after! cider
(add-hook 'company-completion-started-hook 'custom/set-company-maps)
(add-hook 'company-completion-finished-hook 'custom/unset-company-maps)
(add-hook 'company-completion-cancelled-hook 'custom/unset-company-maps)
(defun custom/unset-company-maps (&rest unused)
"Set default mappings (outside of company).
Arguments (UNUSED) are ignored."
(general-def
:states 'insert
:keymaps 'override
"<down>" nil
"<up>" nil
"RET" nil
[return] nil
"C-n" nil
"C-p" nil
"C-j" nil
"C-k" nil
"C-h" nil
"C-u" nil
"C-d" nil
"C-s" nil
"C-S-s" (cond ((featurep! :completion helm) nil)
((featurep! :completion ivy) nil))
"C-SPC" nil
"TAB" nil
[tab] nil
[backtab] nil))
(defun custom/set-company-maps (&rest unused)
"Set maps for when you're inside company completion.
Arguments (UNUSED) are ignored."
(general-def
:states 'insert
:keymaps 'override
"<down>" #'company-select-next
"<up>" #'company-select-previous
"RET" #'company-complete
[return] #'company-complete
"C-w" nil ; don't interfere with `evil-delete-backward-word'
"C-n" #'company-select-next
"C-p" #'company-select-previous
"C-j" #'company-select-next
"C-k" #'company-select-previous
"C-h" #'company-show-doc-buffer
"C-u" #'company-previous-page
"C-d" #'company-next-page
"C-s" #'company-filter-candidates
"C-S-s" (cond ((featurep! :completion helm) #'helm-company)
((featurep! :completion ivy) #'counsel-company))
"C-SPC" #'company-complete-common
;; "TAB" #'company-complete-common-or-cycle
;; [tab] #'company-complete-common-or-cycle
[backtab] #'company-select-previous ))
)
(add-hook! cider-repl-mode #'evil-normalize-keymaps)
(after! smartparens
(use-package! evil-cleverparens
:init
(setq evil-move-beyond-eol t
evil-cleverparens-use-additional-bindings nil
evil-cleverparens-use-s-and-S nil
;; evil-cleverparens-swap-move-by-word-and-symbol t
;; evil-cleverparens-use-regular-insert t
)
:config
(add-hook! '(emacs-lisp-mode clojure-mode) #'evil-cleverparens-mode)
;; (add-hook 'smartparens-enabled-hook #'evil-smartparens-mode)
))
(use-package! aggressive-indent
:defer t
:config (add-hook! '(clojure-mode emacs-lisp-mode) (aggressive-indent-mode 1)))
With lispyville
you can wrap using M-(
for example!
(map! :after smartparens
:map (emacs-lisp-mode-map clojure-mode-map)
:localleader
(:desc "Wrap round" :n "(" #'sp-wrap-round
:desc "Wrap square" :n "[" #'sp-wrap-square
:desc "Wrap curly" :n "{" #'sp-wrap-curly
:desc "Unwrap sexp" :n "u" #'sp-unwrap-sexp
))
(after! cider
(setq nrepl-sync-request-timeout nil))
(after! clojure-mode
(setq clojure-align-forms-automatically t))
Remember you can use gr af
to evaluate the outer form.
ap
is a paragraph, as
is a sentence.
(map! :after cider
:map clojure-mode-map
:localleader
(:desc "eval" :prefix "e"
:desc "sexp in comment" :n "E" #'cider-pprint-eval-last-sexp-to-comment
:desc "defun in comment" :n "D" #'cider-pprint-eval-defun-to-comment
))
(use-package! evil-lisp-state
:defer t
:custom
(evil-lisp-state-global t)
:config (evil-lisp-state-leader "SPC k"))
(require 'miracle)
(defun disable-cider-enable-miracle ()
"Activate miracle for arcadia development"
(interactive)
(setq cider-mode nil)
(cider-mode -1)
(add-hook 'clojure-mode-hook 'clojure-enable-miracle)
(add-to-list 'company-backends 'company-miracle)
;; (miracle)
)
(after! miracle
(defun miracle-eval-string (s callback)
(miracle-send-eval-string
s
(lambda (response)
(miracle-dbind-response response (id value status)
(when (member "done" status)
(remhash id miracle-requests))
(when value
(funcall callback nil value))))))
(defun miracle-get-completions (word callback)
(interactive)
(miracle-eval-string
(format "(do (require '[%s]) (%s/completions \"%s\"))"
"complete.core" "complete.core" word)
(lambda (err s)
(progn
;; XXX
(message (format "received str: %s" s))
(message (format "err: %s" err))
(when (not err)
(funcall callback (read-from-whole-string s)))))))
(defun company-miracle (command &optional arg &rest ignored)
(interactive (list 'interactive))
(cl-case command
(interactive (company-begin-backend 'company-miracle))
(prefix (and (or ;;(eq major-mode 'clojurec-mode)
;;(eq major-mode 'clojure-mode)
(eq major-mode 'miracle-mode))
(get-buffer "*miracle-connection*")
(substring-no-properties (company-grab-symbol))))
(candidates (lexical-let ((arg (substring-no-properties arg)))
(cons :async (lambda (callback)
(miracle-get-completions arg callback)))))))
)
(map! :after miracle
:map miracle-interaction-mode-map
:localleader
(:desc "eval" :prefix "e"
:desc "Expression" :n "e" #'miracle-eval-expression-at-point
:desc "defun" :n "d" #'miracle-eval-defun)
:desc "describe" :n "?" #'miracle-describe
)
(set-popup-rule! "*miracle*" :side 'bottom :size .40)
(after! cider
(set-lookup-handlers! 'clojure-mode
:documentation #'cider-doc))
(defun shell-command-print-separator ()
(overlay-put (make-overlay (point-max) (point-max))
'before-string
(propertize "!" 'display
(list 'left-fringe
'right-triangle))))
(advice-add 'shell-command--save-pos-or-erase :after 'shell-command-print-separator)
(set-popup-rule! "*Async Shell Command*" :side 'bottom :size .40)
(set-popup-rule! "vterm" :side 'right :size .40 :quit 'current :ttl 1)
(set-popup-rule! "*eshell*" :side 'right :size .50)
(after! vterm
(setq vterm-shell (executable-find "fish"))
)
(use-package webkit
:bind ("s-b" 'webkit) ;; Bind to whatever global key binding you want if you want
:init
(setq webkit-search-prefix "https://google.com/search?q=") ;; If you don't care so much about privacy
(setq webkit-ace-chars "aoeuidhtns") ;; More convienent if you use dvorak
;; (setq webkit-history-filename "~/path/to/webkit-history") ;; If you want history saved in a different place
;; (setq webkit-history-filename nil) ;; If you don't want history saved to file (will stay in memory)
;; (setq webkit-own-window t) ;; See above explination; must be set before webkit.el is loaded
;; (setq browse-url-browser-function 'webkit-browse-url) ; Set as the default browse-url browser
;; (setq webkit-browse-url-force-new t) ; Always open a new session instead of reusing a current one
:config
;; (add-hook 'webkit-new-hook #'webkit-enable-javascript) ;; disable javascript
)
(use-package evil-collection-webkit
:config
(evil-collection-xwidget-setup)
)