chore(emacs): Move emacs config to tools/emacs
This commit is contained in:
		
							parent
							
								
									9b35db823f
								
							
						
					
					
						commit
						15c61c0bee
					
				
					 13 changed files with 0 additions and 0 deletions
				
			
		
							
								
								
									
										11
									
								
								tools/emacs/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tools/emacs/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| .smex-items | ||||
| *token* | ||||
| auto-save-list/ | ||||
| clones/ | ||||
| elpa/ | ||||
| irc.el | ||||
| local.el | ||||
| other/ | ||||
| scripts/ | ||||
| themes/ | ||||
| *.elc | ||||
							
								
								
									
										6
									
								
								tools/emacs/README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tools/emacs/README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| emacs.d | ||||
| ======== | ||||
| 
 | ||||
| This contains my emacs.d folder. | ||||
| 
 | ||||
| I use emacs for many things. | ||||
							
								
								
									
										168
									
								
								tools/emacs/init.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								tools/emacs/init.el
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,168 @@ | |||
| ;;; init.el --- Package bootstrapping. -*- lexical-binding: t; -*- | ||||
| 
 | ||||
| ;; Packages are installed via Nix configuration, this file only | ||||
| ;; initialises the newly loaded packages. | ||||
| 
 | ||||
| (require 'use-package) | ||||
| (require 'seq) | ||||
| 
 | ||||
| (package-initialize) | ||||
| 
 | ||||
| ;; Add 'init' folder that contains other settings to load. | ||||
| (add-to-list 'load-path (concat user-emacs-directory "init")) | ||||
| 
 | ||||
| ;; Initialise all packages installed via Nix. | ||||
| ;; | ||||
| ;; TODO: Generate this section in Nix for all packages that do not | ||||
| ;; require special configuration. | ||||
| 
 | ||||
| ;; | ||||
| ;; Packages providing generic functionality. | ||||
| ;; | ||||
| 
 | ||||
| (use-package ace-window | ||||
|   :bind (("C-x o" . ace-window)) | ||||
|   :init | ||||
|   (setq aw-keys '(?f ?j ?d ?k ?s ?l ?a) | ||||
|         aw-scope 'frame)) | ||||
| 
 | ||||
| (use-package auth-source-pass :init (auth-source-pass-enable)) | ||||
| 
 | ||||
| (use-package avy | ||||
|   :bind (("M-j" . avy-goto-char) | ||||
|          ("M-p" . avy-pop-mark) | ||||
|          ("M-g g" . avy-goto-line))) | ||||
| 
 | ||||
| (use-package browse-kill-ring) | ||||
| 
 | ||||
| (use-package company | ||||
|   :hook ((prog-mode . company-mode)) | ||||
|   :bind (:map rust-mode-map ("<tab>" . company-indent-or-complete-common) | ||||
|          :map lisp-mode-map ("<tab>" . company-indent-or-complete-common)) | ||||
|   :init (setq company-tooltip-align-annotations t)) | ||||
| 
 | ||||
| (use-package dash) | ||||
| (use-package dash-functional) | ||||
| (use-package edit-server :init (edit-server-start)) | ||||
| (use-package gruber-darker-theme) | ||||
| (use-package ht) | ||||
| (use-package hydra) | ||||
| (use-package idle-highlight-mode :hook ((prog-mode . idle-highlight-mode))) | ||||
| (use-package paredit :hook ((lisp-mode . paredit-mode) | ||||
|                             (emacs-lisp-mode . paredit-mode))) | ||||
| (use-package multiple-cursors) | ||||
| (use-package pinentry | ||||
|   :init | ||||
|   (setq epa-pinentry-mode 'loopback) | ||||
|   (pinentry-start)) | ||||
| 
 | ||||
| (use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode)) | ||||
| (use-package rainbow-mode) | ||||
| (use-package s) | ||||
| (use-package smartparens :init (smartparens-global-mode)) | ||||
| (use-package string-edit) | ||||
| (use-package telephone-line) ;; configuration happens outside of use-package | ||||
| (use-package undo-tree :init (global-undo-tree-mode)) | ||||
| (use-package uuidgen) | ||||
| (use-package which-key :init (which-key-mode t)) | ||||
| 
 | ||||
| ;; | ||||
| ;; Applications in emacs | ||||
| ;; | ||||
| 
 | ||||
| (use-package magit | ||||
|   :bind ("C-c g" . magit-status) | ||||
|   :init (setq magit-repository-directories '(("/home/vincent/projects" . 2)))) | ||||
| 
 | ||||
| (use-package password-store) | ||||
| (use-package pg) | ||||
| (use-package restclient) | ||||
| 
 | ||||
| ;; | ||||
| ;; Packages providing language-specific functionality | ||||
| ;; | ||||
| 
 | ||||
| (use-package cargo | ||||
|   :hook ((rust-mode . cargo-minor-mode) | ||||
|          (cargo-process-mode . visual-line-mode)) | ||||
|   :bind (:map cargo-minor-mode-map ("C-c C-c C-l" . ignore))) | ||||
| 
 | ||||
| (use-package dockerfile-mode) | ||||
| 
 | ||||
| (use-package eglot | ||||
|   :init (defvar rust-eglot-initialized nil) | ||||
|   :hook ((rust-mode . (lambda () | ||||
|                         (unless rust-eglot-initialized | ||||
|                           (call-interactively #'eglot) | ||||
|                           (setq rust-eglot-initialized t)))))) | ||||
| 
 | ||||
| (use-package erlang | ||||
|   :hook ((erlang-mode . (lambda () | ||||
|                           ;; Don't indent after '>' while I'm writing | ||||
|                           (local-set-key ">" 'self-insert-command))))) | ||||
| 
 | ||||
| (use-package go-mode) | ||||
| (use-package haskell-mode) | ||||
| 
 | ||||
| (use-package jq-mode | ||||
|   :init (add-to-list 'auto-mode-alist '("\\.jq\\'" . jq-mode))) | ||||
| 
 | ||||
| (use-package kotlin-mode | ||||
|   :bind (:map kotlin-mode-map ("<tab>" . indent-relative))) | ||||
| 
 | ||||
| (use-package markdown-mode | ||||
|   :init | ||||
|   (add-to-list 'auto-mode-alist '("\\.txt\\'" . markdown-mode)) | ||||
|   (add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode)) | ||||
|   (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))) | ||||
| 
 | ||||
| (use-package markdown-toc) | ||||
| 
 | ||||
| (use-package nix-mode | ||||
|   :bind (:map nix-mode-map ("<tab>" . nix-indent-line))) | ||||
| 
 | ||||
| (use-package nginx-mode) | ||||
| (use-package rust-mode) | ||||
| (use-package terraform-mode) | ||||
| (use-package toml-mode) | ||||
| (use-package web-mode) | ||||
| (use-package yaml-mode) | ||||
| 
 | ||||
| ;; | ||||
| ;; EXWM / NixOS related packages | ||||
| ;; | ||||
| 
 | ||||
| ;; Configure a few basics before moving on to package-specific initialisation. | ||||
| (setq custom-file (concat user-emacs-directory "init/custom.el")) | ||||
| (load custom-file) | ||||
| 
 | ||||
| (defvar home-dir (expand-file-name "~")) | ||||
| 
 | ||||
| ;; Seed RNG | ||||
| (random t) | ||||
| 
 | ||||
| (defun load-other-settings () | ||||
|   (mapc 'require '(nixos | ||||
| 		   mail-setup | ||||
|                    look-and-feel | ||||
|                    functions | ||||
|                    settings | ||||
|                    modes | ||||
|                    bindings | ||||
|                    term-setup | ||||
|                    eshell-setup)) | ||||
|   (telephone-line-setup) | ||||
|   (ace-window-display-mode) | ||||
| 
 | ||||
|   (use-package sly | ||||
|     :init (setq inferior-lisp-program (concat (nix-store-path "sbcl") "/bin/sbcl")) | ||||
|     ;;(add-to-list 'company-backends 'sly-company) | ||||
|     )) | ||||
| 
 | ||||
| 
 | ||||
| ;; Some packages can only be initialised after the rest of the | ||||
| ;; settings has been applied: | ||||
| 
 | ||||
| (add-hook 'after-init-hook 'load-other-settings) | ||||
| (put 'narrow-to-region 'disabled nil) | ||||
| (put 'upcase-region 'disabled nil) | ||||
							
								
								
									
										54
									
								
								tools/emacs/init/bindings.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								tools/emacs/init/bindings.el
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| ;; Various keybindings, most of them taken from starter-kit-bindings | ||||
| 
 | ||||
| ;; Font size | ||||
| (define-key global-map (kbd "C-+") 'text-scale-increase) | ||||
| (define-key global-map (kbd "C--") 'text-scale-decrease) | ||||
| 
 | ||||
| ;; Use regex searches by default. | ||||
| (global-set-key (kbd "\C-r") 'isearch-backward-regexp) | ||||
| (global-set-key (kbd "M-%") 'query-replace-regexp) | ||||
| (global-set-key (kbd "C-M-s") 'isearch-forward) | ||||
| (global-set-key (kbd "C-M-r") 'isearch-backward) | ||||
| (global-set-key (kbd "C-M-%") 'query-replace) | ||||
| 
 | ||||
| ;; Counsel stuff: | ||||
| (global-set-key (kbd "C-c r g") 'counsel-rg) | ||||
| 
 | ||||
| ;; imenu instead of insert-file | ||||
| (global-set-key (kbd "C-x i") 'imenu) | ||||
| 
 | ||||
| ;; Window switching. (C-x o goes to the next window) | ||||
| (windmove-default-keybindings) ;; Shift+direction | ||||
| 
 | ||||
| ;; Start eshell or switch to it if it's active. | ||||
| (global-set-key (kbd "C-x m") 'eshell) | ||||
| 
 | ||||
| ;; Start a new eshell even if one is active. | ||||
| (global-set-key (kbd "C-x M") (lambda () (interactive) (eshell t))) | ||||
| 
 | ||||
| (global-set-key (kbd "C-x p") 'ivy-browse-repositories) | ||||
| (global-set-key (kbd "M-g M-g") 'goto-line-with-feedback) | ||||
| 
 | ||||
| (global-set-key (kbd "C-c w") 'whitespace-cleanup) | ||||
| (global-set-key (kbd "C-c a") 'align-regexp) | ||||
| 
 | ||||
| ;; Browse URLs (very useful for Gitlab's SSH output!) | ||||
| (global-set-key (kbd "C-c b p") 'browse-url-at-point) | ||||
| (global-set-key (kbd "C-c b b") 'browse-url) | ||||
| 
 | ||||
| ;; Goodness from @magnars | ||||
| ;; I don't need to kill emacs that easily | ||||
| ;; the mnemonic is C-x REALLY QUIT | ||||
| (global-set-key (kbd "C-x r q") 'save-buffers-kill-terminal) | ||||
| (global-set-key (kbd "C-x C-c") 'delete-frame) | ||||
| 
 | ||||
| ;; Open Fefes Blog | ||||
| (global-set-key (kbd "C-c C-f") 'fefes-blog) | ||||
| 
 | ||||
| ;; Open a file in project: | ||||
| (global-set-key (kbd "C-c f") 'project-find-file) | ||||
| 
 | ||||
| ;; Use swiper instead of isearch | ||||
| (global-set-key "\C-s" 'swiper) | ||||
| 
 | ||||
| (provide 'bindings) | ||||
							
								
								
									
										52
									
								
								tools/emacs/init/custom.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								tools/emacs/init/custom.el
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,52 @@ | |||
| (custom-set-variables | ||||
|  ;; custom-set-variables was added by Custom. | ||||
|  ;; If you edit it by hand, you could mess it up, so be careful. | ||||
|  ;; Your init file should contain only one such instance. | ||||
|  ;; If there is more than one, they won't work right. | ||||
|  '(ac-auto-show-menu 0.8) | ||||
|  '(ac-delay 0.2) | ||||
|  '(aprila-nixops-path "/home/vincent/projects/langler/nixops") | ||||
|  '(aprila-release-author "Vincent Ambo <vincent@aprila.no>") | ||||
|  '(aprila-releases-path "/home/vincent/projects/langler/docs/releases") | ||||
|  '(avy-background t) | ||||
|  '(cargo-process--custom-path-to-bin "env CARGO_INCREMENTAL=1 cargo") | ||||
|  '(cargo-process--enable-rust-backtrace 1) | ||||
|  '(custom-enabled-themes (quote (gruber-darker))) | ||||
|  '(custom-safe-themes | ||||
|    (quote | ||||
|     ("d61fc0e6409f0c2a22e97162d7d151dee9e192a90fa623f8d6a071dbf49229c6" "3c83b3676d796422704082049fc38b6966bcad960f896669dfc21a7a37a748fa" "89336ca71dae5068c165d932418a368a394848c3b8881b2f96807405d8c6b5b6" default))) | ||||
|  '(elnode-send-file-program "/run/current-system/sw/bin/cat") | ||||
|  '(frame-brackground-mode (quote dark)) | ||||
|  '(global-auto-complete-mode t) | ||||
|  '(intero-debug nil) | ||||
|  '(intero-global-mode t nil (intero)) | ||||
|  '(intero-package-version "0.1.31") | ||||
|  '(kubernetes-commands-display-buffer-function (quote display-buffer)) | ||||
|  '(magit-log-show-gpg-status t) | ||||
|  '(ns-alternate-modifier (quote none)) | ||||
|  '(ns-command-modifier (quote control)) | ||||
|  '(ns-right-command-modifier (quote meta)) | ||||
|  '(require-final-newline (quote visit-save))) | ||||
| (custom-set-faces | ||||
|  ;; custom-set-faces was added by Custom. | ||||
|  ;; If you edit it by hand, you could mess it up, so be careful. | ||||
|  ;; Your init file should contain only one such instance. | ||||
|  ;; If there is more than one, they won't work right. | ||||
|  '(default ((t (:foreground "#e4e4ef" :background "#181818")))) | ||||
|  '(rainbow-delimiters-depth-1-face ((t (:foreground "#2aa198")))) | ||||
|  '(rainbow-delimiters-depth-2-face ((t (:foreground "#b58900")))) | ||||
|  '(rainbow-delimiters-depth-3-face ((t (:foreground "#268bd2")))) | ||||
|  '(rainbow-delimiters-depth-4-face ((t (:foreground "#dc322f")))) | ||||
|  '(rainbow-delimiters-depth-5-face ((t (:foreground "#859900")))) | ||||
|  '(rainbow-delimiters-depth-6-face ((t (:foreground "#268bd2")))) | ||||
|  '(rainbow-delimiters-depth-7-face ((t (:foreground "#cb4b16")))) | ||||
|  '(rainbow-delimiters-depth-8-face ((t (:foreground "#d33682")))) | ||||
|  '(rainbow-delimiters-depth-9-face ((t (:foreground "#839496")))) | ||||
|  '(term-color-black ((t (:background "#282828" :foreground "#282828")))) | ||||
|  '(term-color-blue ((t (:background "#96a6c8" :foreground "#96a6c8")))) | ||||
|  '(term-color-cyan ((t (:background "#1fad83" :foreground "#1fad83")))) | ||||
|  '(term-color-green ((t (:background "#73c936" :foreground "#73c936")))) | ||||
|  '(term-color-magenta ((t (:background "#9e95c7" :foreground "#9e95c7")))) | ||||
|  '(term-color-red ((t (:background "#f43841" :foreground "#f43841")))) | ||||
|  '(term-color-white ((t (:background "#f5f5f5" :foreground "#f5f5f5")))) | ||||
|  '(term-color-yellow ((t (:background "#ffdd33" :foreground "#ffdd33"))))) | ||||
							
								
								
									
										68
									
								
								tools/emacs/init/eshell-setup.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								tools/emacs/init/eshell-setup.el
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | |||
| ;; EShell configuration | ||||
| 
 | ||||
| (require 'eshell) | ||||
| 
 | ||||
| ;; Generic settings | ||||
| ;; Hide banner message ... | ||||
| (setq eshell-banner-message "") | ||||
| 
 | ||||
| ;; Prompt configuration | ||||
| (defun clean-pwd (path) | ||||
|   "Turns a path of the form /foo/bar/baz into /f/b/baz | ||||
|    (inspired by fish shell)" | ||||
|   (let* ((hpath (replace-regexp-in-string home-dir | ||||
|                                           "~" | ||||
|                                           path)) | ||||
|          (current-dir (split-string hpath "/")) | ||||
| 	 (cdir (last current-dir)) | ||||
| 	 (head (butlast current-dir))) | ||||
|     (concat (mapconcat (lambda (s) | ||||
| 			 (if (string= "" s) nil | ||||
| 			   (substring s 0 1))) | ||||
| 		       head | ||||
| 		       "/") | ||||
| 	    (if head "/" nil) | ||||
| 	    (car cdir)))) | ||||
| 
 | ||||
| (defun vcprompt (&optional args) | ||||
|   "Call the external vcprompt command with optional arguments. | ||||
|    VCPrompt" | ||||
|   (replace-regexp-in-string | ||||
|    "\n" "" | ||||
|    (shell-command-to-string (concat  "vcprompt" args)))) | ||||
| 
 | ||||
| (defmacro with-face (str &rest properties) | ||||
|   `(propertize ,str 'face (list ,@properties))) | ||||
| 
 | ||||
| (defun prompt-f () | ||||
|   "EShell prompt displaying VC info and such" | ||||
|   (concat | ||||
|    (with-face (concat (clean-pwd (eshell/pwd)) " ") :foreground  "#96a6c8") | ||||
|    (if (= 0 (user-uid)) | ||||
|        (with-face "#" :foreground "#f43841") | ||||
|      (with-face "$" :foreground "#73c936")) | ||||
|    (with-face " " :foreground "#95a99f"))) | ||||
| 
 | ||||
| 
 | ||||
| (setq eshell-prompt-function 'prompt-f) | ||||
| (setq eshell-highlight-prompt nil) | ||||
| (setq eshell-prompt-regexp "^.+? \\((\\(git\\|svn\\|hg\\|darcs\\|cvs\\|bzr\\):.+?) \\)?[$#] ") | ||||
| 
 | ||||
| ;; Ignore version control folders in autocompletion | ||||
| (setq eshell-cmpl-cycle-completions nil | ||||
|       eshell-save-history-on-exit t | ||||
|       eshell-cmpl-dir-ignore "\\`\\(\\.\\.?\\|CVS\\|\\.svn\\|\\.git\\)/\\'") | ||||
| 
 | ||||
| ;; Load some EShell extensions | ||||
| (eval-after-load 'esh-opt | ||||
|   '(progn | ||||
|      (require 'em-term) | ||||
|      (require 'em-cmpl) | ||||
|      ;; More visual commands! | ||||
|      (add-to-list 'eshell-visual-commands "ssh") | ||||
|      (add-to-list 'eshell-visual-commands "tail") | ||||
|      (add-to-list 'eshell-visual-commands "sl"))) | ||||
| 
 | ||||
| (setq eshell-directory-name "~/.config/eshell/") | ||||
| 
 | ||||
| (provide 'eshell-setup) | ||||
							
								
								
									
										266
									
								
								tools/emacs/init/functions.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										266
									
								
								tools/emacs/init/functions.el
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,266 @@ | |||
| (require 's) | ||||
| ;; A few handy functions I use in init.el (or not, but they're nice to | ||||
| ;; have) | ||||
| 
 | ||||
| (defun custom-download-theme (url filename) | ||||
|   "Downloads a theme through HTTP and places it in ~/.emacs.d/themes" | ||||
| 
 | ||||
|   ;; Ensure the directory exists | ||||
|   (unless (file-exists-p "~/.emacs.d/themes") | ||||
|     (make-directory "~/.emacs.d/themes")) | ||||
| 
 | ||||
|   ;; Adds the themes folder to the theme load path (if not already | ||||
|   ;; there) | ||||
|   (unless (member "~/.emacs.d/themes" custom-theme-load-path) | ||||
|     (add-to-list 'custom-theme-load-path "~/.emacs.d/themes")) | ||||
| 
 | ||||
|   ;; Download file if it doesn't exist. | ||||
| 
 | ||||
|   (let ((file | ||||
|          (concat "~/.emacs.d/themes/" filename))) | ||||
|     (unless (file-exists-p file) | ||||
|       (url-copy-file url file)))) | ||||
| 
 | ||||
| (defun custom-download-script (url filename) | ||||
|   "Downloads an Elisp script, places it in ~/.emacs/other and then loads it" | ||||
| 
 | ||||
|   ;; Ensure the directory exists | ||||
|   (unless (file-exists-p "~/.emacs.d/other") | ||||
|     (make-directory "~/.emacs.d/other")) | ||||
| 
 | ||||
|   ;; Download file if it doesn't exist. | ||||
|   (let ((file | ||||
|          (concat "~/.emacs.d/other/" filename))) | ||||
|     (unless (file-exists-p file) | ||||
|       (url-copy-file url file)) | ||||
| 
 | ||||
|     (load file))) | ||||
| 
 | ||||
| (defun keychain-password (account &optional keychain) | ||||
|   "Returns the password for the account, by default it's looked up in the Login.keychain but a | ||||
|    different keychain can be specified." | ||||
|   (let ((k (if keychain keychain "Login.keychain"))) | ||||
|     (replace-regexp-in-string | ||||
|      "\n" "" | ||||
|      (shell-command-to-string (concat  "security find-generic-password -w -a " | ||||
|                                        account | ||||
|                                        " " | ||||
|                                        k))))) | ||||
| 
 | ||||
| ;; This clones a git repository to 'foldername in .emacs.d | ||||
| ;; if there isn't already a folder with that name | ||||
| (defun custom-clone-git (url foldername) | ||||
|   "Clones a git repository to .emacs.d/foldername" | ||||
|   (let ((fullpath (concat "~/.emacs.d/" foldername))) | ||||
|     (unless (file-exists-p fullpath) | ||||
|       (async-shell-command (concat "git clone " url " " fullpath))))) | ||||
| 
 | ||||
| (defun load-file-if-exists (filename) | ||||
|   (if (file-exists-p filename) | ||||
|       (load filename))) | ||||
| 
 | ||||
| (defun goto-line-with-feedback () | ||||
|   "Show line numbers temporarily, while prompting for the line number input" | ||||
|   (interactive) | ||||
|   (unwind-protect | ||||
|       (progn | ||||
|         (setq-local display-line-numbers t) | ||||
|         (let ((target (read-number "Goto line: "))) | ||||
|           (avy-push-mark) | ||||
|           (goto-line target))) | ||||
|     (setq-local display-line-numbers nil))) | ||||
| 
 | ||||
| 
 | ||||
| (defun untabify-buffer () | ||||
|   (interactive) | ||||
|   (untabify (point-min) (point-max))) | ||||
| 
 | ||||
| (defun indent-buffer () | ||||
|   (interactive) | ||||
|   (indent-region (point-min) (point-max))) | ||||
| 
 | ||||
| (defun cleanup-buffer () | ||||
|   "Perform a bunch of operations on the whitespace content of a buffer. | ||||
| Including indent-buffer, which should not be called automatically on save." | ||||
|   (interactive) | ||||
|   (untabify-buffer) | ||||
|   (delete-trailing-whitespace) | ||||
|   (indent-buffer)) | ||||
| 
 | ||||
| ;; These come from the emacs starter kit | ||||
| 
 | ||||
| (defun esk-add-watchwords () | ||||
|   (font-lock-add-keywords | ||||
|    nil '(("\\<\\(FIX\\(ME\\)?\\|TODO\\|DEBUG\\|HACK\\|REFACTOR\\|NOCOMMIT\\)" | ||||
|           1 font-lock-warning-face t)))) | ||||
| 
 | ||||
| (defun esk-sudo-edit (&optional arg) | ||||
|   (interactive "p") | ||||
|   (if (or arg (not buffer-file-name)) | ||||
|       (find-file (concat "/sudo:root@localhost:" (read-file-name "File: "))) | ||||
|     (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name)))) | ||||
| 
 | ||||
| ;; Open Fefes blog | ||||
| (defun fefes-blog () | ||||
|   (interactive) | ||||
|   (eww "https://blog.fefe.de/")) | ||||
| 
 | ||||
| ;; Open this machines NixOS config | ||||
| (defun nix-config () | ||||
|   (interactive) | ||||
|   (find-file "/etc/nixos/configuration.nix")) | ||||
| 
 | ||||
| ;; Open the NixOS man page | ||||
| (defun nixos-man () | ||||
|   (interactive) | ||||
|   (man "configuration.nix")) | ||||
| 
 | ||||
| ;; Open local emacs configuration | ||||
| (defun emacs-config () | ||||
|   (interactive) | ||||
|   (dired "~/.emacs.d/")) | ||||
| 
 | ||||
| ;; Get the nix store path for a given derivation. | ||||
| ;; If the derivation has not been built before, this will trigger a build. | ||||
| (defun nix-store-path (derivation) | ||||
|   (let ((expr (concat "with import <nixos> {}; " derivation))) | ||||
|     (s-chomp (shell-command-to-string (concat "nix-build -E '" expr "'"))))) | ||||
| 
 | ||||
| (defun insert-nix-store-path () | ||||
|   (interactive) | ||||
|   (let ((derivation (read-string "Derivation name (in <nixos>): "))) | ||||
|     (insert (nix-store-path derivation)))) | ||||
| 
 | ||||
| (defun toggle-force-newline () | ||||
|   "Buffer-local toggle for enforcing final newline on save." | ||||
|   (interactive) | ||||
|   (setq-local require-final-newline (not require-final-newline)) | ||||
|   (message "require-final-newline in buffer %s is now %s" | ||||
|            (buffer-name) | ||||
|            require-final-newline)) | ||||
| 
 | ||||
| ;; Helm includes a command to run external applications, which does | ||||
| ;; not seem to exist in ivy. This implementation uses some of the | ||||
| ;; logic from Helm to provide similar functionality using ivy. | ||||
| (defun list-external-commands () | ||||
|   "Creates a list of all external commands available on $PATH | ||||
|   while filtering NixOS wrappers." | ||||
|   (cl-loop | ||||
|    for dir in (split-string (getenv "PATH") path-separator) | ||||
|    when (and (file-exists-p dir) (file-accessible-directory-p dir)) | ||||
|    for lsdir = (cl-loop for i in (directory-files dir t) | ||||
|                         for bn = (file-name-nondirectory i) | ||||
|                         when (and (not (s-contains? "-wrapped" i)) | ||||
|                                   (not (member bn completions)) | ||||
|                                   (not (file-directory-p i)) | ||||
|                                   (file-executable-p i)) | ||||
|                         collect bn) | ||||
|    append lsdir into completions | ||||
|    finally return (sort completions 'string-lessp))) | ||||
| 
 | ||||
| (defun run-external-command (cmd) | ||||
|     "Execute the specified command and notify the user when it | ||||
|   finishes." | ||||
|     (message "Starting %s..." cmd) | ||||
|     (set-process-sentinel | ||||
|      (start-process-shell-command cmd nil cmd) | ||||
|      (lambda (process event) | ||||
|        (when (string= event "finished\n") | ||||
|          (message "%s process finished." process))))) | ||||
| 
 | ||||
| (defun ivy-run-external-command () | ||||
|   "Prompts the user with a list of all installed applications and | ||||
|   lets them select one to launch." | ||||
| 
 | ||||
|   (interactive) | ||||
|   (let ((external-commands-list (list-external-commands))) | ||||
|     (ivy-read "Command:" external-commands-list | ||||
|               :require-match t | ||||
|               :history 'external-commands-history | ||||
|               :action #'run-external-command))) | ||||
| 
 | ||||
| (defun ivy-password-store (&optional password-store-dir) | ||||
|   "Custom version of password-store integration with ivy that | ||||
|   actually uses the GPG agent correctly." | ||||
| 
 | ||||
|   (interactive) | ||||
|   (ivy-read "Copy password of entry: " | ||||
|             (password-store-list (or password-store-dir (password-store-dir))) | ||||
|             :require-match t | ||||
|             :keymap ivy-pass-map | ||||
|             :action (lambda (entry) | ||||
|                       (let ((password (auth-source-pass-get 'secret entry))) | ||||
|                         (password-store-clear) | ||||
|                         (kill-new password) | ||||
|                         (setq password-store-kill-ring-pointer kill-ring-yank-pointer) | ||||
|                         (message "Copied %s to the kill ring. Will clear in %s seconds." | ||||
|                                  entry (password-store-timeout)) | ||||
|                         (setq password-store-timeout-timer | ||||
|                               (run-at-time (password-store-timeout) | ||||
|                                            nil 'password-store-clear)))))) | ||||
| 
 | ||||
| (defun ivy-browse-repositories () | ||||
|   "Select a git repository and open its associated magit buffer." | ||||
| 
 | ||||
|   (interactive) | ||||
|   (ivy-read "Repository: " | ||||
|             (magit-list-repos) | ||||
|             :require-match t | ||||
|             :sort t | ||||
|             :action #'magit-status)) | ||||
| 
 | ||||
| (defun warmup-gpg-agent (arg &optional exit) | ||||
|   "Function used to warm up the GPG agent before use. This is | ||||
|    useful in cases where there is no easy way to make pinentry run | ||||
|    in the correct context (such as when sending email)." | ||||
|   (interactive) | ||||
|   (message "Warming up GPG agent") | ||||
|   (epg-sign-string (epg-make-context) "dummy") | ||||
|   nil) | ||||
| 
 | ||||
| (defun bottom-right-window-p () | ||||
|   "Determines whether the last (i.e. bottom-right) window of the | ||||
|   active frame is showing the buffer in which this function is | ||||
|   executed." | ||||
|   (let* ((frame (selected-frame)) | ||||
|          (right-windows (window-at-side-list frame 'right)) | ||||
|          (bottom-windows (window-at-side-list frame 'bottom)) | ||||
|          (last-window (car (seq-intersection right-windows bottom-windows)))) | ||||
|     (eq (current-buffer) (window-buffer last-window)))) | ||||
| 
 | ||||
| (defun inferior-erlang-nix-shell () | ||||
|   "Start an inferior Erlang process from the root of the current | ||||
|   project." | ||||
|   (interactive) | ||||
|   (inferior-erlang | ||||
|    (format "nix-shell --command erl %s" (cdr (project-current))))) | ||||
| 
 | ||||
| (defun intero-fix-ghci-panic () | ||||
|   "Disable deferring of out of scope variable errors, which | ||||
|   triggers a bug in the interactive Emacs REPL printing a panic | ||||
|   under certain conditions." | ||||
| 
 | ||||
|   (interactive) | ||||
|   (let* ((root (intero-project-root)) | ||||
|          (package-name (intero-package-name)) | ||||
|          (backend-buffer (intero-buffer 'backend)) | ||||
|          (name (format "*intero:%s:%s:repl*" | ||||
|                        (file-name-nondirectory root) | ||||
|                        package-name)) | ||||
|          (setting ":set -fno-defer-out-of-scope-variables\n")) | ||||
|     (when (get-buffer name) | ||||
|       (with-current-buffer (get-buffer name) | ||||
|         (goto-char (point-max)) | ||||
|         (let ((process (get-buffer-process (current-buffer)))) | ||||
|           (when process (process-send-string process setting))))))) | ||||
| 
 | ||||
| ;; Brute-force fix: Ensure the setting is injected every time the REPL | ||||
| ;; is selected. | ||||
| ;; | ||||
| ;; Upstream issue: https://github.com/commercialhaskell/intero/issues/569 | ||||
| (advice-add 'intero-repl :after (lambda (&rest r) (intero-fix-ghci-panic)) | ||||
|             '((name . intero-panic-fix))) | ||||
| (advice-add 'intero-repl-load :after (lambda (&rest r) (intero-fix-ghci-panic)) | ||||
|             '((name . intero-panic-fix))) | ||||
| 
 | ||||
| (provide 'functions) | ||||
							
								
								
									
										115
									
								
								tools/emacs/init/look-and-feel.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								tools/emacs/init/look-and-feel.el
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,115 @@ | |||
| ;;; -*- lexical-binding: t; -*- | ||||
| 
 | ||||
| ;; Hide those ugly tool bars: | ||||
| (tool-bar-mode 0) | ||||
| (scroll-bar-mode 0) | ||||
| (menu-bar-mode 0) | ||||
| (add-hook 'after-make-frame-functions | ||||
|           (lambda (frame) (scroll-bar-mode 0))) | ||||
| 
 | ||||
| ;; Don't do any annoying things: | ||||
| (setq ring-bell-function 'ignore) | ||||
| (setq initial-scratch-message "") | ||||
| 
 | ||||
| ;; Remember layout changes | ||||
| (winner-mode 1) | ||||
| 
 | ||||
| ;; Usually emacs will run as a proper GUI application, in which case a few | ||||
| ;; extra settings are nice-to-have: | ||||
| (when window-system | ||||
|   (setq frame-title-format '(buffer-file-name "%f" ("%b"))) | ||||
|   (mouse-wheel-mode t) | ||||
|   (blink-cursor-mode -1)) | ||||
| 
 | ||||
| ;; Configure editor fonts | ||||
| (let ((font (format "Input Mono-%d" 12))) | ||||
|   (setq default-frame-alist `((font-backend . "xft") | ||||
|                               (font . ,font))) | ||||
|   (set-frame-font font t t)) | ||||
| 
 | ||||
| ;; Display battery in mode-line's misc section on adho: | ||||
| (when (equal "adho" (system-name)) | ||||
|   (setq battery-mode-line-format " %b%p%%") | ||||
|   (display-battery-mode)) | ||||
| 
 | ||||
| ;; Configure telephone-line | ||||
| (defun telephone-misc-if-last-window () | ||||
|   "Renders the mode-line-misc-info string for display in the | ||||
|   mode-line if the currently active window is the last one in the | ||||
|   frame. | ||||
| 
 | ||||
|   The idea is to not display information like the current time, | ||||
|   load, battery levels in all buffers." | ||||
| 
 | ||||
|   (when (bottom-right-window-p) | ||||
|       (telephone-line-raw mode-line-misc-info t))) | ||||
| 
 | ||||
| (defun telephone-line-setup () | ||||
|   (telephone-line-defsegment telephone-line-last-window-segment () | ||||
|     (telephone-misc-if-last-window)) | ||||
| 
 | ||||
|   ;; Display the current EXWM workspace index in the mode-line | ||||
|   (telephone-line-defsegment telephone-line-exwm-workspace-index () | ||||
|     (when (bottom-right-window-p) | ||||
|       (format "[%s]" exwm-workspace-current-index))) | ||||
| 
 | ||||
|   ;; Define a highlight font for ~ important ~ information in the last | ||||
|   ;; window. | ||||
|   (defface special-highlight '((t (:foreground "white" :background "#5f627f"))) "") | ||||
|   (add-to-list 'telephone-line-faces | ||||
|                '(highlight . (special-highlight . special-highlight))) | ||||
| 
 | ||||
|   (setq telephone-line-lhs | ||||
|         '((nil . (telephone-line-position-segment)) | ||||
|           (accent . (telephone-line-buffer-segment)))) | ||||
| 
 | ||||
|   (setq telephone-line-rhs | ||||
|         '((accent . (telephone-line-major-mode-segment)) | ||||
|           (nil . (telephone-line-last-window-segment | ||||
|                   telephone-line-exwm-workspace-index)) | ||||
|           (highlight . (telephone-line-notmuch-counts)))) | ||||
| 
 | ||||
|   (setq telephone-line-primary-left-separator 'telephone-line-tan-left | ||||
|         telephone-line-primary-right-separator 'telephone-line-tan-right | ||||
|         telephone-line-secondary-left-separator 'telephone-line-tan-hollow-left | ||||
|         telephone-line-secondary-right-separator 'telephone-line-tan-hollow-right) | ||||
| 
 | ||||
|   (telephone-line-mode 1)) | ||||
| 
 | ||||
| ;; Auto refresh buffers | ||||
| (global-auto-revert-mode 1) | ||||
| 
 | ||||
| ;; Use clipboard properly | ||||
| (setq select-enable-clipboard t) | ||||
| 
 | ||||
| ;; Show in-progress chords in minibuffer | ||||
| (setq echo-keystrokes 0.1) | ||||
| 
 | ||||
| ;; Show column numbers in all buffers | ||||
| (column-number-mode t) | ||||
| 
 | ||||
| ;; Highlight currently active line | ||||
| (global-hl-line-mode t) | ||||
| 
 | ||||
| (defalias 'yes-or-no-p 'y-or-n-p) | ||||
| (defalias 'auto-tail-revert-mode 'tail-mode) | ||||
| 
 | ||||
| ;; Style line numbers (shown with M-g g) | ||||
| (setq linum-format | ||||
|       (lambda (line) | ||||
|         (propertize | ||||
|          (format (concat " %" | ||||
|                          (number-to-string | ||||
|                           (length (number-to-string | ||||
|                                    (line-number-at-pos (point-max))))) | ||||
|                          "d ") | ||||
|                  line) | ||||
|          'face 'linum))) | ||||
| 
 | ||||
| ;; Display tabs as 2 spaces | ||||
| (setq tab-width 2) | ||||
| 
 | ||||
| ;; Don't wrap around when moving between buffers | ||||
| (setq windmove-wrap-around nil) | ||||
| 
 | ||||
| (provide 'look-and-feel) | ||||
							
								
								
									
										98
									
								
								tools/emacs/init/mail-setup.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								tools/emacs/init/mail-setup.el
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,98 @@ | |||
| (require 'notmuch) | ||||
| (require 'counsel-notmuch) | ||||
| 
 | ||||
| (global-set-key (kbd "C-c m") 'notmuch-hello) | ||||
| (global-set-key (kbd "C-c C-m") 'counsel-notmuch) | ||||
| (global-set-key (kbd "C-c C-e n") 'notmuch-mua-new-mail) | ||||
| 
 | ||||
| (setq notmuch-cache-dir (format "%s/.cache/notmuch" (getenv "HOME"))) | ||||
| (make-directory notmuch-cache-dir t) | ||||
| 
 | ||||
| ;; Cache addresses for completion: | ||||
| (setq notmuch-address-save-filename (concat notmuch-cache-dir "/addresses")) | ||||
| 
 | ||||
| ;; Don't spam my home folder with drafts: | ||||
| (setq notmuch-draft-folder "drafts") ;; relative to notmuch database | ||||
| 
 | ||||
| ;; Mark things as read when archiving them: | ||||
| (setq notmuch-archive-tags '("-inbox" "-unread" "+archive")) | ||||
| 
 | ||||
| ;; Show me saved searches that I care about: | ||||
| (setq notmuch-saved-searches | ||||
|       '((:name "inbox" :query "tag:inbox" :count-query "tag:inbox AND tag:unread" :key "i") | ||||
|         (:name "aprila-dev" :query "tag:aprila-dev" :count-query "tag:aprila-dev AND tag:unread" :key "d") | ||||
|         (:name "gitlab" :query "tag:gitlab" :key "g") | ||||
|         (:name "sent" :query "tag:sent" :key "t") | ||||
|         (:name "drafts" :query "tag:draft"))) | ||||
| (setq notmuch-show-empty-saved-searches t) | ||||
| 
 | ||||
| ;; Mail sending configuration | ||||
| (setq send-mail-function 'sendmail-send-it) ;; sendmail provided by MSMTP | ||||
| (setq notmuch-always-prompt-for-sender t) | ||||
| (setq notmuch-mua-user-agent-function | ||||
|       (lambda () (format "Emacs %s; notmuch.el %s" emacs-version notmuch-emacs-version))) | ||||
| (setq mail-host-address (system-name)) | ||||
| (setq notmuch-mua-cite-function #'message-cite-original-without-signature) | ||||
| 
 | ||||
| ;; Close mail buffers after sending mail | ||||
| (setq message-kill-buffer-on-exit t) | ||||
| 
 | ||||
| ;; Ensure sender is correctly passed to msmtp | ||||
| (setq mail-specify-envelope-from t | ||||
|       message-sendmail-envelope-from 'header | ||||
|       mail-envelope-from 'header) | ||||
| 
 | ||||
| ;; Store sent mail in the correct folder per account | ||||
| (setq notmuch-maildir-use-notmuch-insert nil) | ||||
| (setq notmuch-fcc-dirs '(("mail@tazj.in" . "tazjin/Sent") | ||||
|                          ;; Not a mistake, Office365 apparently | ||||
|                          ;; renames IMAP folders (!) to your local | ||||
|                          ;; language instead of providing translations | ||||
|                          ;; in the UI m( | ||||
|                          ("vincent@aprila.no" . "aprila/Sende element"))) | ||||
| 
 | ||||
| ;; I don't use drafts but I instinctively hit C-x C-s constantly, lets | ||||
| ;; handle that gracefully. | ||||
| (define-key notmuch-message-mode-map (kbd "C-x C-s") #'ignore) | ||||
| 
 | ||||
| ;; MSMTP decrypts passwords using pass, but pinentry doesn't work | ||||
| ;; correctly in that setup. This forces a warmup of the GPG agent | ||||
| ;; before sending the message. | ||||
| ;; | ||||
| ;; Note that the sending function is advised because the provided hook | ||||
| ;; for this seems to run at the wrong time. | ||||
| (advice-add 'notmuch-mua-send-common :before 'warmup-gpg-agent) | ||||
| 
 | ||||
| ;; Define a telephone-line segment for displaying the count of unread, | ||||
| ;; important mails in the last window's mode-line: | ||||
| (defvar *last-notmuch-count-redraw* 0) | ||||
| (defvar *current-notmuch-count* nil) | ||||
| 
 | ||||
| (defun update-display-notmuch-counts () | ||||
|   "Update and render the current state of the notmuch unread | ||||
|   count for display in the mode-line. | ||||
| 
 | ||||
|   The offlineimap-timer runs every 2 minutes, so it does not make | ||||
|   sense to refresh this much more often than that." | ||||
| 
 | ||||
|   (when (> (- (float-time) *last-notmuch-count-redraw*) 30) | ||||
|     (setq *last-notmuch-count-redraw* (float-time)) | ||||
|     (let* ((inbox-unread (notmuch-saved-search-count "tag:inbox and tag:unread")) | ||||
|            (devel-unread (notmuch-saved-search-count "tag:aprila-dev and tag:unread")) | ||||
|            (notmuch-count (format "I: %s; D: %s" inbox-unread devel-unread))) | ||||
|       (setq *current-notmuch-count* notmuch-count))) | ||||
| 
 | ||||
|   (when (and (bottom-right-window-p) | ||||
|              ;; Only render if the initial update is done and there | ||||
|              ;; are unread mails: | ||||
|              *current-notmuch-count* | ||||
|              (not (equal *current-notmuch-count* "I: 0; D: 0"))) | ||||
|     *current-notmuch-count*)) | ||||
| 
 | ||||
| (telephone-line-defsegment telephone-line-notmuch-counts () | ||||
|   "This segment displays the count of unread notmuch messages in | ||||
|   the last window's mode-line (if unread messages are present)." | ||||
| 
 | ||||
|   (update-display-notmuch-counts)) | ||||
| 
 | ||||
| (provide 'mail-setup) | ||||
							
								
								
									
										36
									
								
								tools/emacs/init/modes.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								tools/emacs/init/modes.el
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| ;; Initializes modes I use. | ||||
| 
 | ||||
| (add-hook 'prog-mode-hook 'esk-add-watchwords) | ||||
| 
 | ||||
| ;; Use auto-complete as completion at point | ||||
| (defun set-auto-complete-as-completion-at-point-function () | ||||
|   (setq completion-at-point-functions '(auto-complete))) | ||||
| 
 | ||||
| (add-hook 'auto-complete-mode-hook | ||||
|           'set-auto-complete-as-completion-at-point-function) | ||||
| 
 | ||||
| ;; Enable rainbow-delimiters for all things programming | ||||
| (add-hook 'prog-mode-hook 'rainbow-delimiters-mode) | ||||
| 
 | ||||
| ;; Enable Paredit & Company in Emacs Lisp mode | ||||
| (add-hook 'emacs-lisp-mode-hook 'company-mode) | ||||
| 
 | ||||
| ;; Always highlight matching brackets | ||||
| (show-paren-mode 1) | ||||
| 
 | ||||
| ;; Always auto-close parantheses and other pairs | ||||
| ;; (replaced by smartparens) | ||||
| ;; (electric-pair-mode) | ||||
| 
 | ||||
| ;; Keep track of recent files | ||||
| (recentf-mode) | ||||
| 
 | ||||
| ;; Easily navigate sillycased words | ||||
| (global-subword-mode 1) | ||||
| 
 | ||||
| ;; Transparently open compressed files | ||||
| (auto-compression-mode t) | ||||
| 
 | ||||
| ;; Show available key chord completions | ||||
| 
 | ||||
| (provide 'modes) | ||||
							
								
								
									
										103
									
								
								tools/emacs/init/nixos.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								tools/emacs/init/nixos.el
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,103 @@ | |||
| ;; Configure additional settings if this is one of my NixOS machines | ||||
| ;; (i.e. if ExWM is required) | ||||
| ;; -*- lexical-binding: t; -*- | ||||
| 
 | ||||
| (require 's) | ||||
| (require 'f) | ||||
| (require 'dash) | ||||
| 
 | ||||
| (defun pulseaudio-ctl (cmd) | ||||
|   (shell-command (concat "pulseaudio-ctl " cmd)) | ||||
|   (message "Volume command: %s" cmd)) | ||||
| 
 | ||||
| (defun volume-mute () (interactive) (pulseaudio-ctl "mute")) | ||||
| (defun volume-up () (interactive) (pulseaudio-ctl "up")) | ||||
| (defun volume-down () (interactive) (pulseaudio-ctl "down")) | ||||
| 
 | ||||
| (defun brightness-up () | ||||
|   (interactive) | ||||
|   (shell-command "exec light -A 10") | ||||
|   (message "Brightness increased")) | ||||
| 
 | ||||
| (defun brightness-down () | ||||
|   (interactive) | ||||
|   (shell-command "exec light -U 10") | ||||
|   (message "Brightness decreased")) | ||||
| 
 | ||||
| (defun lock-screen () | ||||
|   (interactive) | ||||
|   (shell-command "screen-lock")) | ||||
| 
 | ||||
| (defun generate-randr-config () | ||||
|   (-flatten `(,(-map (lambda (n) (list n "DP2")) (number-sequence 1 7)) | ||||
|               (0 "eDP1") | ||||
|               ,(-map (lambda (n) (list n "eDP1")) (number-sequence 8 9))))) | ||||
| 
 | ||||
| (use-package exwm | ||||
|   :hook ((exwm-update-class . (lambda () | ||||
|                                 ;; Make class name the buffer name | ||||
|                                 (exwm-workspace-rename-buffer exwm-class-name)))) | ||||
|   :init | ||||
|   (progn | ||||
|     (require 'exwm-config) | ||||
| 
 | ||||
|     (fringe-mode 3) | ||||
| 
 | ||||
|     (setq exwm-workspace-number 10) | ||||
| 
 | ||||
|     ;; 's-r': Reset | ||||
|     (exwm-input-set-key (kbd "s-r") #'exwm-reset) | ||||
|     ;; 's-w': Switch workspace | ||||
|     (exwm-input-set-key (kbd "s-w") #'exwm-workspace-switch) | ||||
|     ;; 's-N': Switch to certain workspace | ||||
|     (dotimes (i 10) | ||||
|       (exwm-input-set-key (kbd (format "s-%d" i)) | ||||
|                           `(lambda () | ||||
|                              (interactive) | ||||
|                              (exwm-workspace-switch-create ,i)))) | ||||
| 
 | ||||
|     ;; Launch applications with completion (dmenu style!) | ||||
|     (exwm-input-set-key (kbd "s-d") #'ivy-run-external-command) | ||||
|     (exwm-input-set-key (kbd "s-p") #'ivy-password-store) | ||||
|     (exwm-input-set-key (kbd "C-s-p") '(lambda () | ||||
|                                          (interactive) | ||||
|                                          (ivy-password-store "~/.aprila-secrets"))) | ||||
| 
 | ||||
|     ;; Add Alacritty selector to a key | ||||
|     (exwm-input-set-key (kbd "C-x t") #'counsel-switch-to-alacritty) | ||||
| 
 | ||||
|     ;; Toggle between line-mode / char-mode | ||||
|     (exwm-input-set-key (kbd "C-c C-t C-t") #'exwm-input-toggle-keyboard) | ||||
| 
 | ||||
|     ;; Volume keys | ||||
|     (exwm-input-set-key (kbd "<XF86AudioMute>") #'volume-mute) | ||||
|     (exwm-input-set-key (kbd "<XF86AudioRaiseVolume>") #'volume-up) | ||||
|     (exwm-input-set-key (kbd "<XF86AudioLowerVolume>") #'volume-down) | ||||
| 
 | ||||
|     ;; Brightness keys | ||||
|     (exwm-input-set-key (kbd "<XF86MonBrightnessDown>") #'brightness-down) | ||||
|     (exwm-input-set-key (kbd "<XF86MonBrightnessUp>") #'brightness-up) | ||||
|     (exwm-input-set-key (kbd "<XF86Display>") #'lock-screen) | ||||
| 
 | ||||
|     ;; Line-editing shortcuts | ||||
|     (exwm-input-set-simulation-keys | ||||
|      '(([?\C-d] . delete) | ||||
|        ([?\C-w] . ?\C-c))) | ||||
| 
 | ||||
|     ;; Enable EXWM | ||||
|     (exwm-enable) | ||||
| 
 | ||||
|     ;; Show time in the mode line | ||||
|     (display-time-mode) | ||||
| 
 | ||||
|     ;; Configure xrandr when running on laptop | ||||
|     (when (equal (shell-command-to-string "hostname") "adho\n") | ||||
|       (require 'exwm-randr) | ||||
|       (setq exwm-randr-workspace-output-plist (generate-randr-config)) | ||||
|       (exwm-randr-enable)) | ||||
| 
 | ||||
|     ;; Let buffers move seamlessly between workspaces | ||||
|     (setq exwm-workspace-show-all-buffers t) | ||||
|     (setq exwm-layout-show-all-buffers t))) | ||||
| 
 | ||||
| (provide 'nixos) | ||||
							
								
								
									
										65
									
								
								tools/emacs/init/settings.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								tools/emacs/init/settings.el
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,65 @@ | |||
| (require 'prescient) | ||||
| (require 'ivy-prescient) | ||||
| (require 'uniquify) | ||||
| (require 'ivy-pass) | ||||
| 
 | ||||
| ;; Make ivy go! | ||||
| (ivy-mode 1) | ||||
| (counsel-mode 1) | ||||
| 
 | ||||
| (setq ivy-use-virtual-buffers t) | ||||
| (setq enable-recursive-minibuffers t) | ||||
| 
 | ||||
| ;; Enable support for prescient in ivy & configure it | ||||
| (ivy-prescient-mode) | ||||
| (prescient-persist-mode) | ||||
| (add-to-list 'ivy-prescient-excluded-commands 'counsel-rg) | ||||
| 
 | ||||
| ;; Move files to trash when deleting | ||||
| (setq delete-by-moving-to-trash t) | ||||
| 
 | ||||
| ;; We don't live in the 80s, but we're also not a shitty web app. | ||||
| (setq gc-cons-threshold 20000000) | ||||
| 
 | ||||
| (setq uniquify-buffer-name-style 'forward) | ||||
| 
 | ||||
| ; Fix some defaults | ||||
| (setq visible-bell nil | ||||
|       inhibit-startup-message t | ||||
|       color-theme-is-global t | ||||
|       sentence-end-double-space nil | ||||
|       shift-select-mode nil | ||||
|       uniquify-buffer-name-style 'forward | ||||
|       whitespace-style '(face trailing lines-tail tabs) | ||||
|       whitespace-line-column 80 | ||||
|       default-directory "~" | ||||
|       fill-column 80 | ||||
|       ediff-split-window-function 'split-window-horizontally) | ||||
| 
 | ||||
| (add-to-list 'safe-local-variable-values '(lexical-binding . t)) | ||||
| (add-to-list 'safe-local-variable-values '(whitespace-line-column . 80)) | ||||
| 
 | ||||
| (set-default 'indent-tabs-mode nil) | ||||
| 
 | ||||
| ;; UTF-8 please | ||||
| (setq locale-coding-system 'utf-8) ; pretty | ||||
| (set-terminal-coding-system 'utf-8) ; pretty | ||||
| (set-keyboard-coding-system 'utf-8) ; pretty | ||||
| (set-selection-coding-system 'utf-8) ; please | ||||
| (prefer-coding-system 'utf-8) ; with sugar on top | ||||
| 
 | ||||
| ;; Make emacs behave sanely (overwrite selected text) | ||||
| (delete-selection-mode 1) | ||||
| 
 | ||||
| ;; Keep your temporary files in tmp, emacs! | ||||
| (setq auto-save-file-name-transforms | ||||
|       `((".*" ,temporary-file-directory t))) | ||||
| (setq backup-directory-alist | ||||
|       `((".*" . ,temporary-file-directory))) | ||||
| 
 | ||||
| (remove-hook 'kill-buffer-query-functions 'server-kill-buffer-query-function) | ||||
| 
 | ||||
| ;; Show time in 24h format | ||||
| (setq display-time-24hr-format t) | ||||
| 
 | ||||
| (provide 'settings) | ||||
							
								
								
									
										37
									
								
								tools/emacs/init/term-setup.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								tools/emacs/init/term-setup.el
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| ;; Utilities for Alacritty buffers. | ||||
| 
 | ||||
| (defun open-or-create-alacritty-buffer (buffer-name) | ||||
|   "Switch to the buffer with BUFFER-NAME or create a | ||||
|   new buffer running Alacritty." | ||||
|   (let ((buffer (get-buffer buffer-name))) | ||||
|     (if (not buffer) | ||||
|         (run-external-command "alacritty") | ||||
|       (switch-to-buffer buffer)))) | ||||
| 
 | ||||
| (defun is-alacritty-buffer (buffer) | ||||
|   "Determine whether BUFFER runs Alacritty." | ||||
|   (and (equal 'exwm-mode (buffer-local-value 'major-mode buffer)) | ||||
|        (s-starts-with? "Alacritty" (buffer-name buffer)))) | ||||
| 
 | ||||
| (defun counsel-switch-to-alacritty () | ||||
|   "Switch to a (multi-)term buffer or create one." | ||||
|   (interactive) | ||||
|   (let ((terms (-map #'buffer-name | ||||
|                      (-filter #'is-alacritty-buffer (buffer-list))))) | ||||
|     (if terms | ||||
|         (ivy-read "Switch to Alacritty buffer: " | ||||
|                   (cons "New terminal" terms) | ||||
|                   :caller 'counsel-switch-to-alacritty | ||||
|                   :require-match t | ||||
|                   :action #'open-or-create-alacritty-buffer) | ||||
|       (run-external-command "alacritty")))) | ||||
| 
 | ||||
| (defun alacritty-rename () | ||||
|   "Rename the current terminal buffer." | ||||
|   (interactive) | ||||
|   (let* ((buffer (get-buffer (buffer-name)))) | ||||
|     (if (is-alacritty-buffer buffer) | ||||
|         (rename-buffer (format "Alacritty<%s>" (read-string "New terminal name: "))) | ||||
|       (error "This function is only intended to rename Alacritty buffers.")))) | ||||
| 
 | ||||
| (provide 'term-setup) | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue