SkillAgentSearch skills...

Emacs.d

My life is dope and I have dope emacs configs

Install / Use

/learn @arecker/Emacs.d
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

#+TITLE: Emacs Configuration #+AUTHOR: Alex Recker #+OPTIONS: num:nil #+PROPERTY: header-args :results silent

  • Introduction

This is my Emacs configuration. Before you even open Emacs, clone this repo in your home directory like this:

#+begin_src bash git clone git@github.com:arecker/emacs.d.git ~/.emacs.d #+end_src

So where is the config? The document you are reading /is/ the config. [[https://orgmode.org/worg/org-contrib/babel/][Org Babel]], a native feature of Emacs that can run code snippets embedded in rich text documents, spurred a fad in the Emacs community where users define their personal configs in README documents like this one.

In that spirit, I tried to contain my actual lisp code in this document, save for one function that you need in =init.el= to kick off the process.

#+begin_example (defun recker/load-config () "Tangle configuration and load it." (let ((config (concat (file-name-as-directory user-emacs-directory) "README.org"))) (if (file-exists-p config) (org-babel-load-file config) (warn (concat config " not found - not loading")))))

(recker/load-config) #+end_example

From here on, all lisp code snippets with syntax highlighting are run on startup in the order they appear.

One more note before we get going. You are free to use this as a starting place for your own configuration. All of my custom functions begin with the =recker/= prefix. To change it, just perform a string replace on =(defun recker/= within this document. Beyond that, just update these global variables with your own info.

#+begin_src emacs-lisp (setq user-full-name "Alex Recker") (setq user-mail-address "alex@reckerfamily.com") (setq recker/work-mail-address "arecker@zendesk.com") #+end_src

  • Packages

First, we setup the Emacs package manager. This occurs at the top of the file so we can install packages as we need them.

The Emacs package manager does a nice job. With the help of John Wiegley's [[https://github.com/jwiegley/use-package][use-package]], we can simultaneously declare a package we need and configure the package /after/ it installs and loads.

As far as package maintenance, I sometimes run =M-x package-list-packages= to bring up the packages screen. You can press =U= then =x= at this screen to pull down any updates that are ready, and it's also a good idea to restart Emacs to make sure everything is still working.

#+begin_src emacs-lisp (require 'package)

(defun recker/configure-packages () "Set up the package manager."

;; set and load custom file first (this is gitignored)
(setq custom-file (concat user-emacs-directory "custom.el"))
(if (file-exists-p custom-file) (load custom-file)
  (warn "couldn't find custom file %s" custom-file))

;; set the repo URLs
(setq package-archives '(("gnu" . "http://elpa.gnu.org/packages/")
                         ("melpa" . "https://melpa.org/packages/")
                         ("nongnu" . "https://elpa.nongnu.org/nongnu/")))

;; initialize the package manager
(package-initialize)

;; install use-package
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package)))

(recker/configure-packages) #+end_src

While we are still at the top, use this package to make sure Emacs is using the same PATH as our system.

#+begin_src emacs-lisp (use-package exec-path-from-shell :ensure t :config (exec-path-from-shell-initialize)) #+end_src

  • Application

If you're using Emacs through a CLI, I'd recommend you close it out and download the real thing instead (if you're running a mac, [[https://emacsformacosx.com/][Emacs for Mac OS X]] is great no-frills package). Flipping between emacs and the terminal is still fine, though. Especially since with this config, running the command =emacsclient= will connect to the running Emacs process seamlessly. You can even export =EDITOR=emacsclient= in your environment so other tools can get on the same page.

#+begin_src emacs-lisp (defun recker/configure-application ()

;; prompt when quitting (protects from fat fingers)
(setq-default confirm-kill-emacs #'yes-or-no-p)

;; start the server
(server-start))

(recker/configure-application) #+end_src

  • Appearance

Default Emacs gets a lot of crap for its "ugly" UI. I find it cozy and nostalgic. In an effort to maintain that unmistakable aesthetic, I make just a few modest tweaks to the appearance.

#+begin_src emacs-lisp (defun recker/configure-appearance () "Configure the Emacs UI."

;; Suppress widgets
(menu-bar-mode 0)
(tool-bar-mode 0)
(scroll-bar-mode 0)

;; Set font
(when (string= system-type "darwin")
  (set-frame-font "Monaco 18" nil t))
(when (string= system-type "gnu/linux")
  (set-frame-font "Noto Sans Mono 14" nil t))

;; Uncomment this for full screen by default
;; (unless (eq (frame-parameter (selected-frame) 'fullscreen) 'maximized)
;;   (toggle-frame-maximized))

;; Use this package to hide minor modes.  I like to know which major
;; mode I'm editing, but the minor mode list gets a little too
;; cluttered trying to list all the plugins I have running.
(unless (bound-and-true-p rich-minority-mode) ;it breaks if it runs twice?
  (use-package rich-minority
    :ensure t
    :init (rich-minority-mode 't)
    :config (setq rm-blacklist ""))))

(recker/configure-appearance) #+end_src

  • Text

Automatically clean-up whitespace on save. Trailing whitespace is annoying, and it shouldn't be there in the first place. Also, don't insert tabs unless the major mode really wants to (golang, for example, will do its own thing).

#+begin_src emacs-lisp (add-hook 'before-save-hook 'whitespace-cleanup) (setq-default indent-tabs-mode nil) #+end_src

Bind the build in function =replace-string= to =C-c r=. By default, delete the selected text when you hit "backspace". Also, use =upcase-region= without Emacs bothering you about some nuance that I've never bothered to read closely - the function works just fine for me.

#+begin_src emacs-lisp (global-set-key (kbd "C-c r") 'replace-string) (setq delete-selection-mode 't) (put 'upcase-region 'disabled nil) #+end_src

Bind =C-c l= to the sort lines function. Sorry if this breaks some other workflow I don't yet know about, but for some reason I find myself alphabetizing strings often enough to like this here.

#+begin_src emacs-lisp (global-set-key (kbd "C-c l") #'sort-lines) #+end_src

Bind the handy =expand-region= tool to =C-==. This tool can highlight incrementally larger portions of text like quotes, parentheses, and function definitions.

#+begin_src emacs-lisp (use-package expand-region :ensure t :bind (("C-=" . 'er/expand-region))) #+end_src

Use yasnippet for managing snippets of text. To create a new snippet, run =M-x yas-new-snippet=. This will open a buffer where, [[https://joaotavora.github.io/yasnippet/snippet-development.html][following some simple syntax rules]], you can create dynamic snippets for any editing mode in Emacs. These are saved within the =snippets/= directory of your emacs configuration.

#+begin_src emacs-lisp (use-package yasnippet :ensure t :init (yas-global-mode)) #+end_src

Employ spell checking. Just make sure the =ispell= tool is installed. You can keep your own list of exceptions in =~/.ispell_words= and Emacs is smart enough to add to this when you ask for it.

#+begin_src emacs-lisp (use-package flyspell :config (setq ispell-program-name (executable-find "ispell")) :init (add-hook 'text-mode-hook #'(lambda () (flyspell-mode 1)))) #+end_src

  • Movement

The [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Buffers.html][buffer]] would have to be the most common form of transportation in the Emacs world. Suppressing the more boisterous default splash screen, I've made the =scratch= buffer my home. With these configs, I've made it so that this buffer can never be deleted. I wrote a good amount of custom code to print output from the infamous =fortune= command (or another command if you want) on every launch. It's also a great place to quickly test lisp expressions or paste random text.

#+begin_src emacs-lisp ;; don't show the splash screen (setq inhibit-splash-screen 't)

;; never kill the scratch buffer (defun recker/not-scratch-p () "Return NIL if the current buffer is the scratch buffer." (not (equal (buffer-name (current-buffer)) "scratch")))

(add-hook 'kill-buffer-query-functions 'recker/not-scratch-p)

;; display the output of "fortune" as the scratch message (setq recker/scratch-message-command "fortune --wrap 72 --comment ';; '")

(defun recker/scratch-message () "Return a scratch message from fortune-blog." (concat "\n" (recker/scratch-lisp-comment (format-time-string "%A, %B %-d %Y")) "\n\n" (shell-command-to-string recker/scratch-message-command)))

(defun recker/scratch-lisp-comment (text) "Turn text into a lisp comment." (with-temp-buffer (insert text) (let ((comment-start ";; ")) (comment-region (point-min) (point-max))) (concat "\n" (buffer-string) "\n") (buffer-string)))

(defun recker/refresh-scratch-buffer () "Redraw the scratch buffer." (interactive) (save-excursion (switch-to-buffer "scratch") (erase-buffer) (insert (recker/scratch-message))))

(setq initial-scratch-message (recker/scratch-message)) #+end_src

Where =C-x p= deletes the current buffer, I added my own function that deletes /all/ buffers which you can call by =C-x P=. Just like my browser tabs, sometimes I get a little overwhelmed and I need a clean slate to focus.

#+begin_src emacs-lisp (global-set-key (kbd "C-x k") 'kill-current-buffer)

(defun recker/purge-buffers () "Delete all buffers, except for scratch." (int

Related Skills

View on GitHub
GitHub Stars26
CategoryDevelopment
Updated4d ago
Forks1

Languages

YASnippet

Security Score

75/100

Audited on Mar 20, 2026

No findings