My personal Emacs configuration
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:
- Prelude
- rajeep/emacs
- Magnars/.emacs.d
- ohai-emacs
- technomancy/better-defaults
- Sacha Chua’s .emacs.d
- Bozhidar Batsov’s .emacs.d
- gapar/.emacs.d
Most of the configurations are in this .org file, which is loaded in init.el
I use Emacs Plus. On macOS this can be installed through:
brew tap d12frosted/emacs-plus
brew install emacs-plus
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 this repo to .emacs.d
git clone https://github.com/JungleCandy/ygg-emacs.git .emacs.d
I’m using Neotree with icons, this requires M-x all-the-icons-install-fonts
to be run.
GPL v3, obviously
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
(setq user-full-name "Abizer Nasir"
user-mail-address "[email protected]"
user-domain "abizern.dev")
If I’m running Emacs, I want it to be a server
(require 'server)
(unless (server-running-p)
(server-start))
;; 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)
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)
;; 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)))
;; 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)
Easily move between windows, optimised for Dvorak layout.
C-x o | Put up indicators to make moving between windows easier |
C-x C-o | Swap 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)))
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)))
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)
Drag some things in from Prelude that look like they could be useful
C-c q | Open the currently visited file with an external program |
M-n | Insert an empty line above the current line and indent it properly |
M-p | Insert an empty line and indent it properly |
C-c n | Fix indentation and strip whitespace |
C-c e | Eval a bit of elisp and replace it with the result |
C-x p t | Transpose the buffers between two windows |
C-c D | Delete current file and buffer |
C-c d | Duplicate current line (region) |
C-c r | Rename the current buffer and visited file if any |
C-c k | Kill all but the current buffer |
M-j | Join lines |
s-k | Kill whole line |
C-<backspace> | Kill line backwards |
C-c i | Fix 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.
(use-package eshell
:ensure t)
(use-package eshell-git-prompt
:after shell
:ensure t)
(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))
See more at https://github.com/glasserc/ethan-wspace
C-c c | to 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)
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)
Better handling of splitting and joining file names and paths
(use-package f
:ensure t)
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"))
Mark uncommitted changes in the fringe
(use-package git-gutter-fringe
:ensure t
:config
(global-git-gutter-mode t)
:diminish git-gutter-mode)
Better navigation
M-y | First call open the kill-ring, next call moves to next line |
C-x C-m | helm-M-x |
s-r | Show recent files |
C-x C-b | Return 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)))
Move like a ninja, if I could ever remember the chords
jj | avy-goto-word-1 |
jl | avy-goto-line |
jk | avy-goto-char |
jj | crux-switch-to-previous-buffer |
xx | helm-M-x |
yy | browse-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)))
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)))
Mostly the mode hooks and a couple of keybindings
M-n | Add line below |
M-p | Add 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)))
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-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 |
(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)))
<F5> | neotree-toggle |
Bindings only in Neotree buffer.
n, p | next-line, previos-line |
<SPC>, <RET>, <TAB> | Open current item if file, Toggle if directory |
U | Go up a directory |
g | Refresh |
A | Toggle maximise window |
H | Toggle display hidden files |
Q | Recursively open a directory |
C-c C-n | Create file (directory if filename ends with //) |
C-c C-d | Delete file or directory |
C-c C-r | Rename file or directory |
C-c C-c | Change the root of the directory |
C-c C-p | Copy 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))
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)
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))
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)
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))
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))
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))
Brackets are really, really important
C-M-f | Move forward across one balanced expression |
C-M-b | Move backward across one balanced expression |
C-M-n | Move forward out of one level of parentheses |
C-M-d | Move forward down one level of sexp |
C-M-u | Move backward out of one level of parentheses |
C-M-p | Move backward down one level of sexp |
C-M-w | Copy the following ARG expressions to the kill-ring (sp-copy-sexp) |
M-s | Unwrap the current list |
M-r | Unwrap 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-S | Split the list or string at point into two |
M-J | Join the sexp before and after the point if they are of the same type |
C-M-t | Transpose 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)))
Automatically save files
(use-package super-save
:ensure t
:config
(super-save-mode +1))
(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)
(use-package toml-mode
:ensure t
:mode ("\\.toml$ . toml-mode"))
A little simpler than undo tree
C-z | Undo |
C-S-z | Redo |
(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))
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 "^\\*"))
Show available keybindings after starting to type.
(use-package which-key
:ensure t
:config
(which-key-mode +1)
:diminish
which-key-mode)
(use-package yaml-mode
:ensure t
:mode ("\\.yaml$ . yaml-mode"))
(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))
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)))
(setq-default c-basic-offset 2
c-default-style "linux"
indent-tabs-mode nil
fill-column 140
tab-width 2)
Be more explicit about layout
(use-package editorconfig
:ensure t
:config (editorconfig-mode +1))
(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)
I use SLY not Slime
M-h | sly-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)
Turned off, but I should keep the configuration.
Turned off, but I should keep the configuration.
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)))
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))
;; 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"))
C-c C-r | Mark 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)
M-g M-g | Show 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)
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)))
C-c C-d | 13/4/2024 |
C-u C-t C-d | 2024-04-13 |
C-u C-u C-d C-d | Tuesday, April 13, 2024 |
C-c C-t | ISO 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)
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)))
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)))
;; 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))))