Component clim-lookup

You are here: All Systems / specbot / clim-lookup

(defpackage :clim-lookup (:use :common-lisp :split-sequence)
            (:export :term-lookup :populate-table)
)

(in-package :clim-lookup)

(defvar *clim-table*)

(defvar *clim-abbrev-table*)

(defparameter *clim-file*
  (merge-pathnames "mrindex"
                   (make-pathname
                    :directory
                    (pathname-directory
                     (asdf:component-pathname
                      (asdf:find-system :cliki-bot)
)
)
)
)
)


#|
(defparameter *clim-spec-root*
  "http://www.stud.uni-karlsruhe.de/~unk6/clim-spec/")
|#


(defparameter *clim-spec-root*
  "http://bauhh.dyndns.org:8000/clim-spec/"
)


(defun merge-to-spec (url)
  (concatenate 'string *clim-spec-root* url)
)


(defun set-abbrev (term)
  (let ((abbrev (abbrev:abbrev term)))
    (if abbrev
        (pushnew term (gethash abbrev *clim-abbrev-table* nil)
                 :test #'string-equal
)
)
)
)


(defun populate-table ()
  (setf *clim-table* (make-hash-table :test #'equalp))
  (setf *clim-abbrev-table* (make-hash-table :test #'equalp))
  (with-open-file (f *clim-file* :direction :input)
    (loop for i = (read f nil nil)
          while i
          do (destructuring-bind (ig1 (term sep (ig2 type)) url)
                 i
               (declare (ignore ig1 ig2 sep))
               (setf term (substitute #\space (code-char 160) term :test #'eql))
               (setf type (substitute #\space (code-char 160) type :test #'eql))
               (push (cons type url)
                     (gethash term *clim-table* nil)
)

               (set-abbrev term)
)
)
)
)


(defun abbrev-lookup (term)
  (let ((found (gethash term *clim-abbrev-table* nil)))
    (if found
        (if (eql (length found) 1)
            (let ((r (real-term-lookup (car found))))
              (and r
                   (concatenate 'string (car found) ": " r)
)
)

            (format nil "Multiple matches found. Try any of: ~{~A~^ ~}"
                    found
)
)
)
)
)


(defun real-term-lookup (term)
  (destructuring-bind (real-term &optional type (index-str "0"))
      (split-sequence #\, term)
    (let ((ents (gethash real-term *clim-table* nil))
          (index (parse-integer index-str :junk-allowed t))
)

      (if type
          (let ((all-type (loop for ent in ents
                                if (string-equal (car ent) type)
                                collect ent
)
)
)

            (if (< index (length all-type))
                (merge-to-spec (cdr (nth index all-type)))
                (format nil "Invalid index ~A: must be between 0 and ~A."
                        index (1- (length all-type))
)
)
)

          (if (eql (length ents) 0)
              nil
              (if (eql (length ents) 1)
                  (merge-to-spec (cdr (car ents)))
                  (let ((unique-types nil))
                    (loop for ent in ents
                          do (pushnew (car ent) unique-types :test #'string-equal)
)

                    (format nil "Multiple entries found. Try looking up one of: ~{\"~A\"~^, ~}"
                            (mapcar #'(lambda (type)
                                        (format nil "~A,~A~A"
                                                real-term
                                                type
                                                (let ((count (count type ents :key #'car :test #'string-equal)))
                                                  (if (> count 1)
                                                      (format nil ",{0-~A}"
                                                              (1- count)
)

                                                      ""
)
)
)
)

                                    unique-types
)
)
)
)
)
)
)
)
)


(defun term-lookup (term)
  (or (real-term-lookup term)
      (abbrev-lookup term)
)
)

Lisppaste pastes can be made by anyone at any time. Imagine a fearsomely comprehensive disclaimer of liability. Now fear, comprehensively.