Skip to content
This repository has been archived by the owner on Mar 11, 2021. It is now read-only.

lccambiaghi/.doom.d

Repository files navigation

Preamble

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.

Username and e-mail:

(setq user-full-name "Luca Cambiaghi"
      user-mail-address "luca.cambiaghi@me.com")

Better defaults

(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)

Keybindings

Auto unbind

Let’s have general auto-unbind keys:

(general-auto-unbind-keys)

spacemacs-like

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 ))

evil multiedit

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))

User Interface

Turn off line numbers

(setq display-line-numbers-type nil)

Font and font size:

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))

which-key delay

(after! which-key
    (setq which-key-idle-delay 0.5))

Customize modus themes

(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)

Toggle modus themes at sunrise/sunset

;;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)))

Fancy splash image

(setq +doom-dashboard-banner-file
      (expand-file-name "splash-images/black-hole2.png" doom-private-dir))

Centaur-tabs

(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))

Winum

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
        )))

Extra ligatures

(setq +ligatures-extras-in-modes
      '(not special-mode comint-mode eshell-mode term-mode vterm-mode python-mode))
;; (setq +ligatures-in-modes '(org-mode))

modeline

Hide undesired info

(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))

Show battery and time

(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

Split window and move to it

(setq evil-split-window-below t
      evil-vsplit-window-right t)

Emacs tree sitter

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)
  )

Toggle centered cursor

(use-package! centered-cursor-mode
  :defer t
  :config
  (map! :leader
        :desc "toggle centered cursor"                   :n "t-" (λ! () (interactive) (centered-cursor-mode 'toggle))
        ))

Startup windows

(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)

Elegant emacs

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)
  )

Prescient + selectrum + consult + marginalia + embark

(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))

Dired

Keybindings

  • Jump to current file with SPC o -
  • Hide details with (
  • Hide dotfiles with H
  • Mark with m, unmark with u
  • 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 with q
(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
          ))

  )

Magit

(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))

Company

Delay, prefix length

(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)

Disable tab

(after! company
  (define-key! company-active-map
    "TAB"       nil
    [tab]       nil))

Show yasnippets as company suggestions

(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)))

Org

Better defaults

(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))

Capture templates

(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 %?")))

Prettify bullets

(after! org-superstar
    (setq org-superstar-headline-bullets-list '("" "" "" "" "")
        org-ellipsis ""))

Org agenda popup

(set-popup-rule! "*org agenda*" :side 'right :size .40 :select t :vslot 2 :ttl 3)

ox-ipynb

(after! org
  (require 'ox-ipynb))

Org babel clojure

(after! evil-org
  (setq org-babel-clojure-backend 'cider))

org-re-reveal

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();} }"))
        ))

org-cv

(use-package ox-moderncv
  :after org
  :defer t
  :load-path "/Users/luca/git/org-cv/"
  :init (require 'ox-altacv))
;; :init (require 'ox-moderncv))

Use xelatex

(after! latex
    (setq org-latex-compiler "xelatex"))

HTML export does not fail when org links are present

(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))

org-tree-slide

(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))

beamer export

(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))))

fancy HTML theme

(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))

Jupyter interaction mode

Evaluate buffer

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 new Jupyter REPL

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))))

Key bindings:

;; (: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)))
      )

Popup rules

(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)

Library of babel

(after! evil-org
  (org-babel-lob-ingest "/Users/luca/git/experiments/literate/ml/rpy2.org"))

Eval handler

(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))

Set REPL handler

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))

Use overlays

Evaluate simple expressions to the right of the symbol with =, e e=

(after! ob-jupyter
  (setq jupyter-eval-use-overlays t))

org-babel-jupyter

Org default header arguments:

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"))))

Long outputs

(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"))))

Fix zmq keywords

(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)))

scimax utilities

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 )
  )

Unmap org-metadown

;; (map! :after org-evil
;;         :map evil-org-mode-map
;;       :n "M-<down>" nil
;;       :n "M-j" nil
;;       )

Python

iPython REPL

virtualenv executable

(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)))

Silence warnings when opening REPL

(setq python-shell-prompt-detect-failure-warning nil)

Python console to the bottom

(set-popup-rule! "^\\*Python*"  :side 'bottom :size .30)

Disable native completion

(after! python
  (setq python-shell-completion-native-enable nil))

LSP

Use pyright

(after! lsp-python-ms
  (set-lsp-priority! 'pyright 1))

Don’t guess project root

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")))

Increase bytes read from subprocess

(setq read-process-output-max (* 1024 1024))

lsp-help popup

Lookup documentation with SPC c k

(set-popup-rule! "^\\*lsp-help" :side 'right :size .50 :select t :vslot 1)

Disable lsp flycheck checker and use flake8

(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)

UI

(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))

Don’t restart on exit

(after! lsp-mode
  (setq lsp-restart 'ignore))

Eglot

(when (featurep! +eglot)
  (after! eglot
    (add-to-list 'eglot-server-programs '(python-mode . ("pyright-langserver" "--stdio"))))
  )

Pytest

(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)

dap-mode

dap configure windows

(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)

  )

Remove dap ui features

;; (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)

Debug templates:

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)"))

  )

Debug test 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")))))

virtualenv executable

(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")))

Delete hap hydra bindings

(map! :localleader
        :map +dap-running-session-mode-map
      "d" nil)

;; (map! :after dap-mode
;;     :map dap-mode-map
;;     :localleader "d" nil)

Bindings

(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 ))

Use debugpy

(after! dap-mode
  (setq dap-python-debugger 'debugpy))

emacs-ipython-notebook

Don’t ignore ein buffers

(after! ein
  (set-popup-rule! "^\\*ein" :ignore t))

Bindings

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
      )))

Dash docsets

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")))

Compilation popup

(set-popup-rule! "*compilation*" :side 'right :size .50 :select t :vslot 2 :quit 'current)

Try elpy

(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)))

R

ESS console popup

Disable popup for ESS:

(set-popup-rule! "^\\*R:" :ignore t)

Async eval

(after! ess
  (setq ess-eval-visibly 'nowait))

Syntax highlighting

(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))))

Clojure

Company keybindings

(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    ))
  )

REPL keybindings

(add-hook! cider-repl-mode #'evil-normalize-keymaps)

Cleverparens

(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)
    ))

Aggressive indent

(use-package! aggressive-indent
  :defer t
  :config (add-hook! '(clojure-mode emacs-lisp-mode) (aggressive-indent-mode 1)))

Smartparens keybindings

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
       ))

nREPL timeout

(after! cider
 (setq nrepl-sync-request-timeout nil))

Align vertically automatically

(after! clojure-mode
  (setq clojure-align-forms-automatically t))

Cider keybindings

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
       ))

evil lisp state

(use-package! evil-lisp-state
  :defer t
  :custom
  (evil-lisp-state-global t)
  :config (evil-lisp-state-leader "SPC k"))

Miracle

(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)

cider-doc while developing Unity

(after! cider
  (set-lookup-handlers! 'clojure-mode
    :documentation #'cider-doc))

Shell

Async Shell command

(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)

Async command and vterm popups

(set-popup-rule! "*Async Shell Command*" :side 'bottom :size .40)
(set-popup-rule! "vterm" :side 'right :size .40 :quit 'current :ttl 1)

Eshell popup to the right

(set-popup-rule! "*eshell*" :side 'right :size .50)

Use fish in vterm

(after! vterm
  (setq vterm-shell (executable-find "fish"))
  )

Webkit

(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)
  )

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages