;;; bandali-utils.el --- useful utilities -*- lexical-binding: t; -*- ;; Copyright (c) 2018-2025 Amin Bandali ;; Author: Amin Bandali ;; Keywords: convenience ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; Some useful utilities. ;;; Code: (defun b/insert-asterism () "Insert a centred asterism." (interactive) (let ((asterism "* * *")) (insert (concat "\n" (make-string (floor (/ (- fill-column (length asterism)) 2)) ?\s) asterism "\n")))) (defun b/join-line-top () "Like `join-line', but join next line to the current line." (interactive) (join-line 1)) (defun b/*scratch* () "Switch to `*scratch*' buffer, creating it if it does not exist." (interactive) (let ((fun (if (functionp #'get-scratch-buffer-create) #'get-scratch-buffer-create ; (version<= "29" emacs-version) #'startup--get-buffer-create-scratch))) ; (version< emacs-version "29") (switch-to-buffer (funcall fun)))) (defun b/duplicate-line-or-region (&optional n) "Duplicate the current line, or region (if active). Make N (default: 1) copies of the current line or region." (interactive "*p") (let ((u-r-p (use-region-p)) ; if region is active (n1 (or n 1))) (save-excursion (let ((text (if u-r-p (buffer-substring (region-beginning) (region-end)) (prog1 (thing-at-point 'line) (end-of-line) (if (eobp) (newline) (forward-line 1)))))) (dotimes (_ (abs n1)) (insert text)))))) (defun b/invert-default-face (arg) "Invert the `default' and `mode-line' faces for the current frame. Swap the background and foreground for the two `default' and `mode-line' faces, effectively acting like a simple light/dark theme toggle. If prefix argument ARG is given, invert the faces for all frames." (interactive "P") (let ((frame (unless arg (selected-frame)))) (invert-face 'default frame) (invert-face 'mode-line frame) (when (fboundp #'exwm-systemtray--refresh-background-color) (exwm-systemtray--refresh-background-color 'remap)))) (defun b/unfill-paragraph-or-region (&optional beg end) "Unfill paragraph, or region (if active)." (interactive "r") (let ((fill-column most-positive-fixnum)) (if (use-region-p) (fill-region beg end) (fill-paragraph)))) (defun b/setq-local-indent-tabs-mode-nil () "Locally disable indent-tabs-mode. Useful mainly as a hook for other modes." (setq-local indent-tabs-mode nil)) ;;; Key bindings (b/keymap-global-set "C-c s c" #'b/*scratch*) (b/keymap-global-set "C-c d" #'b/duplicate-line-or-region) (b/keymap-global-set "C-c j" #'b/join-line-top) (b/keymap-global-set "C-S-j" #'b/join-line-top) (b/keymap-global-set "C-c v" #'b/invert-default-face) (b/keymap-global-set "C-c q" #'b/unfill-paragraph-or-region) (b/keymap-set text-mode-map "M-RET" #'b/insert-asterism) (provide 'bandali-utils) ;;; bandali-utils.el ends here