git.fiddlerwoaroof.com
Raw Blame History
#+fw.dump
(eval-when (:compile-toplevel :load-toplevel :execute)
  (load "~/quicklisp/setup.lisp")
  (require :uiop))

#+fw.dump
(ql:quickload '(:net.didierverna.clon :alexandria :dufy))

(defpackage :fwoar.zenburn
  (:use :cl )
  (:export #:dump
           #:html-color
           #:rgb-color))
(in-package :fwoar.zenburn)

(defun 256-color-text (fg bg format &rest args)
  (cond ((or fg bg)
         (format T "~c[~:[~;~:*38;2;~{~d;~}~]~:[~;~:*48;2;~{~d;~}~]m~?~@*~c[39m~:*~c[49m"
                 #\Esc
                 fg
                 bg
                 format
                 args))
        (t (error "must specify either fg or bg for a color"))))

(defparameter *color-alist*
  '((fg+2     . (#xFF #xFF #xEF))
    (fg+1     . (#xF5 #xF5 #xD6))
    (fg       . (#xDC #xDC #xCC))
    (fg-1     . (#xA6 #xA6 #x89))
    (fg-2     . (#x65 #x65 #x55))
    (black    . (#x00 #x00 #x00))
    (bg-2     . (#x00 #x00 #x00))
    (bg-1     . (#x11 #x11 #x12))
    (bg-05    . (#x38 #x38 #x38))
    (bg       . (#x2A #x2B #x2E))
    (bg+05    . (#x49 #x49 #x49))
    (bg+1     . (#x4F #x4F #x4F))
    (bg+2     . (#x5F #x5F #x5F))
    (bg+3     . (#x6F #x6F #x6F))
    (red+2    . (#xEC #xB3 #xB3))
    (red+1    . (#xDC #xA3 #xA3))
    (red      . (#xCC #x93 #x93))
    (red-1    . (#xBC #x83 #x83))
    (red-2    . (#xAC #x73 #x73))
    (red-3    . (#x9C #x63 #x63))
    (red-4    . (#x8C #x53 #x53))
    (red-5    . (#x7C #x43 #x43))
    (red-6    . (#x6C #x33 #x33))
    (orange   . (#xDF #xAF #x8F))
    (yellow   . (#xF0 #xDF #xAF))
    (yellow-1 . (#xE0 #xCF #x9F))
    (yellow-2 . (#xD0 #xBF #x8F))
    (green-5  . (#x2F #x4F #x2F))
    (green-4  . (#x3F #x5F #x3F))
    (green-3  . (#x4F #x6F #x4F))
    (green-2  . (#x5F #x7F #x5F))
    (green-1  . (#x6F #x8F #x6F))
    (green    . (#x7F #x9F #x7F))
    (green+1  . (#x8F #xB2 #x8F))
    (green+2  . (#x9F #xC5 #x9F))
    (green+3  . (#xAF #xD8 #xAF))
    (green+4  . (#xBF #xEB #xBF))
    (cyan     . (#x93 #xE0 #xE3))
    (blue+3   . (#xBD #xE0 #xF3))
    (blue+2   . (#xAC #xE0 #xE3))
    (blue+1   . (#x94 #xBF #xF3))
    (blue     . (#x8C #xD0 #xD3))
    (blue-1   . (#x7C #xB8 #xBB))
    (blue-2   . (#x6C #xA0 #xA3))
    (blue-3   . (#x5C #x88 #x8B))
    (blue-4   . (#x4C #x70 #x73))
    (blue-5   . (#x36 #x60 #x60))
    (magenta  . (#xDC #x8C #xC3))))

(defun theme-color (name)
  (cdr (assoc name *color-alist*)))

(defun html-color (name &optional (s t))
  (let ((values (theme-color name)))
    (prog1 (format s "#~{~2,'0x~}" values)
      (unless (null s)
        (format s "~%")))))

(defun hsv-color (name &optional (s t))
  (let ((values (theme-color name)))
    (destructuring-bind (r g b) values
      (multiple-value-bind (h sa v) (dufy:rgb-to-hsv (/ r 255.0)
                                                     (/ g 255.0)
                                                     (/ b 255.0))
        (prog1 (format s
                       "~,3f ~,3f ~,3f"
                       (/ h 360.0) sa v)
          (unless (null s)
            (format s "~%")))))))

(defmacro may ((op arg &rest r))
  (let ((cond (case op
                (cl:funcall (car r))
                (t arg))))
    (alexandria:once-only (arg)
      `(when ,cond
         (,op ,arg ,@r)))))

(defun rgb-color (name &optional (float t))
  (let* ((lookup (find-symbol (string name) :fwoar.zenburn))
         (color (may (theme-color lookup))))
    (cond ((and color float)
           (mapcar (lambda (it)
                     (/ it 255d0))
                   color))
          (color))))

(defun zenburn-text (fg bg text &rest format-args)
  (let ((fgcolor (when fg (cdr (assoc fg *color-alist* :test 'equal))))
        (bgcolor (when bg (cdr (assoc bg *color-alist* :test 'equal)))))
    (apply #'256-color-text fgcolor bgcolor text format-args)))

(defun summary ()
  (loop for (color . values) in *color-alist*
        do
           (zenburn-text () color (make-string 32 :initial-element #\space))
           (format t "  ~8<~a~> (~{~2x~^, ~}) ~:* (~{~3d~^, ~})~%" color values)))

#+fw.dump
(defvar *synopsis*
  (net.didierverna.clon:defsynopsis (:postfix "[TEXT...]" :make-default nil)
      (flag :short-name "h" :long-name "help")
    (enum :short-name "f" :long-name "fg" :enum (mapcar 'car *color-alist*)
          :description "Set the text's foreground color")
    (enum :short-name "b" :long-name "bg" :enum (mapcar 'car *color-alist*)
          :description "Set the text's background color")
    (enum :long-name "html"  :enum (mapcar 'car *color-alist*)
          :description "Show COLOR as an HTML RGB literal")
    (enum :long-name "hsv"  :enum (mapcar 'car *color-alist*)
          :description "Show COLOR as a RGB hsv")
    (enum :long-name "css"  :enum (mapcar 'car *color-alist*)
          :description "Show COLOR as an CSS RGB literal")))

#+fw.dump
(defun main ()
  (let* ((context (net.didierverna.clon:make-context :synopsis *synopsis*))
         (net.didierverna.clon:*context* context)
         (foreground (net.didierverna.clon:getopt :context context
                                                  :long-name "fg"))
         (background (net.didierverna.clon:getopt :context context
                                                  :long-name "bg"))
         (remainder (net.didierverna.clon:remainder :context context))
         (css (net.didierverna.clon:getopt :context context
                                           :long-name "css"))
         (hsv (net.didierverna.clon:getopt :context context
                                           :long-name "hsv"))
         (html (net.didierverna.clon:getopt :context context
                                            :long-name "html")))
    (cond ((net.didierverna.clon:getopt :context context
                                        :long-name "help")
           (net.didierverna.clon:help))
          ((and html css)
           (format *error-output* "Can't use HTML and CSS options together~%")
           (net.didierverna.clon:help))
          (css
           (let ((values (cdr (assoc css *color-alist*))))
             (format t "rgb(~{~d~^, ~})~%" values)))
          (html
           (html-color html t))
          (hsv
           (hsv-color hsv t))
          ((null remainder)
           (summary))
          ((or foreground background)
           (zenburn-text foreground background "~{~a~^ ~}" remainder))
          (t
           (net.didierverna.clon:help)))))

#+fw.dump
(defun dump ()
  (setf net.didierverna.clon:*context* nil
        *features* (remove :fw.dump *features*)
        *print-case* :downcase)
  (net.didierverna.clon:dump "zenburn" main))