;; -*- lexical-binding: t -*- ;;; Compilation (setq compile-command "make ") ;; C-m functions as \r, so pressing C-x C-m C-m will call compile and skip the prompt. (global-set-key (kbd "C-x C-m") 'compile) ;; Nicer movement in compilation-mode. (add-hook 'compilation-mode-hook (lambda () (local-set-key (kbd "n") 'compilation-next-error))) (add-hook 'compilation-mode-hook (lambda () (local-set-key (kbd "p") 'compilation-previous-error))) ;; Function for selecting the current line. (defun fez/mark-line () "Selects the current line with the mark." (interactive) (move-beginning-of-line nil) (set-mark (point)) (next-line)) (defun fez/toggle-indent () "Toggle between indenting with tabs or spaces." (interactive) (setq-default indent-tabs-mode (not indent-tabs-mode))) (defun fez/current-line-empty-p () "Checks if the current line is empty or not." (save-excursion (beginning-of-line) (looking-at-p "[[:space:]]*$"))) (defun fez/current-line-comment-p () "Checks if the current line is a commented out one or not." (save-excursion (beginning-of-line) (let ((a (point))) (end-of-line) (let ((b (point))) (comment-only-p a b))))) (defun fez/flash-region (&optional timeout) "Temporarily highlight region from START to END. Taken from SLIME source code and modified." (interactive) (transient-mark-mode) (save-excursion (mark-defun) ;; Don't mark the line or the comments above the s-expression. (while (or (fez/current-line-empty-p) (fez/current-line-comment-p)) ;; Can probably be optimized... (forward-char)) (let* ((start (region-beginning)) (end (region-end)) (overlay (make-overlay start end))) (deactivate-mark) (overlay-put overlay 'face 'secondary-selection) (run-with-timer (or timeout 0.2) nil 'delete-overlay overlay))) (transient-mark-mode)) (defun fez/insert-keybind () "Prompts the user for a key combination like C-h k does, then inserts that key combination." (interactive) (insert (concat "(kbd \"" (key-description (read-key-sequence-vector "Key sequence: ")) "\")"))) (defun fez/time-stamp () "Insert the current date." (interactive) (shell-command "LANG=nb_NO.UTF-8 date +%Y-%m-%d" t)) (defun fez/kill-all-buffers () "Kill all buffers other than the currently active one." (interactive) (mapc #'kill-buffer (delete (current-buffer) (buffer-list)))) (defun fez/view-kill-ring () "Display the kill ring in a buffer." (interactive) (get-buffer-create "*kill-buffer*") (switch-to-buffer-other-window "*kill-buffer*") (erase-buffer) (dolist (l (reverse kill-ring)) (insert l))) (defun fez/lookup-key () "Search for KEY in all known keymaps (outputs to *Messages*)" (interactive) (let ((key (read-key-sequence-vector "Key sequence: "))) (mapatoms (lambda (ob) (when (and (boundp ob) (keymapp (symbol-value ob))) (when (functionp (lookup-key (symbol-value ob) key)) (message (symbol-name ob))))) obarray))) (defun fez/ttm-upload () "Upload file in selected buffer to ttm.sh and output the link in the echo area (and in *Messages*)" (interactive) (let ((link (shell-command-to-string (concat "curl -Ffile=@" (buffer-file-name) " https://ttm.sh -s")))) (message "%s" link) (kill-new link))) (defun fez/last-occurrence-of-char (c) "Go to the previous occurrence of C in the current buffer." (interactive) (when (equal (following-char) c) (backward-char)) (while (not (equal (following-char) c)) (backward-char))) (defun fez/last-open-paren () (interactive) (fez/last-occurrence-of-char ?\()) (defun fez/send-vterm-command (cmd) "Executes CMD in a vterm buffer." (kill-new cmd) (vterm-yank) (vterm-send-return)) (defun fez/cl () "Prepares the environment for Common Lisp development." (interactive) (let ((original-buffer (current-buffer))) (vterm) (let ((vterm-buffer (current-buffer))) (fez/send-vterm-command "slystart") (switch-to-buffer original-buffer) ;; This is probably useless for anyone that doesn't use frames-only-mode (make-frame-command) (switch-to-buffer vterm-buffer))) (sleep-for 1) (sly-connect "localhost" 4005)) (defmacro fez/save-buffer-excursion (&rest body) (declare (indent defun)) (let ((original-buffer (gensym))) `(let ((,original-buffer (current-buffer))) ,@body (switch-to-buffer ,original-buffer)))) (defun fez/goto-first-occurrence (str) (goto-char (point-min)) (search-forward-regexp str) (beginning-of-thing 'symbol)) ;; https://emacs.stackexchange.com/a/33709 (defmacro with-keybinding (map key command &rest body) `(let* ((map ,map) (key ,key) (newcommand ,command) (prevbinding (lookup-key map key))) (unwind-protect (progn (define-key map key newcommand) ,@body) (define-key map key prevbinding)))) (defun fez/org-roam-new-note () "Creates a new org-roam note, and adds an entry to that note in my index.org file." (interactive) (let ((category (read-string "Category: "))) (find-file (concat org-roam-directory "/index.org")) (fez/goto-first-occurrence (concat "^\* " category)) (end-of-line) (newline) (org-cycle) (with-keybinding selectrum-minibuffer-map (kbd "SPC") (lambda () (interactive (insert-char ?-))) (org-roam-insert)))) (setq x-mouse-on t) (setq x-mouse-value "13") (defun fez/toggle-x-mouse () "Toggle the X mouse." (interactive) (setq x-mouse-on (not x-mouse-on)) (shell-command (concat "xinput " (if x-mouse-on "--enable " "--disable ") x-mouse-value)) (message (concat "Mouse " (if x-mouse-on "enabled." "disabled.")))) (defun fez/screenshot () "Prompts the user for a filename and saves a screenshot at that path." (interactive) (let ((path (read-string "Filename: "))) (shell-command (concat "import -window root " path)))) (setq current-layout "nous") (defun fez/swap-keyboard () "Swap between my selected keyboard layouts." (interactive) (cond ((string= current-layout "nous") (setq current-layout "ru")) (t (setq current-layout "nous"))) (shell-command (concat "setxkbmap " current-layout))) (defun fez/change-volume (delta) "Change volume. Delta must be a valid amixer string, like '5%+' or '5%-'" (interactive) (shell-command (concat "amixer sset Master " delta " | grep \"Front Left:\" | head -n 1 | sed 's/\\].*//g' | sed 's/.*\\[//g'"))) (defun fez/man-at-point () (interactive) (let ((word (current-word))) (if word (man word) "Not a word."))) (defun fez/insert-line () (interactive) (move-beginning-of-line nil) (open-line 1)) ;; TODO: Put this in C-mode or something (defun fez/include-guard () (interactive) (let ((guard (concat (upcase (file-name-base (buffer-file-name))) "_H"))) (goto-char (point-min)) (insert (concat "#ifndef " guard "\n#define " guard "\n")) (goto-char (point-max)) (insert (concat "\n\n\n#endif /* " guard " */\n"))) (forward-line -3)) (defun fez/tex-word-count () (interactive) (message (substring (shell-command-to-string (concat "texcount " (buffer-file-name) " | grep \"^Words in text:\"")) 0 -1))) (defun fez/log () "Add entry to daily log." (interactive) (let ((temp-buffer (generate-new-buffer (generate-new-buffer-name "temp-log")))) (switch-to-buffer temp-buffer) (text-mode) (writeroom-mode) (local-set-key (kbd "C-c C-c") (lambda () (interactive) (find-file "~/doc/log.txt") (goto-char (point-max)) (insert "\n") (fez/time-stamp) (goto-char (point-max)) (insert-buffer-substring temp-buffer) (insert "\nHumør:") (save-buffer) (bookmark-set "log.txt") (insert " ") (kill-buffer temp-buffer))))) (defun fez/eshell-new () "Open a new instance of eshell." (interactive) (eshell 'N)) (defun fez/goto-file () "Go to the file associated with the given name in fez/file-keys." (interactive) (let ((match (assoc (completing-read "Key: " fez/file-keys) fez/file-keys))) (when match (find-file (cdr match))))) (defun fez/dired-open-file () "In dired, open the file named on this line in the default application for the filetype." (interactive) (let ((file (dired-get-filename nil t))) (message "Opening %s..." file) (call-process "xdg-open" nil 0 nil file) (message "Opening %s done" file))) ;; Eshell convenience commands. (defalias 'open 'find-file-other-window) (defalias 'clean 'eshell/clear-scrollback) ;;; Keybinds ;; C-x C-z and C-z are normally mapped to suspend-frame, an absolutely useless function. ;; Unbind them before making the keybind useful. (global-unset-key (kbd "C-x C-z")) (global-unset-key (kbd "C-z")) (global-set-key (kbd "C-x C-z") 'fez/mark-line) ;; Better buffer management (smol). (global-set-key (kbd "C-x C-b") 'bs-show) ;; Kill the current buffer and close the window it occupied. (global-set-key (kbd "C-x C-k") (lambda () (interactive) (kill-this-buffer) (when (> (length (window-list)) 1) (delete-window)))) (global-set-key (kbd "C-c t") 'fez/time-stamp) (global-set-key (kbd "C-z C-m") 'fez/man-at-point) (global-set-key (kbd "C-S-o") 'open-line) (global-set-key (kbd "C-o") 'fez/insert-line) (global-set-key (kbd "C-c C-s") 'fez/eshell-new) ;; zap-up-to-char > zap-to-char (global-set-key (kbd "M-z") 'zap-up-to-char) ;; Binds for switching between light and dark themes. (defun fez/switch-theme (new-theme) (lambda () (interactive) (disable-theme (car custom-enabled-themes)) (enable-theme new-theme))) (global-set-key [f5] (fez/switch-theme 'magik)) (global-set-key [f6] (fez/switch-theme 'basic)) (add-hook 'emacs-lisp-mode-hook (lambda () (local-set-key (kbd "C-c k") #'fez/insert-keybind))) ;;; Variables (setq ssh-private-key-location "~/.ssh/id_ed25519") (setq ssh-public-key-location (concat ssh-private-key-location ".pub"))