Commit 93b0fed1 authored by Dave Cooper's avatar Dave Cooper
Browse files

Merge pull request #114 from nicklevine/master

bootstrapping gendl-slime
parents c1f77c73 afeae362
Welcome to the Genworks® Gendl™ Environment
After some time, you should see a "GDL-USER>" command prompt.
A web server also starts by default on port 9000 of the local host,
which allows you to visit, for example:
If you accept the default robot:assembly, then click the hover-over
"pencil" icon next to the robot in the tree, you should see a
wireframe rendering of a simplified android robot.
See "Troubleshooting" below if you experience trouble starting up.
Emacs and Gendl
Although you are free to use other editors or IDEs, spending some time
to get familiar with Emacs is the best small investment you can make
for working with a Lisp-based system like Gendl. Slime (Superior Lisp
Interaction Mode for Emacs) which works across all major OS platforms
and CL implementations and is well-supported by the Common Lisp
community. Genworks plans to continue adding specialized Gendl support
to Slime.
If you are new to Emacs, you can get a general Emacs Tutorial under
the Help menu above. After completing the Tutorial, try to practice
what you learned by forcing yourself not to use the mouse too much in
Touch-typing ability is definitely an asset for Gendl development, but
with auto-completion of symbols (possible with M-/ -- you'll know what
that means after looking at the tutorial) it is possible to become a
world-class Gendl developer without having world-class typing speed.
It is strongly recommended to map your Caps Lock key to be a Control
key. This will give you a much more comfortable experience, allowing
you to use all the Emacs navigation keystrokes without constantly
curling your left little finger down to the Control key. For Linux
and Mac, this is easy to do in your System Preferences. For Windows,
here are some resources which can help you do this (the first one
appears not to require Administrator access on your machine):
Note that if you are running Windows in a Virtual Machine hosted under
MacOS or Linux, it is sufficient to map the Caps Lock to to Control in
the host system.
Finally, please see the Genworks Documentation (URL below) for an
introductory video on using Emacs in the Gendl environment.
Learning Gendl
Absolutely the best way to learn Gendl is to dive in and start using
it for small exercises and projects.
The work-in-progress tutorial.pdf is shipped with this distribution.
Other Documentation:
Then click the link for Documentation.
When you have had enough of using Gendl with Slime, you should do
two things:
1. type
M-x gdl-quit (and press <Return>)
from anywhere in Emacs, to kill the Gendl process.
2. (optional) type
C-x C-c (that's Control-x, Control-c)
to kill the Emacs process and exit the window.
3. If you kept Emacs up and running, it is possible to restart the
Gendl session again with "M-x gdl" or "M-x slime"
Customizing Emacs
If a file exists in your home directory called ".emacs-gendl" this will
be loaded upon startup. You can put any custom emacs-lisp code in this
file to customize your startup (see below for an example to customize
the color theme).
You can always find out where Emacs thinks is your home directory's
location by typing
C-x d ~/ <RET>
This should present the list of files in the home directory, and show
its full name on the first line. Likewise, to visit your init file,
C-x C-f ~/.emacs-gendl <RET>.
Color Themes
Gendl comes packaged with the color-theme:
package for Gnu emacs.
You can select any of the themes from color-theme with
M-x color-theme-select
(Click on the color theme you want to select then press <Return>).
To set a color theme automatically, put something like the following
at the end of your ~/.emacs-gendl :
(color-theme-bharadwaj) ;; for solarized dark theme, or
Emacs Keychord Reference
The following is a reference for the Emacs keychords which are
commonly used when working with Gendl. They will be understandable after
you have completed the Emacs Tutorial mentioned above. If you force
yourself to use these for a few days, they will quickly feel natural.
;; Backing out of a command (important! use this whenever you are lost)
C-g : quit the active command (use this if you ever get confused)
;; Navigating Through the Buffer
C-n : next line
C-p : previous line
C-f : forward char
M-f : forward word
C-M-f : forward s-expression
C-b : backward char
M-b : backward word
C-M-b : backward s-expression
C-a : begin of line
C-e : end of line
;; Auto-completion
M-/ : complete word
C-c ] : "super-bracket" -- close parens to enclosing toplevel.
;; Copying, Cutting, Pasting, working with Lisp S-expressions
C-d : delete character
M-d : delete word
C-M-k : kill s-expression
C-<space> : begins a selection
C-M-<space> : selects current sexpression
M-w : copies selection
C-w : cuts selection
C-y : yanks (pastes) the selection
M-y : yanks previous
C-k : kills current line
C-x u : Undo!
M-<space> : removes all but one whitespace under point.
M-\ : removes all whitespace under point.
;; Indenting
C-M-q indents entire expression (with cursor on opening parenthesis)
C-q indents and word-wraps a paragraph of text to reasonable line
;; Working with Files & Buffers
C-x C-b : get list of open buffers
C-x k : kills current buffer
C-x b : visit other buffer (default is previous)
C-x C-s : saves current buffer to file
C-x C-w : saves current buffer to a new file
C-x C-f : find file (i.e. file open)
;; Dired (Directory editor) mode
C-x C-f to visit a directory, then <Enter> for Directory Editor (Dired)
Within Dired:
d : marks file for deletion
f : visits the file or directory
~ : marks all backup files for deletion
x : executes pending commands (usually deletions)
;; Windows and Frames
C-x 2 : split screen into two windows
C-x 1 : make current window be the only window
C-x 0 : close current window
C-x o : change to next window
C-x y : change to previous window
C-x 2 5 : Open a new Frame (a new desktop window)
C-x & : Jump to *gdl-devo* buffer
;; Command-line Shortcuts
M-p : bring back previous command
M-n : bring back next command
;; Compiling and Loading from Buffer
C-c C-k : Compile Buffer
C-c C-c : Compile current form (e.g. define-object or defun)
C-x C-e : Evaluate Form (with cursor after closing parenthesis)
Webserver Fails to serve on Port 9000
First of all, you may receive a message from your Firewall asking
for permission to unblock services from the dx86cl64 executable. You
should grant this permission.
If you are unable to see the following URL:
then it is possible your machine already has another process running
on Port 9000. For example, some online gaming software will set up a
proxy service on this port.
If this is the case, then you can start Gendl serving on a different
port. To do this, try the following at the "gdl-user>" command
prompt (using port 8888 as an example):
(gwl:start-gwl :port 8888)
Now try visiting
If this works, then you can put these commands into the
initialization file in your home directory.
This diff is collapsed.
This diff is collapsed.
;;; color-theme_seldefcustom.el --- color-theme selection via customize interface
;;; Commentary:
;; Peter S Galbraith <>, 2005-10-25
;; License: GPLV2 or later.
;; A color-theme can can selected and enabled for future sessions by
;; customizing the variable `color-theme-selection' and saving the setting
;; instead of calling the interactive command `color-theme-select'
;;; Code:
(require 'color-theme)
(defcustom color-theme-selection nil
"Color theme selection.
Select and save to enable your choice in future sessions.
There is very limited undo capability to the previous state only."
:type (progn
(setq color-themes (delq (assq 'color-theme-snapshot color-themes)
color-themes (delq (assq 'bury-buffer color-themes)
(cons '(const :tag "Undo" nil)
(mapcar (function (lambda (arg) `(const ,arg)))
(mapcar '(lambda (x) (elt x 1)) color-themes)))))
:set (lambda (symbol value)
(set-default symbol value)
(require 'color-theme) ; :load doesn't seem to work
(unless color-theme-initialized (color-theme-initialize))
(fset 'color-theme-snapshot (color-theme-make-snapshot))
(delq nil
'(lambda (x) (if (string-equal (elt x 1) value)
(car x)))
((fboundp 'color-theme-snapshot)
:group 'color-theme
:require 'color-theme_seldefcustom)
(provide 'color-theme_seldefcustom)
;;; color-theme_seldefcustom.el ends here
;; The purpose of this document is to configure emacs to load SLIME
;; and start an inferior lisp process which will itself load and run
;; the GENDL development environment.
;; The intended readership is users and project developers.
;; This document is not confidential. See end for copyright
;; information.
(require 'cl)
(defvar *gdl-home* (file-truename (concat (file-name-directory (file-truename load-file-name)) "../")))
;; This section is not SLIME-specific.
;; 3.1 Flags, for commenting in or out.
;; FLAG -- comment the following if you want a tool bar.
;; (errors ignored in case running in a console terminal)
(ignore-errors (tool-bar-mode -1))
(setq visible-bell t)
;; FLAG -- uncomment the following if you don't need a menu bar.
;; (errors ignored in case running in a console terminal)
;;(ignore-errors (menu-bar-mode -1))
;; 3.2. Set up color-theme and solarized color-themes
(add-to-list 'load-path (concat *gdl-home* "emacs/emacs-color-theme"))
(require 'color-theme)
;; 3.3. Indents
(defmacro defindent (name indentation)
(let* ((keyword-list '(lisp-font-lock-keywords t t t nil nil nil "&allow-other-keys"))
(spec (if (eq indentation 'gdl-object-style) `((1 t ,keyword-list) (0 t 2)) indentation)))
`(put ',name 'lisp-indent-hook ',spec)))
(defun gdl:define-indents ()
(defindent define-object gdl-object-style)
(defindent define-view (like define-object))
(defindent define-format (like define-object))
(defindent defpart (like define-object))
(defindent defwriter (like define-object))
(defindent defcompanion (like define-object)))
;; 3.4. Some handy global keybindings
(defun gdl:global-keys ()
(global-set-key "\M-p" 'fi:pop-input)
(global-set-key "\M-n" 'fi:push-input)
(global-set-key "\C-xy" '(lambda() (interactive) (other-window -1)))
;; Use C-j for newline-and-indent. If you really like it, you can bind
;; it to [Enter] by uncommenting the following line (from
;;(global-set-key (kbd "C-m") 'newline-and-indent)
;; 3.5. Font
(defun gdl:set-font ()
;;(ignore-errors (set-frame-font "-bitstream-Courier 10 Pitch-normal-normal-normal-*-*-*-*-*-m-0-iso10646-1"))
(ignore-errors (set-frame-font "-outline-Consolas-normal-normal-normal-mono-15-*-*-*-c-*-fontset-auto2")))
;; 3.6. Miscellania
(show-paren-mode t)
;; Use M-x clear-kill-ring in case you have too much garbage in the
;; kill ring
(defun clear-kill-ring () (interactive) (setq kill-ring nil))
;; 4.1. Some synonyms
(defun gendl () (interactive) (with-temp-buffer (cd *gdl-home*) (slime)))
(defun gdl () (interactive) (gendl))
(defun gdl-quit () (interactive) (slime-quit-lisp))
(defun gq () (interactive) (gdl-quit))
(defun gendl-quit () (interactive) (gdl-quit))
;; 4.2. Configure slime
;; Where is our Common Lisp implementation? Where is slime-helper.el?
;; Loading the latter means we can load slime-autoloads.el (which
;; enables SLIME itself).
(defun configure-slime ()
(setq lisp-invocation nil)
(setq path-to-quicklisp-helper nil)
(let ((config-file (concat *gdl-home* "configure.el")))
(when (file-exists-p config-file)
;; Loading this file sets lisp-invocation and path-to-quicklisp-helper
(load-file config-file))
(when lisp-invocation
(setq slime-lisp-implementations `((gendl ,lisp-invocation))))
(load-file path-to-quicklisp-helper)))
(require 'slime-autoloads)
;; 4.3. Configure SLIME
(eval-after-load "slime"
(slime-setup '(slime-fancy slime-banner))
(add-hook 'slime-connected-hook 'load-gendl t)
(add-hook 'slime-connected-hook 'set-slime-shortcuts)
(add-hook 'slime-repl-mode-hook 'remove-dos-eol)
(add-to-list 'auto-mode-alist '("\\.cl\\'" . lisp-mode))
(add-to-list 'auto-mode-alist '("\\.gdl\\'" . lisp-mode))
(add-to-list 'auto-mode-alist '("\\.gendl\\'" . lisp-mode))))
(defun load-gendl ()
(insert (format "(load \"%sload-gendl.lisp\")" *gdl-home*))
(insert "(in-package gdl-user)")
(defun set-slime-shortcuts ()
"Set keybindings for switching to slime buffers"
(global-set-key "\C-x&" '(lambda()(interactive) (switch-to-buffer (slime-repl-buffer))))
(global-set-key "\C-x*" '(lambda()(interactive) (switch-to-buffer "*inferior-lisp*"))))
(defun remove-dos-eol ()
"Do not show ^M in files containing mixed UNIX and DOS line endings."
(setq buffer-display-table (make-display-table))
(aset buffer-display-table ?\^M []))
;; 4.4. Prior to SLIME
(defun prior-to-slime ()
(find-file (concat *gdl-home* "emacs/README.txt"))
(let ((frame-title "Genworks® Gendl™ Interactive Authoring Environment"))
(modify-frame-parameters nil
(list (cons 'name frame-title))))
(message "Please see the Startup section of this document for starting the Gendl environment.")
(when (file-exists-p "~/.emacs-gendl")
(load-file "~/.emacs-gendl"))
(setq inhibit-splash-screen t)
(cd "~/")
(set-frame-parameter nil 'fullscreen 'maximized))
;; Copyright 2013 Genworks International
;; This source file is part of the General-purpose Declarative
;; Language project (GDL).
;; This source file contains free software: you can redistribute it
;; and/or modify it under the terms of the GNU Affero General Public
;; License as published by the Free Software Foundation, either
;; version 3 of the License, or (at your option) any later version.
;; This source file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; Affero General Public License for more details.
;; You should have received a copy of the GNU Affero General Public
;; License along with this source file. If not, see
;; <>.
;; $Id: // $
(in-package :swank)
;; Nick Levine, Ravenbrook Limited, 2013-05-02
;; The purpose of this document is to implement GENDL customisations
;; for SLIME.
;; The following features have been implemented so far:
;; * modeline and completion help for the keywords accepted by
;; gendl:define-object,
;; * modeline and completion help for the keywords accepted inside an
;; :objects or :hidden-objects argument to gendl:define-object,
;; gendl:make-object, or gendl:make-self.
;; The intended readership is project developers.
;; This document is not confidential. See end for copyright
;; information.
(defparameter *gendl-slime-release* "0.1.0")
;; 2. TESTS
;; It's handy to be able to test this outside of the SLIME environmemnt.
;; '("define-object" "empty" nil ":objects" ("" swank::%cursor-marker%))
;; ->
;; "(define-object name mixin-list &key ===> objects <=== &allow-other-keys)"
(defun gendl-autodoc-test (raw-form)
(let ((*buffer-package* (find-package "GDL-USER"))
(*buffer-readtable* *readtable*))
(car (autodoc raw-form))))
;; 3. MACROS
;; We need a (very, very) basic and portable advice facility. The
;; potentially dangerous assumption it makes is that the original
;; function won't be redefined behind our backs. I can't think of an
;; easy way to prevent users from doing that. On the other hand,
;; there's no reason why they should.
;; The #+lispworks conditionalisations immediately below are present
;; purely as development aids.
(dspec:define-dspec-alias def-wrap (name)
`(defun ,name))
(defmacro def-wrap (name lambda-list &body body)
"Wrap BODY around the function defined by NAME. Locally defined #'PUNT
will access the original definition."
(let* ((args-var (gensym "ARGS-"))
(cache-form `(unless (get ',name 'gendl-unwrapped)
(setf (get ',name 'gendl-unwrapped) (symbol-function ',name))))
(wrapped-body `(,@(loop for next = (first body)
while (or (stringp next)
(and (consp next)
(eq (car next) 'declare)))