version.el v1.0 (fix)

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

version.el v1.0 (fix)

Vinicius Jose Latorre
With some minor error fix.


;;; version.el --- version string comparison

;; Copyright (C) 2005 Vinicius Jose Latorre

;; Author: Vinicius Jose Latorre <[hidden email]>
;; Maintainer: Vinicius Jose Latorre <[hidden email]>
;; Keywords: help, internal, maintenance, debug
;; Time-stamp: <2005/06/05 14:22:33 vinicius>
;; Version: 1.0
;; X-URL: http://www.cpqd.com.br/~vinicius/emacs/

;; This file is *NOT* (yet?) part of GNU Emacs.

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;;; Commentary:

;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Introduction
;; ------------
;;
;; This package provides routines to compare string version and to convert
;; string version to an integer list.
;;
;; version was tested with GNU Emacs 22.0.50.1.
;;
;; I don't know if still is compatible with XEmacs.
;;
;;
;; Usage
;; -----
;;
;; To use version, insert in your Emacs Lisp code:
;;
;;        (require 'version)
;;
;; So, you can compare versions in Emacs Lisp code like:
;;
;; (and (< (version-compare other-version "6.6pre4") 0)
;;      (error "`my-pack' requires `other' package version 6.6pre4 or later"))
;;
;;
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;; code:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User variables


(defgroup version nil
  "Version group"
  :link '(emacs-library-link :tag "Source Lisp File" "version.el")
  :prefix "version-"
  :group 'internal
  :group 'maintenance
  :group 'debug)


(defcustom version-separator "."
  "*Specify the string used to separate the version elements.

Usually the separator is \".\", but it can be any other string."
  :type '(string :tag "Version Separator")
  :group 'version)


(defcustom version-regexp-alist
  '(("^a\\(lpha\\)?$" . 0)
    ("^b\\(eta\\)?$"  . 1)
    ("^pre\\|rc$"     . 2))
  "*Specify association between non-numeric version part and a priority.

This association is used to handle version string like
\"1.0pre2\", \"0.9alpha1\", etc.  It's used by
`version-to-list' (which see) to convert the non-numeric part to
an integer.  For example:

   ORIGINAL VERSION VERSION CONVERTED
   1.0pre2 1.0.2.2
   1.0PRE2 1.0.2.2
   22.8beta3 22.8.1.3
   22.8Beta3 22.8.1.3
   0.9alpha1 0.9.0.1
   0.9AlphA1 0.9.0.1

Each element has the following form:

   (REGEXP . PRIORITY)

Where:

REGEXP regexp used to match non-numeric part of a version string.

PRIORITY integer which indicate the non-numeric priority."
  :type '(repeat :tag "Version Regexp Alist"
                 (cons :tag ""
                       (string :tag "Version Regexp")
                       (integer :tag "Version Priority")))
  :group 'version)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions


(defun version-to-list (ver)
  "Convert version string VER into an integer list.

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).

As an example of valid version syntax:

   1.0pre2   1.0.7.5   22.8beta3   0.9alpha1

As an example of invalid version syntax:

   1.0prepre2   1.0..7.5   22.8X3   alpha3.2   .5

As an example of version convertion:

   ORIGINAL VERSION VERSION CONVERTED
   \"1.0.7.5\"            (1 0 7 5)
   \"1.0pre2\"            (1 0 2 2)
   \"1.0PRE2\"            (1 0 2 2)
   \"22.8beta3\"          (22 8 1 3)
   \"22.8Beta3\"          (22 8 1 3)
   \"0.9alpha1\"          (0 9 0 1)
   \"0.9AlphA1\"          (0 9 0 1)
   \"0.9alpha\"           (0 9 0)
"
  (or (and (stringp ver) (not (string= ver "")))
      (error "Invalid version string: '%s'" ver))
  (save-match-data
    (let ((i 0)
          case-fold-search ; ignore case in matching
          lst s al)
      (while (and (setq s (string-match "[0-9]+" ver i))
                  (= s i))
        ;; handle numeric part
        (setq lst (cons (string-to-number (substring ver i (match-end 0)))
                        lst)
              i   (match-end 0))
        ;; 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))
          ;; 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)))
            (or al (error "Invalid version syntax: '%s'" ver))
            (setq lst (cons (cdar al) lst)))))
      (if (null lst)
          (error "Invalid version syntax: '%s'" ver)
        (nreverse lst)))))


(defun version-compare (v1 v2)
  "Compare version string V1 with V2.

If V1 = V2, return 0.
If V1 > V2, return 1.
If V1 < V2, return -1.
It is an error if V1 or V2 is not a valid string version.

It uses `version-to-list' (which see)."
  (let ((l1 (version-to-list v1))
        (l2 (version-to-list v2))
        (r  0)
        e1 e2)
    (while (and (= r 0) l1 l2)
      (setq e1 (car l1)
            e2 (car l2)
            l1 (cdr l1)
            l2 (cdr l2)
            r  (cond ((= e1 e2) 0)
                     ((> e1 e2) 1)
                     (t         -1))))
    (cond ((or (/= r 0) (and (null l1) (null l2)))
           r)
          ;; r = 0 and l1 not null and l2 null ==> l1 length > l2 length
          (l1 1)
          ;; r = 0 and l1 null and l2 not null ==> l2 length > l1 length
          (t  -1))))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


(provide 'version)


;;; version.el ends here

_______________________________________________
Gnu-emacs-sources mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/gnu-emacs-sources