aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.org105
-rw-r--r--iota.el67
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
diff --git a/iota.el b/iota.el
new file mode 100644
index 0000000..0d1c8cc
--- /dev/null
+++ b/iota.el
@@ -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