KCL on a unix-pc

Alex S. Crain alex at umbc3.UMD.EDU
Sun Oct 16 12:18:44 AEST 1988


In article <217 at arnold.UUCP> dave at arnold.UUCP (Dave Arnold) writes:
>Does anybody know how I can format the KCL docs?  I don't have the
>Kroff program.

	A TeX version of the kcl doc exists, kclreport.tex or something
close to that. Anonymous ftp from rascal.ics.utexas.edu, and probably
uunet. Note that this only covers the internals, for the fuction defs, get
_Common Lisp the Language_ by Guy Steel. This is the definition of CL, and
the model for the KCL system.

	As a side note, here is the kcl-mode that I wrote. I think that its
pretty portable, moderatly well documented, and not too discustingly coded.
It provides on line help for CL through \C-h\C-l, automatic size limits on
the interpretur buffer, and a few other funzies. Comments and critisizms are
most welcome. to use it, just load the file. I have 

(autoload 'run-kcl "kcl-mode" "" t nil)

in my startup file, so the interactive command run-kcl does it all.

------------------- cut here --------------------
;; KCL (Koyto Common Lisp) mode/environment for emacs
;; Written By Alex Crain -- alex at umbc3.umd.edu

;; Start
;;
;;

(defvar *buff-max-size* 100 
   "The maximum size that a shell buffer is allowed to become before
it is truncated from the top by (check-buffer-size).")

(defvar *buff-decrement* 10
   "The stepping value for truncating a limited buffer")

(defun check-buffer-size ()
   (interactive)
   (progn
      (save-excursion
	 (beginning-of-line)
	 (if (> (count-lines 1 (point)) *buff-max-size*)
	       (let ((save-kill kill-ring))
		  (goto-char 1)
		  (kill-line *buff-decrement*)
		  (setq kill-ring save-kill))))
      (shell-send-input)))

(defvar shell-mode-map nil)

(setq shell-mode-map (make-sparse-keymap))
                       ;;;
                       ;;; We do all this for this line...
                       ;;;
(define-key shell-mode-map "\C-m" 'check-buffer-size)

(define-key shell-mode-map "\C-c\C-d" 'shell-send-eof)
(define-key shell-mode-map "\C-c\C-u" 'kill-shell-input)
(define-key shell-mode-map "\C-c\C-w" 'backward-kill-word)
(define-key shell-mode-map "\C-c\C-c" 'interrupt-shell-subjob)
(define-key shell-mode-map "\C-c\C-z" 'stop-shell-subjob)
(define-key shell-mode-map "\C-c\C-\\" 'quit-shell-subjob)
(define-key shell-mode-map "\C-c\C-o" 'kill-output-from-shell)
(define-key shell-mode-map "\C-c\C-r" 'show-output-from-shell)
(define-key shell-mode-map "\C-c\C-y" 'copy-last-shell-input)

(load "shell")

;;
;; Redefine this here so that we can fix the documentation.
;;


(defun inferior-lisp-mode ()
""  (interactive)
  (kill-all-local-variables)
  (setq major-mode 'inferior-kcl-mode)
  (setq mode-name "Inferior KCL")
  (setq mode-line-process '(": %s"))
  (lisp-mode-variables t)
  (use-local-map inferior-lisp-mode-map)
  (make-local-variable 'last-input-start)
  (setq last-input-start (make-marker))
  (make-local-variable 'last-input-end)
  (setq last-input-end (make-marker))
  (run-hooks 'shell-mode-hook 'lisp-mode-hook))

(defun inferior-kcl-mode nil 
   "Major mode for interacting with an inferior KCL process.
A modification of inferior-lisp-mode, and is a superset of
that mode plus KCL specific extensions. Runs a KCL interpreter
as a subprocess of Emacs, with Lisp I/O through an Emacs buffer.

The lisp buffer is named 'Kcl <run>'. In addition, a shell buffer is
opened in the current directory, this buffer is called *unix*.
Emacs will recognise certain lisp expressions and respond to them. 
Currently these are:

(cd <directory>)	directory is a string or symbol refering
 			to a subdirectory. symbols are converted to 
			uppercase automatically. Emacs will respond
			by attempting to cd the buffer to the new 
			directory.

(bye)			Emacs changes the buffer name to reflect an
			inactive process, and cd's the buffer to the
			users home directory. in addition, the 'r' key
			will automatically restart the KCL process.

(exit)			emacs will query-save all the buffers and exit.

In addition, this mode knows about many of the standard CL forms for
indenting purposes.

Buffer size restrictions:
Emacs will restrict the lisp buffer to a size stored in *buffer-max-size*,
by periodically deleting the topmost lines of the buffer. This is done to
avoid extreamly large buffers generated by extended interactive lisp sessions.
The buffer is decremented whenever the buffer length (in lines) exceedes
*buffer-max-size* + *buff-decrement*, when *buff-decrement* lines will be 
deleted. The default sizes for *buff-max-size* and *buff-decrement* are
100 and 10, respectively.

Commands:
DELETE converts tabs to spaces as it moves back.
TAB indents for Lisp; with argument, shifts rest
 of expression rigidly with the current line.
Meta-Control-Q does TAB on each line starting within following expression.
Paragraphs are separated only by blank lines.  Semicolons start comments.

Return at end of buffer sends line as input.
Return not at end copies rest of line to end and sends it.

Help for common lisp is implemented in a manner simular to elisp
help. C-hC-l involks help which propts for a lisp symbol, the symbol
at the current cursor position is offered as a default.

The following commands imitate the usual Unix interrupt and
editing control characters:
\\{shell-mode-map}

Entry to this mode calls the value of lisp-mode-hook with no arguments,
if that value is non-nil.  Likewise with the value of shell-mode-hook.
lisp-mode-hook is called after shell-mode-hook.

You can send text to the inferior Lisp from other buffers
using the commands process-send-region, process-send-string
and \\[lisp-send-defun]."
(interactive)
(inferior-lisp-mode))

(shell)

(save-excursion
(set-buffer "*shell*")
(rename-buffer "*unix*"))

;(setq inferior-lisp-program "kcl")

(defvar *kcl-program-name* "kcl"
   "The name of the Koyto Common Lisp executable.")

(defun run-kcl nil 
   "The autoload tag for the kcl-mode file."
   (interactive)
   (atom t))

(defun start-kcl ()
   (interactive)
   (progn
      (define-key inferior-lisp-mode-map "r" 'self-insert-command)
      (apply 'start-process
	     "lisp"
	     (current-buffer)
	     (concat exec-directory "env")
	     (format "TERMCAP=emacs:co#%d:tc=unknown:" (screen-width))
	     "TERM=emacs"
	     "EMACS=t"
	     "-"
	     (list *kcl-program-name*))
      (rename-buffer "KCL: <Run>")))

(switch-to-buffer (get-buffer-create "KCL: <No Process>"))
(start-kcl)
(inferior-lisp-mode)
(setq mode-line-format 
      '( "                                                       %20b" ))


;;;
;;; CL forms
;;;
(put 'block 'lisp-indent-hook 0)
(put 'tagbody 'lisp-indent-hook 0)

(put 'do 'lisp-indent-hook 0)
(put 'do* 'lisp-indent-hook 0)

(put 'let 'lisp-indent-hook 1)
(put 'flet 'lisp-indent-hook 1)
(put 'macrolet 'lisp-indent-hook 1)
(put 'labels 'lisp-indent-hook 1)

(put 'loop 'lisp-indent-hook 0)

(put 'prog 'lisp-indent-hook 1)
(put 'progn 'lisp-indent-hook 0)
(put 'prog1 'lisp-indent-hook 0)
(put 'prog2 'lisp-indent-hook 0)
(put 'progv 'lisp-indent-hook 0)

(put 'if 'lisp-indent-hook 2)
(put 'when 'lisp-indent-hook 1)
(put 'unless 'lisp-indent-hook 1)
(put 'cond 'lisp-indent-hook 0)
(put 'typecase 'lisp-indent-hook 1)

(put 'dolist 'lisp-indent-hook 1)
(put 'dotimes 'lisp-indent-hook 1)

;;;
;;; indenting characteristics
;;;
   
(setq lisp-body-indent 3)
   
   
;;
;; Interactive emacs help for kcl bound to C-hC-l
;;

(defvar *help-file* "/usr/local/doc/prindoc.out")

(defun kcl-help (s &optional no-error)
   (interactive
    (let* ((sname (symbol-at-point))
	   (val (read-from-minibuffer 
		 (if (equal sname "")
		       "KCL Symbol> "
		    (format "KCL Symbol (default: %s) " (upcase sname))))))
       (list 
	(if (equal val "")
	      sname
	   val))))
   (let ((buff (or
		(get-buffer "*KCL: <Help>*")
		(gen-help-buff))))
      (save-excursion
	 (set-buffer buff)
	 (or no-error (goto-char 1))
	 (or
	  (search-forward (concat "------------------
" s " ") 512000 t)
	  (search-forward (concat "------------------
si:" s " ") 512000 t)
	  (if no-error (throw 'help-exit nil)
	     (error "No documentation on KCL Symbol %s." (upcase s)))
	  )
	 (beginning-of-line)
	 (save-excursion
	    (previous-line 1)
	    (condition-case ()
		  (split-window
		   (selected-window)
		   (min
		    (count-lines (point)
				 (progn
				    (forward-line)
				    (search-forward "------------------------")
				    (beginning-of-line)
				    (point)))
		    10))
	       (error 
		(message "base window too small to split for help screen")))))
      (switch-to-buffer buff)
      (set-window-start (selected-window) (point))
      (other-window 1)
      (catch 'help-exit (kcl-help s t))
      (bury-buffer "*KCL: <Help>*")
      ))

(defun gen-help-buff ()
   (save-excursion
      (set-buffer (find-file-noselect *help-file*))
      (rename-buffer "*KCL: <Help>*")
      (setq mode-line-format 
 '( "                                                       KCL: <Help>" ))
      (get-buffer (current-buffer))))
	      
(global-set-key "\C-h\C-l" 'kcl-help)

(defun help-for-help ()
  "You have typed C-h, the help character.  Type a Help option:

A  command-apropos.   Give a substring, and see a list of commands
              (functions interactively callable) that contain
	      that substring.  See also the  apropos  command.
B  describe-bindings.  Display table of all key bindings.
C  describe-key-briefly.  Type a command key sequence;
	      it prints the function name that sequence runs.
F  describe-function.  Type a function name and get documentation of it.
I  info. The  info  documentation reader.
K  describe-key.  Type a command key sequence;
	      it displays the full documentation.
L  view-lossage.  Shows last 100 characters you typed.
M  describe-mode.  Print documentation of current major mode,
	      which describes the commands peculiar to it.
N  view-emacs-news.  Shows emacs news file.
S  describe-syntax.  Display contents of syntax table, plus explanations
T  help-with-tutorial.  Select the Emacs learn-by-doing tutorial.
V  describe-variable.  Type name of a variable;
	      it displays the variable's documentation and value.
W  where-is.  Type command name; it prints which keystrokes
	      invoke that command.
C-c print Emacs copying permission (General Public License).
C-d print Emacs ordering information.
C-l Help for Koyto Common Lisp. Type a CL symbol name;
              it displayes all references to that symbol from the KCL 
              documentation.
C-n print news of recent Emacs changes.
C-w print information on absence of warranty for GNU Emacs."
  (interactive)
  (message
"A B C F I K L M N S T V W C-c C-d C-l C-n C-w.  Type C-h again for more help:")
  (let ((char (read-char)))
    (if (or (= char ?\C-h) (= char ??))
	(save-window-excursion
	  (switch-to-buffer "*Help*")
	  (erase-buffer)
	  (insert (documentation 'help-for-help))
	  (goto-char (point-min))
	  (while (memq char '(?\C-h ?? ?\C-v ?\ ?\177 ?\M-v))
	    (if (memq char '(?\C-v ?\ ))
		(scroll-up))
	    (if (memq char '(?\177 ?\M-v))
		(scroll-down))
	    (message "A B C F I K L M N S T V W C-c C-d C-l C-n C-w%s: "
		     (if (pos-visible-in-window-p (point-max))
			 "" " or Space to scroll"))
	    (let ((cursor-in-echo-area t))
	      (setq char (read-char))))))
    (let ((defn (cdr (assq (downcase char) (cdr help-map)))))
      (if defn (call-interactively defn) (ding)))))

(defun symbol-at-point ()
  (condition-case ()
	(save-excursion
	   (forward-sexp -1)
	   (skip-chars-forward "'(#?\ 	")
	   (buffer-substring (point)
			     (progn
				(skip-chars-forward "a-zA-Z0-9\-*$_")
				(point))))
     (error nil)))

;;;;;;;;
;;;
;;;  From kcl-shell.el
;;;
;;;;;;;;

(defun shell-set-directory ()
   (cond
      ;;;
      ;;; (bye) Must return us to the $HOME directory, or init.kcl won't
      ;;;    get loaded on restart.
      ;;;
      ((looking-at "([ \n\t]*bye[ \n\t]*)")
       (progn
	  (define-key inferior-lisp-mode-map "r" 'start-kcl)
	  (rename-buffer "KCL: <No Process>")
	  (cd (getenv "HOME"))))
      ;;;
      ;;; (exit) is a fatal command. Query to save buffers and exit emacs.
      ;;;
      ((looking-at "([ \n\t]*exit[ \n\t]*)")
       (progn
	  (rename-buffer "KCL: <Exiting>")
	  (kill-process "shell")
	  (kill-process "lisp")
	  (save-buffers-kill-emacs)))
      ;;;
      ;;; This bit is for keeping emacs in the smae dir as kcl.
      ;;;
      ((looking-at "(cd[ \n\t)]") 
       (let (dir)
	  (forward-char 3)
	  (skip-chars-forward " \t\n\"")
	  (if (eq (char-after (point)) 41)
		(cd (getenv "HOME"))
	     (if (file-directory-p
		  (setq dir
			(expand-file-name
			 (substitute-in-file-name
			  (upcase
			   (let ((ts (buffer-substring
				      (point)
				      (progn
					 (skip-chars-forward "^\n \t\")")
					 (point)))))
			      (if (string-equal "^" ts)
				    ".."
				 ts)))))))
		   (cd dir)))))))

;;
;;
;; end
-- 
					:alex.
					Systems Programmer
nerwin!alex at umbc3.umd.edu		UMBC
alex at umbc3.umd.edu



More information about the Comp.sys.att mailing list