Skip to content

Latest commit

 

History

History
818 lines (677 loc) · 22.4 KB

Alex.org

File metadata and controls

818 lines (677 loc) · 22.4 KB

Alex Scott’s Emacs configuration

Configuration

This emacs.d setup uses a literate programming style. A term coined by Donald Knuth.

  • In order to generate a init.el file, run org tangle C-c v t and the different Babel code blocks will create Alex.el. I then create a symlink for init.el from that in my .emacs.d folder.

Inspired by Sacha Chua’s literate .emacs.d.

I like EXWM as a WM.

Personal information

(setq user-full-name "Alex Scott"
      user-mail-address "[email protected]")

Starting up

Here’s how we start:

;; This sets up the load path so that we can override it
(package-initialize)
;; (add-to-list 'load-path "/usr/local/share/emacs/site-lisp")
;; (add-to-list 'load-path "~/vendor/org-mode/lisp")
;; (add-to-list 'load-path "~/vendor/org-mode/contrib/lisp")
;; (require 'org)
(setq custom-file "~/.emacs.d/custom-settings.el")
(setq use-package-always-ensure t)
(load custom-file t)

Add package sources

(unless (assoc-default "melpa" package-archives)
  (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t))
(unless (assoc-default "org" package-archives)
  (add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/") t))

Use M-x package-refresh-contents to reload the list of packages after adding these for the first time.

Add my elisp directory and other files

(add-to-list 'load-path "~/elisp")
(unless (package-installed-p 'use-package)
  (package-install 'use-package))
(setq use-package-verbose t)
(setq use-package-always-ensure t)
(require 'use-package)
(use-package quelpa)
(use-package quelpa-use-package)
(use-package auto-compile
  :config (auto-compile-on-load-mode))
(setq load-prefer-newer t)

Environment

It would be nice if we could set the default sync already set. Maybe loading timing.

So just use keys that pulse audio provides. C-x / i set sync m mute/unmute v volume

(use-package pulseaudio-control
:ensure t)

(pulseaudio-control-default-keybindings)
;; (setq pulseaudio-control-default-source "0")
;; (pulse-audio-control-select-sink-by-index)
;; (pulseaudio-control-toggle-current-sink-mute)
;; (pulseaudio-control-set-volume "70%")

Libraries

(use-package dash :ensure t)
(use-package diminish :ensure t)

Yes / no

Enable y/n answers

(fset 'yes-or-no-p 'y-or-n-p)

Hippie expand

Bind to Alt Space

(global-set-key "\M- " 'hippie-expand)

Expand region

(global-set-key (kbd "C-c e") 'er/expand-region)

Ace jump mode

;; (use-package ace-jump
;; :ensure t
;; :config
;; (define-key global-map (kbd "C-c SPC") 'ace-jump-mode)
;; )

Ace window

;; (use-package ace-window
;; :config
;; (global-set-key (kbd "M-o") 'ace-window)
;;   :ensure t)

Ace window

(use-package winum
:init
(winum-mode)
:ensure t)

Multiple cursors

(use-package multiple-cursors
:config
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines)
(global-set-key (kbd "C-S-q") 'mc/keyboard-quit)
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this)
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
(global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this)
:ensure t)

Recent files

(require 'recentf)
(setq recentf-max-saved-items 200
      recentf-max-menu-items 15)
(recentf-mode)

Time in the modeline

(display-time-mode 1)

Winner mode - undo and redo window configuration

winner-mode lets you use C-c <left> and C-c <right> to switch between window configurations. This is handy when something has popped up a buffer that you want to look at briefly before returning to whatever you were working on. When you’re done, press C-c <left>.

;; (use-package winner
;;   :defer t)

SSH agent

(use-package keychain-environment
  :ensure t
  :config (keychain-refresh-environment))
;; Avoid repetition?
(keychain-refresh-environment)

Markdown

(use-package ox-gfm
:ensure t)

  (use-package markdown-mode
    :ensure t
    :commands (markdown-mode gfm-mode)
    :mode (("README\\.md\\'" . gfm-mode)
           ("\\.md\\'" . markdown-mode)
           ("\\.mdx\\'" . markdown-mode)
           ("\\.markdown\\'" . markdown-mode))
    :init (setq markdown-command "multimarkdown"))

EXWM

(use-package exwm)
(use-package exwm-firefox-core
  :ensure t)
(require 'exwm)
(require 'exwm-config)
(exwm-config-example)
(require 'exwm-firefox-core) ; Would be nice to defer loading this. :defer ?

Useful when in other applications. Build on defaults by adding cut and paste. Exwm input simulation keys Logout and in again to take affect.

(setq exwm-input-simulation-keys
      '(
        ;; movement
        ([?\C-b] . [left])
        ([?\M-b] . [C-left])
        ([?\C-f] . [right])
        ([?\M-f] . [C-right])
        ([?\C-p] . [up])
        ([?\C-n] . [down])
        ([?\C-a] . [home])
        ([?\C-e] . [end])
        ([?\M-v] . [prior])
        ([?\C-v] . [next])
        ([?\C-d] . [delete])
        ([?\C-k] . [S-end delete])
        ;; cut/paste.
        ([?\C-w] . [?\C-x])
        ([?\M-w] . [?\C-c])
        ([?\C-y] . [?\C-v])
        ;; Search
        ([?\C-s] . [?\C-f])))


        (exwm-input-set-key (kbd "s-p") 'exwm-input-toggle-keyboard)

For this to have worked you will need to be able to suspend without a password:

(exwm-input-set-key (kbd "s-<f12>")
(lambda () (interactive) (start-process "" nil "sudo" "pm-suspend")))

Org capture url

https://elmord.org/blog/?entry=20180214-exwm-org-capture

 (defun elmord-exwm-get-firefox-url ()
   (exwm-input--fake-key ?\C-l)
   (sleep-for 0.05)                      ; Wait a bit for the browser to respond.
   (exwm-input--fake-key ?\C-c)
   (sleep-for 0.05)
   (gui-backend-get-selection 'CLIPBOARD 'STRING))


 (defun elmord-exwm-org-store-link ()
   (when (and (equal major-mode 'exwm-mode)
              (member exwm-class-name '("Firefox")))
     (org-store-link-props
      :type "http"
      :link (elmord-exwm-get-firefox-url)
      :description exwm-title)))


;; (org-link-set-parameters "firefox" :store 'elmord-exwm-org-store-link)

Documentation

When you call org-capture and use a template the includes a link and a description, then both will be added to the capture results.

Shortcuts for frecuent commands.

  (defalias 'oc 'org-capture)
(defalias 'oa 'org-agenda)
(defalias 'lp 'list-processes)
(defalias 'ogc 'org-cliplink)
  (defalias 'gf 'grep-find)
  (defalias 'fd 'find-dired)
  (defalias 'ff 'find-file)
  (defalias 'ms 'magit-status)
  ;; What does it take to make this work
  (defalias 'fnd 'find-name-dired)

Super

  (if  (file-exists-p "~/super.el")
      (load "~/super.el"))

(if  (file-exists-p "~/elisp/js-react-redux-yasnippets.el")
    (load "~/elisp/js-react-redux-yasnippets.el"))


Backups

This is one of the things people usually want to change right away. By default, Emacs saves backup files in the current directory. These are the files ending in ~ that are cluttering up your directory lists. The following code stashes them all in ~/.config/emacs/backups, where I can find them with C-x C-f (find-file) if I really need to.

(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
(setq create-lockfiles nil) ;; No lock files.
(setq delete-old-versions -1)
(setq version-control t)
(setq vc-make-backup-files t)
(setq auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save-list/" t)))

Babel and code blocks.

Do we need ORG mode?

;; (use-package org-tempo)

(setq org-confirm-babel-evaluate nil)

  ; languages for org-babel support

(org-babel-do-load-languages
 'org-babel-load-languages
 '(
   (shell . t)
   (dot . t)
   (latex .t)
   (clojure . t)
   (scheme . t)
   (C . t)
   (js . t)
   (lisp . t)
   (ruby . t)
   (org . t)
   (python . t)
   (sql . t)
   ))

Magit and code source.

(use-package magit
:ensure t
:bind
("C-c g" . magit-file-dispatch))
(use-package forge
  :ensure t
  :after magit)

(use-package orgit-forge
  :ensure t
  :after magit)

Project navigation.

(use-package ag
  :ensure t)

  ;; https://www.manueluberti.eu/emacs/2019/11/16/helm/
  ;; https://github.com/emacs-helm/helm-ls-git
    (use-package helm-ls-git
    :ensure t)
(global-set-key (kbd "C-c h P") 'helm-browse-project)
(global-set-key (kbd "C-c h H") 'helm-projects-history)
(global-set-key (kbd "C-x C-d") 'helm-browse-project)

https://emacs-helm.github.io/helm/

  (use-package helm
    :diminish helm-mode
    :init
    (progn
      (require 'helm-config)
      (require 'helm-for-files)
      (setq helm-candidate-number-limit 100)
      (setq helm-completing-read-handlers-alist
            '((describe-function)
              (consult-bookmark)
              (consult-outline)
              (org-refile)
              (consult-line)
              (consult-mark)
              (consult-multi-occur)
              (describe-variable)
              (execute-extended-command)
              (consult-yank)))
      ;; From https://gist.github.com/antifuchs/9238468
      (setq helm-idle-delay 0.0 ; update fast sources immediately (doesn't).
            helm-input-idle-delay 0.01  ; this actually updates things
                                          ; reeeelatively quickly.
            helm-yas-display-key-on-candidate t
            helm-quick-update t
            helm-ff-file-name-history-use-recentf t
            helm-M-x-requires-pattern nil
            helm-ff-skip-boring-files t)
      (helm-mode))
    :config
    (defadvice helm-files-insert-as-org-links (around sacha activate)
      (insert (mapconcat (lambda (candidate)
                           (org-link-make-string candidate))
                         (helm-marked-candidates)
                         "\n")))
    :bind (("C-c h" . helm-command-prefix)))
  (ido-mode -1) ;; Turn off ido mode in case I enabled it accidentally
  (use-package helm-ls-git)

  (setq helm-mini-default-sources '(helm-source-buffers-list
                                    helm-source-recentf
                                    helm-source-bookmarks
                                    helm-source-buffer-not-found))

(global-set-key (kbd "M-x") 'helm-M-x)
(global-set-key (kbd "M-y") 'helm-show-kill-ring)


Auto revert

(setq global-auto-revert-mode t)

Helm AG

(use-package helm-ag
:ensure t)

Helm-swoop - quickly finding lines

This promises to be a fast way to find things. Let’s bind it to Ctrl-Shift-S to see if I can get used to that…

(use-package helm-swoop
  :bind
  (("C-S-s" . helm-swoop)
   ("M-i" . helm-swoop)
   ("M-s s" . helm-swoop)
   ("M-s M-s" . helm-swoop)
   ("M-I" . helm-swoop-back-to-last-point)
   ("C-c M-i" . helm-multi-swoop)
   ("C-x M-i" . helm-multi-swoop-all)
   )
  :config
  (progn
    (define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch)
    (define-key helm-swoop-map (kbd "M-i") 'helm-multi-swoop-all-from-helm-swoop))
  )

PDFs

(use-package pdf-tools
  :ensure t
  :magic ("%PDF" . pdf-view-mode)
  :config
  (pdf-tools-install :no-query))

(use-package org-noter
:ensure t)

Browser

Set EWW readable.

Org

(use-package ob-async
:ensure t)

Visual line mode for wrapping lines in org mode.

(with-eval-after-load 'org
  ;;(setq org-startup-indented t)
  (add-hook 'org-mode-hook #'visual-line-mode))
(add-hook 'text-mode-hook #'visual-line-mode)
(use-package org-pomodoro
  :ensure t
  :config
  (global-set-key (kbd "<f12>") 'org-pomodoro))

Org roam

(use-package org-roam
      :ensure t
      :hook
      (after-init . org-roam-mode)
      :bind (:map org-roam-mode-map
              (("C-c n l" . org-roam)
               ("C-c n f" . org-roam-find-file)
               ("C-c n g" . org-roam-graph))
              :map org-mode-map
              (("C-c n i" . org-roam-insert))
              (("C-c n I" . org-roam-insert-immediate))))

Org brain

(use-package org-brain :ensure t
  :config
  (bind-key "C-c b" 'org-brain-prefix-map org-mode-map);; binds in org mode.
  ;; (push '("b" "Brain" plain (function org-brain-goto-end)
  ;;         "* %i%?" :empty-lines 1)
  ;;       org-capture-templates)
 (setq org-brain-title-max-length 16))

Org indent mode

(add-hook 'org-mode-hook 'org-indent-mode)

Org bullets

(use-package org-bullets
  :ensure t
  :config
  (add-hook 'org-mode-hook #'org-bullets-mode))

Polymode.

;; (use-package polymode
;; :ensure t
;; :config
;; (add-hook 'org-brain-visualize-mode-hook #'org-brain-polymode))

Dired

(setq dired-dwim-target t)

Coding

Javascript

I like js and js2-modes.

          (setq js-indent-level 2)
          (setq js-switch-indent-offset 2)

            (use-package tagedit
            :ensure t)

          (eval-after-load 'sgml-mode
            '(progn
               (require 'tagedit)
               (tagedit-add-paredit-like-keybindings)
               (add-hook 'html-mode-hook (lambda () (tagedit-mode 1)))))

          (define-key html-mode-map (kbd "C-<right>") 'tagedit-forward-slurp-tag)
          (define-key html-mode-map (kbd "C-<left>") 'tagedit-forward-barf-tag)
          (define-key html-mode-map (kbd "M-r") 'tagedit-raise-tag)
          (define-key html-mode-map (kbd "M-s") 'tagedit-splice-tag)
          (define-key html-mode-map (kbd "M-J") 'tagedit-join-tags)
          (define-key html-mode-map (kbd "M-S") 'tagedit-split-tag)
          (define-key html-mode-map (kbd "M-?") 'tagedit-convolute-tags)
          (define-key html-mode-map (kbd "C-k") 'tagedit-kill)
          (define-key html-mode-map (kbd "s-k") 'tagedit-kill-attribute)


            (add-to-list 'auto-mode-alist '("\\.js\\'\\|\\.json\\'" . js2-mode))
            (add-to-list 'auto-mode-alist '("\\.tsx\\'" . js2-mode))



            (eval-after-load "sgml-mode"
              '(progn
                 (require 'tagedit)
                 (tagedit-add-paredit-like-keybindings)
                 (add-hook 'html-mode-hook (lambda () (tagedit-mode 1)))))

        (add-hook 'js2-mode-hook
                  (lambda () (flycheck-mode t)))

;; js2 refactor
      (use-package js2-refactor
      :ensure t)
    (js2r-add-keybindings-with-prefix "C-c C-m")
  (add-hook 'js2-mode-hook #'js2-refactor-mode)
(use-package flycheck
  :ensure t)

Handy shortcuts:

(use-package js2-mode
  :mode "\\.js\\'")

(use-package json-mode
  :mode "\\.json\\'")

JS comint

(use-package js-comint
:ensure t)

Paredit

        (use-package paredit
          :ensure t
          :init
          (autoload 'enable-paredit-mode "paredit" "Turn on pseudo-structural editing of Lisp code." t)
          (add-hook 'emacs-lisp-mode-hook       #'enable-paredit-mode)
          (add-hook 'eval-expression-minibuffer-setup-hook #'enable-paredit-mode)
          (add-hook 'ielm-mode-hook             #'enable-paredit-mode)
          (add-hook 'lisp-mode-hook             #'enable-paredit-mode)
      ;;    (add-hook 'js-mode-hook               #'enable-paredit-mode) Messes with JXS
          (add-hook 'js2-mode-hook               #'enable-paredit-mode)
          (add-hook 'lisp-interaction-mode-hook #'enable-paredit-mode)
          (add-hook 'scheme-mode-hook           #'enable-paredit-mode)

          ;; eldoc-mode shows documentation in the minibuffer when writing code
          ;; http://www.emacswiki.org/emacs/ElDoc
          (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
          (add-hook 'lisp-interaction-mode-hook 'turn-on-eldoc-mode)
          (add-hook 'ielm-mode-hook 'turn-on-eldoc-mode))

    ;; (use-package autopairs
    ;; :ensure t)
;; Built into emacs.
  (electric-pair-mode t)

      (defun ais-paredit-nonlisp ()
        "Turn on paredit mode for non-lisps."
        (interactive)
        (set (make-local-variable 'paredit-space-for-delimiter-predicates)
             '((lambda (endp delimiter) nil)))
        (paredit-mode 1))
      (add-hook 'js2-mode-hook 'ais-paredit-nonlisp)

Whitespace

(add-hook 'before-save-hook #'whitespace-cleanup)

No hard tabs

(setq-default indent-tabs-mode nil)

Theme

;; (setq custom-theme-directory "~/.emacs.d/poet")
 ;; (add-hook 'text-mode-hook
 ;;            (lambda ()
 ;;             (variable-pitch-mode 1)))
 ;; (load-theme 'poet-dark t)

 ;; Decent font size.
 ;; (set-face-attribute 'default nil :height 140)

Clojure

(use-package clojure-mode
 :ensure t)

(use-package cider
 :ensure t)

;; Enable paredit for Clojure
(add-hook 'clojure-mode-hook 'enable-paredit-mode)

;; This is useful for working with camel-case tokens, like names of
;; Java classes (e.g. JavaClassName)
(add-hook 'clojure-mode-hook 'subword-mode)

;; A little more syntax highlighting
;; (require 'clojure-mode-extra-font-locking)

;; syntax hilighting for midje
(add-hook 'clojure-mode-hook
          (lambda ()
            (setq inferior-lisp-program "lein repl")
            (font-lock-add-keywords
             nil
             '(("(\\(facts?\\)"
                (1 font-lock-keyword-face))
               ("(\\(background?\\)"
                (1 font-lock-keyword-face))))
            (define-clojure-indent (fact 1))
            (define-clojure-indent (facts 1))
            (rainbow-delimiters-mode)))

;;;;
;; Cider
;;;;

;; provides minibuffer documentation for the code you're typing into the repl
(add-hook 'cider-mode-hook 'eldoc-mode)

;; go right to the REPL buffer when it's finished connecting
(setq cider-repl-pop-to-buffer-on-connect t)

;; When there's a cider error, show its buffer and switch to it
(setq cider-show-error-buffer t)
(setq cider-auto-select-error-buffer t)

;; Where to store the cider history.
(setq cider-repl-history-file "~/.emacs.d/cider-history")

;; Wrap when navigating history.
(setq cider-repl-wrap-history t)

;; enable paredit in your REPL
(add-hook 'cider-repl-mode-hook 'paredit-mode)

;; Use clojure mode for other extensions
(add-to-list 'auto-mode-alist '("\\.edn$" . clojure-mode))
(add-to-list 'auto-mode-alist '("\\.boot$" . clojure-mode))
(add-to-list 'auto-mode-alist '("\\.cljs.*$" . clojure-mode))
(add-to-list 'auto-mode-alist '("lein-env" . enh-ruby-mode))


;; key bindings
;; these help me out with the way I usually develop web apps
(defun cider-start-http-server ()
  (interactive)
  (cider-load-current-buffer)
  (let ((ns (cider-current-ns)))
    (cider-repl-set-ns ns)
    (cider-interactive-eval (format "(println '(def server (%s/start))) (println 'server)" ns))
    (cider-interactive-eval (format "(def server (%s/start)) (println server)" ns))))


(defun cider-refresh ()
  (interactive)
  (cider-interactive-eval (format "(user/reset)")))

(defun cider-user-ns ()
  (interactive)
  (cider-repl-set-ns "user"))

(eval-after-load 'cider
  '(progn
     (define-key clojure-mode-map (kbd "C-c C-v") 'cider-start-http-server)
     (define-key clojure-mode-map (kbd "C-M-r") 'cider-refresh)
     (define-key clojure-mode-map (kbd "C-c u") 'cider-user-ns)
     (define-key cider-mode-map (kbd "C-c u") 'cider-user-ns)))

Ediff

(setq ediff-window-setup-function 'ediff-setup-windows-plain)
;; (add-hook 'ediff-prepare-buffer-hook #'show-all)

Lisp

Will need the file added as elisp.

https://github.com/DEADB17/ob-racket/

;; (use-package ob-racket
;;   :ensure t
;;   :after org
;;   :pin manual
;;   :config
;;   (append '((racket . t) (scribble . t)) org-babel-load-languages))

Yasnippet

(use-package yasnippet
:ensure t
:init
(yas-global-mode))

Test

https://emacs.stackexchange.com/questions/53531/emacs-and-exwm-window-manager-switch-between-applications-and-emacs-buffer

(setq exwm-input-global-keys
     `(
     ;; Move around
     (,(kbd "s-<up>") . windmove-up)
     (,(kbd "s-<down>") . windmove-down)
     (,(kbd "s-<left>") . windmove-left)
     (,(kbd "s-<right>") . windmove-right)
     (,(kbd "s-o") . 'ace-window)
     ;; 's-r': Reset (to line-mode).
     ([?\s-r] . exwm-reset)
     ;; 's-w': Switch workspace.
     ([?\s-w] . exwm-workspace-switch)
     ;; 's-&': Launch application.
     ([?\s-&] . (lambda (command)
     (interactive (list (read-shell-command "$ ")))
     (start-process-shell-command command nil command)))
     ;; 's-N': Switch to certain workspace.
     ,@(mapcar (lambda (i)
     `(,(kbd (format "s-%d" i)) .
     (lambda ()
     (interactive)
     (exwm-workspace-switch-create ,i))))
     (number-sequence 0 9))))