#+TITLE: yuzu-emacs #+STARTUP: overview #+LANGUAGE: en #+OPTIONS: num:nil [[./yuzu-emacs.png]] * Introduction yuzu-emacs is my personal configuration for emacs. It is a (currently) very basic configuration, which is heavily inspired by [[https://github.com/snackon/Witchmacs][Witchmacs]], the main difference is that this configuration is leaning a bit more towards vim-keybindings. My goal is to make this into a fully functional IDE for RoR, Python and C. * 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 *** Disable automatic creation of backup files #+begin_src emacs-lisp (setq make-backup-files nil) (setq auto-save-default nil) #+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 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 *** 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 *** 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 * 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 #+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)) #+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" "s" "d" "f" "h" "j" "k" "l")) :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/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= #+begin_src emacs-lisp (use-package page-break-lines :ensure t :diminish page-break-lines-mode) #+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