This document is a way for me to organize and navigate my configuration. It’s not a teaching moment or an exercise in literate programming.
This goes first so that we don’t see unsightly stuff appear while Emacs is loading.
(when (display-graphic-p)
(menu-bar-mode 1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(tooltip-mode -1))
Is this a useful thing, I wonder?
(easy-menu-define keith-menu nil "My Menu"
'("Keith"
["Light Theme" kfi/modus-light]
["Dark Theme" kfi/modus-dark]
"-----------"
["Bookmarks" bookmark-bmenu-list]
["Double Width" kfi/dw]
["Single Width" kfi/sw]))
(define-key-after global-map [menu-bar keith]
(cons "Keith" keith-menu) 'tools)
(use-package all-the-icons
:ensure t)
(use-package emacs
:config
(when (display-graphic-p)
(defvar kfi/font-choices '("Menlo" "Monaco")
"Font faces I'm fond of.")
(defun kfi/switch-font ()
"Choose a font."
(interactive)
(let ((font (completing-read "Font:" kfi/font-choices)))
(if font
(set-face-attribute 'default nil :family font)
(message "ERROR: Invalid font: %s." font))))
(set-face-attribute 'default nil
:family "Menlo"
:height 140
:weight 'medium)))
(use-package modus-themes
:ensure t
:config
(setq modus-operandi-theme-slanted-constructs t)
(setq modus-operandi-theme-bold-constructs t)
(setq modus-operandi-theme-proportional-fonts nil)
(setq modus-operandi-theme-distinct-org-blocks t)
(setq modus-operandi-theme-visible-fringes nil)
(setq modus-operandi-theme-scale-headings nil))
Add a face for Org Mode
checklists such that when you check them off,
they grey out and get a strike through. The regex matcher isn’t
perfect because you can make your text contain another checklist, such
as:
- [ ] Finish the task 2) [X] again
The word “again” will get the font face. I need to check for spaces/nums at the beginning, or something: or just don’t do the kind of thing up there.
(defface org-checkbox-done-text '((t (:inherit org-done)))
"Face for the text part of a checked org-mode checkbox.")
(font-lock-add-keywords
'org-mode
`(("^\\(.*?[\\)\\.\\+\\-]+? \\[X\\] \\)\\(.*\\)$"
2 ;; use the second match
'org-checkbox-done-text prepend))
'append)
(set-face-attribute 'org-checkbox-done-text nil
:strike-through t
:foreground "gray40")
Some utility functions for switching themes. The dark theme switcher
updates an Org Mode
face, so it has to be loaded after Org Mode
.
(use-package emacs
:config
(defun kfi/unload-themes ()
"Disable all custom themes."
(interactive)
(dolist (theme custom-enabled-themes)
(disable-theme theme)))
(defun kfi/modus-light ()
"Use the modus light theme."
(interactive)
(kfi/unload-themes)
(load-theme 'modus-operandi t)
;; (set-face-attribute 'mode-line nil :box nil)
(set-face-attribute 'org-default nil :foreground "black")
(set-face-attribute 'bold nil :foreground "black")
(set-face-attribute 'org-headline-done nil :strike-through t :foreground "gray40"))
(with-eval-after-load 'org
(defun kfi/modus-dark ()
"Use the modus dark theme."
(interactive)
(kfi/unload-themes)
(load-theme 'modus-vivendi t)
;; (set-face-attribute 'mode-line nil :box nil)
(set-face-attribute 'org-default nil :foreground "#c7c7c7")
(set-face-attribute 'bold nil :foreground "white")
(set-face-attribute 'org-headline-done nil :strike-through t :foreground "gray40"))
(when (display-graphic-p)
(kfi/modus-light))))
https://github.com/seagle0128/doom-modeline
(use-package doom-modeline
:ensure t
:disabled
:config
(when (display-graphic-p)
(doom-modeline-mode 1)
;; Some themes set this, so unset it just in case.
(set-face-attribute 'mode-line nil :box nil)))
(use-package company-emoji
:ensure t
:pin melpa
:config
(when (and (display-graphic-p) (eq system-type 'darwin))
(set-fontset-font "fontset-default" 'unicode "Apple Color Emoji" nil 'prepend)
(add-to-list 'company-backends 'company-emoji)))
(use-package company
:ensure t
:defer t)
-from-shell
(use-package exec-path-from-shell
:if (memq window-system '(mac ns))
:ensure t
:config
(setq exec-path-from-shell-check-startup-files nil)
(exec-path-from-shell-initialize)
(exec-path-from-shell-copy-env "JAVA_HOME")
(exec-path-from-shell-copy-env "GOPATH")
)
(use-package flycheck
:ensure t
:commands (flycheck-mode global-flycheck-mode))
(use-package fullframe
:ensure t)
Ok, I’ve discovered this annoys me more than it helps. Editors with more, uh, graphical affordances make this kind of thing work well. Emacs, not so much, or not this module, anyway. I’ll keep it here in case I want to flip it on, but for now, it’s default off.
(use-package git-gutter
:ensure t
:config
(global-git-gutter-mode 0))
(use-package ibuffer
:bind (("C-x C-b" . ibuffer)
("s-8" . ibuffer))
:config
(setq ibuffer-saved-filter-groups
(quote (("default"
("documents" (or (mode . org-mode)
(mode . markdown-mode)
(mode . text-mode)))
("swift" (mode . swift-mode))
("elisp" (mode . emacs-lisp-mode))
("web" (or (mode . css-mode)
(mode . html-mode)
(mode . nxml-mode)
(mode . js-mode)
(mode . web-mode)))
("salesforce" (or (name . "[.]vfp$")
(name . "[.]apxc$")
(name . "[.]vfc$")))
("python" (mode . python-mode))
("json" (mode . json-mode))
("java" (mode . java-mode))
("clojure" (mode . clojure-mode))
("erc" (name . "^\\#"))
("dirs" (mode . dired-mode))
("temps" (name . "^\\*.*\\*$"))))))
(defun kfi/setup-ibuffer ()
(hl-line-mode 1)
(ibuffer-switch-to-saved-filter-groups "default"))
(add-hook 'ibuffer-mode-hook 'kfi/setup-ibuffer))
Completion utility (https://oremacs.com/swiper/).
(use-package ivy
:ensure t
:config
(ivy-mode 1)
(setq ivy-display-style 'fancy)
(setq ivy-use-virtual-buffers t)
;; (setq ivy-count-format "(%d/%d) ")
(setq ivy-count-format "") ;; "("%d/%d) "
(setq ivy-re-builders-alist '((t . ivy--regex-fuzzy)))
(setq ivy-use-selectable-prompt t))
(use-package swiper
:ensure t
:after ivy)
(use-package counsel
:ensure t
:config
(global-set-key (kbd "C-x C-f") 'counsel-find-file)
(global-set-key (kbd "C-h v") 'counsel-describe-variable)
(global-set-key (kbd "C-h f") 'counsel-describe-function)
(global-set-key (kbd "M-x") 'counsel-M-x)
(global-set-key (kbd "s-f") 'swiper)
(global-set-key (kbd "s-b") 'ivy-switch-buffer)
;; Has to be set here because counsel overrides ivy.
;; - Remove the ^ regex assumption for all searches
(setq ivy-initial-inputs-alist nil))
(use-package flx ; used by regex-fuzzy, I think.
:ensure t)
(use-package smex ; counsel-M-x will use this?
:ensure t)
(use-package ivy-rich
:ensure t
:after ivy
:config
(ivy-rich-mode 1)
(setq ivy-rich-path-style 'abbrev))
(use-package multiple-cursors
:commands multiple-cursors-mode
:ensure t
:pin melpa
:config
(setq mac-command-modifier 'super)
:bind (("C-s-c k" . mc/edit-lines)
("C-M->" . mc/mark-all-like-this)
("C-<" . mc/mark-previous-like-this)
("C->" . mc/mark-next-like-this)))
(use-package paredit
:ensure t
:commands paredit-mode)
(use-package paren-face
:ensure t
:config
(global-paren-face-mode 1))
(use-package projectile
:ensure t
:bind (("s-p" . projectile-find-file)
("C-c p" . projectile-find-file))
:init
(setq projectile-completion-system 'ivy))
https://github.com/pashky/restclient.el https://github.com/alf/ob-restclient.el https://github.com/iquiw/company-restclient
(use-package restclient
:ensure t
:config
(add-hook 'restclient-mode-hook (lambda ()
(company-mode 1))))
(use-package ob-restclient
:ensure t
:config
(org-babel-do-load-languages
'org-babel-load-languages
'((restclient . t))))
(use-package company-restclient
:ensure t
:config
(add-to-list 'company-backends 'company-restclient))
Control-meta-super-F
(use-package ripgrep
:ensure t
:bind (("C-M-s-f" . projectile-ripgrep)))
https://github.com/Alexander-Miller/treemacs
;; (use-package treemacs
;; :ensure t
;; :defer t
;; :config
;; (setq treemacs-width 30)
;; (treemacs-resize-icons 16))
;; (use-package treemacs-projectile
;; :after treemacs projectile
;; :ensure t)
which-key
is a minor mode for Emacs that displays the key bindings
following your currently entered incomplete command (a prefix) in a
popup.
https://github.com/justbur/emacs-which-key
(use-package which-key
:ensure t
:init (which-key-mode 1))
http://joaotavora.github.io/yasnippet/
(use-package yasnippet
:ensure t
:init
;; I can't get this to work as a minor mode, for some reason.
(yas-global-mode))
(use-package dired
:bind ("C-x C-q" . wdired-change-to-wdired-mode)
:config
(defun kfi/dired-mode-hook ()
(dired-hide-details-mode)
(when (display-graphic-p)
(hl-line-mode)))
(add-hook 'dired-mode-hook 'kfi/dired-mode-hook)
(setq dired-listing-switches "-l")
(when (eq system-type 'darwin)
(setq trash-directory "~/.Trash")
(setq delete-by-moving-to-trash t))
(when (eq system-type 'darwin)
(setq dired-use-ls-dired nil)))
(use-package erc
:config
(defun kfi/erc-mode-hook ()
(make-local-variable 'global-hl-line-mode)
(setq global-hl-line-mode nil))
(add-hook 'erc-mode-hook 'kfi/erc-mode-hook)
;; Not sure if this is necessary.
(add-to-list 'erc-modules 'truncate)
(add-to-list 'erc-modules 'scrolltobottom)
(erc-update-modules)
(erc-scrolltobottom-mode 1)
(setq erc-hide-list '("JOIN" "PART" "QUIT"))
(setq erc-fill-prefix " ")
(setq erc-prompt (lambda () (concat "\n" (buffer-name) " >")))
(setq erc-fill-column 79)
(setq erc-scroll-to-bottom -2)
(setq erc-truncate-buffer-on-save t)
(setq erc-max-buffer-size 30000)
(add-hook 'erc-insert-post-hook 'erc-truncate-buffer)
(setq erc-truncate-buffer-on-save t))
(use-package erc-hl-nicks
:ensure t)
(use-package magit
:ensure t
:bind (("C-c g" . kfi/magit-start-session)
("C-c l" . kfi/magit-log-session)
:map magit-status-mode-map
("q" . kfi/magit-quit-session))
:config
(defun kfi/magit-start-session ()
"Go full screen when invoking magit-status."
(interactive)
(window-configuration-to-register :magit-fullscreen)
(call-interactively 'magit-status)
(delete-other-windows))
(defun kfi/magit-log-session ()
"Go full screen when invoking magit-log."
(interactive)
(window-configuration-to-register :magit-fullscreen)
(call-interactively 'magit-log)
(delete-other-windows))
(defun kfi/magit-quit-session ()
"Quit the magit session and restore windows."
(interactive)
(kill-buffer)
(jump-to-register :magit-fullscreen)))
(use-package persistent-scratch
:ensure t
:config
(persistent-scratch-setup-default)
(persistent-scratch-autosave-mode 1))
https://github.com/akermu/emacs-libvterm
(use-package vterm
:ensure t
:bind (("C-c v" . vterm)
("C-c h" . vterm))
:init (setq vterm-kill-buffer-on-exit t)
:config
(defun kfi/setup-vterm ()
(define-key vterm-mode-map (kbd "C-v") 'vterm-yank)
(define-key vterm-mode-map (kbd "s-v") 'vterm-yank)
(set-face-attribute 'vterm-color-cyan nil :foreground "dodgerblue")
(set-face-attribute 'vterm-color-yellow nil :foreground "peru")
(if (member 'modus-vivendi custom-enabled-themes)
(set-face-attribute 'vterm-color-default nil :foreground "#c7c7c7")
(set-face-attribute 'vterm-color-default nil :foreground "#444444")))
(add-hook 'vterm-mode-hook 'kfi/setup-vterm))
(use-package dockerfile-mode
:commands dockerfile-mode
:ensure t
:defer t)
(use-package css-mode
:commands css-mode
:init
(defun kfi/css-setup ()
(company-mode 1)
;; (set (make-local-variable 'company-backends) '(company-css))
;; (turn-on-css-eldoc)
(setq css-indent-offset 2)
(local-set-key (kbd "TAB") 'company-complete)
(local-set-key (kbd "RET") 'newline-and-indent))
(add-hook 'css-mode-hook 'kfi/css-setup))
(use-package css-eldoc
:ensure t
:defer t)
(use-package html-mode
:commands html-mode
:init
(add-hook 'html-mode-hook
(lambda ()
(local-set-key (kbd "RET") 'newline-and-indent))))
(use-package json-mode
:ensure t
:commands json-mode
:init
(add-hook 'js-mode-hook (lambda ()
(setq indent-tabs-mode nil)
(setq js-indent-level 2)
(local-set-key (kbd "RET") 'newline-and-indent))))
(use-package markdown-mode
:ensure t
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("readme\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:bind (("C-b" . markdown-insert-bold)
("s-i" . markdown-insert-italic)
("s-k" . kfi/markdown-insert-small))
:config
;; Cut/paste from markdown-mode.el
(defun kfi/markdown-insert-small ()
(interactive)
(if (markdown-use-region-p)
;; Active region
(let ((bounds (markdown-unwrap-things-in-region
(region-beginning) (region-end)
markdown-regex-code 1 3)))
(markdown-wrap-or-insert
"<small>" "</small>" nil (car bounds) (cdr bounds)))
(if (markdown-inline-code-at-point)
(markdown-unwrap-thing-at-point nil 0 2)
(markdown-wrap-or-insert "<small>" "</small>" 'word nil nil))))
;;
(add-hook 'markdown-mode-hook 'turn-on-flyspell)
(add-hook 'markdown-mode-hook (lambda ()
(visual-line-mode 1)
;;(auto-fill-mode 1)
)))
Provide “pretty” bullets for Org Mode
.
(use-package org-superstar
:ensure t
:after org)
I’ve configured the Org Mode
to use hard line-breaks for paragraphs at
70 characters (rather than using visual-line mode) so that an org
document will be readable (except for tags) at the command line.
Turn off indentation, pretty bullets and so on when running in terminal mode because it just makes things even uglier for those few times you need it.
(use-package org
:ensure t
:pin org
:config
(setq org-ellipsis " … "
org-fontify-done-headline t
org-agenda-start-on-weekday 0
org-hide-emphasis-markers t
org-src-window-setup 'split-window-below
org-support-shift-select t
org-src-tab-acts-natively t
org-src-window-setup 'current-window)
(defun kfi/inline-css-hook (exporter)
"Merge ./style.css or ~/.emacs.d/org-style.css into HTML document."
;; credits: https://stackoverflow.com/a/37132338
(when (eq exporter 'html)
(let* ((dir (ignore-errors (file-name-directory (buffer-file-name))))
(path (concat dir "style.css"))
(homestyle (or (null dir) (null (file-exists-p path))))
(final (if homestyle "~/.emacs.d/org-style.css" path))) ;; <- set your own style file path
(setq org-html-head-include-default-style nil)
(setq org-html-head (concat
"<style type=\"text/css\">\n"
"<!--/*--><![CDATA[/*><!--*/\n"
(with-temp-buffer
(insert-file-contents final)
(buffer-string))
"/*]]>*/-->\n"
"</style>\n")))))
(defun kfi/org-align-tags ()
"Align tags to their columns."
(interactive)
(org-align-tags t))
(defun kfi/org-toggle-markers ()
"Toggle showing markup markers (italics, bold, etc)."
(interactive)
(org-toggle-link-display))
(defun kfi/org-keys-setup ()
(define-key org-mode-map (kbd "<f1>") 'org-tree-to-indirect-buffer)
(define-key org-mode-map (kbd "<s-escape>") 'org-tree-to-indirect-buffer)
(define-key org-mode-map (kbd "C-c a") 'org-agenda)
(define-key org-mode-map (kbd "C-c t") 'kfi/org-align-tags))
(defun kfi/org-graphic-mode-setup ()
(when (display-graphic-p)
;; Have to set this so that I can adjust it when switching to
;; the theme.
(buffer-face-set 'org-default)
(org-indent-mode 1)
(org-superstar-mode 1)
(setq-local global-hl-line-mode nil)))
(defun kfi/org-standard-setup ()
(auto-fill-mode 1)
(yas-minor-mode-on))
;; Is this necessary? I have a vague memory that this
;; helps with org exports to HTML.
(use-package htmlize
:ensure t)
(global-set-key (kbd "C-x <tab>") 'outline-hide-subtree)
(add-hook 'org-export-before-processing-hook 'kfi/inline-css-hook)
(add-hook 'org-mode-hook 'kfi/org-graphic-mode-setup)
(add-hook 'org-mode-hook 'kfi/org-keys-setup)
(add-hook 'org-mode-hook 'kfi/org-standard-setup))
Facilitates a web page with CSS, Javascript and HTML mixed together.
(use-package web-mode
:ensure t
:commands web-mode
:mode (("\\.html?\\'" . web-mode)
("\\.vfp?\\'" . web-mode)
("\\.cmp?\\'" . web-mode)
("\\.design?\\'" . web-mode))
:config
(setq web-mode-markup-indent-offset 2
web-mode-css-indent-offset 2
web-mode-code-indent-offset 2
web-mode-indent-style 2)
(setq web-mode-content-types (cons '("jsx" . "\\.js\\'") web-mode-content-types))
(set-face-attribute 'web-mode-html-tag-face nil :foreground "cornflowerblue")
(set-face-attribute 'web-mode-html-tag-bracket-face nil :foreground "goldenrod"))
(use-package yaml-mode
:commands yaml-mode
:ensure t)
This needs to be revisited if I start using Clojure again.
(use-package cider
:disabled
:ensure t
:after company
:config
(setq cider-font-lock-dynamically '(macro core function var))
(setq cider-eldoc-display-context-dependent-info t)
(setq cider-repl-use-clojure-font-lock t)
(setq cider-repl-use-pretty-printing t)
(setq cider-repl-wrap-history t)
(setq cider-repl-history-size 3000)
(setq cider-repl-display-help-banner nil)
(add-hook 'cider-mode-hook #'eldoc-mode)
(add-hook 'cider-repl-mode-hook #'company-mode)
(add-hook 'cider-mode-hook #'company-mode))
(use-package clojure-mode-extra-font-locking
:disabled
:ensure t)
(use-package clojure-mode
:disabled
:commands clojure-mode
:ensure t
:delight "clj"
:config
(put-clojure-indent 'Conditional 1)
(put-clojure-indent 'ControlBar 0)
(put-clojure-indent 'DisplayBlock 1)
(put-clojure-indent 'Container 2)
(put-clojure-indent 'IncludeIf 0)
(put-clojure-indent 'Table 1)
(put-clojure-indent 'protobuf 1)
(put-clojure-indent 'POST 2)
(put-clojure-indent 'GET 2)
(add-hook 'clojure-mode-hook 'prettify-symbols-mode)
(add-hook 'clojure-mode-hook 'paredit-mode)
(add-hook 'clojure-mode-hook 'cider-mode)
(setq clojure-indent-style nil))
(use-package emacs
:ensure t
:init
(defun kfi/emacs-lisp-mode-setup ()
(paredit-mode 1)
(setq indent-tabs-mode nil)
(local-set-key (kbd "RET") 'newline-and-indent)
(company-mode 1)
(when (display-graphic-p)
(hl-line-mode 1)))
(add-hook 'lisp-interaction-mode-hook 'turn-on-eldoc-mode)
(add-hook 'ielm-mode-hook 'turn-on-eldoc-mode)
(add-hook 'emacs-lisp-mode-hook 'kfi/emacs-lisp-mode-setup))
Revisit if I use Go again.
https://github.com/golang/tools/blob/master/gopls/doc/emacs.md
;; (use-package flycheck-golangci-lint
;; :ensure t
;; :hook (go-mode . flycheck-golangci-lint-setup))
;; (use-package go-mode
;; :ensure t
;; :commands go-mode
;; :init
;; (add-hook 'go-mode-hook 'flycheck-mode)
;; :config
;; ;;(setq gofmt-command "goimports")
;; )
;; (use-package golint
;; :ensure t)
;; (use-package groovy-mode
;; :disabled
;; :ensure t
;; :defer t
;; :mode (("\\.groovy" . groovy-mode)
;; ("\\.gradle" . groovy-mode)))
TODO: Check out this config hlissner’s config.el to see how I might customize lsp so it’s not so facey.
(use-package cc-mode
:init
(add-hook 'java-mode-hook (lambda ()
(hl-line-mode t)
(display-line-numbers-mode 1)
(setq c-basic-offset 4)
(setq tab-width 4)
(setq indent-tabs-mode nil))))
;; (use-package lsp-mode
;; :ensure t)
;; (use-package hydra
;; :ensure t)
;; (use-package company-lsp
;; :ensure t)
;; (use-package lsp-ui
;; :ensure t
;; :config
;; ;; If the popups get too tiresome, use this:
;; (setq lsp-auto-configure nil))
;; (use-package lsp-java
;; :ensure t
;; :after lsp
;; :config (add-hook 'java-mode-hook (lambda ()
;; (company-mode)
;; (lsp)
;; (flycheck-mode 1))))
;; (use-package dap-mode
;; :ensure t
;; :disabled
;; :after lsp-mode
;; :config (progn (dap-mode t)
;; (dap-ui-mode t)))
(use-package js-mode
:commands js-mode
:init
(add-hook 'js-mode-hook (lambda ()
(setq indent-tabs-mode nil)
(setq js-indent-level 4)
(local-set-key (kbd "RET") 'newline-and-indent))))
(use-package lsp-mode
:ensure t
:commands (lsp lsp-deferred)
:hook (go-mode . lsp-deferred)
:config
(defun kfi/lsp-go-install-save-hooks ()
(add-hook 'before-save-hook #'lsp-format-buffer t t)
(add-hook 'before-save-hook #'lsp-organize-imports t t))
(add-hook 'go-mode-hook #'kfi/lsp-go-install-save-hooks)
;; https://emacs-lsp.github.io/lsp-mode/tutorials/how-to-turn-off/
(setq lsp-gopls-staticcheck t)
(setq lsp-eldoc-render-all t)
(setq lsp-eldoc-enable-hover t)
(setq lsp-ui-doc-enable nil) ;; doc popups above cursor word
(setq lsp-rust-analyzer-proc-macro-enable t)
(setq lsp-rust-analyzer-cargo-load-out-dirs-from-check t)
(setq lsp-gopls-complete-unimported t))
(use-package lsp-ui
:ensure t
:commands lsp-ui-mode
:init
(setq lsp-ui-doc-enable nil
lsp-ui-peek-enable t
lsp-ui-sideline-enable t
lsp-ui-imenu-enable t
lsp-ui-flycheck-enable t))
;; No longer available
;; (use-package company-lsp
;; :ensure t)
;; (use-package elpy
;; :ensure t
;; :defer t
;; :init
;; (advice-add 'python-mode :before 'elpy-enable))
;; (use-package py-autopep8
;; :ensure t
;; :defer t
;; :init
;; (add-hook 'elpy-mode-hook 'py-autopep8-enable-on-save)
;; (setq flycheck-python-pycompile- executable "python3"))
(use-package lsp-python-ms
:ensure t
:hook (python-mode . (lambda ()
(require 'lsp-python-ms)
(lsp))))
Check: https://robert.kra.hn/posts/2021-02-07_rust-with-emacs/
;; (use-package rustic
;; :ensure t
;; :init
;; (setq rustic-lsp-server 'rust-analyzer)
;; (setq rustic-flycheck-setup-mode-line-p nil)
;; :hook ((rustic-mode . (lambda ()
;; (lsp-ui-doc-mode)
;; (company-mode))))
;; :config
;; (setq rust-indent-method-chain t)
;; (setq rustic-format-on-save t))
;; (use-package flycheck-rust
;; :ensure t)
See also: http://wiki.call-cc.org/emacs
;; (use-package racket-mode
;; :ensure t
;; :config
;; (defun kfi/racket-mode-hook ()
;; (company-mode 1)
;; (paredit-mode 1))
;; (add-hook 'racket-mode-hook 'kfi/racket-mode-hook)
;; (add-hook 'racket-repl-mode-hook 'kfi/racket-mode-hook))
;; (use-package emacs
;; ;; :ensure t
;; :config
;; ;; http://wiki.call-cc.org/emacs
;; (defun scheme-module-indent (state indent-point normal-indent) 2)
;; (put 'module 'scheme-indent-function 'scheme-module-indent)
;; (put 'and-let* 'scheme-indent-function 1)
;; (put 'parameterize 'scheme-indent-function 1)
;; (put 'handle-exceptions 'scheme-indent-function 1)
;; (put 'when 'scheme-indent-function 1)
;; (put 'if 'scheme-indent-function 1)
;; (put 'unless 'scheme-indent-function 1)
;; (put 'match 'scheme-indent-function 1)
;; (defun kfi/scheme-mode-hook ()
;; (company-mode 1)
;; (paredit-mode 1))
;; (add-hook 'scheme-mode-hook 'kfi/scheme-mode-hook))
;; (use-package swift-mode
;; :ensure t
;; :defer t
;; :config
;; (defun kfi/swift-mode ()
;; ;;(lsp) ;; I don't think this works for XCode projects.
;; (setq swift-mode:basic-offset 4)
;; (setq indent-tabs-mode nil)
;; (hl-line-mode 1)
;; (company-mode 1))
;; (add-hook 'swift-mode-hook 'kfi/swift-mode))
See if lsp-sourcekit
is a pleasant diversion from Xcode.
;; (use-package lsp-sourcekit
;; :after lsp-mode
;; :ensure t
;; :config
;; (setenv "SOURCEKIT_TOOLCHAIN_PATH" "/Library/Developer/Toolchains/swift-latest.xctoolchain")
;; ;; xcrun --find sourcekit-lsp
;; (setq lsp-sourcekit-executable (expand-file-name "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/sourcekit-lsp")))
I don’t think this works too well if you point it at a random Xcode based project. I get a lot of errors like:
could not find manifest, or not a SwiftPM package: /Path/To/Xcode/Project
So, this is a no go for the time being.
(setq default-directory "~/")
(set-default 'cursor-type 'hollow)
Global Auto Revert mode is a global minor mode that reverts any buffer associated with a file when the file changes on disk.
(global-auto-revert-mode 1)
Do not wrap lines when they’re too long.
(setq-default truncate-lines t)
Toggle automatic parens pairing (Electric Pair mode).
(electric-pair-mode 1)
When Delete Selection mode is enabled, typed text replaces the selection if the selection is active. Otherwise, typed text is just inserted at point regardless of any selection.
(delete-selection-mode 1)
Toggle column number display in the mode line (Column Number mode).
(column-number-mode 1)
CUA mode is a global minor mode. When enabled, typed text replaces the active selection, and you can use C-z, C-x, C-c, and C-v to undo, cut, copy, and paste in addition to the normal Emacs bindings. The C-x and C-c keys only do cut and copy when the region is active, so in most cases, they do not conflict with the normal function of these prefix keys.
(cua-mode 1)
Toggle visualization of matching parens (Show Paren mode).
(show-paren-mode t)
Mimics normal Mac keybindings for font resizing.
(global-set-key (kbd "s-+") 'text-scale-increase)
(global-set-key (kbd "s-_") 'text-scale-decrease)
(global-set-key (kbd "M-`") 'other-frame)
(global-set-key (kbd "s-<right>") 'windmove-right)
(global-set-key (kbd "s-<left>") 'windmove-left)
(global-set-key (kbd "s-<up>") 'windmove-up)
(global-set-key (kbd "s-<down>") 'windmove-down)
(defun kfi/goto-scratch ()
"Switch (or create) the *scratch* buffer."
(interactive)
(switch-to-buffer (get-buffer-create "*scratch*"))
(lisp-interaction-mode))
(global-set-key (kbd "s-0") 'delete-window)
(global-set-key (kbd "s-1") 'delete-other-windows)
(global-set-key (kbd "s-2") 'split-window-below)
(global-set-key (kbd "s-3") 'split-window-right)
(global-set-key (kbd "s-9") 'kfi/goto-scratch)
Rules:
- Terminal windows appear at the bottom.
- Help windows appear docked on the left.
(use-package emacs
:hook ((help-mode . visual-line-mode))
:init
(setq display-buffer-alist
'(("\\*Help.*"
(display-buffer-in-side-window)
(window-parameters . ( ;;(no-other-window . t)
(mode-line-format . (" " mode-line-buffer-identification))))
(window-width . 0.5)
(side . left)
(slot . 0))
;; ("\\*eshell.*"
;; (display-buffer-in-side-window)
;; (window-parameters . ((mode-line-format . (" " mode-line-buffer-identification))))
;; (window-height . 0.2)
;; (side . bottom)
;; (slot . 0))
)))
;; banish custom config to another file
(setq custom-file "~/.emacs.d/custom.el")
;; UTF0-8 (still necessary?)
(prefer-coding-system 'utf-8)
(when (display-graphic-p)
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)))
;; Don't require spelling out yes or no.
(fset 'yes-or-no-p 'y-or-n-p)
(setq make-backup-files nil)
(setq auto-save-default nil)
(if (display-graphic-p)
(progn (scroll-bar-mode 0)
(fringe-mode '(10 . 10)))
(progn (menu-bar-mode 0)))
(setq ns-use-mwheel-momentum nil)
(pixel-scroll-mode 0)
(custom-set-variables '(indent-tabs-mode nil))
(setq-default line-spacing 1)
(setq-default inhibit-startup-screen t)
(setq-default standard-indent 2)
(setq-default tab-width 2)
(add-hook 'before-save-hook 'whitespace-cleanup)
(blink-cursor-mode 0)
(setq ring-bell-function 'ignore)
;; Set the frame title to the visited file's path
;; using the abbreviated form (~ for home).
(setq frame-title-format
'((:eval (if (buffer-file-name)
(abbreviate-file-name (buffer-file-name))
"%b"))))
(setq mac-command-modifier 'super)
;; Quick access to shell
(global-set-key (kbd "C-c e") 'eshell)
(setq ns-use-srgb-colorspace t)
(defun kfi/sort-lines-nocase ()
"Sort lines ignoring case"
(interactive)
(let ((sort-fold-case t))
(call-interactively 'sort-lines)))
What I use when I can’t use Keyboard Maestro. Each of the formats
could be made into a yasnippet
(which is what I do with KB Maestro)
using an elisp expression as its body. But I like the completing-read
minibuffer menu thing here.
(defvar kfi/timestamp-formats
'(("March 15, 2020 @ 9:33 PM" . "%B %-d, %Y @ %-I:%M %p")
("March 15, 2020" . "%B %-d, %Y")
("2020-03-15T21:33:54" . "%Y-%m-%dT%H:%M:%S")
("2020-03-15" . "%Y-%m-%d")
("2020-03-15 09:35 PM" . "%Y-%m-%d %I:%M %p")
("2020-03-15T21:39:20-0700" . "%FT%T%z"))
"Formats for inserting a timestamp into a document.")
(defun kfi/timestamp ()
"Choose a format, then insert a timestamp."
(interactive)
(if-let* ((choices (mapcar #'car kfi/timestamp-formats))
(choice (completing-read "Format:" choices))
(format (cdr (assoc choice kfi/timestamp-formats))))
(insert (format-time-string format))
(insert "<error:nil-selection>")))
(defun kfi/unsmart ()
"Remove smart quotes from buffer."
(interactive)
(save-excursion
(goto-char (point-min))
(while (re-search-forward "’" nil t)
(replace-match "'"))
(goto-char (point-min))
(while (re-search-forward "”" nil t)
(replace-match "\""))
(goto-char (point-min))
(while (re-search-forward "“" nil t)
(replace-match "\""))))
Actually, this doesn’t do what I think it does: it seems to go to the stop of the buffer, when it should instead find the beginning of the paragraph. I wonder what the original intent was?
(defun kfi/unwrap-line ()
"Remove newlines until end-of-paragraph."
(interactive)
(let ((start (point-min))
(end (copy-marker (or (search-forward "\n\n" nil t)
(point-max))))
(fill-column (point-max)))
(fill-region start end)
(goto-char end)
(newline)
(goto-char start)))
(defun kfi/set-frame-width (arg)
"Set the width of the frame to ARG."
(interactive "nFrame width: ")
(set-frame-width (selected-frame) arg))
(defun kfi/dw ()
"Set frame to double-wide."
(interactive)
(kfi/set-frame-width 180))
(defun kfi/sw ()
"Set frame to single-wide."
(interactive)
(kfi/set-frame-width 90))
(global-set-key (kbd "C-c C-x w") 'kfi/dw)
(global-set-key (kbd "C-c C-x s") 'kfi/sw)
(defun kfi/set-frame-height (arg)
"Set frame height to ARG."
(interactive "nFrame height: ")
(set-frame-height (selected-frame) arg))
(defun kfi/set-frame-dimensions (w h)
"Set frame dimensions to W and H."
(interactive "nFrame width: \nnFrame height: ")
(set-frame-width (selected-frame) w)
(set-frame-height (selected-frame) h))
(defun kfi/back-window ()
"Go back to previously visited window."
(interactive)
(other-window -1))
(global-set-key (kbd "C-x p") 'kfi/back-window)
(defun kfi/open-this ()
"Open the buffer using MacOS defaults."
(interactive)
(shell-command (concat "open '" (buffer-file-name) "'")))
(global-set-key (kbd "C-c C-x o") 'kfi/open-this)
(defun kfi/set-font-size (size)
"Set the font SIZE."
(interactive "nNew size: ")
(set-face-attribute 'default nil :height size))
(defun kfi/font-size-up ()
"Shift font size up by 10 units."
(interactive)
(kfi/set-font-size (+ (face-attribute 'default :height) 10)))
(defun kfi/font-size-down ()
"Shift font size down by 10 units."
(interactive)
(kfi/set-font-size (- (face-attribute 'default :height) 10)))
(defun kfi/lorem ()
"Output a bunch of lorem ipsum text."
(interactive)
(insert
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do "
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim"
"ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
"aliquip ex ea commodo consequat. Duis aute irure dolor in "
"reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
"pariatur. Excepteur sint occaecat cupidatat non proident, sunt in "
"culpa qui officia deserunt mollit anim id est laborum."))
(defun kfi/sort-words (reverse beg end)
"Sort region words REVERSE if negative from BEG to END.
Prefixed with negative \\[universal-argument], sorts in reverse.
The variable `sort-fold-case' determines whether alphabetic case
affects the sort order. See `sort-regexp-fields'."
(interactive "*P\nr")
(sort-regexp-fields reverse "\\w+" "\\&" beg end))
(defun kfi/transparency-on ()
"Turn on frame transparency."
(interactive)
(set-frame-parameter nil 'alpha '(95 95))
(add-to-list 'default-frame-alist '(alpha 95 95)))
(defun kfi/transparency-no ()
"Turn off frame transparency."
(interactive)
(set-frame-parameter nil 'alpha '(100 100))
(add-to-list 'default-frame-alist '(alpha 100 100)))
(defun kfi/edit-init-el ()
"Visit the init.el file."
(interactive)
(find-file "~/.emacs.d/init.el"))
(defun kfi/my-config ()
"Visit my configuration.org file for Emacs."
(interactive)
(find-file "~/.emacs.d/configuration.org"))
Do something like the following, and have that function check for words beginning and ending with “=” or “@” or “#” or “~”.
(add-hook 'java-mode-hook
(lambda ()
(setq flyspell-generic-check-word-predicate 'my-new-function)))
Also check: https://emacs.stackexchange.com/a/31302 for using faces to avoid spellchecking in comments, though I’m not sure this will work in org-mode given it’s not a programming mode. Hm.
(setq flyspell-prog-text-faces
(delq 'font-lock-string-face
flyspell-prog-text-faces))
Try M-$
, then i
then yes
to accept the word. Maybe sure the word is
highlighted.
To double check your learned words, look in ~/.aspell.pws
.
Look in ~/.aspell.pws
.
Quit emacs, then go into ~/.emacs.d
and remove the workspace
directory. When you restart, things should be better.
Also, visit build.gradle and run M-x
lsp-java-update-project-configuration
, and make lsp-restart-workspace
.
When you enter in the path to the new project for your workspace,
remove the trailing /
from the path.