itch

Switch to and create scratch buffers
git clone https://git.jamzattack.xyz/itch
Log | Files | Refs | LICENSE

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