Skip to content

My personal emacs configuration. This is not a starter kit.

License

Notifications You must be signed in to change notification settings

JungleCandy/ygg-emacs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ygg-Emacs

My personal Emacs configuration

Preamble

This is not a starter kit, but maybe someone will find it useful, just as I have found others’ configuration files useful, in particular, and not exclusively:

Most of the configurations are in this .org file, which is loaded in init.el

Installation

Install Emacs

I use Emacs Plus. On macOS this can be installed through:

brew tap d12frosted/emacs-plus

brew install emacs-plus

Install Spell checking support

brew install hunspell

in ~/Library/Spelling/ download and install the required dictionaries with

get http://cgit.freedesktop.org/libreoffice/dictionaries/plain/en/en_GB.aff

get http://cgit.freedesktop.org/libreoffice/dictionaries/plain/en/en_GB.dic

Running (getenv "LANG") on my system shows that the installed language is en_GB so there is no need to create symlinks to the directory as some web guides have suggested.

Clone the repo

Clone this repo to .emacs.d

git clone https://github.com/JungleCandy/ygg-emacs.git .emacs.d

Install Fonts

I’m using Neotree with icons, this requires M-x all-the-icons-install-fonts to be run.

Licence

GPL v3, obviously

Notes

Doing this in Org-Mode As a better way to be organised. And while I am looking at it I can try and figure out what I know and what I need to know about

  • Flyspell
  • Company
  • abbrev and family
  • Projectile
  • Org Mode

Configuration

Built-Ins

Personal Information

(setq user-full-name "Abizer Nasir"
      user-mail-address "[email protected]"
      user-domain "abizern.dev")  

Server

If I’m running Emacs, I want it to be a server

(require 'server)
(unless (server-running-p)
  (server-start))

Built-in Configuration

;; We don't need a startup message.
(setq inhibit-startup-message t)

;; disable the annoying bell ring
(setq ring-bell-function 'ignore)

;; A suitably wide fill-column
(set-default 'fill-column 140)

;; Show column and line number in the modeline
(setq line-number-mode t)
(setq column-number-mode t)

;; Turn off modes that look ugly.
(mapc
 (lambda (mode)
   (when (fboundp mode)
     (funcall mode -1)))
 '(menu-bar-mode tool-bar-mode scroll-bar-mode horizontal-scroll-bar-mode))


;; more useful frame title, that show either a file or a
;; buffer name (if the buffer isn't visiting a file)
(setq frame-title-format
      '((:eval (if (buffer-file-name)
                   (abbreviate-file-name (buffer-file-name))
                 "%b"))))

;; Tab-bar-mode
(tab-bar-mode 1)
(setq tab-bar-show 1)

;; Always load the newest version of a file, prevents stale compiled elisp code
(setq load-prefer-newer t)

;; Tab indentation is a curse, a historical pestilence.
;; Turn it off and let's never talk about this default again.
(set-default 'indent-tabs-mode nil)

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

;; Automatically save buffers before launching M-x compile and friends,
;; instead of asking you if you want to save.
(setq compilation-ask-about-save nil)

;; Make the selection work like most people expect.
(delete-selection-mode t)
(transient-mark-mode t)

;; Automatically update unmodified buffers whose files have changed.
(global-auto-revert-mode t)

;; We aren't using monospace typewriters anymore
(setq sentence-end-double-space nil)

;; Since ethan-wspace takes care of this for us, we don't need it
(setq mode-require-final-newline nil)
(setq require-final-newline nil)

;; Turn off defadvice warnings during startup
(setq ad-redefinition-action 'accept)

;; use hippie-expand instead of dabbrev
(global-set-key (kbd "M-/") 'hippie-expand)

;; Always indent after a newline
(define-key global-map (kbd "RET") 'newline-and-indent)

;; A quick major mode help with discover-my-major
(define-key 'help-command (kbd "C-m") 'discover-my-major)

;; Align your code in a pretty way.
(global-set-key (kbd "C-x \\") 'align-regexp)

;; Ask for y/n confirmation instead of yes/no
(fset 'yes-or-no-p 'y-or-n-p)

;; Make sure to always use UTF-8
(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)

Themes

Use the Dracula Pro theme

(defun setup-gold-cursor (frame)
  "A gold bar cursor"
  (progn
    (set-cursor-color "gold1")
    (setq-default cursor-type 'bar)))

(add-to-list 'custom-theme-load-path "~/.emacs.d/themes")
(add-hook 'after-make-frame-functions 'setup-gold-cursor t)
(load-theme 'dracula-pro-pro :no-confirm)

Custom storage directories

;; Directory for support files. Create if needed.
(defvar savefile-dir (expand-file-name "savefile" user-emacs-directory)
  "The directory that stores support files.")
(unless (file-exists-p savefile-dir)
  (make-directory savefile-dir))

;; Define where to keep the autoload declarations.
(setq autoload-file (expand-file-name "loaddefs.el" savefile-dir))

;; Define where to keep user-settings, and load them.
(setq custom-file (expand-file-name "custom.el" savefile-dir))
(load custom-file 'noerror)

;; User lisp files. Create if needed.
(defvar ygg-lisp-dir (expand-file-name "lisp" user-emacs-directory)
  "The directory for user lisp files.")
(unless (file-exists-p ygg-lisp-dir)
  (make-directory ygg-lisp-dir))
;; Add the user-lisp directory to the load path.
(add-to-list 'load-path ygg-lisp-dir)

;; store all backup and autosave files in the tmp dir
(setq backup-directory-alist
      `((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
      `((".*" ,temporary-file-directory t)))

Packages

;; Update package metadata if required
(unless package-archive-contents
  (package-refresh-contents))

(unless (package-installed-p 'use-package)
  (package-install 'use-package))

(require 'use-package)

;; For more verbose startup, uncomment the line below
;; (setq use-package-verbose t)  

Configuration

ace-window

Easily move between windows, optimised for Dvorak layout.

C-x oPut up indicators to make moving between windows easier
C-x C-oSwap windows
(use-package ace-window
  :ensure t
  :bind (("C-x o" . ace-window)
         ("C-x C-o" . ace-swap-window))
  :config
  (setq aw-keys '(?a ?o ?e ?u ?i ?d ?h ?t ?n)))  

avy

Quick navigation by word or character

C-;avy-goto-word-1
C-:avy-goto-char
(use-package avy
  :ensure t
  :defer t
  :bind (("C-;" . avy-goto-word-1)
         ("C-:" . avy-goto-char)))

company

All good IDEs have some interactivity

(use-package company
  :ensure t
  :init (add-hook 'after-init-hook #'global-company-mode)
  :commands company-mode
  :config
  ;; Enable company-mode globally.
  (global-company-mode +1)
  ;; Except when you're in term-mode.
  (setq company-global-modes '(not term-mode))
  ;; Give Company a decent default configuration.
  (setq company-minimum-prefix-length 2
        company-selection-wrap-around t
        company-show-numbers t
        company-tooltip-align-annotations t
        company-require-match nil
        company-dabbrev-downcase nil
        company-dabbrev-ignore-case nil)
  ;; Sort completion candidates that already occur in the current
  ;; buffer at the top of the candidate list.
  (setq company-transformers '(company-sort-by-occurrence))
  ;; Show documentation where available for selected completion
  ;; after a short delay.

  (use-package company-quickhelp
    :ensure t
    :config
    (setq company-quickhelp-delay 1)
    (company-quickhelp-mode 1))
  ;; Use C-\ to activate the Company autocompleter.
  ;; We invoke company-try-hard to gather completion candidates from multiple
  ;; sources if the active source isn't being very forthcoming.

  (use-package company-try-hard
    :ensure t
    :commands company-try-hard
    :bind ("C-\\" . company-try-hard)
    :config
    (bind-keys :map company-active-map
               ("C-\\" . company-try-hard)))
  :diminish company-mode)  

crux

Drag some things in from Prelude that look like they could be useful

C-c qOpen the currently visited file with an external program
M-nInsert an empty line above the current line and indent it properly
M-pInsert an empty line and indent it properly
C-c nFix indentation and strip whitespace
C-c eEval a bit of elisp and replace it with the result
C-x p tTranspose the buffers between two windows
C-c DDelete current file and buffer
C-c dDuplicate current line (region)
C-c rRename the current buffer and visited file if any
C-c kKill all but the current buffer
M-jJoin lines
s-kKill whole line
C-<backspace>Kill line backwards
C-c iFix word using iSpall and then save to abbrev
(use-package crux
    :ensure t
    :commands crux-switch-to-previous-buffer
    :bind
    ("C-c o" . crux-open-with)                                      ;; Open the currently visited file with an external program
    ("M-n" . crux-smart-open-line-above)                            ;; Insert an empty line above the current line and indent it properly
    ("M-p" . crux-smart-open-line)                                  ;; Insert empty line and indent it properly
    ("C-c n" . crux-cleanup-buffer-or-region)                       ;; Fix indentation and strip whitespace
    ("C-c e" . crux-eval-and-replace)                               ;; Eval a bit of elisp and replace it with it's result
    ("C-x p t" . crux-transpose-windows)                            ;; Transpose the buffers between two windows
    ("C-c D" . crux-delete-file-and-buffer)                         ;; Delete current file and buffer
    ("C-c d" . crux-duplicate-current-line-or-region)               ;; Duplicate current line (region)
    ("C-c M-d" . crux-duplicate-and-comment-current-line-or-region) ;; Duplicate and comment current line (region)
    ("C-c r" . crux-rename-file-and-buffer)                         ;; Rename the current buffer and visited file if any
    ("C-c k" . crux-kill-other-buffers)                             ;; Kill all but the current buffer
    ("M-j" . crux-top-join-lines)                                   ;; Join lines
    ("s-k" . crux-kill-whole-line)                                  ;; Kill whole line
    ("C-<backspace>" . crux-kill-line-backwards)                    ;; Kill line backwards
    ("C-c i" . crux-ispell-word-then-abbrev))                       ;; Fix word using ispell and then save to abbrev.  

eshell

(use-package eshell
  :ensure t)

eshell-git-prompt

(use-package eshell-git-prompt
  :after shell
  :ensure t)

eshell-syntax-highlighting

(use-package eshell-syntax-highlighting
  :ensure t
  :config
  (eshell-syntax-highlighting-global-mode +1)
  :init
  (defface eshell-syntax-highlighting-invalid-face
    '((t :inherit diff-error))
    "Face used for invalid Eshell commands."
    :group 'eshell-syntax-highlighting))

ethan-wspace

See more at https://github.com/glasserc/ethan-wspace

C-c cto clean up a file
(use-package ethan-wspace
  :ensure t
  :commands
  global-ethan-wspace-mode
  :config
  (global-ethan-wspace-mode 1)
  :bind
  ("C-c c" . ethan-wspace-clean-all)
  :diminish
  ethan-wspace-mode)  

expand-region

Select successively larger logical units. Works really well with multiple-cursors

C-=Select and expand by logical units
M-C-=Contract the region be logical units
(use-package expand-region
  :ensure t)
(global-set-key (kbd "C-=") 'er/expand-region)
(global-set-key (kbd "M-C-=") 'er/contract-region)

f

Better handling of splitting and joining file names and paths

(use-package f
  :ensure t)

flyspell

Spell checking, which I don’t know much about.

(use-package flyspell
  :hook ((text-mode . flyspell-mode)
         (prog-mode . flyspell-prog-mode))
  :config (when (executable-find "hunspell")
            (setq ispell-program-name (executable-find "hunspell"))
            (setq ispell-really-hunspell t)
            (setenv "DICTIONARY" "en_GB")
            (setq ispell-hunspell-dictionary-alist '(("en_GB" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "en_GB") nil utf-8))))
  (setq ispell-dictionary "en_GB"))  

git-gutter-fringe

Mark uncommitted changes in the fringe

(use-package git-gutter-fringe
  :ensure t
  :config
  (global-git-gutter-mode t)
  :diminish git-gutter-mode)  

helm

Better navigation

M-yFirst call open the kill-ring, next call moves to next line
C-x C-mhelm-M-x
s-rShow recent files
C-x C-bReturn the current list of buffers
(use-package helm
  :ensure t
  :config
  (progn
    (helm-mode 1))
  :bind
  (("M-y" . helm-show-kill-ring)
   ("C-x C-m" . helm-M-x)
   ("s-r" . helm-recentf)
   ("C-x C-b" . helm-buffers-list)))  

key-chord

Move like a ninja, if I could ever remember the chords

jjavy-goto-word-1
jlavy-goto-line
jkavy-goto-char
jjcrux-switch-to-previous-buffer
xxhelm-M-x
yybrowse-kill-ring
(use-package key-chord
  :ensure t
  :init
  (progn
    (key-chord-mode 1)
    (key-chord-define-global "jj" 'avy-goto-word-1)
    (key-chord-define-global "jl" 'avy-goto-line)
    (key-chord-define-global "jk" 'avy-goto-char)
    (key-chord-define-global "JJ" 'crux-switch-to-previous-buffer)
    (key-chord-define-global "xx" 'helm-M-x)
    (key-chord-define-global "yy" 'browse-kill-ring)))  

magit

Maybe outdated, but I’ve become used to this over the years

(defadvice magit-status (around magit-fullscreen activate)
  "Activate full screen when using Magit."
  (window-configuration-to-register :magit-fullscreen)
  ad-do-it
  (delete-other-windows))

(defadvice magit-quit-window (around magit-restore-screen activate)
  "Restore previously hidden windows."
  ad-do-it
  (jump-to-register :magit-fullscreen))

(defun magit-quit-session ()
  "Restore the previous window configuration and kill the magit buffer."
  (interactive)
  (kill-buffer)
  (jump-to-register :magit-fullscreen))

;; Use C-x g to open a magit status window for the current directory.
(use-package magit
  :ensure t
  :commands magit-status
  :bind (("C-x g" . magit-status)
         :map magit-status-mode-map
         ("q" . magit-quit-session)))

markdown-mode

Mostly the mode hooks and a couple of keybindings

M-nAdd line below
M-pAdd line above
(use-package markdown-mode
  :ensure t
  :config
  (progn
    (bind-key "M-n" 'open-line-below markdown-mode-map)
    (bind-key "M-p" 'open-line-above markdown-mode-map))
  :mode (("\\.markdown$" . markdown-mode)
         ("\\.md$" . markdown-mode)))

multiple-cursors

Why edit one line when you can work on many

C->mc/mark-next-like-this
C-<mc/mark-previous-like-this
C-c C-cmc/mark-all-like-this
C-S-c C-S-cmc/edit-lines
C-S-c C-S-emc/edit-ends-of-lines
C-S-c C-S-amc/edit-beginnings-of-lines
(use-package multiple-cursors
  :ensure t
  :commands multiple-cursors-mode
  :bind (("C->" . mc/mark-next-like-this)
         ("C-<" . mc/mark-previous-like-this)
         ("C-c C-<" . mc/mark-all-like-this)
         ("C-S-c C-S-c" . mc/edit-lines)
         ("C-S-c C-S-e" . mc/edit-ends-of-lines)
         ("C-S-c C-S-a" . mc/edit-beginnings-of-lines))
  :config
  (setq mc/list-file (expand-file-name ".mc-lists.el" savefile-dir)))  

neotree

<F5>neotree-toggle

Bindings only in Neotree buffer.

n, pnext-line, previos-line
<SPC>, <RET>, <TAB>Open current item if file, Toggle if directory
UGo up a directory
gRefresh
AToggle maximise window
HToggle display hidden files
QRecursively open a directory
C-c C-nCreate file (directory if filename ends with //)
C-c C-dDelete file or directory
C-c C-rRename file or directory
C-c C-cChange the root of the directory
C-c C-pCopy a file or a directory
(use-package neotree
  :ensure t
  :bind ("<f5>" . neotree-toggle)
  :custom
  (neo-theme 'icons)
  (neo-smart-open t)
  (neo-autorefresh t)
  (neo-show-hidden-files t))

(use-package all-the-icons

  :ensure t
  :defer
  :if (display-graphic-p))

(use-package all-the-icons-completion
  :ensure t
  :defer
  :hook (marginalia-mode . #'all-the-icons-completion-marginalia-setup)
  :init
  (all-the-icons-completion-mode))

org-mode

This is where the magic happens!

(use-package org
  :ensure t
  :config
  ;; Stop org-mode from hijacking shift-cursor keys.
  (add-hook 'org-mode-hook (lambda ()
                             (visual-line-mode 1)
                             (define-key org-mode-map (kbd "C-c t") 'yas-next-field))
            (setq org-src-tab-acts-natively t))
  (bind-keys :map org-mode-map
             ("M-j" . org-metaup)
             ("M-k" . org-metadown))
  (setq org-directory "~/Documents/Org")
  (setq org-metadir (concat org-directory "_orgmata/"))
  (setq org-archive-location (concat org-metadir "archive.org::date-tree"))
  (setq org-default-notes-file (concat org-directory "refile.org"))
  (setq org-agenda-files (quote ("~/Documents/Org/")))
  (setq org-startup-indented t)
  (setq org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d)")
                            (sequence "DRAFT(r)" "|" "PUBLISH(p)")))
  (setq org-use-fast-todo-selection t) ;; done with C-c C-t KEY
  (setq org-log-done 'time)
  (setq org-treat-S-cursor-todo-selection-as-state-change nil) ;; Change state with S-left / right. Skip timestamp processing. Handy when just clearing up.


  ;; Fancy bullet rendering.
  (use-package org-bullets
    :ensure t
    :config
    (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))
  ;; Flashcards
  (use-package org-drill
    :ensure t
    :config (progn
              (add-to-list 'org-modules 'org-drill)
              (setq org-drill-add-random-noise-to-intervals-p t)
              (setq org-drill-learn-fraction 0.25)))
  ;; Insert links from clipboard.
  (use-package org-cliplink
    :ensure t
    :config
    (with-eval-after-load "org"
      (define-key org-mode-map (kbd "C-c M-l") 'org-cliplink)))
  (require 'ox-latex)
  (unless (boundp 'org-latex-classes)
    (setq org-latex-classes nil))
  ;; Override standard article classes
  ;; Select this by adding #+LaTeX_CLASS: <class-name> to the org file preamble
  (add-to-list 'org-latex-classes
               '("article"
                 "\\documentclass[a4paper]{scrartcl}
    \\usepackage[utf8]{inputenc}
    \\usepackage{amsmath}
    \\usepackage{amssymb}
    \\usepackage{fullpage}"
                 ("\\section{%s}" . "\\section*{%s}")
                 ("\\subsection{%s}" . "\\subsection*{%s}")
                 ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
                 ("\\paragraph{%s}" . "\\paragraph*{%s}")
                 ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
  (add-to-list 'org-latex-classes
               '("tufte-handout"
                 "\\documentclass[a4paper]{tufte-handout}
    \\usepackage[utf8]{inputenc}
    \\usepackage{amsmath}
    \\usepackage{amssymb}"
                 ("\\section{%s}" . "\\section*{%s}")
                 ("\\subsection{%s}" . "\\subsection*{%s}")
                 ("\\paragraph{%s}" . "\\paragraph*{%s}")
                 ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))))

;; ox-hugo
(use-package ox-hugo
  :ensure t
  :pin melpa
  :after ox)   ;; Org-mode global keys

(global-set-key (kbd "C-c l") #'org-store-link)
(global-set-key (kbd "C-c a") #'org-agenda)
(global-set-key (kbd "C-c c") #'org-capture)

Projectile

Something I need to look into so I can use it better. https://docs.projectile.mx/projectile/index.html

(use-package projectile
  :ensure t
  :init
  (projectile-mode +1)
  :bind (:map projectile-mode-map
              ("s-p" . projectile-command-map)
              ("C-c p" . projectile-command-map)))

(use-package helm-projectile
  :ensure t
  :config (helm-projectile-on))

rainbow-mode

Colourise names of colours in certain modes

(use-package rainbow-mode
  :ensure t
  :config
  (dolist (mode '(css-mode less-css-mode html-mode web-mode))
    (add-hook (intern (concat (symbol-name mode) "-hook"))
              (lambda () (rainbow-mode))))
  :diminish rainbow-mode)  

recentf

Recent File handling

(use-package recentf
  :ensure t
  :init
  (progn
    (setq recentf-save-file (expand-file-name "recentf" savefile-dir))
    (setq recentf-auto-cleanup 'never)
    (recentf-mode 1))
  :config (setq recentf-max-saved-items 100
                recentf-max-menu-items 15))  

savehist

Save history.

(use-package savehist
  :config
  (setq savehist-additional-variables
        ;; search entries
        '(search-ring regexp-search-ring)
        ;; save every minute
        savehist-autosave-interval 60
        ;; keep the home clean
        savehist-file (expand-file-name "savehist" savefile-dir))
  (savehist-mode +1))  

saveplace

Save point position between sessions.

(use-package saveplace
  :ensure t
  :init
  (setq save-place-file (expand-file-name ".places" savefile-dir))
  :config
  (setq-default save-place t))

smartparens

Brackets are really, really important

C-M-fMove forward across one balanced expression
C-M-bMove backward across one balanced expression
C-M-nMove forward out of one level of parentheses
C-M-dMove forward down one level of sexp
C-M-uMove backward out of one level of parentheses
C-M-pMove backward down one level of sexp
C-M-wCopy the following ARG expressions to the kill-ring (sp-copy-sexp)
M-sUnwrap the current list
M-rUnwrap the list and kill everything inside expect the next expression
C-)Slurp the following list into current by moving the closing delimiter
C-}Remove the last sexp in the current list by moving the closing delimiter
C-(Slurp the preceding sexp into the current one my moving the opening delimeter
C-{Barfs backwards
M-SSplit the list or string at point into two
M-JJoin the sexp before and after the point if they are of the same type
C-M-tTranspose the expressions around the point
(use-package smartparens
  :ensure t
  :init
  (progn
    (require 'smartparens-config)
    (smartparens-global-mode t)
    (show-smartparens-global-mode t))
  :config
  (progn
    (add-hook 'prog-mode-hook (lambda () (smartparens-strict-mode t))) ;; If I don't do this, it doesn't turn on properly.
    (sp-local-pair 'emacs-lisp-mode "`" nil :when '(sp-in-string-p))
    (setq sp-highlight-pair-overlay nil)
    (setq sp-highlight-wrap-overlay nil)
    (setq sp-highlight-wrap-tag-overlay nil))
  :bind
  (("C-M-f" . sp-forward-sexp)
   ("C-M-b" . sp-backward-sexp)
   ("C-M-n" . sp-up-sexp)
   ("C-M-d" . sp-down-sexp)
   ("C-M-u" . sp-backward-up-sexp)
   ("C-M-p" . sp-backward-down-sexp)
   ("C-M-w" . sp-copy-sexp)
   ("M-s" . sp-splice-sexp)
   ("M-r" . sp-splice-sexp-killing-around)
   ("C-)" . sp-forward-slurp-sexp)
   ("C-}" . sp-forward-barf-sexp)
   ("C-(" . sp-backward-slurp-sexp)
   ("C-{" . sp-backward-barf-sexp)
   ("M-S" . sp-split-sexp)
   ("M-J" . sp-join-sexp)
   ("C-M-t" . sp-transpose-sexp)))  

super-save

Automatically save files

(use-package super-save
  :ensure t
  :config
  (super-save-mode +1))  

tex

(use-package tex
  :ensure auctex
  :config
  (setq-default TeX-master nil)
  (setq TeX-auto-save t
        TeX-parse-self t
        TeX-PDF-mode t)
  (add-hook 'LaTeX-mode-hook 'visual-line-mode)
  (add-hook 'LaTeX-mode-hook 'flyspell-mode)
  (add-hook 'LaTeX-mode-hook 'LaTeX-math-mode)
  :ensure company-auctex)

toml-mode

(use-package toml-mode
  :ensure t
  :mode ("\\.toml$ . toml-mode")) 

undo-fu

A little simpler than undo tree

C-zUndo
C-S-zRedo
(use-package undo-fu
  :ensure t
  :config
  (global-unset-key (kbd "C-z"))
  (global-set-key (kbd "C-z") 'undo-fu-only-undo)
  (global-set-key (kbd "C-S-z") 'undo-fu-only-redo))  

uniquify

Make buffer titles unique by adding more information, not just another number

(use-package uniquify
  :config (setq uniquify-buffer-name-style 'forward
                uniquify-separator "/"
                uniquify-after-kill-buffer-p t     ;; Rename after killing uniquified
                uniquify-ignore-buffers-re "^\\*"))  

which-key

Show available keybindings after starting to type.

(use-package which-key
  :ensure t
  :config
  (which-key-mode +1)
  :diminish
  which-key-mode)

yaml-mode

(use-package yaml-mode
  :ensure t
  :mode ("\\.yaml$ . yaml-mode"))

yasnippet

(use-package yasnippet
  :ensure t
  :init
  (progn
    (add-hook 'after-save-hook
              (lambda ()
                (when (eql major-mode 'snippet-mode)
                  (yas-reload-all))))
    (setq yas-snippet-dirs (list (f-expand "snippets" user-emacs-directory)))
    (setq yas-indent-line 'auto)
    (yas-global-mode 1))
  :mode ("\\.yasnippet" . snippet-mode))

(use-package helm-c-yasnippet
  :ensure t
  :init
  (setq helm-yas-space-match-any-greedy t)
  (global-set-key (kbd "C-c y") 'helm-yas-complete)
  (yas-global-mode 1))  

zop-to-char

A better version of zap-to-char.

(use-package zop-to-char
  :ensure t
  :bind
  (("M-z" . zop-up-to-char)
   ("M-Z" . zop-to-char)))  

Programming Modes

Configuration

Default spacing
(setq-default c-basic-offset 2
              c-default-style "linux"
              indent-tabs-mode nil
              fill-column 140
              tab-width 2)
editorconfig

Be more explicit about layout

(use-package editorconfig
  :ensure t
  :config (editorconfig-mode +1))
LSP support
(use-package eglot
  :ensure t
  :config
  (add-to-list 'eglot-server-programs '((C++-mode c-mode) "clangd"))
  (add-hook 'c-mode-hook 'eglot-ensure)
  (add-hook 'c++-mode 'eglot-ensure))

;; Used to interface with swift-lsp.
(use-package lsp-mode
  :ensure t
  :commands lsp
  :hook ((swift-mode . lsp)))

;; lsp-mode's UI modules
(use-package lsp-ui
  :ensure t)

Common-lisp

I use SLY not Slime

M-hsly-documentation-lookup
(defun setup-sly()
  (setq inferior-lisp-program "/opt/homebrew/bin/sbcl")
  (use-package sly
    :ensure t
    :config
    (with-eval-after-load 'sly
      `(define-key sly-prefix-map (kbd "M-h") 'sly-documentation-lookup))))

(defun lisp-program-location ()
  "The system dependent location of SBCL. Just macOS at the moment, update from Linux system later."
  "/opt/homebrew/bin/sbcl")

(setup-sly)

Go Mode

Turned off, but I should keep the configuration.

Haskell

Turned off, but I should keep the configuration.

json-mode

C-c <tab>Beautify
(use-package json-mode
  :ensure t
  :commands json-mode
  :config
  (bind-keys :map json-mode-map
             ("C-c <tab>" . json-mode-beautify)))  

Ruby

Mostly Major mode support.

;; Use Ruby syntax for Cartfiles
(add-to-list 'auto-mode-alist '("Cartfile\\'" . ruby-mode))

;; Use Ruby for Fastlane files
(add-to-list 'auto-mode-alist '("Fastfile\\'" . ruby-mode))

;; Use Ruby syntax for Podfiles - You never know, I might actually need to edit them
(add-to-list 'auto-mode-alist '("Podfile\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("\\.podspec\\'" . ruby-mode))  

Swift

;; Locate sourcekit-lsp
(defun find-sourcekit-lsp ()
  (or (executable-find "sourcekit-lsp")
      (and (eq system-type 'darwin)
           (string-trim (shell-command-to-string "xcrun -f sourcekit-lsp")))
      "/home/abizern/swift-6.0.3/usr/bin/sourcekit-lsp"))

;; Swift editing support
(use-package swift-mode
  :ensure t
  :mode "\\.swift\\'"
  :interpreter "swift"
  :hook (swift-mode . (lambda ()
                        (lsp)
                        (setq tab-width 2)
                        (setq swift-mode:basic-offset 2))))

;; sourcekit-lsp support
(use-package lsp-sourcekit
  :ensure t
  :after lsp-mode
  :custom
  (lsp-sourcekit-executable (find-sourcekit-lsp) "Find sourcekit-lsp"))  

web-mode

C-c C-rMark the tag we’re in and it’s pair for renaming
(use-package web-mode
  :ensure t
  :mode (;; Want to use web-mode for HTML, not default html-mode.
         ("\\.html?\\'" . web-mode)
         ;; Add some extensions as per web-mode docs
         ("\\.phtml\\'" . web-mode)
         ("\\.tpl\\.php\\'" . web-mode)
         ("\\.[agj]sp\\'" . web-mode)
         ("\\.erb\\'" . web-mode)
         ("\\.mustache\\'" . web-mode)
         ("\\.djhtml\\'" . web-mode))
  :config
  ;; Highlight element under the cursor.
  (setq-default web-mode-enable-current-element-highlight t)
  ;; Key for renaming tags
  (bind-keys :map web-mode-map
             ("C-c C-r" . 'mc/mark-sgml-tag-pair)))

(defun my-web-mode-hook ()
  "Hooks for web-mode"
  (setq web-mode-markup-indent-offset 2
        web-mode-css-indent-offset 2
        web-mode-code-indent-offset 2))

(add-hook 'web-mode-hook 'my-web-mode-hook) 

Helper Functions

goto-line-with-feedback

M-g M-gShow line numbers temporarily and prompt for the line to move to
(defun goto-line-with-feedback ()
  "Show line numbers temporarily, while prompting for the line number input."
  (interactive)
  (unwind-protect
      (progn
        (display-line-numbers-mode 1)
        (call-interactively 'goto-line))
    (display-line-numbers-mode -1)))

;; Remaps goto-line so that line numbers are turned on only when needed. M-g M-g
(global-set-key [remap goto-line] 'goto-line-with-feedback)  

json-format

Pretty print JSON using the Python helper function

(defun json-format ()
  "Reformats the JSON in the region for humans."
  (interactive)
  (save-excursion
    (shell-command-on-region (mark) (point) "python -m json.tool" (buffer-name) t)))

Custom Date insertion

C-c C-d13/4/2024
C-u C-t C-d2024-04-13
C-u C-u C-d C-dTuesday, April 13, 2024
C-c C-tISO 8601 formatted date/time
;; Insert Date
;; Usage
;; - `C-c C-d` -> 13/04/2024
;; - `C-u C-c C-d` -> 2024-04-13
;; - `C-u C-u C-d C-d` -> Tuesday, April 13, 2024
(defun ygg-insert-date (prefix)
  "Insert the current date. With prefix-argument use ISO format. With two
      prefix arguments, write out the day and month name"
  (interactive "P")
  (let ((format (cond
                 ((not prefix) "%d/%m/%Y")
                 ((equal prefix '(4)) "%F")
                 ((equal prefix '(16)) "%A, %B %d, %Y")))
        (system-time-locale "en_GB"))
    (insert (format-time-string format))))

(defun ygg-insert-iso-date-time ()
  "Insert the current date in ISO format for UTC"
  (interactive)
  (insert (format-time-string "%FT%T%z" nil "UTC")))

(global-set-key (kbd "C-c C-d") 'ygg-insert-date)
(global-set-key (kbd "C-c C-t") 'ygg-insert-iso-date-time)

Xcode Line up/down

M-S-]Move line up
M-S-[Move line down
;; Xcode binding to move line up
(defun ygg/move-line-up ()
  "Move the current line up"
  (interactive)
  (transpose-lines 1)
  (forward-line -2)
  (indent-according-to-mode))

(global-set-key (kbd "M-s-]")
                (lambda ()
                  (interactive)
                  (ygg/move-line-up)))

;; Xcode binding to move line down
(defun ygg/move-line-down ()
  "Move the current line down"
  (interactive)
  (forward-line 1)
  (transpose-lines 1)
  (forward-line -1)
  (indent-according-to-mode))

(global-set-key (kbd "M-s-[")
                (lambda ()
                  (interactive)
                  (ygg/move-line-down)))  

ygg/wrap-with

Wrapper for parentheses

(defun ygg/wrap-with (s)
  "Create a wrapper function for smartparens using S."
  `(lambda (&optional arg)
     (interactive "P")
     (sp-wrap-with-pair ,s)))  

Better Movement

;; Move about more quickly
;; move about in steps of 5 with C-S insteard of just C-
(global-set-key (kbd "C-S-n")
                (lambda ()
                  (interactive)
                  (ignore-errors (forward-line 5))))

(global-set-key (kbd "C-S-p")
                (lambda ()
                  (interactive)
                  (ignore-errors (forward-line -5))))

(global-set-key (kbd "C-S-f")
                (lambda ()
                  (interactive)
                  (ignore-errors (forward-char 5))))

(global-set-key (kbd "C-S-b")
                (lambda ()
                  (interactive)
                  (ignore-errors (backward-char 5))))

 

About

My personal emacs configuration. This is not a starter kit.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published