diff options
-rw-r--r-- | README.org | 105 | ||||
-rw-r--r-- | iota.el | 67 |
2 files changed, 172 insertions, 0 deletions
diff --git a/README.org b/README.org new file mode 100644 index 0000000..a4b9c1b --- /dev/null +++ b/README.org @@ -0,0 +1,105 @@ +#+TITLE: iota.el +#+AUTHOR: Thomas Voss +#+DESCRIPTION: Simple- and easy Emacs enumerations + +Iota is a very simple Emacs package that allows you to easily perform +enumerations. It makes use of the ~iota-regexp~ variable to match substrings +within a region. These substrings are then replaced with incrementing integers, +although more complex enumeration is also possible. + +* Installation + +Iota is available through MELPA: + +#+BEGIN_SRC elisp + + (use-package iota) + +#+END_SRC + +It’s recommended however that you bind the Iota functions to keybindings for +easy access: + +#+BEGIN_SRC elisp + + (use-package iota + :bind (("C-c i" . #'iota) + ("C-c I" . #'iota-complex))) + +#+END_SRC + +* Usage + +One important part of Iota is the ~iota-regexp~ variable. By default +~iota-regexp~ is set to ~"\\<N\\>"~, so to create an ordered-list you could +execute ~iota~ on the following region: + +#+BEGIN_EXAMPLE + +Before calling ‘iota’: + + N. List item + N. Another list item + N. Final list item + +After calling ‘iota’: + + 1. List item + 2. Another list item + 3. Final list item + +#+END_EXAMPLE + +By default the ~iota~ function replaces all matches with an incrementing number +beginning with 1, however you can begin at any point by specifying the universal +argument. For example, to begin the list above at 4, you could run =C-u 4 M-x +iota RET=. + +If for whatever reason however you want something that isn’t increments by 1, +then you can make use of the ~iota-complex~ function. ~iota-complex~ works +mostly the same as ~iota~ except you get prompted for two values. The first +value is the initial value to start at. The second and perhaps more interesting +value is the function to use to generate the next numerical value. You can +provide any valid emacs-lisp expression so long as it evaluates to a function +that takes one numerical parameter and returns an integer: + +#+BEGIN_EXAMPLE + +Before calling ‘iota-complex’: + + #define BIT1 N + #define BIT2 N + #define BIT3 N + #define BIT4 N + #define BIT5 N + #define BIT6 N + #define BIT7 N + #define BIT8 N + +After calling ‘iota-complex’ with ‘initial’ as 1 and ‘function’ as +‘(lambda (x) (* 2 x))’: + + #define BIT1 1 + #define BIT2 2 + #define BIT3 4 + #define BIT4 8 + #define BIT5 16 + #define BIT6 32 + #define BIT7 64 + #define BIT8 128 + +#+END_EXAMPLE + +Or perhaps if you want to enumerate in the negative direction: + +#+BEGIN_EXAMPLE + +Before calling ‘iota-complex’: + + It started at N and then dropped to N! + +After calling ‘iota-complex’ with ‘initial’ as ‘-3’ and ‘function’ as ‘1-’: + + It started at -3 and then dropped to -4! + +#+END_EXAMPLE @@ -0,0 +1,67 @@ +;;; iota.el --- Replace marker with increasing integers + +;; Copyright © 2023 Thomas Voss + +;; Author: Thomas Voss <mail@thomasvoss.com> +;; Keywords: accumulator increment +;; URL: https://git.sr.ht/~mango/iota +;; Version: 1.0.0 + +;; Permission to use, copy, modify, and/or distribute this software for any +;; purpose with or without fee is hereby granted. +;; +;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +;; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +;; AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +;; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +;; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +;; OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +;; PERFORMANCE OF THIS SOFTWARE. + +;;; Commentary: + +;; Iota is a very simple package that provides an easy way to replace strings in +;; a region with an incrementing count. This can be useful in a variety of +;; settings for doing things such as creating numbered lists, creating +;; enumerations, and more. The substrings to match are defined by the variable +;; ‘iota-regexp’ while the functions ‘iota’ and ‘iota-complex’ offer simple- and +;; advanced methods of enumeration. You probably do not want to use these +;; functions in your emacs-lisp code; they are intended for interactive use. + +;;; Code: + +(defcustom iota-regexp "\\<N\\>" + "Regular expression to match substrings that should be replaced with the +accumulator." + :type '(regexp)) + +(defun iota (start end &optional initial) + "Replace all substrings in the region of START and END that match the regular +expression defined by ‘iota-regexp’ with incrementing integers beginning with +INITIAL or 1 if INITIAL is nil. When called interactively, the universal +argument can be used to specify INITIAL." + (interactive "*r\np") + (iota--internal start end initial #'1+)) + +(defun iota-complex (start end &optional initial function) + "Replace all substrings in the region of START and END that match the regular +expression defined by ‘iota-regexp’ with the result of calling FUNCTION with the +argument N which starts at INITIAL and increments by 1 every replacement." + (interactive "*r\nnInitial value: \nxFunction: ") + (iota--internal start end initial function)) + +(defun iota--internal (start end initial function) + (let ((m1 (make-marker)) + (m2 (make-marker)) + (initial (or initial 1))) + (set-marker m1 start) + (set-marker m2 end) + (save-mark-and-excursion + (save-match-data + (goto-char m1) + (while (re-search-forward iota-regexp m2 'noerror) + (replace-match (int-to-string initial)) + (setq initial (apply function initial nil))))))) + +(provide 'iota) +;;; iota.el ends here |