Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 29 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,51 @@
Need to plot some data from Common Lisp? This will solve your problem
by making a pretty plot in your web browser, effectively using that
browser as a display for your chart. It uses a cute Javascript
plotting widget known as flot. But it can do much more; you can push
arbitrary content to a webpage, and by using other Javascript widgets
lots of other things are possible; including maps, rich text editors,
syntax highlighting, etc. etc.
`plot-window` provides Javascript code and content push capability to a web browser using websockets. `plot-window` goes a step further by providing tooling for using and interacting with Javascript and Javascript libraries. Javscript interaction is done usin parenscript providing a holistic interaction between Lisp and the browser.

Examples have been provided for working with the following libraries:
* flot - Plotting
* d3js - Plotting
* mapstraction - Openstreet Maps Mapping
* nice-edit - Rich text editor
* syntax-highlighter - Syntax highlighting

Getting Started
---------------

First: clone this repository (to ~/.quicklisp/local-projects for example),
then having assured that ASDF can find it (say by resetting ASDF's source respository
<code>(asdf:clear-source-registry)</code>), and then load and run the application as so:
then having assured that ASDF can find it (say by resetting ASDF's source respository `(asdf:clear-source-registry)`)

`plot-window` requires version 0.2.5 of cl-interpol. Until the Quicklisp pull from the cl-interpol upstream, you will need to clone cl-interpol from it's github repository https://github.com/edicl/cl-interpol.git.
```
git clone https://github.com/edicl/cl-interpol.git
```

The plot-window can be loaded and ran as so:
```common-lisp
> (ql:quickload "plot-window")
> (cl-user:initialize-application)
> (in-package :pw)
> (pw:initialize-application)
```

Second: Visit http://localhost:8765/ in a quality web browser. I've only tried chrome.
The resulting page becomes your REPL's display window.

Third: Load up an example, in this case a plot widget: `(ql:quickload "plot-window-flot")`

Third: Load up an example, in this case a plot widget:
```common-lisp
> (pw:plot (loop for i below 50 collect (list i (random 20))))
> (ql:quickload "plot-window-flot")`
> (flot-example-1)
> (plot (loop for i below 50 collect (list i (random 20))))
```

You can clear the window with `(ps:clear-display-window)`, and you can add single elements to the page using `(ps:add-element "<p>Hi there</p>")`
You can clear the window with `(clear-display-window)`, and you can add single elements to the page using `(pw:add-element "<p>Hi there</p>")`

A number of examples are in the example's subdirectory. Each of these has it's on asd. You may load them all via `(ql:quickload "plot-window-examples")`. And once they are all loaded you can run a little demo: `(ql:demo t)`

Generated Javascript modules are stored in the static directory this location set with the parameter `*where-to-store-js-module-files*`. It is set by default to the ASDF system relative path of `plot-window`.

Magic
-----

The chart is drawn by [flot](http://www.flotcharts.org/), a javascript
library. The page is rendered via Hunchentoot. The dynamic updating
library. The page is rendered via -Hunchentoot. The dynamic updating
is done via websockets (with the help of
[clws](http://www.cliki.net/clws)). A tangle of javascript glues it
all together, and that's implemented using parenscript. Various
Expand Down
2 changes: 1 addition & 1 deletion main.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

;;;; Starting our Servers

(defun cl-user::initialize-application (&key (port 8765))
(defun initialize-application (&key (port 8765))
(start-web-server :port port)
(start-clws-server)
(start-and-register-json-rpc-resource))
Expand Down
2 changes: 1 addition & 1 deletion packages.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#:make-css-var #:pt #:px)
(:nicknames "PW")
(:export
;; also cl-user:initalize-application
#:initialize-application
#:plot))

(unless (named-readtables:find-readtable :cl-interpol)
Expand Down
2 changes: 1 addition & 1 deletion ps-modules.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@

;;;;

(defparameter *where-to-store-js-module-files* "/Users/bhyde/w/plot-window/static/")
(defparameter *where-to-store-js-module-files* (namestring (asdf:system-relative-pathname 'plot-window "static/")))

(defgeneric update-js-module-file-if-necessary (m)
(:documentation "Compile time hook which provides an oportunity to regenerate the javascript file."))
Expand Down
2 changes: 1 addition & 1 deletion ps-utilities.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ body after the given number of milliseconds."
"Avoid the need to use a unique read table."
(assert (stringp str))
(with-input-from-string (s str)
(cl-interpol::interpol-reader s #\? nil)))
(cl-interpol:interpol-reader s #\? nil :recursive-p nil)))

(defmacro interpolate (str)
(interp% str))
Expand Down
4 changes: 2 additions & 2 deletions servers.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@

;;;; JSON messaging over that web socket.

(defvar *current-websocket-client*)
(defvar *last-websocket-client*)
(defvar *current-websocket-client* nil)
(defvar *last-websocket-client* nil)
(defvar *json-rcp-handlers* (make-hash-table :test #'equalp))

(defmacro define-json-message-handler (name (&rest parameters) &body body)
Expand Down