Created
November 28, 2015 05:30
-
-
Save dunn/ae99094ce3524e8d1bc5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defun version-to-list (ver) | |
"Convert version string VER into a list of integers. | |
The version syntax is given by the following EBNF: | |
VERSION ::= NUMBER ( SEPARATOR NUMBER )*. | |
NUMBER ::= (0|1|2|3|4|5|6|7|8|9)+. | |
SEPARATOR ::= `version-separator' (which see) | |
| `version-regexp-alist' (which see). | |
The NUMBER part is optional if SEPARATOR is a match for an element | |
in `version-regexp-alist'. | |
Examples of valid version syntax: | |
1.0pre2 1.0.7.5 22.8beta3 0.9alpha1 6.9.30Beta OTP-10.0.3 2.4.snapshot | |
Examples of invalid version syntax: | |
1.0prepre2 1.0..7.5 22.8X3 .5 | |
Examples of version conversion: | |
Version String Version as a List of Integers | |
\"1.0.7.5\" (1 0 7 5) | |
\"0.9snapshot\" (0 9 -4) | |
\"1.0-git\" (1 0 -4) | |
\"1.0.cvs\" (1 0 -4) | |
\"1.0pre2\" (1 0 -1 2) | |
\"1.0PRE2\" (1 0 -1 2) | |
\"22.8beta3\" (22 8 -2 3) | |
\"22.8 Beta3\" (22 8 -2 3) | |
\"0.9alpha1\" (0 9 -3 1) | |
\"0.9AlphA1\" (0 9 -3 1) | |
\"0.9 alpha\" (0 9 -3) | |
See documentation for `version-separator' and `version-regexp-alist'." | |
(or (and (stringp ver) (> (length ver) 0)) | |
(error "Invalid version string: `%s'" ver)) | |
;; Change .x.y to 0.x.y | |
(if (and (>= (length ver) (length version-separator)) | |
(string-equal (substring ver 0 (length version-separator)) | |
version-separator)) | |
(setq ver (concat "0" ver))) | |
;; Strip any non-numeric prefix (see Erlang and their OTP-18.1.5 version-strings) | |
(while (not (string-match "^[0-9]" ver)) | |
(setq ver (substring ver 1))) | |
(save-match-data | |
(let ((i 0) | |
(case-fold-search t) ; ignore case in matching | |
lst s al) | |
;; Starting from the beginning of the string (i = 0), find | |
;; number-y chunks and parse them. A "number-y chunk" is a | |
;; technical term for a string that begins with a number but | |
;; might have non-numeric elements. | |
(while (and (setq s (string-match "[0-9]+" ver i)) | |
(= s i)) | |
;; Add the numeric part to the beginning of lst | |
(setq lst (cons (string-to-number (substring ver i (match-end 0))) lst) | |
;; set i to the end of the numeric part | |
i (match-end 0)) | |
(message lst) | |
;; handle non-numeric part | |
(when (and (setq s (string-match "[^0-9]+" ver i)) | |
(= s i)) | |
(setq s (substring ver i (match-end 0)) | |
i (match-end 0)) | |
(message s) | |
;; handle alpha, beta, pre, etc. separator | |
(unless (string= s version-separator) | |
(setq al version-regexp-alist) | |
(while (and al (not (string-match (caar al) s))) | |
(setq al (cdr al))) | |
(cond | |
;; If the separator matches one of the regexps from the | |
;; alist, add its priority to lst | |
(al (push (cdar al) lst)) | |
;; If it doesn't match the alist, it might still be | |
;; salvageable. | |
;; | |
;; Convert 22.3a to 22.3.1, 22.3b to 22.3.2, etc. | |
((string-match "^[-\._+ ]?\\([a-zA-Z]\\)$" s) | |
(push (- (aref (downcase (match-string 1 s)) 0) ?a -1) | |
lst)) | |
;; If it can't be parsed: | |
(t (error "Invalid version syntax: `%s'" ver)))))) | |
(if (null lst) | |
(error "Invalid version syntax: `%s'" ver) | |
(nreverse lst))))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment