;;;; -*- Mode:Common-Lisp; Package:COMMON-LISP-USER; Syntax:common-lisp -*- ;;;; *-* File: /usr/local/gbbopen/extended-repl.lisp *-* ;;;; *-* Edited-By: cork *-* ;;;; *-* Last-Edit: Mon Apr 20 02:23:44 2015 *-* ;;;; *-* Machine: phoenix *-* ;;;; ************************************************************************** ;;;; ************************************************************************** ;;;; * ;;;; * Extended REPL Command Processing ;;;; * ;;;; * for ABCL, CLISP, Closure CL, CMUCL, ECL, Lispworks, SBCL, SCL, and ;;;; * XCL REPL and for SLIME (Emacs->Swank) ;;;; * ;;;; ************************************************************************** ;;;; ************************************************************************** ;;; ;;; Written by: Dan Corkill ;;; ;;; Copyright (C) 2005-2015, Dan Corkill ;;; Part of the GBBopen Project. ;;; Licensed under Apache License 2.0 (see LICENSE for license information). ;;; ;;; Porting Notice: ;;; ;;; These extensions add: ;;; - keyword-command capabilities to the REPL in CLISP, CMUCL, SBCL, ;;; and SCL ;;; - interface into CLISP's *user-commands* facility ;;; - extend ECL's command repertoire ;;; - add keyword-command support to SLIME's Emacs->Swank interface ;;; ;;; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ;;; ;;; 06-04-05 File created. (Corkill) ;;; 02-02-06 Added ECL support. (Corkill) ;;; 02-04-06 Added SLIME (Emacs->Swank) support. (Corkill) ;;; 04-17-08 Reworked SLIME mechanism. (Corkill) ;;; 10-15-09 Added XCL support. (Corkill) ;;; 01-04-11 Added partial ABCL support. (Corkill) ;;; 09-13-11 Completed ABCL support. (Corkill) ;;; 05-28-12 SBCL now prefers EXIT over QUIT. (Corkill) ;;; 04-20-15 Fix typo in load-swank placeholder on Lispworks (thanks Martti ;;; Halminen for report). (Corkill) ;;; ;;; * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * (in-package :common-lisp-user) ;;; --------------------------------------------------------------------------- ;;; In ECL, setup an Extended REPL command topic (must be done destructively, ;;; as si::*tpl-commands* is already lexically bound in the default TLP) #+ecl (setf (rest si::*tpl-commands*) (adjoin (list "Extended REPL Commands") (cdr si::*tpl-commands*) :key #'car :test #'equal)) ;;; --------------------------------------------------------------------------- ;;; In Allegro, we hide non-native help commands by saving the command-name ;;; strings in *non-native-help-commands* and fwrapping ;;; TPL::GET-COMMANDS-LIST to remove the commands from its returned value. #+allegro (defvar *non-native-help-commands* nil) #+allegro (def-fwrapper filtered-get-commands-list-wrap () ;; Remove non-native extended-REPL commands: (remove-if #'(lambda (command) (member (first command) *non-native-help-commands* :test #'equal)) (call-next-fwrapper))) #+allegro (fwrap 'top-level::get-commands-list 'extended-repl 'filtered-get-commands-list-wrap) ;;; --------------------------------------------------------------------------- ;;; With-system-name (copied in module-manager/module-manager.lisp for ;;; startup.lisp only invocation) (defvar *current-system-name* nil) (defmacro with-system-name ((&optional system-name) &body body) (unless (keywordp system-name) (error "System name, ~s, must be a keyword." system-name)) `(let ((*current-system-name* ',system-name)) ,@body)) ;;; --------------------------------------------------------------------------- (defvar *extended-repl-commands* nil) (defun get-extended-repl-command (command) (assoc command *extended-repl-commands* :test #'eq)) (compile-if-advantageous 'get-extended-repl-command) ;;; =========================================================================== ;;; Define-repl-command (defun redefining-cl-user-repl-command-warning (command fn) ;; avoid SBCL optimization warning: (declare (optimize (speed 1))) (let ((*package* (find-package ':common-lisp))) (format t "~&;; Redefining ~s function for REPL-command ~s~%" fn command))) (compile-if-advantageous 'redefining-cl-user-repl-command-warning) ;;; --------------------------------------------------------------------------- (defun add-repl-command-spec (command-spec) (setf *extended-repl-commands* (cons command-spec (delete (first command-spec) (the list *extended-repl-commands*) :test #'eq :key #'car)))) (compile-if-advantageous 'add-repl-command-spec) ;;; --------------------------------------------------------------------------- (defun eval-special-repl-variable (var) (if (member var '(* ** *** =) :test #'eq) (eval var) var)) (compile-if-advantageous 'eval-special-repl-variable) ;;; --------------------------------------------------------------------------- #+(or abcl xcl) (defun read-args-from-string (string) (when string (ignore-errors (read-from-string (concatenate 'string "(" string ")"))))) ;;; --------------------------------------------------------------------------- (defmacro define-repl-command (command-name lambda-list &rest body) (let ((.options. nil)) ;; Handle (