itch.el (4734B)
1 ;;; itch.el --- Switch to and create scratch buffers -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2020 Jamie Beardslee 4 5 ;; Author: Jamie Beardslee <jdb@jamzattack.xyz> 6 ;; Version: 2020.11.16 7 ;; URL: https://git.jamzattack.xyz/itch 8 ;; Package-Requires: ((emacs "24.3")) 9 ;; Keywords: convenience 10 11 ;; This program is free software; you can redistribute it and/or modify 12 ;; it under the terms of the GNU General Public License as published by 13 ;; the Free Software Foundation, either version 3 of the License, or 14 ;; (at your option) any later version. 15 16 ;; This program is distributed in the hope that it will be useful, 17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 ;; GNU General Public License for more details. 20 21 ;; You should have received a copy of the GNU General Public License 22 ;; along with this program. If not, see <https://www.gnu.org/licenses/>. 23 24 ;;; Commentary: 25 26 ;; This library provides a unified interface to switch to and create 27 ;; buffers of a particular major mode. Basically, I wanted to switch 28 ;; to the scratch buffer quickly but that wasn't high-tech enough. 29 30 ;; - If prefix arg is a number, the buffer is named "NAME<PREFIX>". 31 ;; - e.g. C-2 M-x itch-org RET will switch to "*org*<2>" 32 33 ;; - If prefix arg is (16) (that is, a list whose sole element is the 34 ;; number 16, accessible with a double universal prefix C-u C-u), 35 ;; switch to a buffer chosen from all existing buffers in MODE whose 36 ;; name starts with NAME 37 38 ;; - If the current buffer is in MODE and its name starts with NAME, 39 ;; bury it. 40 41 ;;; Code: 42 43 ;;; Internal function 44 45 (defun itch (mode name &optional prefix post-create-function) 46 "Create a temporary buffer in MODE called NAME. 47 This follows some complex but intuitive logic (in order): 48 - If PREFIX is a number, the buffer is named \"NAME<PREFIX>\" 49 - If PREFIX is (16), switch to a buffer chosen from all existing 50 buffers in MODE whose name starts with NAME 51 - If the current buffer is in MODE and its name starts with NAME, 52 bury it. 53 - If the buffer is newly created (i.e. empty and not narrowed), 54 POST-CREATE-FUNCTION will be called in the new buffer." 55 (let ((buffer-name (cond ((numberp prefix) 56 (format "%s<%d>" name prefix)) 57 ((consp prefix) 58 (generate-new-buffer-name name)) 59 (t 60 name)))) 61 (if (equal prefix '(16)) 62 (setq buffer-name 63 (read-buffer 64 (format "Switch to %s buffer: " mode) name nil 65 (lambda (buffer) 66 (and (string-prefix-p name buffer) 67 (with-current-buffer buffer 68 (eq mode major-mode))))))) 69 (if (and (not prefix) (string-prefix-p name (buffer-name))) 70 (bury-buffer) 71 (let ((buffer (get-buffer-create buffer-name))) 72 (with-current-buffer buffer 73 (unless (derived-mode-p mode) 74 (funcall mode)) 75 (when (and post-create-function 76 (not (buffer-narrowed-p)) 77 (= (point-min) (point-max))) 78 (funcall post-create-function) 79 (set-buffer-modified-p nil))) 80 (pop-to-buffer-same-window buffer))))) 81 82 83 ;;; Putting above function to use 84 85 ;;; Eshell 86 87 (defun itch-eshell (&optional arg) 88 "Create or switch to an eshell buffer. 89 Prefix ARG is passed to `itch'. See its docstring for usage." 90 (interactive "P") 91 (itch 'eshell-mode "*eshell*" arg)) 92 93 (defun itch-switch-to-eshell () 94 "Switch to an existing eshell buffer." 95 (interactive) 96 (itch-eshell '(16))) 97 98 ;;; Elisp 99 100 (defun itch-elisp (&optional arg) 101 "Create or switch to an emacs lisp buffer. 102 Prefix ARG is passed to `itch'. See its docstring for usage." 103 (interactive "P") 104 (itch 'emacs-lisp-mode "*scratch*" arg 105 (lambda () 106 (insert (substitute-command-keys initial-scratch-message))))) 107 108 (defun itch-switch-to-elisp () 109 "Switch to an existing emacs lisp scratch buffer." 110 (interactive) 111 (itch-elisp '(16))) 112 113 ;;; Org 114 115 (defun itch-org (&optional arg) 116 "Create or switch to an org buffer. 117 Prefix ARG is passed to `itch'. See its docstring for usage." 118 (interactive "P") 119 (itch 'org-mode "*org*" arg 120 (lambda () 121 (insert 122 (format "#+title: Temporary buffer %s\n\n" 123 (if (string-match "<\\([0-9]+\\)>" (buffer-name)) 124 (match-string 1 (buffer-name)) 125 1)))))) 126 127 (defun itch-switch-to-org () 128 "Switch to an existing org scratch buffer." 129 (interactive) 130 (itch-org '(16))) 131 132 ;;; Fundamental-mode 133 134 (defun itch-fundamental (&optional arg) 135 "Create or switch to a `fundamental-mode' buffer. 136 Prefix ARG is passed to `itch'. See its docstring for usage." 137 (interactive "P") 138 (itch 'fundamental-mode "*fundamental*" arg nil)) 139 140 (defun itch-switch-to-fundamental () 141 "Switch to an existing `fundamental-mode' scratch buffer." 142 (interactive) 143 (itch-fundamental '(16))) 144 145 (provide 'itch) 146 ;;; itch.el ends here