#+AUTHOR: yuzu-eva #+STARTUP: overview #+LANGUAGE: en #+OPTIONS: num:nil * Introduction yuzu-emacs is my personal configuration for emacs. It disables some visual annoyances and sets some helpful functions and keybinds. Currently configured for C/C++, Ruby and Python. * 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 *** Kill dired-buffer when changing directory #+begin_src emacs-lisp (setq dired-kill-when-opening-new-dired-buffer t) #+end_src *** Disable auto-merge in ido #+begin_src emacs-lisp (setq ido-auto-merge-work-directories-length -1) #+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. Also using relative line numbers. #+begin_src emacs-lisp (add-hook 'prog-mode-hook 'display-line-numbers-mode) (add-hook 'text-mode-hook 'display-line-numbers-mode) (setq display-line-numbers 'relative) #+end_src *** Enable column number #+begin_src emacs-lisp (column-number-mode 1) #+end_src *** Enable whitespace-mode #+begin_src emacs-lisp (setq whitespace-line-column 72) (setq whitespace-style '(face trailing tabs newline missing-newline-at-eof empty indentation space-after-tab space-before-tab tab-mark newline-mark)) (global-whitespace-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 Set a different color for each matching pair of brackets. Uses [[https://github.com/Fanael/rainbow-delimiters][rainbow-delimiters]]. #+begin_src emacs-lisp ;; colors for light mode (set-face-foreground 'rainbow-delimiters-unmatched-face "red") (set-face-foreground 'rainbow-delimiters-depth-1-face "black") (set-face-foreground 'rainbow-delimiters-depth-2-face "blue") (set-face-foreground 'rainbow-delimiters-depth-3-face "dark magenta") (set-face-foreground 'rainbow-delimiters-depth-4-face "dark orange4") (set-face-foreground 'rainbow-delimiters-depth-5-face "chocolate4") (set-face-foreground 'rainbow-delimiters-depth-6-face "gray42") (set-face-foreground 'rainbow-delimiters-depth-7-face "violetred4") (set-face-foreground 'rainbow-delimiters-depth-8-face "dodgerblue4") (set-face-foreground 'rainbow-delimiters-depth-9-face "dark goldenrod") ;; colors for dark mode ;; (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 "green") ;; (set-face-foreground 'rainbow-delimiters-depth-3-face "magenta") ;; (set-face-foreground 'rainbow-delimiters-depth-4-face "orange") ;; (set-face-foreground 'rainbow-delimiters-depth-5-face "cyan") ;; (set-face-foreground 'rainbow-delimiters-depth-6-face "yellew") ;; (set-face-foreground 'rainbow-delimiters-depth-7-face "chocolate4") ;; (set-face-foreground 'rainbow-delimiters-depth-8-face "gray42") ;; (set-face-foreground 'rainbow-delimiters-depth-9-face "dark goldenrod") (add-hook 'prog-mode-hook 'rainbow-delimiters-mode) #+end_src *** Show parent parentheses #+begin_src emacs-lisp (show-paren-mode 1) #+end_src *** Enable conservative scrolling #+begin_src emacs-lisp (setq scroll-conservatively 100) #+end_src *** Set font #+begin_src emacs-lisp (add-to-list 'default-frame-alist '(font . "Iosevka Term Custom-13")) #+end_src *** Keep syntax-highlighting to a minimum #+begin_src emacs-lisp (setq font-lock-maximum-decoration '((t . 1))) #+end_src *** Display date-time in status bar #+begin_src emacs-lisp (setq display-time-day-and-date t display-time-24hr-format t) (display-time) #+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 (with-eval-after-load 'electric (electric-indent-mode -1)) (setq-default indent-tabs-mode nil) (setq backward-delete-char-untabify-method nil) (setq c-default-style "k&r") (setq tab-width 4) (setq standard-indent 4) (setq c-basic-offset 4) (setq python-indent-offset 4) (setq sgml-basic-offset 4) (setq ruby-indent-level 4) (add-hook 'prog-mode-hook 'electric-indent-local-mode) #+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) (ido-mode 1) #+end_src *** Change default buffer-list I don't like 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 *** Use MIT-Scheme #+begin_src emacs-lisp (setq scheme-program-name "mit-scheme") #+end_src *** Use forward-to-word instead of forward-word #+begin_src emacs-lisp (global-set-key (kbd "M-f") 'forward-to-word) (global-set-key (kbd "M-F") 'forward-word) #+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)) (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=1in" "geometry" nil))) (setq org-latex-caption-above nil) (setq org-html-table-caption-above 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} \\pagenumbering{roman} \\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{1in}{1in}{*} % Left and right margin \\setulmarginsandblock{1in}{1in}{*} % Upper and lower margin \\checkandfixthelayout % Much more laTeX code omitted " ("\\chapter{%s}" . "\\chapter*{%s}") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}"))) #+end_src * Notmuch config #+begin_src emacs-lisp (setq notmuch-search-oldest-first nil) ;; Drafts folder (setq notmuch-draft-folder "Drafts") ;; default: drafts (setq notmuch-draft-tags '("+draft" "-inbox" )) ;; when saved, default within inbox (setq mail-user-agent 'notmuch-user-agent) #+end_src * Use-Package section ** 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) (diminish 'auto-fill-function) (diminish 'eldoc-mode) (diminish 'yas-minor-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 =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 =sly= Sly REPL #+begin_src emacs-lisp (use-package sly :ensure t) (setq inferior-lisp-program "/usr/local/bin/sbcl") #+end_src ** Initialize =smex= Minibuffer for "execute-extended-commands" #+begin_src emacs-lisp (use-package smex :ensure t :init (smex-initialize) :bind ("M-x" . smex)) #+end_src ** Initialize =sudo-edit= Allow for editing files as sudo #+begin_src emacs-lisp (use-package sudo-edit :ensure t :config (setq sudo-edit-local-method "sudo") :bind ("s-C-e" . sudo-edit)) #+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 =move-text= Move line or region around using M-p M-n #+begin_src emacs-lisp (use-package move-text :ensure t :bind ("M-p" . move-text-up) ("M-n" . move-text-down)) #+end_src ** Initialize =magit= Magical Git interface #+begin_src emacs-lisp (use-package magit :ensure t :config (setq magit-auto-revert-mode nil)) #+end_src ** Initialize =GLSL-mode= Mode for OpenGL Shading Language #+begin_src emacs-lisp (use-package glsl-mode :ensure t :config (add-to-list 'auto-mode-alist '("\\.fs$" . glsl-mode))) #+end_src <<<<<<< Updated upstream ======= ** Initialize =smtpmail-multi= #+begin_src emacs-lisp (use-package smtpmail-multi :ensure t :bind ("C-c m" . notmuch)) #+end_src ** Initialize =elfeed= #+begin_src emacs-lisp (use-package elfeed :ensure t) (load "elfeed-urls.el") #+end_src ** Initialize =yasnippet= #+begin_src emacs-lisp (use-package yasnippet :ensure t :config (setq yas-snippet-dirs '("~/.emacs.d/snippets")) (yas-global-mode 1)) #+end_src >>>>>>> Stashed changes * Programming section ** Initialize =simpc= [[https://github.com/rexim/simpc-mode][simpc]] is a simple c mode that aims to be faster than the default c-mode. #+begin_src emacs-lisp (add-to-list 'auto-mode-alist '("\\.[hc]\\(pp\\)?\\'" . simpc-mode)) (defun astyle-buffer (&optional justify) (interactive) (let ((saved-line-number (line-number-at-pos))) (shell-command-on-region (point-max) (point-min) "astyle --style=kr" nil t) (goto-line saved-line-number))) (add-hook 'simpc-mode-hook (lambda () (interactive) (setq-local fill-paragraph-function 'astyle-buffer))) #+end_src ** 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 1) :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 'simpc-mode-hook 'irony-mode) (add-hook 'irony-mode-hook 'irony-cdb-autosetup-compile-options)) (push 'c-mode irony-supported-major-modes) (push 'c++-mode irony-supported-major-modes) (push 'simpc-mode irony-supported-major-modes) #+end_src ** Initialize =inf-ruby= #+begin_src emacs-lisp (use-package inf-ruby :ensure t) #+end_src ** Initialize =robe= #+begin_src emacs-lisp (use-package robe :ensure t :diminish robe-mode :config (require 'company) (add-hook 'ruby-mode-hook 'robe-mode) (add-to-list 'company-backends 'company-robe)) #+end_src ** Initialize =ruby-electric= #+begin_src emacs-lisp (use-package ruby-electric :ensure t :diminish ruby-electric-mode :config (add-hook 'ruby-mode-hook (lambda () (ruby-electric-mode t)))) #+end_src ** Initialize =rubocop= #+begin_src emacs-lisp (use-package rubocop :ensure t :init (add-hook 'ruby-mode-hook 'rubocop-mode) :diminish rubocop-mode) #+end_src ** Initialize =pyvenv= #+begin_src emacs-lisp (use-package pyvenv :ensure t :config (pyvenv-mode 1)) #+end_src # ** Configuring =tree-sitter= # Install tree sitter grammar packages # #+begin_src emacs-lisp # (setq treesit-language-source-alist # '((ruby "https://github.com/tree-sitter/tree-sitter-ruby") # (c "https://github.com/tree-sitter/tree-sitter-c") # (cpp "https://github.com/tree-sitter/tree-sitter-cpp"))) # ;;; comment this out after installing packages # ;;; otherwise it'll clone the repos everytime the config is loaded # ;;(mapc #'treesit-install-language-grammar (mapcar #'car treesit-language-source-alist)) # (setq major-mode-remap-alist # '((ruby-mode . ruby-ts-mode) # (c-mode . c-ts-mode) # (c++-mode . c++-ts-mode))) # #+end_src * Custom functions ** toggle-transparency Function to toggle transparency #+begin_src emacs-lisp (defconst frame-transparency 85) (defun toggle-transparency () "Toggle transparency. Requires a compositor, e.g picom." (interactive) (let ((frame-alpha (frame-parameter nil 'alpha))) (if (or (not frame-alpha) (= (cadr frame-alpha) 100)) (set-frame-parameter nil 'alpha `(,frame-transparency ,frame-transparency)) (set-frame-parameter nil 'alpha '(100 100))))) (global-set-key (kbd "C-c C-SPC t") 'toggle-transparency) #+end_src ** config-edit/-reload *** edit #+begin_src emacs-lisp (defun config-visit () "Visit config.org file." (interactive) (find-file "~/.emacs.d/config.org")) (global-set-key (kbd "C-c C-SPC e") 'config-visit) #+end_src *** reload #+begin_src emacs-lisp (defun config-reload () "Reload the emacs configuration file." (interactive) (org-babel-load-file (expand-file-name "~/.emacs.d/config.org"))) (global-set-key (kbd "C-c C-SPC r") 'config-reload) #+end_src ** kill all buffers #+begin_src emacs-lisp (defun kill-all-buffers () "Kill all currently open buffers." (interactive) (mapc 'kill-buffer (buffer-list))) (global-set-key (kbd "C-M-s-k") 'kill-all-buffers) #+end_src ** find-next-file and find-prev-file #+begin_src emacs-lisp (defun find-next-file () "Find the next file (by name) in the current directory." (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) 1) (length files)))) (find-file (nth pos files))))) (defun find-prev-file () "Find the prev file (by name) in the current directory." (interactive) (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) -1) (length files)))) (find-file (nth pos files))))) (global-set-key (kbd "C-c C-SPC n") 'find-next-file) (global-set-key (kbd "C-c C-SPC p") 'find-prev-file) #+end_src ** moving around brackets Taken from [[http://xahlee.info][Xah Lee]]. #+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)) (global-set-key (kbd "C-9") 'xah-backward-left-bracket) (global-set-key (kbd "C-0") 'xah-forward-right-bracket) #+end_src ** insert newline above/below Inserts a newline above or below, like O and o in vim #+begin_src emacs-lisp (defun newline-above-and-move () "Inserts a new line above current line and moves cursor to that position" (interactive) (beginning-of-line) (newline-and-indent) (previous-line)) (global-set-key (kbd "M-O") 'newline-above-and-move) (defun newline-below-and-move () "Inserts a new line below current line and moves cursor to that position" (interactive) (end-of-line) (newline-and-indent)) (global-set-key (kbd "M-o") 'newline-below-and-move) #+end_src ** compilation mode #+begin_src emacs-lisp (setq-default compilation-scroll-output t) (defun colorize-compilation-buffer () "Colorize the compilation buffer" (read-only-mode nil) (ansi-color-apply-on-region compilation-filter-start (point)) (read-only-mode 1)) (add-hook 'compilation-filter-hook 'colorize-compilation-buffer) #+end_src ** create TAGS #+begin_src emacs-lisp (defun create-tags (dir-name) "Create TAGS file." (interactive "DDirectory") (cd dir-name) (shell-command "ctags -e *")) #+end_src ** download / play video with mpv #+begin_src emacs-lisp (defun play-with-mpv (start end) "Play link in selected region with mpv" (interactive "r") (save-window-excursion (async-shell-command (concat "mpv " (buffer-substring start end) "\&")))) (defun download-video (start end) "Download link in selected region with yt-dlp" (interactive "r") (save-window-excursion (async-shell-command (concat "yt-dlp -o \"~/vids/download/%(title)s.%(ext)s\" " (buffer-substring start end) "\&")))) (define-key elfeed-show-mode-map (kbd "C-c o") 'play-with-mpv) (define-key elfeed-show-mode-map (kbd "C-c d") 'download-video) #+end_src ** temperature converter #+begin_src emacs-lisp (defun c-to-f (temp) "Convert temperature from Celsius to Fahrenheit" (interactive "nTemperature in Celsius: ") (message "%0.2f" (+ 32 (* temp 1.8)))) (defun f-to-c (temp) "Convert temperature from Fahrenheit to Celsius" (interactive "nTemperature in Fahrenheit: ") (message "%0.2f" (/ (- temp 32) 1.8))) #+end_src ** statistics #+begin_src emacs-lisp (defun validate-list (lst) "Check if input list is a symbol and ensure it's a list" (when (symbolp lst) (setq lst (symbol-value lst))) (unless (listp lst) (error "Input must be a list!")) (if (null lst) (error "Empty list!")) lst) (defun sum (lst) "Calculate the sum of a list" (interactive "xEnter a list: ") (let* ((lst (validate-list lst)) (result (if (null (cdr lst)) (car lst) (+ (car lst) (sum (cdr lst)))))) (when (called-interactively-p 'any) (message "Sum: %.2f" (float result))) result)) (defun mean (lst) "Calculate the mean of a list." (interactive "xEnter a list: ") (let* ((lst (validate-list lst)) (mean-value (/ (float (sum lst)) (length lst)))) (when (called-interactively-p 'any) (message "Mean: %.2f" mean-value)) mean-value)) (defun sqr-diff-mean (x mean) "Calculate squared difference (datapoint - mean)" (let ((diff (- x mean))) (expt diff 2))) (defun mean-avg-dev (lst) "Calculate Mean Average Deviation of a list" (interactive "xEnter a list: ") (let* ((lst (validate-list lst)) (mean-value (mean lst)) (abs-dev-sum (sum (mapcar (lambda (x) (abs (- x mean-value))) lst))) (mad-value (/ abs-dev-sum (length lst)))) (when (called-interactively-p 'any) (message "Mean Average Deviation: %.2f" mad-value)) mad-value)) (defun pstd-dev (lst) "Calculate Population Standard Deviation of a list" (interactive "xEnter a list: ") (let* ((lst (validate-list lst)) (n (length lst)) (mean-value (mean lst)) (squared-diffs (mapcar (lambda (x) (sqr-diff-mean x mean-value)) lst)) (sum-squared-diffs (sum squared-diffs)) (stddev (if (< n 2) 0 (sqrt (/ (float sum-squared-diffs) (1- n)))))) (when (called-interactively-p 'any) (message "%.2f" stddev)) stddev)) (defun sstd-dev (lst) "Calculate Sample Standard Deviation of a list" (interactive "xEnter a list: ") (let* ((lst (validate-list lst)) (n (length lst)) (mean-value (mean lst)) (squared-diffs (mapcar (lambda (x) (sqr-diff-mean x mean-value)) lst)) (sum-squared-diffs (sum squared-diffs)) (stddev (if (< n 2) 0 (sqrt (/ (float sum-squared-diffs) n))))) (when (called-interactively-p 'any) (message "%.2f" stddev)) stddev)) (defun scov (xset yset) (interactive "xEnter independant list: \nxEnter dependant list: ") (let* ((xset (validate-list xset)) (yset (validate-list yset)) (n (length xset)) (xmean (mean xset)) (ymean (mean yset)) (sum-dev-prod (sum (cl-mapcar (lambda (x y) (* (- x xmean) (- y ymean))) xset yset))) (result (/ sum-dev-prod n))) (when (called-interactively-p 'any) (message "Sample Covariance: %.2f" result)) result)) (defun pcov (xset yset) (interactive "xEnter independant list: \nxEnter dependant list: ") (let* ((xset (validate-list xset)) (yset (validate-list yset)) (n (length xset)) (xmean (mean xset)) (ymean (mean yset)) (sum-dev-prod (sum (cl-mapcar (lambda (x y) (* (- x xmean) (- y ymean))) xset yset))) (result (/ sum-dev-prod (1- n)))) (when (called-interactively-p 'any) (message "Sample Covariance: %.2f" result)) result)) (defun pearson-scc (xset yset) "Calculate the Pearson Sample Correlation Coefficient between x and y" (interactive "xEnter independant list: \nxEnter dependant list: ") (let* ((xset (validate-list xset)) (yset (validate-list yset)) (n (length xset)) (denominator (* (sstd-dev xset) (sstd-dev yset)))) (if (zerop denominator) (message "Correlation coefficient: NaN (denominator is zero)") (let ((r (/ (scov xset yset) denominator))) (when (called-interactively-p 'any) (message "Correlation coefficient: %.2f" r)) r)))) (defun pearson-pcc (xset yset) "Calculate the Pearson Population Correlation Coefficient between x and y" (interactive "xEnter independant list: \nxEnter dependant list: ") (let* ((xset (validate-list xset)) (yset (validate-list yset)) (n (length xset)) (denominator (* (pstd-dev xset) (pstd-dev yset)))) (if (zerop denominator) (message "Correlation coefficient: NaN (denominator is zero)") (let ((r (/ (scov xset yset) denominator))) (when (called-interactively-p 'any) (message "Correlation coefficient: %.2f" r)) r)))) #+end_src * Custom keybinds and re-binds Some keybinds to make life easier ** make