* auto-version.el [ELPA-ready (?) package #3]
@ 2024-08-17 2:11 Emanuel Berg
0 siblings, 0 replies; only message in thread
From: Emanuel Berg @ 2024-08-17 2:11 UTC (permalink / raw)
To: emacs-devel
I'm gonna forget about everything that has been and just focus
on my own activity.
Skip wordy introduction, go directly to the package:
(re-search-forward ";;; auto-version.el")
Right, so I talked about fun-names.el the other day, and if
that package is fun and useful, this, auto-version.el, is
useful in a way that you never notice or think of. Actually,
it isn't fun at all!
Let's see if you like it! I have used it a lot, including for
the period of its own development, indeed, that version 1.16.3
below is auto-incremented all the way from 0.0.0 and the first
update to 0.0.1. It means, I've updated that file 723 times!
After enabling auto-version, you never ever have to think
about the version. No more moving up and down the buffer to
set it, and no more having Emacs do that on `undo' which is
VERY annoying and disruptive BTW.
It is linted by 3 linters [1] so that is cool.
There are more interesting things about the version, more to
it than most people think, so this package, God willing, will
be updated further with more interesting functions to decode
and use them. But this, the automatic uptick, is by far the
most important feature.
And before someone says it, shouldn't one have a scheme that
carries more information, indeed - as it is called, semantic
versioning? Well, that is an interesting idea, and fascinating
to some, but in my experience the practical result is a lot of
time spent thinking about it and then never having the
supposed advantages come to use anyway. So IMO a simple
incremental x.y.z is more than enough and if you never have to
think about it, even better.
[1] The three Elisp linters, namely `elint-current-buffer',
`checkdoc-current-buffer', and
`package-lint-current-buffer'.
And now the package:
;;; auto-version.el --- Automatic x.y.z version -*- lexical-binding: t -*-
;;
;; Author: Emanuel Berg <incal@dataswamp.org>
;; Created: 2024-08-01
;; Keywords: convenience, lisp, tools
;; License: GPL3+
;; Package-Requires: ((emacs "25.1"))
;; URL: https://dataswamp.org/~incal/elpa/auto-version.el
;; Version: 1.16.3
;;
;;; Commentary:
;;
;; __________________________________________________________
;; ^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`
;;
;; auto-version.el -- automatic x.y.z version
;;
;; __________________________________________________________
;; `^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^`^
;;
;; Automatic version number uptick.
;;
;; The version number looks like this:
;;
;; x.y.z
;;
;; Uptick is by default 20 for x and y. Increments to z are
;; by 1 every update. z resets and increments y; y resets
;; and increments x. x doesn't reset or increment:
;;
;; 0 <= z < 20
;; 0 <= y < 20
;; 0 <= x
;;
;; ----------------------------------------------------------
;;
;; To enable in Emacs Lisp buffers:
;;
;; (keymap-set emacs-lisp-mode-map "C-x C-s" #'auto-version-save)
;;
;; ----------------------------------------------------------
;;
;; The most important function, see its docstring:
;; `auto-version'
;;
;; Automates version update for every save, all transparent:
;; `auto-version-save'
;;
;; Extra material. How many updates is there in a version?
;; Plus version compare, and more.
;; `auto-version--updates'
;; `auto-version<'
;;
;; ----------------------------------------------------------
;;
;; If you want to update the version at most once a day set:
;; `auto-version--max-once-a-day'
;;
;; ----------------------------------------------------------
;;
;;; Code:
(require 'cl-lib)
(defvar auto-version--max-once-a-day nil
"Non-nil and `auto-version' increments version(s) at most once a day.")
(defun auto-version-save (&rest arg)
"Uptick version and save, see `auto-version'.
Also see `auto-version--max-once-a-day'.
ARG are passed on to `save-buffer', you can
use this just as you did `save-buffer'."
(interactive "p")
(let ((buffer-undo-list t)
(today (format-time-string "%F")))
(if (not auto-version--max-once-a-day)
(auto-version)
(when (and auto-version--max-once-a-day
(not (and (stringp auto-version--max-once-a-day)
(string= today auto-version--max-once-a-day))))
(auto-version)
(setq auto-version--max-once-a-day today)) ))
(save-buffer arg))
(defun auto-version (&optional yz-max label)
"Uptick the x.y.z version number if present.
y and z overtick at YZ-MAX, default 20.
LABEL is prepended to the version search string, it defaults
to \"^;; Version: \" in Elisp buffers and otherwise to
\"\\\\W\".
Also see: `auto-version-save'"
(interactive)
(or yz-max (setq yz-max 20))
(or label (setq label (if (eq major-mode 'emacs-lisp-mode)
"^;; Version: "
"\\W")))
(when (buffer-modified-p)
(save-mark-and-excursion
(goto-char (point-min))
(when (re-search-forward
(format "%s\\([0-9]+.[0-9]+.[0-9]+\\)\\b" label)
nil t)
(pcase-let ((`(,x ,y ,z) (version-to-list (match-string 1))))
(when (zerop (setq z (mod (cl-incf z) yz-max)))
(when (zerop (setq y (mod (cl-incf y) yz-max)))
(cl-incf x)))
(let ((ver (format "%d.%d.%d" x y z)))
(replace-match ver nil nil nil 1)
ver))))))
(defun auto-version< (ver1 ver2 &optional otick1 otick2)
"Do VER1 has less updates than VER2?
OTICK1 and OTICK2 defaults to 20 for both."
(interactive
(list
(read-string "version 1 [x.y.z]: ")
(read-string "version 2 [a.b.c]: ")
(read-number "version 1 overtick" 20)
(read-number "version 2 overtick" 20)))
(or otick1 (setq otick1 20))
(or otick2 (setq otick2 20))
(let* ((up1 (auto-version--updates ver1 otick1))
(up2 (auto-version--updates ver2 otick2))
(res (< up1 up2)))
(prog1
res
(message "updates %s: %d [%s]\nupdates %s: %d" ver1 up1 res ver2 up2))))
(defun auto-version--updates (ver &optional overtick)
"Translate VER into the number of updates it represents.
Overtick is OVERTICK for y and z, default 20.
For example, version 0.0.1 is the first update or update number 1;
and version 7.4.19 is already at update number 2899.
\(+ (* 7 (expt 20 2)) (* 4 (expt 20 1)) (* 19 (expt 20 0)))"
(interactive (list
(read-string "Version: ")
(read-number "Overtick: " 20)))
(or overtick (setq overtick 20))
(let* ((vel (version-to-list ver)))
(cl-loop
with ups = 0
for i downfrom (1- (length vel))
for d in vel do
(cl-incf ups (* d (expt overtick i)))
finally return ups)))
(provide 'auto-version)
;;; auto-version.el ends here
--
underground experts united
https://dataswamp.org/~incal
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2024-08-17 2:11 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-17 2:11 auto-version.el [ELPA-ready (?) package #3] Emanuel Berg
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).