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
				
			
		
							
								
								
									
										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