lspx/lspx.lisp

121 lines
4.2 KiB
Common Lisp

;;;; lspx.lisp
(in-package #:lspx)
(defparameter *server* nil)
(defun main ()
(multiple-value-bind (opts args) (get-opts)
(declare (ignore args))
;; --log
(when (getf opts :logging)
(let ((keyw (car (member (intern (string-upcase (getf opts :logging))
:keyword)
+valid-log-levels+))))
(if keyw
(log:config keyw)
(progn
(format t "bad value for logging level specified.~%proper values are ~{~(~A~)~^, ~}~%"
(mapcar #'string +valid-log-levels+))
(uiop:quit 1)))))
;; -h/--help
(when (getf opts :help)
(opts:describe :usage-of "lspx")
(uiop:quit 0))
;; --version
(when (getf opts :version)
(format t "lspx v~A~%" #.(asdf:component-version
(asdf:find-system :lspx)))
(uiop:quit 0))
(setf
;; -v/--verbose OR envvar ENV != production
*verbose* (or (getf opts :verbose)
(and (not (str:emptyp (uiop:getenv "ENV")))
(not (string= (uiop:getenv "ENV")
"production"))))
*html-backtrace* (getf opts :backtrace)
;; sets our local pathnames based on arguments provided
(logical-pathname-translations "WEB")
`(
;; sets our cache directory
("WEB:CACHE;**;*.*.*"
,(merge-pathnames ".cache/**/*.*" (namestring (uiop:getcwd))))
;; sets our static asset directory
("WEB:STATIC;**;*.*.*"
,(str:concat (str:ensure-suffix "/" (getf-dir opts :static-root "static/"))
"/**/*.*"))
;; sets our template root
("WEB:TEMPLATE;**;*.*.*"
,(str:concat (str:ensure-suffix "/" (getf-dir opts :template-root "templates/"))
"/**/*.*"))
;; sets our root web path to /provided/path
("WEB:PAGES;**;*.*.*"
,(str:concat (str:ensure-suffix "/" (getf-dir opts :web-root (uiop:getcwd)))
"**/*.*"))))
;; -l/--load
(let ((load-file (getf opts :load-file)))
(when load-file
(log:info "loading specified file: ~A" load-file)
(let ((*package* #.(find-package :lspx.user))
(*read-eval* t))
(load (namestring load-file)))))
;; deletes the cache if it already exists, ensuring we're in a consistent state
;; then creates the directories
(uiop:delete-directory-tree (translate-logical-pathname "web:cache;")
:validate t :if-does-not-exist :ignore)
(ensure-directories-exist "web:cache;")
(log:debug "Using ~A for pages."
(translate-logical-pathname "web:pages;"))
(log:debug "Using ~A for static assets."
(translate-logical-pathname "web:static;"))
(log:debug "Using ~A for templates."
(translate-logical-pathname "web:template;"))
(log:debug "loading templates...")
(let ((*package* #.(find-package :lspx.user)))
(uiop:collect-sub*directories
"web:template;" (constantly t) (constantly t)
#'(lambda (dir)
(mapcar #'load (uiop:directory-files dir "*.lspt")))))
;; creates our server handler, fetching the port if provided
(setf *server*
(clack:clackup #'web-handler
:server #+woo :woo
#-woo :hunchentoot
:silent t
:port (getf opts :port 5000)))
;; ensure we print a "Server Started" message regardless of logging
(log:info "LSPX server started at 127.0.0.1:~A using ~A backend"
(getf opts :port 5000)
#+woo :woo
#-woo :hunchentoot)
;; blocks until we C-c
(handle-user-abort
(bt:join-thread (find-if (lambda (th)
(search #+woo "woo"
#-woo "hunchentoot"
(bt:thread-name th)))
(bt:all-threads)))
(error (e)
(log:fatal "!!ERROR ~A~%~%BACKTRACE: ~A"
e (trivial-backtrace:print-backtrace e :output nil))))
(clack:stop *server*)))