#+TITLE: yuzu-emacs #+AUTHOR: yuzu-eva #+STARTUP: overview #+LANGUAGE: en #+OPTIONS: num:nil [[./yuzu-emacs.png]] * Introduction yuzu-emacs is my personal configuration for emacs. It is a very basic configuration, which is heavily inspired by [[https://github.com/snackon/Witchmacs][Witchmacs]], the main difference is that this configuration uses standard emacs keybindings, no evil mode at all. Mainly used for programming in C and writing documents in org-mode. * Terminal ** Setting default shell to zsh #+begin_src emacs-lisp (defvar my-term-shell "/bin/zsh") (defadvice ansi-term (before force-bash) (interactive (list my-term-shell))) (ad-activate 'ansi-term) (global-set-key (kbd "") 'ansi-term) #+end_src * QoL section Some quality-of-life improvements ** Disable annoyances *** Disable default startup screen #+begin_src emacs-lisp (setq inhibit-startup-message t) #+end_src *** Disable most GUI elements #+begin_src emacs-lisp (tool-bar-mode -1) (menu-bar-mode -1) (scroll-bar-mode -1) #+end_src *** Change directory where backups are saved #+begin_src emacs-lisp (setq backup-directory-alist '(("." . "~/.emacs.d/emacs_saves"))) #+end_src *** Disable ring-bell #+begin_src emacs-lisp (setq ring-bell-function 'ignore) #+end_src *** Disable fringes #+begin_src emacs-lisp (set-fringe-mode 0) #+end_src *** Use bash for TRAMP #+begin_src emacs-lisp (eval-after-load 'tramp '(setenv "SHELL" "/bin/bash")) #+end_src ** Visual improvements *** Enable line number Certain modes will break with line-numbers-mode (e.g. ansi-term) so I'm only enabling it on some major modes rather than globally #+begin_src emacs-lisp (add-hook 'prog-mode-hook 'display-line-numbers-mode) (add-hook 'text-mode-hook 'display-line-numbers-mode) #+end_src *** Enable column number #+begin_src emacs-lisp (column-number-mode 1) #+end_src *** Enable prettify symbols #+begin_src emacs-lisp (global-prettify-symbols-mode t) #+end_src *** Enable rainbow-delimiters in all programming modes #+begin_src emacs-lisp (set-face-foreground 'rainbow-delimiters-unmatched-face "red") (set-face-foreground 'rainbow-delimiters-depth-1-face "white") (set-face-foreground 'rainbow-delimiters-depth-2-face "deep sky blue") (set-face-foreground 'rainbow-delimiters-depth-3-face "magenta") (set-face-foreground 'rainbow-delimiters-depth-4-face "spring green") (set-face-foreground 'rainbow-delimiters-depth-5-face "chocolate") (set-face-foreground 'rainbow-delimiters-depth-6-face "dark gray") (set-face-foreground 'rainbow-delimiters-depth-7-face "yellow") (set-face-foreground 'rainbow-delimiters-depth-8-face "tomato2") (set-face-foreground 'rainbow-delimiters-depth-9-face "LightGoldenrod1") (add-hook 'prog-mode-hook 'rainbow-delimiters-mode) #+end_src *** Show parent parentheses #+begin_src emacs-lisp (show-paren-mode 1) #+end_src *** Highlight current line #+begin_src emacs-lisp (global-hl-line-mode t) #+end_src *** Enable conservative scrolling #+begin_src emacs-lisp (setq scroll-conservatively 100) #+end_src *** Set font #+begin_src emacs-lisp (set-face-attribute 'default nil :font "Hack Nerd Font" :height 110) #+end_src *** Set initial buffer to dashboard #+begin_src emacs-lisp (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))) #+end_src ** Ease of use *** Set default directory #+begin_src emacs-lisp (setq default-directory "~/") #+end_src *** Enable copy-pasting outside of emacs #+begin_src emacs-lisp (setq x-select-enable-clipboard t) #+end_src *** Enable pair-matching #+begin_src emacs-lisp (electric-pair-mode t) #+end_src *** Enable subword-mode #+begin_src emacs-lisp (global-subword-mode 1) #+end_src *** Indentation #+begin_src emacs-lisp (setq-default tab-width 4) (setq-default standard-indent 4) (setq c-basic-offset tab-width) (setq-default electric-indent-inhibit t) (setq-default indent-tabs-mode t) (setq backward-delete-char-untabify-method 'nil) #+end_src *** Change yes/no prompt to just y/n #+begin_src emacs-lisp (defalias 'yes-or-no-p 'y-or-n-p) #+end_src *** Enable ido mode #+begin_src emacs-lisp (setq ido-enable-flex-matching nil) (setq ido-create-new-buffer 'always) (setq ido-everywhere t) (setq ido-vertical-define-keys 'C-n-and-C-p-only) (ido-mode 1) #+end_src *** Change default buffer-list I hate the default buffer list. I'm using ido-switch-buffer on "C-x C-b" and ibuffer on "C-x b" #+begin_src emacs-lisp (global-set-key (kbd "C-x C-b") 'ido-switch-buffer) (global-set-key (kbd "C-x b") 'ibuffer) #+end_src *** Display PDFs to the right instead of below current window #+begin_src emacs-lisp (add-to-list 'display-buffer-alist '("\\.pdf$" . (display-buffer-pop-up-window-split-horizontally))) (defun display-buffer-pop-up-window-split-horizontally (buffer alist) "Call `display-buffer-pop-up-window', setting `split-height-threshold' and `split-width-threshold' so that the split is always horizontal." (let ((split-height-threshold nil) (split-width-threshold 0)) (display-buffer-pop-up-window buffer alist))) #+end_src *** Moving around brackets Thanks to [[http://xahlee.info][Xah Lee]] for this code. #+begin_src emacs-lisp (defvar xah-brackets '("“”" "()" "[]" "{}" "<>" "<>" "()" "[]" "{}" "⦅⦆" "〚〛" "⦃⦄" "‹›" "«»" "「」" "〈〉" "《》" "【】" "〔〕" "⦗⦘" "『』" "〖〗" "〘〙" "「」" "⟦⟧" "⟨⟩" "⟪⟫" "⟮⟯" "⟬⟭" "⌈⌉" "⌊⌋" "⦇⦈" "⦉⦊" "❛❜" "❝❞" "❨❩" "❪❫" "❴❵" "❬❭" "❮❯" "❰❱" "❲❳" "〈〉" "⦑⦒" "⧼⧽" "﹙﹚" "﹛﹜" "﹝﹞" "⁽⁾" "₍₎" "⦋⦌" "⦍⦎" "⦏⦐" "⁅⁆" "⸢⸣" "⸤⸥" "⟅⟆" "⦓⦔" "⦕⦖" "⸦⸧" "⸨⸩" "⦅⦆") "A list of strings, each element is a string of 2 chars, the left bracket and a matching right bracket. Used by `xah-select-text-in-quote' and others.") (defconst xah-left-brackets (mapcar (lambda (x) (substring x 0 1)) xah-brackets) "List of left bracket chars. Each element is a string.") (defconst xah-right-brackets (mapcar (lambda (x) (substring x 1 2)) xah-brackets) "List of right bracket chars. Each element is a string.") (defun xah-backward-left-bracket () "Move cursor to the previous occurrence of left bracket. The list of brackets to jump to is defined by `xah-left-brackets'. URL `http://xahlee.info/emacs/emacs/emacs_navigating_keys_for_brackets.html' Version: 2015-10-01" (interactive) (re-search-backward (regexp-opt xah-left-brackets) nil t)) (defun xah-forward-right-bracket () "Move cursor to the next occurrence of right bracket. The list of brackets to jump to is defined by `xah-right-brackets'. URL `http://xahlee.info/emacs/emacs/emacs_navigating_keys_for_brackets.html' Version: 2015-10-01" (interactive) (re-search-forward (regexp-opt xah-right-brackets) nil t)) #+end_src * Org mode My preferred org-mode defaults #+begin_src emacs-lisp (use-package org :config (add-hook 'org-mode-hook 'org-indent-mode) (add-hook 'org-mode-hook #'(lambda () (visual-line-mode 1)))) (use-package org-indent :diminish org-indent-mode) (use-package htmlize :ensure t) #+end_src #+begin_src emacs-lisp (setq org-latex-pdf-process '("latexmk -pdflatex='pdflatex -interaction nonstopmode' -pdf -bibtex -f %f")) (setq org-latex-toc-command "\\tableofcontents \\clearpage") (setq org-latex-packages-alist '(("margin=2cm" "geometry" nil))) (unless (boundp 'org-latex-classes) (setq org-latex-classes nil)) (add-to-list 'org-latex-classes '("ethz" "\\documentclass[a4paper,11pt,titlepage]{memoir} \\usepackage[utf8]{inputenc} \\usepackage[T1]{fontenc} \\usepackage{fixltx2e} \\usepackage{graphicx} \\usepackage{longtable} \\usepackage{float} \\usepackage{wrapfig} \\usepackage{rotating} \\usepackage[normalem]{ulem} \\usepackage{amsmath} \\usepackage{textcomp} \\usepackage{marvosym} \\usepackage{wasysym} \\usepackage{amssymb} \\usepackage{hyperref} \\usepackage{mathpazo} \\usepackage{color} \\usepackage{enumerate} \\definecolor{bg}{rgb}{0.95,0.95,0.95} \\tolerance=1000 [NO-DEFAULT-PACKAGES] [PACKAGES] [EXTRA] \\linespread{1.1} \\hypersetup{pdfborder=0 0 0}" ("\\chapter{%s}" . "\\chapter*{%s}") ("\\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 '("article" "\\documentclass[11pt,a4paper]{article} \\usepackage[utf8]{inputenc} \\usepackage[T1]{fontenc} \\usepackage{fixltx2e} \\usepackage{graphicx} \\usepackage{longtable} \\usepackage{float} \\usepackage{wrapfig} \\usepackage{rotating} \\usepackage[normalem]{ulem} \\usepackage{amsmath} \\usepackage{textcomp} \\usepackage{marvosym} \\usepackage{wasysym} \\usepackage{amssymb} \\usepackage{hyperref} \\usepackage{mathpazo} \\usepackage{color} \\usepackage{enumerate} \\definecolor{bg}{rgb}{0.95,0.95,0.95} \\tolerance=1000 [NO-DEFAULT-PACKAGES] [PACKAGES] [EXTRA] \\linespread{1.1} \\hypersetup{pdfborder=0 0 0}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}"))) (add-to-list 'org-latex-classes '("ebook" "\\documentclass[11pt, oneside]{memoir} \\setstocksize{9in}{6in} \\settrimmedsize{\\stockheight}{\\stockwidth}{*} \\setlrmarginsandblock{2cm}{2cm}{*} % Left and right margin \\setulmarginsandblock{2cm}{2cm}{*} % Upper and lower margin \\checkandfixthelayout % Much more laTeX code omitted " ("\\chapter{%s}" . "\\chapter*{%s}") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}"))) #+end_src * Custom functions ** Toggle transparency Something happened between emacs 28 and 29 that this needs to be toggled twice for the first time. After that, it toggles as expected. Will try to fix this when I find the time to do so. #+begin_src emacs-lisp (defun toggle-transparency() (interactive) (let ((alpha (frame-parameter nil 'alpha))) (set-frame-parameter nil 'alpha (if (eql (cond ((numberp alpha) alpha) ((numberp (cdr alpha)) (cdr alpha))) 100) '(90 . 90) '(100 . 100))))) (global-set-key (kbd "C-c t") 'toggle-transparency) #+end_src ** Config edit/reload *** edit #+begin_src emacs-lisp (defun config-visit () (interactive) (find-file "~/.emacs.d/config.org")) (global-set-key (kbd "C-c e") 'config-visit) #+end_src *** reload #+begin_src emacs-lisp (defun config-reload () (interactive) (org-babel-load-file (expand-file-name "~/.emacs.d/config.org"))) (global-set-key (kbd "C-c r") 'config-reload) #+end_src ** Creating new window automatically focuses it *** horizontal #+begin_src emacs-lisp (defun split-and-follow-horizontally () (interactive) (split-window-below) (balance-windows) (other-window 1)) (global-set-key (kbd "C-x 2") 'split-and-follow-horizontally) #+end_src *** vertical #+begin_src emacs-lisp (defun split-and-follow-vertically () (interactive) (split-window-right) (balance-windows) (other-window 1)) (global-set-key (kbd "C-x 3") 'split-and-follow-vertically) #+end_src ** Always kill current buffer #+begin_src emacs-lisp (defun kill-curr-buffer () (interactive) (kill-buffer (current-buffer))) (global-set-key (kbd "C-x C-k") 'kill-curr-buffer) #+end_src ** Kill all buffers #+begin_src emacs-lisp (defun kill-all-buffers () (interactive) (mapc 'kill-buffer (buffer-list))) (global-set-key (kbd "C-M-s-k") 'kill-all-buffers) #+end_src ** Find-next-file #+begin_src emacs-lisp (defun find-next-file (&optional backward) "Find the next file (by name) in the current directory. With prefix arg, find the previous file." (interactive "P") (when buffer-file-name (let* ((file (expand-file-name buffer-file-name)) (files (cl-remove-if (lambda (file) (cl-first (file-attributes file))) (sort (directory-files (file-name-directory file) t nil t) 'string<))) (pos (mod (+ (cl-position file files :test 'equal) (if backward -1 1)) (length files)))) (find-file (nth pos files))))) (global-set-key (kbd "C-c C-j") 'find-next-file) (global-set-key (kbd "C-c C-k") (lambda () (interactive) (find-next-file :backward))) #+end_src * Use-Package section ** Initialize =dashboard= Configure a custom starting buffer #+begin_src emacs-lisp (use-package dashboard :ensure t :defer nil :preface (defun update-config () (interactive) (let ((dir (expand-file-name user-emacs-directory))) (if (file-exists-p dir) (progn (message "yuzu-emacs is updating!") (cd dir) (shell-command "git pull") (message "Update finished. See changes in *Message* buffer and then restart.")) (message "\"%s\" doesn't exist")))) (defun create-scratch-buffer () (interactive) (switch-to-buffer (get-buffer-create "*scratch*")) (lisp-interaction-mode)) :config (dashboard-setup-startup-hook) (setq dashboard-items '((recents . 5))) (setq dashboard-banner-logo-title "haaaiiii :3") (setq dashboard-startup-banner "~/.emacs.d/cirno.png") (setq dashboard-center-content t) (setq dashboard-show-shortcuts nil) (setq dashboard-set-init-info t) (setq dashboard-init-info (format "%d packages loaded in %s" (length package-activated-list) (emacs-init-time))) (setq dashboard-set-footer nil) (setq dashboard-set-navigator t) (setq dashboard-navigator-buttons `(;; line1 ((,nil "yuzu-emacs on github" "Open yuzu-emacs' github page on your browser" (lambda (&rest _) (browse-url "https://github.com/yuzu-eva/yuzu-emacs"))) (nil "Update yuzu-emacs" "Get the latest yuzu-emacs update. See github commits for changes" (lambda (&rest _) (update-config))) (nil "Open scratch buffer" "Switch to the scratch buffer" (lambda (&rest _) (create-scratch-buffer))) ) ;;line 2 ((,nil "Open config.org" "Open configuration file" (lambda (&rest _) (find-file "~/.emacs.d/config.org"))) (nil "Open init.el" "Open the init file" (lambda (&rest _) (find-file "~/.emacs.d/init.el"))))))) #+End_src ** Initialize =auto-package-update= Auto-package-update automatically updates and removes old packages #+begin_src emacs-lisp (use-package auto-package-update :defer nil :ensure t :config (setq auto-package-update-delete-old-versions t) (setq auto-package-update-hide-results t) (auto-package-update-maybe)) #+end_src ** Initialize =diminish= Hides minor modes to prevent cluttering modeline #+begin_src emacs-lisp (use-package diminish :ensure t :init (diminish 'subword-mode) (diminish 'visual-line-mode) (diminish 'abbrev-mode)) #+end_src ** Initialize =which-key= Completion menu for keybinds #+begin_src emacs-lisp (use-package which-key :ensure t :diminish which-key-mode :init (which-key-mode)) #+end_src ** Initialize =ido-vertical-mode= Uses a vertical mini-buffer for ido, instead of a horizontal one #+begin_src emacs-lisp (use-package ido-vertical-mode :ensure t :init (ido-vertical-mode 1)) #+end_src ** Initialize =smex= Vertical mini-buffer for interactive commands, similar to ido-vertical #+begin_src emacs-lisp (use-package smex :ensure t :init (smex-initialize) :bind ("M-x" . smex)) #+end_src ** Initialize =avy= Pressing "M-s" prompts for a character. Entering a character will highlight all of them in the current visible buffer with another letter overlayed. Pressing that letter will move the cursor to the highlighted character #+begin_src emacs-lisp (use-package avy :ensure t :bind ("M-s" . avy-goto-char)) #+end_src ** Initialize =rainbow-mode= Displays colour of a hex code as background colour behind said hex code #+begin_src emacs-lisp (use-package rainbow-mode :ensure t :init (add-hook 'css-mode-hook 'rainbow-mode)) #+end_src ** Initialize =switch-window= Better way to switch windows #+begin_src emacs-lisp (use-package switch-window :ensure t :config (setq switch-window-input-style 'minibuffer) (setq switch-window-increase 4) (setq switch-window-threshold 2) (setq switch-window-shortcut-style 'qwerty) (setq switch-window-qwerty-shortcuts '("a" "o" "e" "u" "h" "t" "n" "s")) :bind ([remap other-window] . switch-window)) #+end_src # ** Initialize =evil= # vim keybindings in emacs text editing. I don't like emacs' default editor # keybinds. This emacs config uses vim keybinds only for text editing. Everthing # else still uses emacs bindings # #+begin_src emacs-lisp # (use-package evil # :ensure t # :defer nil # :init # (setq evil-want-keybinding nil) # (setq evil-want-C-u-scroll t) # :config # (evil-mode 1) # (evil-set-undo-system 'undo-redo) # (evil-set-initial-state 'dired-mode 'emacs)) # #+end_src # ** Initialize =evil-org-mode= # Evil extension for org-mode # #+begin_src emacs-lisp # (use-package evil-org # :ensure t # :after org # :config # (require 'evil-org-agenda) # (evil-org-agenda-set-keys) # :init # (add-hook 'org-mode-hook 'evil-org-mode)) # #+end_src # ** Initialize =evil-surround= # Minor mode that emulates vim-surround by Tim Pope # #+begin_src emacs-lisp # (use-package evil-surround # :ensure t # :config # (global-evil-surround-mode 1)) # #+end_src # ** Initialize =evil-commentary= # Minor mode that emulates vim-commentary by Tim Pope # #+begin_src emacs-lisp # (use-package evil-commentary # :ensure t # :diminish evil-commentary-mode # :init # (evil-commentary-mode)) # #+end_src ** Initialize =sly= Sly REPL #+begin_src emacs-lisp (use-package sly :ensure t) (setq inferior-lisp-program "/usr/local/bin/sbcl") #+end_src ** Initialize =sudo-edit= Allow for editing files as sudo #+begin_src emacs-lisp (use-package sudo-edit :ensure t :bind ("s-C-e" . sudo-edit)) #+end_src ** Initialize =powerline= Better looking modeline. Using powerline with the spaceline theme #+begin_src emacs-lisp (use-package spaceline :ensure t) (use-package powerline :ensure t :config (setq powerline-default-separator 'arrow) :init (spaceline-spacemacs-theme) :hook ('after-init-hook) . 'powerline-reset) #+end_src ** Initialize =popup-kill-ring= Replaces the default "M-y" kill ring with a popup menu for easy selection #+begin_src emacs-lisp (use-package popup-kill-ring :ensure t :bind ("M-y" . popup-kill-ring)) #+end_src ** Initialize =page-break-lines= Display ^L page breaks as a horizontal line #+begin_src emacs-lisp (use-package page-break-lines :ensure t :diminish page-break-lines-mode) #+end_src ** Initialize =multiple-cursors= Allow for editing with multiple cursors at the same time #+begin_src emacs-lisp (use-package multiple-cursors :ensure t :bind ("C-S-c C-S-c" . mc/edit-lines) ("C->" . mc/mark-next-like-this) ("C-<" . mc/mark-previous-like-this) ("C-c C-<" . mc/mark-all-like-this)) #+end_src ** Initialize =drag-stuff= Move line or region around using M- M- M- M- #+begin_src emacs-lisp (use-package drag-stuff :ensure t :diminish drag-stuff-mode :config (drag-stuff-global-mode 1) (drag-stuff-define-keys)) #+end_src * Programming section ** Initialize =company= Company is an autocompletion frontend #+begin_src emacs-lisp (use-package company :ensure t :config (setq company-idle-delay 0) (setq company-minimum-prefix-length 3) :init (add-hook 'after-init-hook 'global-company-mode)) (with-eval-after-load 'company (define-key company-active-map (kbd "M-n") nil) (define-key company-active-map (kbd "M-p") nil) (define-key company-active-map (kbd "C-n") 'company-select-next) (define-key company-active-map (kbd "C-p") 'company-select-previous)) #+end_src ** Initialize =company-irony= Autocompletion backend for C and C++ #+begin_src emacs-lisp (use-package company-irony :ensure t :config (require 'company) (add-to-list 'company-backends 'company-irony)) (use-package irony :ensure t :config (add-hook 'c++-mode-hook 'irony-mode) (add-hook 'c-mode-hook 'irony-mode) (add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options)) #+end_src * Custom keybinds Some keybinds to make life easier ** Open URL in browser #+begin_src emacs-lisp (global-set-key (kbd "C-c o") 'browse-url-at-point) #+end_src ** Open recent files menu #+begin_src emacs-lisp (global-set-key (kbd "C-c f") 'recentf-open-files) #+end_src ** More comfortable resize bindings #+begin_src emacs-lisp (global-set-key (kbd "s-C-") 'shrink-window-horizontally) (global-set-key (kbd "s-C-") 'enlarge-window-horizontally) (global-set-key (kbd "s-C-") 'shrink-window) (global-set-key (kbd "s-C-") 'enlarge-window) #+end_src ** Xah Lee bracket movement #+begin_src emacs-lisp (global-set-key (kbd "C-9") 'xah-backward-left-bracket) (global-set-key (kbd "C-0") 'xah-forward-right-bracket) #+end_src