paultopia / yakmacs

baby tries to migrate off spacemacs with a clean config...

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Wth?

I’m now running this emacs config on my mac! I’ve escaped spacemacs! Even though it’s not done yet, it’s functional enough that I can use it, and I got sick of worrying about what kinds of things would have to be changed after moving machines.

doing the literate org config, so this readme file is also my config file! (Well, most of it. I defined a little bit of stuff that applies to this file itself, like a snippet to get elisp code blocks that I didn’t know how to escape, in init.el.) So that’s cool.

Conventions

  • I use the tag dev for headlines that contain code that might go away when I’m happy with this config, like the snippet I bound to @ below.
  • I use the tag key for headlines that contain code with a keybinding in it. This is for ease of later documentation.
    • At some point I want to create a personal usage manual.
  • I use the tag fragile for headlines containing code with non-obvious or even downright mysterious failure potential, where I made it work with pure guesswork.
  • As much as possible, I try to keep keybindings together rather than with their associated packages. This might be a mistake?

Keybindings are now listed in keybindings.org in this repository

Package management

Straight appears to be an actual package manager unlike stuff like use-package. I can get a lockfile with commit hashes for every package I use with (straight-freeze-versions) .

Given that emacs packages seem to just love generating side effects, this seems like a thing that is absolutely mandatory. I’ve already had one nasty package conflict scare.

(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 5))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))

I’m also going to add a directory for totally random elisp, such as the integration code provided by spacehammer.

(add-to-list 'load-path "~/.emacs.d/rando-elisp/")

Make things involving the commandline work on mac.

(straight-use-package 'exec-path-from-shell)
(setq exec-path-from-shell-arguments nil)
(exec-path-from-shell-initialize)

Make use of the trash can before I start trying to use things like dired UNTESTED

(straight-use-package 'osx-trash)
(when (eq system-type 'darwin)
  (osx-trash-setup))
(setq delete-by-moving-to-trash t)

Emacs mechanical tweaks

Kill all the damn beeping

(setq visible-bell 1)

Also kill all the annoying confirmations. Borrowed from here.

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

(setq confirm-nonexistent-file-or-buffer nil)

(setq kill-buffer-query-functions
  (remq 'process-kill-buffer-query-function
         kill-buffer-query-functions))

Get my mac keys back. From here This is a consequence of switching from emacs-plus to emacs-macport

For some reason, it needs to be called twice to get it to work. But calling it twice does work, so.

(global-set-key [(hyper a)] 'mark-whole-buffer)
(global-set-key [(hyper v)] 'yank)
(global-set-key [(hyper c)] 'kill-ring-save)
(global-set-key [(hyper x)] 'kill-region)
(global-set-key [(hyper s)] 'save-buffer)
(global-set-key [(hyper l)] 'goto-line)
(global-set-key [(hyper w)]
                (lambda () (interactive) (delete-window)))
(global-set-key [(hyper z)] 'undo)

(defun mac-switch-meta () 
  "switch meta between Option and Command"
  (interactive)
  (if (eq mac-option-modifier nil)
      (progn
	(setq mac-option-modifier 'meta)
	(setq mac-command-modifier 'hyper)
	)
    (progn 
      (setq mac-option-modifier nil)
      (setq mac-command-modifier 'meta)
      )
    )
  )

(mac-switch-meta)
(mac-switch-meta)

I’m over the backup files. Borrowing code from the wiki

(defvar backup-dir "~/Dropbox/emacs-backup-files")
    (setq backup-directory-alist
          `((".*" . ,backup-dir)))
    (setq auto-save-file-name-transforms
          `((".*" ,backup-dir t)))

Let’s see if I can get a restart in

(straight-use-package 'restart-emacs)

Getting sick of having a window with the welcome message show up when I open something from the commandline

(setq inhibit-startup-screen t)

I don’t need these libs until I get to origami in markdown mode in an entire separate config file, but they’re generally useful enough that I’d rather load them up right on top.

(straight-use-package 'dash)
(straight-use-package 's)

Everything is UTF-8. EVERYTHING. Borrowed from here.

(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))

Maybe a bit more help

(straight-use-package 'helpful)
(setq counsel-describe-function-function #'helpful-callable)
(setq counsel-describe-variable-function #'helpful-variable)

helpful-variable seems to fail randomly when point is at the wrong place in a buffer, might want to switch back to built-in describe-variable. Seethis issue.

I also want a global editing setting to overwrite when I select, because that’s the functionality I’m used to.

(delete-selection-mode 1)

Undo-redo

Undo-redo is impossibly confusing and I can never redo anything and I hate it to death. Let’s try a lib. Using undo-fu because it seems normal. keybindings down below per usual, but also suggested keybindings in here for evil.

(actually I take that back. I’m going to define them down below in general, but I’m going to use C-u and C-r for it globally, including in insert mode, because fuck that noise.

(straight-use-package 'undo-fu)

While I’m here, I also want to fix evil undo some more. These are apparently supposed to happen before evil is loaded.

(setq evil-undo-system 'undo-fu)


(setq evil-want-fine-undo t)

Browsing and Finding Things

Files and such

Spacemacs uses helm, but lots of people who start with helm seem to love Ivy

(straight-use-package 'counsel)
(ivy-mode 1)

I think projectile will be useful for things like project-wide find

(straight-use-package 'projectile)
(require 'projectile)
(projectile-mode +1)
(setq projectile-completion-system 'ivy)

Ivy rich looks nice in the screenshots on the repo. But does it do anything? I don’t see a difference, but let’s see.

(straight-use-package 'ivy-rich)
(require 'ivy-rich)
(ivy-rich-mode 1)
(setcdr (assq t ivy-format-functions-alist) #'ivy-format-function-line)

Commands

Which-key is apparently The Thing

(straight-use-package 'which-key)
(require 'which-key)
(which-key-mode)

Characters

(straight-use-package 'avy)
(require 'avy)
(straight-use-package 'avy-menu)
(require 'avy-menu)

(setq avy-keys (nconc 
                      (number-sequence ?1 ?9)
                      '(?0)
                      (number-sequence ?a ?z)
))
(setq avy-background t)
(setq avy-style 'pre)

Evilify everything because emacs keybindings are horrible

Base evil

(straight-use-package 'evil)
(setq evil-want-keybinding nil)  ;; this is apparently required for evil-collection keybindings.
(setq evil-disable-insert-state-bindings t)  ;; make insert mode behave like emacs mode
(require 'evil)
(evil-mode)

I’m having weird glitches with changes disappearing in big markdown buffers, and I’m wondering if that has something to do with evil. So this is an experiment.

(fset 'evil-visual-update-x-selection 'ignore) 

Add more evil bindings

Let’s get as much evilified as humanly possible just to start, eh?

(straight-use-package 'evil-commentary)
(require 'evil-commentary)
(evil-commentary-mode)

(straight-use-package 'evil-collection)

(straight-use-package 'evil-org)
(require 'evil-org)
(add-hook 'org-mode-hook 'evil-org-mode)
(evil-org-set-key-theme '(navigation insert textobjects additional calendar))
(require 'evil-org-agenda)
(evil-org-agenda-set-keys)

I have keybindings for this down below, but I need a universal bail out of things command.

(straight-use-package 'evil-escape)

I wish I knew how the parsing/evaluation order of these files worked. Can I set a keybinding for something before actually using it? I feel like I’ve seen people actually call functions before defining them in blog posts and such about elisp.

Make startup useful

(straight-use-package 'dashboard)
(require 'dashboard)
(dashboard-setup-startup-hook)

(setq dashboard-set-init-info t)
(setq dashboard-set-footer nil)
(setq dashboard-projects-backend 'projectile)

(setq dashboard-items '((recents  . 5)
                        (projects . 5)
                        (bookmarks . 5)
                        (registers . 5)))

Misc utility functions

Find non-ascii text (swiped from the wiki)

(defun find-non-ascii ()
  "Find any non-ascii characters in the current buffer."
  (interactive)
  (occur "[^[:ascii:]]"))

Machine-specific config

I’m using this emacs config across work and home machines, but some stuff is different. Particularly, I only use dropbox on my home machine, and use onedrive for work things; configuration that requires saving to a dropbox file should only happen on a personal computer.

Right now, I’m just setting up environment variable to get a machine identifier. Will create machine-specific config down the line.

I really want to use an enum for this, but right now it’s just a string. So permissible values are “home-computer” and “office-computer)

(exec-path-from-shell-copy-env "WHICH_COMPUTER")
(defvar which-computer)

(setq which-computer (getenv "WHICH_COMPUTER"))

; just to make sure I can detect computer

(defun say-computer ()
(interactive)
(cond ((string= which-computer "home-computer") (print "I'm the home computer!"))
      ((string= which-computer "office-computer") (print "I'm the office computer!"))
      (t (print "I don't know which computer I am. :-(")))
)

Popup buffers

(straight-use-package 'popper)
(require 'popper)
(setq popper-reference-buffers
      '("\\*Messages\\*"
        "Output\\*$"
        help-mode
        compilation-mode))
(popper-mode +1)

PDF Tools

Docview is agonizingly slow and I hate it. Time to replace.

(straight-use-package 'tablist)
(straight-use-package 'pdf-tools)
(pdf-tools-install)

(evil-make-overriding-map pdf-view-mode-map 'normal)

Visual

It’s too hard to see which window is active.

(straight-use-package 'auto-dim-other-buffers)
(auto-dim-other-buffers-mode t)

Theme

Setup

(straight-use-package 'leuven-theme)

Convenience functions

(defvar dark-theme 'leuven-dark)
(defvar light-theme 'leuven)

(defun disable-all-themes ()
  "disable all active themes."
  (dolist (i custom-enabled-themes)
    (disable-theme i)))

(defun dark-mode ()
(interactive)
(disable-all-themes)
(load-theme dark-theme t))


(defun light-mode ()
(interactive)
(disable-all-themes)
(load-theme light-theme t))

Dark mode for programming

(add-hook 'prog-mode-hook 'dark-mode)

Light mode for writing

(add-hook 'text-mode-hook 'light-mode)

Start out in light mode

(add-hook 'dashboard-mode-hook 'light-mode)

Font

(defvar code-font-string "Inconsolata Light 18")
(defvar prose-font-string "IBM Plex Serif 16")

(defun code-font () 
(interactive)
(set-frame-font code-font-string nil t))

(defun prose-font () 
(interactive)
(set-frame-font prose-font-string nil t))

(code-font)

A quick fix for org.

(setq org-fontify-whole-heading-line t)

GUI tweaks

Get rid of menubar, toolbar, scrollbar

(menu-bar-mode -1)
(tool-bar-mode -1)
(toggle-scroll-bar -1)

Start full-sized

(add-to-list 'initial-frame-alist '(fullscreen . fullboth))

Make clicking in margins bring point to visual line.

 (defun set-point-to-margin-click (event) 
   (interactive "e")
   (let ((position (cddr (mouse-position)))
        (clicked-window (posn-window (event-start event))))
     (select-window clicked-window)
     (let ((topline (car (cdr (window-body-edges)))))
       (move-to-window-line 0)
       (line-move-visual (- position topline)))))
     
	(global-set-key (kbd "<left-margin> <mouse-1>") 'set-point-to-margin-click)
	(global-set-key (kbd "<right-margin> <mouse-1>") 'set-point-to-margin-click)

Let’s get scrolling working in the margins too. I think this might be specific to the macport build I’m using; may break on office computer.

If it breaks on office computer, I can just try mwheel-scroll without the modifier.

(global-set-key (kbd "<left-margin> <wheel-down>") 'mac-mwheel-scroll)
(global-set-key (kbd "<left-margin> <wheel-up>") 'mac-mwheel-scroll)
(global-set-key (kbd "<left-margin> <wheel-left>") 'mac-mwheel-scroll)
(global-set-key (kbd "<left-margin> <wheel-right>") 'mac-mwheel-scroll)

(global-set-key (kbd "<right-margin> <wheel-down>") 'mac-mwheel-scroll)
(global-set-key (kbd "<right-margin> <wheel-up>") 'mac-mwheel-scroll)
(global-set-key (kbd "<right-margin> <wheel-left>") 'mac-mwheel-scroll)
(global-set-key (kbd "<right-margin> <wheel-right>") 'mac-mwheel-scroll)

Line numbers

(straight-use-package 'linum-relative)
(require 'linum-relative)
(setq linum-relative-backend 'display-line-numbers-mode)

Rainbow parens

Can’t even begin to edit elisp without this, I want it in this mode noooow.

(straight-use-package 'rainbow-delimiters)
(add-hook 'org-mode-hook #'rainbow-delimiters-mode)
(add-hook 'prog-mode-hook #'rainbow-delimiters-mode)

Modeline

(straight-use-package 'telephone-line)
(straight-use-package 'nyan-mode)
(require 'nyan-mode)
(nyan-mode)

(setq telephone-line-lhs
      '((evil   . (telephone-line-airline-position-segment
                   telephone-line-evil-tag-segment
                   telephone-line-vc-segment
                   telephone-line-process-segment
                   telephone-line-buffer-segment
                   telephone-line-buffer-modified-segment))
(nil . (telephone-line-nyan-segment))
))
(setq telephone-line-rhs
      '(
;(nil . (telephone-line-nyan-segment))
(evil    . (telephone-line-major-mode-segment)
)))

(telephone-line-mode 1)

Golden ratio

I’ve decided this should be off by default. It’s useful but also annoying. I’ll bind it to a key.

(straight-use-package 'golden-ratio)
(require 'golden-ratio)
; (golden-ratio-mode 1)

Git

(straight-use-package 'magit)

Trying to create the equivalent of git add . — the function magit-stage-modified is close, but appears to require a prefix argument to make it work.

Following the suggestion in this SO I’m going to just try to force that in.

Actually, it looks like I don’t need to do all that jazz with forced prefix arguments and call-interactively — I can just pass it a value. For now? Is this a bug/undocumented behavior or do I just not understand the function definition? Is there a way to get emacs to give you the code for a function?

I can probably get rid of that current prefix arg thing. but this works now, so, why?

(defun git-add-all ()
  (interactive)
  (let ((current-prefix-arg '(4)))
  (magit-stage-modified "t")))

Ok, now let’s see if I can get a straight-up commit going.

(defun git-quick-commit ()
(interactive)
(git-add-all)
(magit-commit-create))

I’d like to be able to pull; setting global auto-revert mode to avoid pain like pulling open buffers, which would be a bad oops.

(global-auto-revert-mode t)

I’m going to create a special derived mode for commit messages so that I can try to bail out of it with a normal key binding. See discussion in this SO

(define-derived-mode magit-commit-message-mode text-mode "Magit-Commit" "Major mode for editing commit messages with magit.")

(setq git-commit-major-mode 'magit-commit-message-mode)

General Programming

LSP

(straight-use-package 'lsp-mode)
(straight-use-package 'lsp-ui)
(require 'lsp-mode)

Completions

(straight-use-package 'company)
(add-hook 'prog-mode-hook 'company-mode)
(straight-use-package 'company-quickhelp)
(add-hook 'prog-mode-hook 'company-quickhelp-mode)

Line numbers

(add-hook 'prog-mode-hook 'display-line-numbers-mode)
; (setq linum-format "%4d \u2502 ")

Get rid of visual line mode just in case I switched in from text.

(add-hook 'prog-mode-hook (lambda () (visual-line-mode -1)))

Make sure code is in a proper code font

(add-hook 'prog-mode-hook `code-font)

Time to take control of my parens.

evil cleverparens doesn’t appear to work though, at least not in this file. It still lets me delete

  (straight-use-package 'smartparens)
  (straight-use-package 'evil-cleverparens)
  (add-hook 'smartparens-enabled-hook #'evil-cleverparens-mode)
  (require 'smartparens-config)
  (add-hook 'prog-mode-hook #'smartparens-mode)

; just to make it easier to work on lisp
  (sp-local-pair 'emacs-lisp-mode "'" nil :actions nil)
  (sp-local-pair 'org-mode "'" nil :actions nil)

While I’m at it, it’s silly not to have parens matched instantly.

(setq show-paren-delay 0)
(show-paren-mode 1)

Syntax checking

(straight-use-package 'flycheck)
(add-hook 'prog-mode-hook #'global-flycheck-mode)

installed on my system: pylint (python, via pip install pylint) eslint (js, via npm install -g eslint) html-tidy (html, via brew install tidy-html5) jq (json, via brew install jq) shellcheck (bash, via brew install shellcheck) yamllint (yaml, via pip install yamllint) stylelint (css, via npm install -g stylelint stylelint-config-standard) luacheck (lua, via luarocks install luacheck)

Languages in separate files (clojure, python, swift, javascript)

(org-babel-load-file "~/.emacs.d/clojure/clojure.org")
(org-babel-load-file "~/.emacs.d/python/python.org")
(org-babel-load-file "~/.emacs.d/swift/swift.org")

Javascript includes vue, html, etc. all the web shit. Most of it sucks and I got rid of it, so all that’s left right now is really vue mode. The rest made my emacs slow down horribly and I hate it. I feel like probably all the JS stuff is abandoned because every js dev uses vscode. Whev.

(org-babel-load-file "~/.emacs.d/javascript/javascript.org")

Org

I want to be able to use shift select.

(setq org-support-shift-select t)

I HATE org’s link hiding. HATE IT. It makes it impossible to edit links. Die die die die.

(setq org-descriptive-links nil)

Setting up org capture in a separate file in order to make it visually easier to just change as I change projects. This is going to shift a lot.

(org-babel-load-file "~/.emacs.d/org/capture.org")

experimental: org roam

(org-babel-load-file "~/.emacs.d/org/roam.org")

I’m not a big fan of the default return behavior, especially in lists. So:

(straight-use-package 'org-autolist)
(add-hook 'org-mode-hook 'org-autolist-mode) 

(add-hook 'org-mode-hook
	  (lambda () (electric-indent-local-mode -1)))

For reasons that are completely mysterious to me, running org-reload seems to be necessary to get PDF export to work. So I’m just going to run it in my init and see if that fixes the problem.

(org-reload)

Markdown

Moved to its own file

(org-babel-load-file "~/.emacs.d/markdown/markdown-main.org")

Latex

Where the hell is auctex? Can straight handle it? Let’s see.

(straight-use-package 'auctex)
(setq TeX-auto-save t)
(setq TeX-parse-self t) 	
(setq-default TeX-master nil)

JSON

I’m going to start making use of JQ to try to work with some citeproc-json goodness. right now it’s just here for testing.

(straight-use-package 'counsel-jq)

I want JSON enhancements too

(straight-use-package 'json-mode)

Lua and fennel

(straight-use-package 'lua-mode)
(straight-use-package 'fennel-mode)

Visual changes between writing and programming

(defun text-margins ()
  (setq left-margin-width 16)
  (setq right-margin-width 16))
(add-hook 'markdown-mode-hook 'text-margins)

(defun prog-margins ()
  (setq left-margin-width 2)
  (setq right-margin-width 2))
(add-hook 'prog-mode-hook 'prog-margins)

(defun text-linespacing ()
  (setq line-spacing 0.5))
(add-hook 'markdown-mode-hook 'text-linespacing)

(defun prog-linespacing ()
  (setq line-spacing nil))
(add-hook 'prog-mode-hook 'prog-linespacing)

(add-hook 'text-mode-hook 'visual-line-mode)

Data serialization languages

Yaml

(straight-use-package 'yaml-mode)

(add-hook 'yaml-mode-hook #'global-flycheck-mode)

Keybindings

Set up evil escape

(evil-escape-mode)
(setq-default evil-escape-delay 0.2)
(global-set-key (kbd "ESC ESC") 'evil-escape)

Load up general

(straight-use-package 'general)

(defconst leader "SPC")
(defconst mode-leader ",")
(general-create-definer leader-binding
  :prefix leader
  :states 'normal
  :keymaps 'override) 

(general-create-definer mode-binding
  :prefix mode-leader
  :states 'normal
  :major-modes t
  :keymaps 'override)

Set up evil collection keybindings… this rarely seems to work right, and it’s starting to piss me off honestly.

(evil-collection-init '(dashboard magit))

Load up keybindings file

(org-babel-load-file "~/.emacs.d/keybindings.org")

Development (of emacs config) conveniences

Keybinding to make delimiter for elisp blocks with @

This is slightly black-magic-ey. add-lisp-delimiters is defined in init.el. That function looks for a variable called in-config-file, and, if it’s set (as it is on the very first line of this file… and apparently it has to be the very first line, the second line won’t do), then it pastes in the BEGIN_SRC stuff. So I bind it to ampersand, because I don’t think anything else uses @ …?

(add-hook 'org-mode-hook 
  (lambda () 
    (evil-global-set-key 'normal (kbd "@") 'add-lisp-delimiters)))

Talk to other applications

Start a server for commandline client use

(server-start)

Start a server to edit browser textareas

(straight-use-package 'atomic-chrome)
(require 'atomic-chrome)
(atomic-chrome-start-server)
(setq atomic-chrome-buffer-open-style 'frame)

For spacehammer— edit from anywhere

(load "spacehammer")

(not currently perfect working. see agzam/spacehammer#76

enhancements to make

Fancier modeline with mode and git enhancements

  • I’m happy with telephone-line for now, except I’d like to be able to have three color chunks, one reflecting mode, 1 reflecting file save status, and 1 reflecting git status.

minor keybinding tweaks

  • bind the arrow keys to paging in which-keys (so sue me, I like arrow keys)

some kind of non-utf-8 utility

actually, I really want something that will highlight (a) non utf-8 characters, and (b) characters that look like normal ascii characters but aren’t.

  • this might be ok just for markdown mode. the point is for copy-paste quotes that introduce shit characters that blow up latex

swipe-scrolling on the touchpad like with vim

window management

  • some way to pin a buffer to a window, so that I can close the window and reopen w/ same buffer there.

Markdown enhancements

  • word count in the modeline that just treats markdown punctuation as spaces
  • a nice UI to query a CSL json for citations (built on ivy?)

org enhancements

  • fix the weird thing where these internal lists don’t tab-indent to same spot
  • MORE KEYBINDINGS for stuff I actually use.

inspo

this person also. this setup this person has a million perf tweaks

About

baby tries to migrate off spacemacs with a clean config...


Languages

Language:Emacs Lisp 94.8%Language:Clojure 3.3%Language:Python 1.3%Language:Swift 0.4%Language:JavaScript 0.3%