Skip to content

anschwa/emacs.d

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

78 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Emacs Org Configuration

Description

This configuration is designed for Emacs 28 and above. This file includes everything required to setup my environment.

If starting Emacs for the first time using this configuration, you will need to do the following:

  1. Visit this file and execute M-x org-babel-tangle.
  2. Restart Emacs.

    screenshot.png

Starting Emacs

Exchange startup time for elegance:

;;; init.el
(require 'ob-tangle)
(org-babel-load-file (expand-file-name "readme.org" user-emacs-directory))

Essentials

;; Turn off mouse interface early in startup to avoid momentary display.
(if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
(if (fboundp 'menu-bar-mode) (menu-bar-mode -1))
(if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))

;; No splash screen.
(setq inhibit-startup-message t)

;; No fascists.
(setq initial-scratch-message nil)

;; No alarms.
(setq ring-bell-function 'ignore)

;; Productive default mode.
(setq initial-major-mode 'org-mode)

;; Change cursor.
(setq-default cursor-type 'box)
(blink-cursor-mode -1)

;; When on a tab, make the cursor the tab length…
(setq-default x-stretch-cursor t)

;; But never insert tabs…
(set-default 'indent-tabs-mode nil)

;; Except in Makefiles.
(add-hook 'makefile-mode-hook 'indent-tabs-mode)

;; Keep files clean.
(setq-default require-final-newline t)
(setq-default show-trailing-whitespace t)
(add-hook 'before-save-hook 'whitespace-cleanup)

Housekeeping

;; No backups or auto-save
(setq auto-save-default nil)
(setq make-backup-files nil)

;; Don't write lock-files
(setq create-lockfiles nil)

;; Keep emacs Custom-settings in separate file
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(when (not (file-exists-p custom-file))
  (write-region "" nil custom-file))
(load custom-file)

Better Defaults

;; Line Numbers
(global-display-line-numbers-mode t)

;; Fix empty clipboard error
(setq save-interprogram-paste-before-kill nil)

;; Remove text in active region if inserting text
(delete-selection-mode 1)

;; Don't automatically copy selected text
(setq select-enable-primary nil)

;; Full path in frame title.
(setq frame-title-format '(buffer-file-name "%f" ("%b")))

;; Auto refresh buffers when edits occur outside emacs
(global-auto-revert-mode 1)

;; Also auto refresh Dired, but be quiet about it
(setq global-auto-revert-non-file-buffers t)
(setq auto-revert-verbose nil)

;; Quickly copy/move file in Dired
(setq dired-dwim-target t)

;; Show keystrokes in progress
(setq echo-keystrokes 0.1)

;; Move files to trash when deleting
(setq delete-by-moving-to-trash t)

;; Transparently open compressed files
(auto-compression-mode t)

;; Show matching parens
(setq show-paren-delay 0)
(show-paren-mode 1)

;; Auto-close brackets and double quotes
(electric-pair-mode 1)

;; Don't automatically indent lines
(electric-indent-mode -1)

;; Answering just 'y' or 'n' will do
(defalias 'yes-or-no-p 'y-or-n-p)

;; UTF-8 please
(setq locale-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(prefer-coding-system 'utf-8)

;; Always display line and column numbers
(setq line-number-mode t)
(setq column-number-mode t)

;; Wrap lines at 80 characters wide, not 72
(setq fill-column 80)

;; Smooth Scroll.
(setq mouse-wheel-scroll-amount '(1 ((shift) .1))) ; one line at a time

;; Scroll one line when hitting bottom of window
(setq scroll-conservatively 10000)

;; Navigate sillycased words
(global-subword-mode 1)

;; Word wrap (t is no wrap, nil is wrap)
(setq-default truncate-lines nil)

;; Sentences do not need double spaces to end. Period.
(set-default 'sentence-end-double-space nil)

;; Don't use shift to mark things.
(setq shift-select-mode nil)

;; eval-expression-print-level needs to be set to nil (turned off) so
;; that you can always see what's happening
(setq eval-expression-print-level nil)

;; Allow clipboard from outside emacs
(setq select-enable-clipboard t
      save-interprogram-paste-before-kill t
      apropos-do-all t
      mouse-yank-at-point t)

;; Improve performance of very long lines
(setq-default bidi-display-reordering 'left-to-right)

Package Management

(require 'package)
(package-initialize)

(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/") t)

;; Ensure use-package is installed
(when (not (package-installed-p 'use-package))
  (package-refresh-contents)
  (package-install 'use-package))

(eval-when-compile
  (require 'use-package))

Better Package Defaults

;; Add parts of each file's directory to the buffer name if not unique
(use-package uniquify
  :config
  (setq uniquify-buffer-name-style 'forward))

;; Save point position between sessions
(use-package saveplace
  :config
  (setq-default save-place t)
  (setq save-place-file (expand-file-name "places" user-emacs-directory)))

;; Fido (icomplete now includes fuzzy matching for M-x and other completions)
(use-package icomplete
  :demand t
  :config
  (add-hook 'icomplete-minibuffer-setup-hook
            (lambda () (setq-local max-mini-window-height 10)))
  (fido-vertical-mode 1)
  :bind (:map icomplete-fido-mode-map
   ("RET" . icomplete-fido-ret)
   ("TAB" . icomplete-force-complete)))

;; Recent Files
(use-package recentf
  :config
  (setq recentf-auto-cleanup 'never) ;; prevent issues with Tramp
  (setq recentf-max-saved-items 100)
  (setq recentf-max-menu-items 15)
  (recentf-mode t)

  (defun my/recentf-ido-find-file ()
    "Find a recent file using ido."
    (interactive)
    (let ((file (completing-read "Choose recent file: " recentf-list nil t)))
      (when file
        (find-file file))))

  :bind ("C-x f" . my/recentf-ido-find-file))

Global Keybindings

;; Exiting
;; The mnemonic is C-x REALLY QUIT
(global-set-key (kbd "C-x r q") 'save-buffers-kill-terminal)
(global-set-key (kbd "C-x C-c") 'delete-frame)

;; Dvorak
(global-set-key (kbd "C-t") ctl-x-map)
(global-set-key (kbd "M-t") 'execute-extended-command)

;; Symbol completion
(global-set-key (kbd "M-/") 'hippie-expand)

(setq tab-always-indent 'complete)
(setq hippie-expand-try-functions-list
      '(try-expand-dabbrev
        try-expand-dabbrev-from-kill
        try-expand-dabbrev-all-buffers
        try-complete-file-name
        try-complete-lisp-symbol-partially
        try-complete-lisp-symbol))

;; Window Navigation
(global-set-key (kbd "M-o") 'other-window)

;; Buffer Navigation
(global-set-key (kbd "C-x C-b") 'switch-to-buffer)

;; Cycle Whitespace
(global-set-key (kbd "C-c C-SPC") 'cycle-spacing)

;; Window splitting
(global-set-key (kbd "M-0") 'delete-window)
(global-set-key (kbd "M-1") 'delete-other-windows)
(global-set-key (kbd "M-2") 'split-window-vertically)
(global-set-key (kbd "M-3") 'split-window-horizontally)
(global-set-key (kbd "M-=") 'balance-windows)

;; More parity with readline
(defun my/backward-kill-word (&optional arg)
  "kill active region or one word backward"
  (interactive "p")
  (if (region-active-p)
      (kill-region (region-beginning) (region-end))
    (backward-kill-word arg)))

(global-set-key (kbd "C-h") 'backward-delete-char) ; help is still available with M-x describe-*
(global-set-key (kbd "C-w") 'my/backward-kill-word)

;; Unset keys
(dolist (keys '("<M-up>" "<M-down>" "<s-left>" "<s-right>"
                "s-c" "s-v" "s-x" "s-v" "s-q" "s-s" "s-w"
                "s-a" "s-o" "s-n" "s-p" "s-k" "s-u" "s-m"
                "s-f" "s-z" "s-g" "s-d" "s-," "s-:" "s-e"
                "s-t" "C-z" "C-\\" "C-M-i"))
  (global-unset-key (kbd keys)))

Appearance

Mode Line

;; Remove all minor modes (mode-line-modes)
(setq-default mode-line-format
      '("%e"
        mode-line-front-space
        mode-line-mule-info
        mode-line-client
        mode-line-modified
        mode-line-remote
        mode-line-frame-identification
        mode-line-buffer-identification
        "    "
        mode-line-position
        (vc-mode vc-mode)
        " (" mode-name ") "
        mode-line-misc-info
        mode-line-end-spaces))

;; Add Date
(setq display-time-day-and-date t
      display-time-format "%a %b %d %R"
      display-time-interval 60
      display-time-default-load-average nil)
(display-time)

Theme

Emacs 28.1 now includes the Modus Themes, which were carefully designed to comply with the highest accessibility standard for color contrast and supports nearly all of the popular third-party Emacs packages as well.

However, I like to disable some of the programming related font-faces via customize-face.

(use-package emacs
  :init
  (setq modus-themes-syntax '(faint yellow-comments))
  (setq modus-themes-paren-match '(intense))
  (setq modus-themes-org-blocks 'gray-background)
  :custom-face
  (eglot-highlight-symbol-face ((t :inherit underline)))
  (font-lock-builtin-face ((t (:inherit modus-themes-bold :foreground "nil" :weight bold))))
  (font-lock-constant-face ((t (:inherit modus-themes-bold :foreground "nil" :weight bold))))
  (font-lock-function-name-face ((t (:foreground "nil"))))
  (font-lock-keyword-face ((t (:inherit modus-themes-bold :foreground "nil" :weight bold))))
  (font-lock-negation-char-face ((t (:foreground "nil"))))
  (font-lock-type-face ((t (:foreground "nil"))))
  (font-lock-variable-name-face ((t (:foreground "nil"))))
  :config
  (load-theme 'modus-operandi))

Major Modes

Org

Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system.

(use-package org
  :requires (ob-core org-agenda org-capture ox ox-md ox-html)
  :mode ("\\.org\\'" . org-mode)
  :commands (org-babel-do-load-languages org-demote-subtree org-promote-subtree)
  :bind (:map org-mode-map
         ("<M-right>" . org-demote-subtree)
         ("<M-left>" . org-promote-subtree))
  :config
  (setq org-export-backends '(ascii html icalendar latex odt md))
  (setq org-src-fontify-natively t)
  (setq org-log-done 'time)
  (setq org-html-doctype "html5")
  (setq org-html-html5-fancy t)
  (setq org-export-headline-levels 6)
  (setq org-export-with-smart-quotes t)
  (setq org-adapt-indentation nil)
  (setq org-edit-src-content-indentation 0)

  ;; Custom TODO keywords
  (setq org-todo-keywords
        '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!)" "CANCELED(c@)")))
  (setq org-todo-keyword-faces
        '(("TODO" :foreground "red" :weight bold)
          ("NEXT :foreground "blue :weight bold)
          ("DONE :foreground "forest green :weight bold)
          ("CANCELED" :foreground "forest green" :weight bold)))

  ;; setup org-capture
  ;; `M-x org-capture' to add notes. `C-u M-x org-capture' to visit file
  (setq org-capture-templates
        `(("t" "Tasks" entry (file ,(concat org-directory "/todo.org"))
           "* TODO %?\n %U\n  %i\n  %a")
          ("n" "Notes" entry (file ,(concat org-directory "/notes.org"))
           "* %?\n %U\n %i\n")))

  ;; setup org-agenda
  (setq org-agenda-files (list org-directory))
  (setq org-agenda-window-setup 'current-window)

  ;; Set up babel source-block execution
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((emacs-lisp . t)
     (python . t)
     (haskell . t)
     (C . t)
     (shell . t)))

  ;; Set up latex
  (setq org-export-with-LaTeX-fragments t)
  (setq org-preview-latex-default-process 'imagemagick)

  ;; local variable for keeping track of pdf-process options
  (setq pdf-processp nil)

  ;; Prevent Weird LaTeX class issue
  (unless (boundp 'org-latex-classes)
    (setq org-latex-classes nil))
  (add-to-list 'org-latex-classes
               '("per-file-class"
                 "\\documentclass{article}
                      [NO-DEFAULT-PACKAGES]
                      [EXTRA]")))

;; Other config
(defun toggle-org-latex-pdf-process ()
  "Change org-latex-pdf-process variable.

    Toggle from using latexmk or pdflatex. LaTeX-Mk handles BibTeX,
    but opens a new PDF every-time."
  (interactive)
  (if pdf-processp
      ;; LaTeX-Mk for BibTex
      (progn
        (setq pdf-processp nil)
        (setq org-latex-pdf-process
              '("latexmk -pdflatex='pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f' -gg -pdf -bibtex-cond -f %f"))
        (message "org-latex-pdf-process: latexmk"))

    ;; Plain LaTeX export
    (progn
      (setq pdf-processp t)
      (setq org-latex-pdf-process
            '("xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
      (message "org-latex-pdf-process: xelatex"))))

Include syntax highlighting when exporting Org documents to HTML.

(use-package htmlize
  :ensure t)

C-Family

;; Use One True Brace Style (K&R style indentation)
(setq c-default-style "k&r"
      c-basic-offset 4)

;; Use C-Mode for CUDA
(add-to-list 'auto-mode-alist '("\\.cu\\'" . c-mode))

Ruby

The standard ruby-mode is pretty good on its own. In fact, it is written and maintained by “Matz”, who is the creator of Ruby itself.

However, you can get more linting data by using rubocop, and solargraph is the canonical language server.

gem install rubocop solargraph solargraph-rails
(use-package ruby-mode
  :ensure t
  :config
  (defun my/ruby-mode-hook()
    (setq tab-width 2)
    (setq ruby-align-to-stmt-keywords nil)
    (setq ruby-insert-encoding-magic-comment nil)
    (setq flymake-mode 1)
    (setq eldoc-mode 1))
  :hook ((ruby-mode . my/ruby-mode-hook)))
(use-package rubocop
  :ensure t
  :config
  (add-hook 'ruby-mode-hook #'rubocop-mode))
(use-package rspec-mode
  :ensure t
  :config
  (setq rspec-primary-source-dirs '("app" "lib" "packs"))

  (defun my/rspec-compile()
    (interactive)
    (rspec-compile
     (read-from-minibuffer
      "Rspec: "
      (format "%s:%d" buffer-file-name (line-number-at-pos))))))

Web Mode

  • C-c C-f: folds html tags
  • C-c C-n: moves between the start / end tag
  • C-c C-w: shows problematic white-space
    (use-package web-mode
      :ensure t
      :mode ("\\.html\\'" "\\.php\\'" "\\.vue\\'" "\\.eex\\'" "\\.tmpl\\'")
      :custom-face
      (web-mode-doctype-face ((t (:inherit font-lock-builtin-face))))
      (web-mode-html-attr-name-face ((t :foreground "nil")))
      (web-mode-html-attr-value-face ((t (:inherit font-lock-string-face))))
      (web-mode-html-tag-face ((t :foreground "nil")))
      (web-mode-symbol-face ((t (:weight bold))))
      :config
      (add-to-list 'web-mode-comment-formats '("javascript" . "//"))
      (setq web-mode-markup-indent-offset 2)
      (setq web-mode-css-indent-offset 2)
      (setq web-mode-code-indent-offset 2)
      (setq web-mode-style-padding 0)
      (setq web-mode-script-padding 0)
    
      (defun my/web-mode-hook()
        ;; Do not over-indent method chains
        (add-to-list 'web-mode-indentation-params '("lineup-calls" . nil)))
    
      :hook ((web-mode . my/web-mode-hook)))
        

Emmet

(use-package emmet-mode
  :ensure t
  :commands (emmet-expand-line emmet-expand)
  :bind (:map emmet-mode-keymap
              ("C-j" . emmet-expand-line)
              ("<C-return>" . emmet-expand))
  :config
  (setq emmet-indentation 2)
  (defadvice emmet-preview-accept (after expand-and-fontify activate)
    "Update the font-face after an emmet expantion."
    (font-lock-flush))
  :hook ((sgml-mode . emmet-mode)
         (web-mode . emmet-mode)
         (css-mode . emmet-mode)
         (js-jsx-mode . emmet-mode)))

CSS

(use-package css-mode
  :mode ("\\css\\'" "\\.scss\\'" "\\.sass\\'")
  :config
  (setq css-indent-offset 2))

Javascript

(use-package js
  :config
  (setq js-indent-level 2))
(use-package prettier-js
  :hook ((js-mode . prettier-js-mode)
         (web-mode . prettier-js-mode)))
(use-package add-node-modules-path
  :hook ((js-mode . add-node-modules-path)
         (web-mode . add-node-modules-path)))

Compilation Mode

(add-hook 'compilation-mode-hook (lambda () (setq truncate-lines t)))

Language Server (eglot)

Eglot works primarily with Emacs’ built-in libraries and not with third-party replacements for those facilities.

  • definitions can be found via xref-find-definitions;
  • on-the-fly diagnostics are given by flymake-mode;
  • function signature hints are given by eldoc-mode;
  • completion can be summoned with completion-at-point.
  • projects are discovered via project.el’s API;
(use-package eglot
  :ensure t)

Go

go get -u golang.org/x/tools/gopls
(use-package go-mode
  :ensure t
  :config
  (defun my/go-mode-hook()
    (setq tab-width 2)
    (setq gofmt-args '("-s"))
    (add-hook 'before-save-hook 'gofmt-before-save)
    (setq-local compile-command "go test")
    (eglot-ensure))
  :hook ((go-mode . my/go-mode-hook)))

Magit

Magit is an amazing interface for using git within Emacs.

One of my favorite features is being able to quickly cycle through the history of the file I’m looking at. To do this, execute magit-file-dispatch (C-c M-g) and then use n and p to load the file history into a read-only buffer.

(use-package magit
  :ensure t
  :commands (magit-section-toggle)
  :bind (:map magit-mode-map
              ("<tab>" . magit-section-toggle)))

Ediff

Emacs diff tool. Can be activated from Magit by pressing e on a conflicting file. Use n, p to jump between conflicts and select changes to keep using a, b.

(use-package ediff
  :config
  (setq ediff-split-window-function 'split-window-horizontally)
  (setq ediff-window-setup-function 'ediff-setup-windows-plain))

Bash

(use-package flymake-shellcheck
  :ensure t
  :init
  (add-hook 'sh-mode-hook 'flymake-shellcheck-load))

Dired

(use-package dired
  :config
  (setq dired-dwim-target t)
  (setq dired-listing-switches "-Alpvh") ; ls flags
  :hook ((dired-after-readin . hl-line-mode)))

Minor Modes

Wgrep

Like wdired for rgrep and ag-project.

  • C-c C-p to enable (wgrep-change-to-wgrep-mode)
  • C-c C-c to execute
  • C-c C-k to abort
    (use-package wgrep
      :ensure t
      :config
      (setq wgrep-auto-save-buffer t))
        

Ripgrep

rg.el provides a nice interface on top of rgrep and includes support for wgrep.

Results Buffer:

  • m Open menu
  • e Toggle wgrep
  • t Interpret search string literally
  • r Interpret search string as regexp
  • c Toggle case sensitivity
  • g Rerun search
    (use-package rg
      :ensure t
      :config
      (rg-define-search my/rg-project
        "Search for any files in project or current directory"
        :query ask
        :format literal
        :confirm prefix
        :files "everything"
        :flags ("--hidden -g !.git")
        :dir (if (vc-root-dir)
                 (vc-root-dir)
               default-directory))
      :bind
      ("M-SPC" . my/rg-project))
        

Rainbow Mode

rainbow-mode highlights color codes in a given buffer.

(use-package rainbow-mode
  :ensure t
  :hook ((web-mode . rainbow-mode)
         (css-mode . rainbow-mode)))

Flyspell

Enable spell-checking in Emacs using Aspell

(use-package flyspell
  :ensure t
  :config
  (setq flyspell-issue-welcome-flag nil)
  (setq flyspell-issue-message-flag nil)
  (setq flyspell-mark-duplications-flag nil)
  (setq-default ispell-program-name "aspell")
  (setq-default ispell-list-command "list")
  (define-key flyspell-mouse-map [down-mouse-3] 'flyspell-correct-word)
  (define-key flyspell-mouse-map [mouse-3] 'undefined)
  :hook ((text-mode . flyspell-mode)
         (org-mode . flyspell-mode)
         (prog-mode . flyspell-prog-mode)))

Helpful Default Keybindings

C-. corrects word at point. C-,​ to jump to next misspelled word.

Expand Region

Expand-region can make selections based on semantic units / delimiters like quotes, parens, or markup tags.

(use-package expand-region
  :ensure t
  :commands (er/expand-region)
  :bind ("C-=" . er/expand-region))

Skeleton Mode

Skeleton mode provides a way to define elisp functions that evaluate into dynamic / static templates.

;; Global
(defun insert-date (str)
  "Insert current date in ISO 8601.
    Typing 'v' will insert the current date verbosely.
    Typing 't' will append the time in H:M:S to either format."
  (interactive "sType (v) for verbose date | (t) for time: ")
  (if (string-match-p "v" str)
      (insert (format-time-string "%B %e, %Y"))
    (insert (format-time-string "%Y-%m-%d")))
  (when (string-match-p "t" str)
    (insert (format-time-string " %T"))))

(define-skeleton insert-iso-date-skeleton
  "Skeleton wrapper for INSERT-DATE"
  "ISO Date"
  '(insert-date ""))

(define-skeleton insert-verbose-date-skeleton
  "Skeleton wrapper for INSERT-DATE"
  "Verbose Date"
  '(insert-date "v"))

;; Org
(define-skeleton org-skeleton-header
  "Insert document headers."
  "Title: "
  "#+TITLE: " str | (buffer-name) "\n"
  "#+AUTHOR: " (user-full-name) "\n"
  "#+DATE: " (insert-date "v") "\n"
  "#+OPTIONS: ':true *:true toc:nil num:nil ^:nil\n" _)

(define-skeleton org-skeleton-latex-header
  "Insert document headers and essential LaTeX header options."
  "options"
  '(org-skeleton-header)
  "\n#+LaTeX_HEADER: \\renewcommand{\\thesection}{\\hspace*{-1.0em}}\n"
  "#+LaTeX_HEADER: \\renewcommand{\\thesubsection}{\\hspace*{-1.0em}}\n"
  "#+LaTeX_HEADER: \\setlength{\\parindent}{0pt}\n"
  "#+LaTeX_HEADER: \\usepackage[margin=1in]{geometry}\n" _)

;; LaTeX
(define-skeleton latex-skeleton-begin
  "Insert a LaTeX BEGIN block."
  "Block type: "
  "\\begin{" str | "align*" "}\n" _ "\n\\end{" str | "align*" "}\n")

;; BibTeX
(defun bibtex-insert-citation (str)
  "Insert a BibTeX citation.
  Begin by inserting the citation type, then call
  BIBTEX-SKELETON-CITATION to prompt for a label and insert the rest."
  (interactive "s(a)rticle | (b)ook | (c)ollection | (w)ebsite: ")
  (let ((type))
    (cond ((string-match-p "^a\\|rticle" str)
           (setq type "article"))
          ((string-match-p "^b\\|ook" str)
           (setq type "book"))
          ((string-match-p "^c\\|ollection" str)
           (setq type "incollection"))
          ((string-match-p "^w\\|ebsite" str)
           (setq type "misc")))
    (insert "@"type"{"))
  (bibtex-skeleton-citation))

(define-skeleton bibtex-skeleton-citation
  "Insert the contents of a BibTeX citation starting with the label."
  "Label: "
  str | "label" ",\n"
  >"author     = \"\",\n"
  >"title      = \"\",\n"
  >"%journal   = \"\",\n"
  >"%booktitle = \"\",\n"
  >"%publisher = \"\",\n"
  >"%editor    = \"\",\n"
  >"%volume    = \"\",\n"
  >"%number    = \"\",\n"
  >"%series    = \"\",\n"
  >"%edition   = \"\",\n"
  >"%address   = \"\",\n"
  >"%type      = \"\",\n"
  >"%chapter   = \"\",\n"
  >"%pages     = \"\",\n"
  >"%year      = \"\",\n"
  >"%month     = \"\",\n"
  >"%url       = \"\",\n"
  >"note       = \"Accessed " '(insert-date "t") "\",\n"
  "},\n" _
  )

(define-skeleton bibtex-skeleton-insert-citation
  "Skeleton wrapper for BIBTEX-INSERT-CITATION"
  "(a)rticle | (b)ook | (c)ollection | (w)ebsite: "
  "(bibtex-insert-citation \"" str "\")"_)

;; C
(define-skeleton c-skeleton-hello
  "Inserts a simple 'hello-world' program in C."
  nil
  "#include<stdio.h>\n\n"
  "int main (int argc, char *argv[]) {\n"
  _  >"printf(\"%s\", \"Hello world.\\n\");\n"
  >"return 0;\n"
  "}\n")

;; Go
(define-skeleton go-err-check
  "Go error check boilerplate"
  nil
  "if err != nil {\n"
  > _"\n"
  "}\n")

(define-skeleton go-append
  "go append() boilerplate"
  nil
  '(setq v1 (skeleton-read "var? "))
  > v1 " = append(" v1 ", " _ ")")

(define-skeleton go-test-case
  "go t.Run boilerplate"
  nil
  "t.Run(\""_"\", func(t *testing.T) {\n"
  > "\n"
  "})\n")

;; JavaScript
(define-skeleton js-skeleton-jest
  "Inserts a test block for jest."
  nil
  _"('', () => {\n"
  >"\n"
  "});\n")

(define-skeleton js-skeleton-log
  "Inserts console.log()"
  nil
  "console.log("_")"\n)

;; Ruby
(define-skeleton ruby-skeleton-rspec
  "Inserts a test block for rspec"
  nil
  "it \""_"\" do\n\n"
  "end\n")

Abbrev Mode

Abbrev mode is a built-in tool that expands abbreviations (or evaluates elisp). Combining an abbrev expansion with a skeleton template is very powerful. Expansions can be either global or local to a specific major mode.

;; enable abbrev for all buffers
(use-package abbrev
  :init
  (setq-default abbrev-mode t))

;; Abbrev Tables
(define-abbrev-table 'global-abbrev-table
  '(
    ("8date" "" insert-iso-date-skeleton 0)
    ("8today" "" insert-verbose-date-skeleton 0)
    ))

(define-abbrev-table 'org-mode-abbrev-table
  '(
    ("8header" "" org-skeleton-header 0)
    ("8lheader" "" org-skeleton-latex-header 0)
    ("8begin" "" latex-skeleton-begin 0)
    ))

(define-abbrev-table 'bibtex-mode-abbrev-table
  '(
    ("8cite" "" bibtex-skeleton-insert-citation 0)
    ))

(define-abbrev-table 'c-mode-abbrev-table
  '(
    ("8hello" "" c-skeleton-hello 0)
    ))

(define-abbrev-table 'go-mode-abbrev-table
  '(
    ("8err" "" go-err-check 0)
    ("8append" "" go-append 0)
    ("8test" "" go-test-case 0)
    ))

(define-abbrev-table 'js-mode-abbrev-table
  '(
    ("8jest" "" js-skeleton-jest 0)
    ("8log" "" js-skeleton-log 0)
    ))

(define-abbrev-table 'web-mode-abbrev-table
  '(
    ("8log" "" js-skeleton-log 0)
    ))

(define-abbrev-table 'ruby-mode-abbrev-table
  '(
    ("8it" "" ruby-skeleton-rspec)
    ))

;; stop asking whether to save newly added abbrev when quitting emacs
(setq save-abbrevs nil)

Git Link

git-link will open your web browser to a specific line or region of a file under source control.

(use-package git-link
  :ensure t
  :config
  (setq git-link-open-in-browser t))

Custom Functions

Reload current file without confirmation

(defun my/reload-buffer ()
  (interactive)
  (revert-buffer t t))

Create new scratch buffer

(defun my/create-scratch-buffer nil
  "Create a new scratch buffer to work in."
  (interactive)
  (let ((n 0)
        (bufname nil))
    (while (progn
             (setq bufname (if (= n 0) "*scratch*" (format "*scratch%d" n)))
             (setq n (1+ n))
             (get-buffer bufname)))
    (switch-to-buffer (get-buffer-create bufname))
    (org-mode)))

Rename Buffer & File

(defun my/rename-current-buffer-file ()
  "Renames current buffer and file it is visiting."
  (interactive)
  (let ((name (buffer-name))
        (filename (buffer-file-name)))
    (if (not (and filename (file-exists-p filename)))
        (error "Buffer '%s' is not visiting a file!" name)
      (let ((new-name (read-file-name "New name: " filename)))
        (if (get-buffer new-name)
            (error "A buffer named '%s' already exists!" new-name)
          (rename-file filename new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil)
          (message "File '%s' successfully renamed to '%s'"
                   name (file-name-nondirectory new-name)))))))

Delete Buffer & File

(defun my/delete-current-buffer-file ()
  "Removes file connected to current buffer and kills buffer."
  (interactive)
  (let ((filename (buffer-file-name))
        (buffer (current-buffer))
        (name (buffer-name)))
    (if (not (and filename (file-exists-p filename)))
        (kill-buffer buffer)
      (when (yes-or-no-p "Are you sure you want to remove this file? ")
        (delete-file filename)
        (kill-buffer buffer)
        (message "File '%s' successfully removed" filename)))))

Remove Secondary Selection

(defun my/unset-secondary-selection ()
  (interactive)
  (delete-overlay mouse-secondary-overlay))

ANSI Color Codes

(use-package ansi-color
  :config
  (defun my/ansi-color (&optional beg end)
    "Interpret ANSI color esacape sequence by colorifying content. Operate on selected region or whole buffer."
    (interactive
     (if (use-region-p)
         (list (region-beginning) (region-end))
       (list (point-min) (point-max))))
    (let ((inhibit-read-only t))
      (ansi-color-apply-on-region beg end))))

Miscellaneous

macOS

;; Are we on a Mac?
(when (equal system-type 'darwin)
  (use-package exec-path-from-shell
    :ensure t
    :init
    (menu-bar-mode 1)

    ;; Set modifier keys
    (setq mac-command-modifier 'super)
    (setq mac-option-modifier 'meta)
    (setq mac-control-modifier 'control)
    (setq ns-function-modifier 'hyper)

    ;; Use right option for spacial characters.
    (setq mac-right-option-modifier 'none)

    (exec-path-from-shell-initialize)
    (setq-default ispell-program-name "/usr/local/bin/aspell")))

Server / Client

(server-start)

About

My complete Emacs configuration.

Resources

License

Stars

Watchers

Forks

Packages

No packages published