+(in-package #:clnl-cli)
+
+(defvar *cli* nil)
+(defvar *cli-dims* (list 0 0))
+
+(defvar *info* nil)
+
+(defun run ()
+ "RUN => RESULT
+
+ARGUMENTS AND VALUES:
+
+ RESULT: undefined, should never get here
+
+DESCRIPTION:
+
+ RUN runs the command line interface in the running terminal.
+
+ This should become the main REPL for a CLNL program. If you want to use you're
+ own REPL, you should use the rest of the functions in CLNL to recreate it."
+ (initscr)
+ (init-interface)
+ (loop
+ :for str := (cffi:with-foreign-pointer-as-string (str 255) (wgetnstr *cli* str 255))
+ :while str
+ :while (and (string/= str "q") (string/= str "Q"))
+ :do (print-command-and-response str (execute str)))
+ (endwin)
+ (sb-ext:exit :abort t))
+
+(defun execute (str)
+ (handler-case
+ (with-output-to-string (*standard-output*)
+ (clnl:run-commands str))
+ (error (e) (format nil "Ok, something went wrong: ~A" e))))
+
+; for ui, we need to do at a minimum:
+; - cli, first pass, read things in, bottom of the screen,
+; - just use getstr with a limit to be something like screen width - 10 for now
+; - print what the user inputted, dont' bomb on error messages, give target for show
+; - for overly long printing, go ahead and truncate with "..."
+; - for info, this should put out a simple message about the program, maintainer, purpose, links, etc
+
+(defun init-interface ()
+ (let
+ ((cli-height (min 10 (floor (* *lines* .3)))))
+ (setup-info (- *lines* cli-height) *cols*)
+ (setup-cli cli-height *cols* (- *lines* cli-height))))
+
+(defun refresh-cli ()
+ (wmove *cli* (1- (car *cli-dims*)) 0)
+ (whline *cli* (char-code #\Space) (cadr *cli-dims*))
+ (mvwprintw *cli* (1- (car *cli-dims*)) 0 ">")
+ (wmove *cli* (1- (car *cli-dims*)) 2)
+ (wrefresh *cli*))
+
+(defun print-command-and-response (command response)
+ (loop
+ :for i :from 1 :to (- (car *cli-dims*) 3)
+ :do (wmove *cli* i 0)
+ :do (whline *cli* (char-code #\Space) (cadr *cli-dims*)))
+ (mvwprintw *cli* 1 0 (format nil "> ~A" command))
+ (mvwprintw *cli* 3 0 (format nil "~A" response))
+ (refresh-cli))
+
+(defun setup-cli (height width top)
+ (setf *cli* (newwin height width top 0))
+ (setf *cli-dims* (list height width))
+ (whline *cli* 0 (cadr *cli-dims*))
+ (wmove *cli* (- (car *cli-dims*) 2) 0)
+ (whline *cli* (char-code #\.) (cadr *cli-dims*))
+ (wmove *cli* (1- (car *cli-dims*)) 2)
+ (wrefresh *cli*)
+ (refresh-cli))
+
+(defun setup-info (num-tall num-wide)
+ (setf *info* (newwin 20 60 (floor (- num-tall 20) 2) (floor (- num-wide 60) 2)))
+ (mvwprintw *info* 1 1
+ (format nil
+ "
+ .
+ / \\
+ / \\ Welcome to CLNL version ~A!
+ / \\
+ /_______\\
+
+ CLNL is an experiment at creating an alternate
+ implementation of NetLogo.
+
+ You can enter in various netlogo commands below,
+ or use q to quit the program.
+
+ See http://github.com/frankduncan/clnl for more
+ information about CLNL and to keep apprised of
+ any updates that may happen."
+ (asdf:component-version (asdf:find-system :clnl))))
+ (box *info* 0 0)
+ (wrefresh *info*))