gnu-emacs-sources
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

version.el v1.0


From: Vinicius Jose Latorre
Subject: version.el v1.0
Date: Sun, 05 Jun 2005 13:53:03 -0300
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.8) Gecko/20050511

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

;; Copyright (C) 2005 Vinicius Jose Latorre

;; Author:    Vinicius Jose Latorre <address@hidden>
;; Maintainer:    Vinicius Jose Latorre <address@hidden>
;; Keywords:    help, internal, maintenance, debug
;; Time-stamp:    <2005/06/05 13:49:36 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 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

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 syntax: '%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-string v1))
   (l2 (version-to-string 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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]