(require :asdf :asdf-utils)
(defpackage :ratpoison
  (:use :cl))

;; Needs the CLOCC PORT package
(asdf:operate 'asdf:load-op :port)

(in-package :ratpoison)

(defvar ratpoison-program
  (or (asdf-utils:getenv "RATPOISON")
      "ratpoison"))

(defmacro defun-ratpoison (cmd)
  (let ((sym (intern (concatenate 'string "RP-" (symbol-name cmd)))))
    `(progn (defun ,sym (&rest args)
              (apply 'ratpoison-cmd ,(string-downcase (symbol-name cmd)) args))
            (export ',sym))))

(defun ratpoison-cmd (cmd &rest args)
  (labels ((mapconcat (fn list sep)
                     (apply 'concatenate 'string
                            (loop for x on list
                                  collect (if (cdr x)
                                              (concatenate 'string (funcall fn (car x)) sep)
                                            (funcall fn (car x))))))
         (build-cmd (cmd args)
                    (mapconcat (lambda (x)
                                 (if (stringp x)
                                     x
                                   (prin1-to-string x)))
                               (nconc (list cmd) args) " ")))
    (let ((stream (port:pipe-input ratpoison-program
                                   "-c" (build-cmd cmd args))))
    (do ((line (read-line stream nil nil)
               (read-line stream nil nil))
         (accum nil (cons line accum)))
        ((null line) accum)))))

(defun-ratpoison abort)
(defun-ratpoison addhook)
(defun-ratpoison alias)
(defun-ratpoison banish)
(defun-ratpoison chdir)
(defun-ratpoison clrunmanaged)
(defun-ratpoison colon)
(defun-ratpoison curframe)
(defun-ratpoison definekey)
(defun-ratpoison undefinekey)
(defun-ratpoison delete)
(defun-ratpoison delkmap)
(defun-ratpoison echo)
(defun-ratpoison escape)
(defun-ratpoison exec)
(defun-ratpoison execa)
(defun-ratpoison execf)
(defun-ratpoison fdump)
(defun-ratpoison focus)
(defun-ratpoison focusprev)
(defun-ratpoison focusdown)
(defun-ratpoison exchangeup)
(defun-ratpoison exchangedown)
(defun-ratpoison exchangeleft)
(defun-ratpoison exchangeright)
(defun-ratpoison swap)
(defun-ratpoison focuslast)
(defun-ratpoison focusleft)
(defun-ratpoison focusright)
(defun-ratpoison focusup)
(defun-ratpoison frestore)
(defun-ratpoison fselect)
(defun-ratpoison gdelete)
(defun-ratpoison getenv)
(defun-ratpoison gmerge)
(defun-ratpoison gmove)
(defun-ratpoison gnew)
(defun-ratpoison gnewbg)
(defun-ratpoison gnumber)
(defun-ratpoison grename)
(defun-ratpoison gnext)
(defun-ratpoison gprev)
(defun-ratpoison gother)
(defun-ratpoison gravity)
(defun-ratpoison groups)
(defun-ratpoison gselect)
(defun-ratpoison help)
(defun-ratpoison hsplit)
(defun-ratpoison info)
(defun-ratpoison kill)
(defun-ratpoison lastmsg)
(defun-ratpoison license)
(defun-ratpoison link)
(defun-ratpoison listhook)
(defun-ratpoison meta)
(defun-ratpoison msgwait)
(defun-ratpoison newkmap)
(defun-ratpoison newwm)
(defun-ratpoison next)
(defun-ratpoison nextscreen)
(defun-ratpoison number)
(defun-ratpoison only)
(defun-ratpoison other)
(defun-ratpoison prev)
(defun-ratpoison prevscreen)
(defun-ratpoison quit)
(defun-ratpoison ratinfo)
(defun-ratpoison ratrelinfo)
(defun-ratpoison banishrel)
(defun-ratpoison ratwarp)
(defun-ratpoison ratrelwarp)
(defun-ratpoison ratclick)
(defun-ratpoison rathold)
(defun-ratpoison readkey)
(defun-ratpoison redisplay)
(defun-ratpoison remhook)
(defun-ratpoison remove)
(defun-ratpoison resize)
(defun-ratpoison restart)
(defun-ratpoison rudeness)
(defun-ratpoison select)
(defun-ratpoison set)
(defun-ratpoison setenv)
(defun-ratpoison shrink)
(defun-ratpoison sfrestore)
(defun-ratpoison source)
(defun-ratpoison sselect)
(defun-ratpoison startup_message)
(defun-ratpoison time)
(defun-ratpoison title)
(defun-ratpoison tmpwm)
(defun-ratpoison unalias)
(defun-ratpoison unmanage)
(defun-ratpoison unsetenv)
(defun-ratpoison verbexec)
(defun-ratpoison version)
(defun-ratpoison vsplit)
(defun-ratpoison warp)
(defun-ratpoison windows)
(defun-ratpoison cnext)
(defun-ratpoison cother)
(defun-ratpoison cprev)
(defun-ratpoison dedicate)
(defun-ratpoison describekey)
(defun-ratpoison inext)
(defun-ratpoison iother)
(defun-ratpoison iprev)
(defun-ratpoison prompt)
(defun-ratpoison sdump)
(defun-ratpoison sfdump)
(defun-ratpoison undo)
(defun-ratpoison redo)
(defun-ratpoison putsel)
(defun-ratpoison getsel)
(defun-ratpoison compat)
