Component system-server

You are here: All Systems / lisppaste / system-server

(in-package :lisppaste)

(defparameter *memoize-colorize-table* (make-hash-table :test #'equal))

(defun all-system-names ()
  (loop for i being each hash-key of asdf::*defined-systems* collect i)
)


(defun find-component-from-string (string &key root)
  (multiple-value-bind (component-name start-of-rest)
      (split-sequence:split-sequence #\/ string :count 1)
    (let ((new-root (asdf:find-component root (car component-name))))
      (if new-root
          (if (> (length string) start-of-rest)
              (find-component-from-string (subseq string start-of-rest) :root new-root)
              new-root
)
)
)
)
)


(defclass main-system-server-handler (handler) ())

(defclass show-component-handler (handler) ())

(defmethod handle-request-response ((handler main-system-server-handler) method request)
  (request-send-headers request :expires 0)
  (xml-output-to-stream
   (request-stream request)
   (lisppaste-wrap-page
    "Select a System"
    (<div class="controls">
          (<ul>
           (loop for i in (all-system-names)
              for system = (asdf:find-system i)
              collect (<li>
                       (<a href=?(urlstring (merge-url *show-component-url*
                                                       i
)
)
>
                           i
)

                       " - "
                       (or (ignore-errors (asdf:system-description system))
                           (ignore-errors (asdf:system-long-description system))
                           "No Description"
)
)
)
)
)
)
)
)


(defun memoize-colorize-file (component type)
  (let ((ent (list (asdf:component-pathname component)
                   colorize:*version-token*
                   (file-write-date (asdf:component-pathname component))
)
)
)

    (multiple-value-bind (val found) (gethash ent *memoize-colorize-table*)
      (if found
          val
          (setf (gethash ent *memoize-colorize-table*)
                (with-output-to-string (s)
                  (colorize:colorize-file-to-stream type
                                                    (asdf:component-pathname component) s :wrap nil :css-background "paste"
)
)
)
)
)
)
)

  
(defun component-sorter (c1 c2)
  (if (typep c1 'asdf:module)
      (if (typep c2 'asdf:module)
          (string< (asdf:component-name c1) (asdf:component-name c2))
          t
)

      (if (typep c2 'asdf:module)
          nil
          (string< (asdf:component-name c1) (asdf:component-name c2))
)
)
)


(defun module-div (component url)
  (<div>
   (when (typep component 'asdf:system)
     (<div class="info-text">
           (<span class="small-header">
                  (format nil "About system \"~A\""
                          (asdf:component-name component)
)
)

           <p/>
           (<table>
            (<tr>
             (<td> (<b> "Name"))
             (<td> (asdf:component-name component))
)

            (<tr>
             (<td> (<b> "Version"))
             (<td> (or (ignore-errors (asdf:component-version component)) "None"))
)

            (<tr>
             (<td> (<b> "Author"))
             (<td> (or (ignore-errors (asdf:system-author component)) "None"))
)

            (<tr>
             (<td> (<b> "License"))
             (<td> (or (ignore-errors (asdf:system-license component)) "None"))
)

            (<tr>
             (<td> (<b> "Description"))
             (<td> (or (ignore-errors (asdf:system-description component)) "None"))
)

            (<tr>
             (<td> (<b> "Long Description"))
             (<td> (or (ignore-errors (asdf:system-long-description component)) "None"))
)
)
)
)

   (<div class="controls">
         (<span class="small-header"> "Select a component:")
         (<ul>
          (loop for i in (sort (copy-list (asdf:module-components component)) #'component-sorter)
              for link = (<a href=?(concatenate 'string
                                                  url
                                                  "/"
                                                  (asdf:component-name i)
)
>
                             (asdf:component-name i)
)

              if (typep i 'asdf:module) collect (<li> (<b> link))
              else collect (<li> link)
)
)
)
)
)


(defun file-div (component type)
  (<table width="100%" class="paste-area">
          (<tr>
           (<td bgcolor="#F4F4F4">
                (if (eql type :none)
                    (<pre>
                     (with-output-to-string (s)
                       (with-open-file (f (asdf:component-pathname component) :direction :input)
                         (loop for line = (read-line f nil nil)
                            while line
                            do (progn (write-string line s)
                                      (terpri s)
)
)
)
)
)

                    (<tt>
                     (make-unescaped-string
                      (memoize-colorize-file component type)
)
)
)
)
)
)
)


(defmethod handle-request-response ((handler show-component-handler) method request)
  (let ((component (find-component-from-string (request-unhandled-part request))))
    (and component
         (progn
           (request-send-headers request :expires 0)
           (xml-output-to-stream
            (request-stream request)
            (lisppaste-wrap-page
             (format nil "Component ~A" (asdf:component-name component))
             (<div>
              (<div class="controls">
                    "You are here: "
                    (<a href=?(urlstring *main-system-server-url*)>
                        "All Systems"
)

                    (loop for i in (reverse (maplist #'reverse (nreverse (split-sequence:split-sequence #\/ (request-unhandled-part request)))))
                       collect " / "
                       collect (<a href=?(urlstring (merge-url *show-component-url*
                                                               (format nil "~{~A~^/~}"
                                                                       i
)
)
)
>
                                   (car (last i))
)
)
)

              <p/>
              (typecase component
                (asdf:module (module-div component (urlstring (request-url request))))
                (asdf:cl-source-file (file-div component :common-lisp-file))
                (asdf:static-file
                 (file-div component (if (equalp (pathname-type (asdf:component-pathname component)) "lisp")
                                         :common-lisp-file
                                         :none
)
)
)

                (t (<div class="paste-area">
                         "I'm afraid I don't quite know what to do with this file."
)
)
)
)
)
)
)
)
)
)


(when *serve-source*
  (install-handler
   (http-listener-handler *paste-listener*)
   (make-instance 'main-system-server-handler)
   (urlstring *main-system-server-url*) t
)

  
  (install-handler
   (http-listener-handler *paste-listener*)
   (make-instance 'show-component-handler)
   (urlstring *show-component-url*) nil
)
)

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