about summary refs log tree commit diff
path: root/users/sterni/clhs-lookup/clhs-lookup.lisp
blob: 0e61dd901f936ce2f31891de691b23faed22bb63 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
(in-package :clhs-lookup)
(declaim (optimize (safety 3)))

(defun find-symbols-paths (syms clhs)
  "Find pathnames to HyperSpec files describing the listed
  symbol names (as strings). Paths are returned in the order
  of the symbols given with missing entries removed."
  (check-type syms list)
  (check-type clhs pathname)
  (let* ((data-dir (merge-pathnames "HyperSpec/Data/" clhs))
         (data (merge-pathnames "Map_Sym.txt" data-dir))
         (found (make-hash-table :test #'equal))
         (syms (mapcar #'string-upcase syms)))
  (with-open-file (s data :direction :input)
    (loop
      with missing    = syms
      for symbol-line = (read-line s nil :eof)
      for path-line   = (read-line s nil :eof)
      until (or (eq symbol-line :eof)
                (eq path-line   :eof)
                (null missing))
      for pos = (position symbol-line missing :test #'equal)
      when pos
      do (progn
           (delete symbol-line missing)
           (setf (gethash symbol-line found) path-line)))
    ; TODO(sterni): get rid of Data/../ in path
    (mapcar
      (lambda (x) (merge-pathnames x data-dir))
      (remove nil
        (mapcar (lambda (x) (gethash x found)) syms))))))

(defun main ()
  (let* ((browser (or (uiop:getenvp "BROWSER") "xdg-open"))
         (args    (uiop:command-line-arguments))
         (prin    (member "--print" args :test #'equal))
         (syms    (remove-if (lambda (x) (eq (char x 0) #\-)) args))
         (paths (find-symbols-paths syms *clhs-path*)))
      (if (null paths)
        (uiop:quit 1)
        (dolist (p paths)
          (if prin
            (format t "~A~%" p)
            (uiop:launch-program
              (format nil "~A ~A" browser p)
              :force-shell t))))))