From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kalle Olavi Niemitalo To: guile-emacs@sourceware.cygnus.com Subject: patch: some macros and symbol completion Date: Thu, 16 Mar 2000 16:57:00 -0000 Message-id: <8766umzawq.fsf@PC486.Niemitalo.LAN> X-SW-Source: 2000-q1/msg00031.html Here's a patch for guile-emacs 0.2. It adds a new module (emacs macro), more imports in (emacs import), some documentation strings and symbol completion with Tab. 2000-03-17 Kalle Olavi Niemitalo * emacs.scm: Changed GNU Emacs to Guile Emacs in license notice. (lisp-variable-ref, lisp-variable-set!): Added docstring. (lisp-variable-set!): Return *unspecified*. (import-lisp-variable, import-lisp-function, define-variable, define-command): Documented with comments. (define-command): Propagate the docstring to the Lisp side. * guile.scm: Changed GNU Emacs to Guile Emacs in license notice. Also use modules (emacs macro), (ice-9 session) and (ice-9 regex). (guile-scheme-mode, scheme-set-module, scheme-eval-expression, scheme-eval-region, scheme-eval-last-sexp, scheme-eval-print-last-sexp): Added docstring. (scheme-interaction-mode): Extended docstring. (scheme-set-module, scheme-eval-define): Use `save-excursion'. (scheme-complete-symbol): New function. (scheme-eval-define): Use (interactive), not (interactive ()). * import.scm: Changed GNU Emacs to Guile Emacs in license notice. Also import these functions: mark-marker, set-marker (as set-marker!), make-marker, skip-syntax-forward, try-completion, delete-region, display-completion-list, ding, get-buffer-create, erase-buffer, set-buffer-modified-p (as set-buffer-modified?!), display-buffer, select-window. * macro.scm: New file. diff -xCVS -bruNF^( /home/kalle/src/FOREIGN-CVS/guile-emacs/emacs/emacs.scm /home/kalle/share/emacs/site-scheme/emacs/emacs.scm --- /home/kalle/src/FOREIGN-CVS/guile-emacs/emacs/emacs.scm Thu Mar 16 05:16:38 2000 +++ /home/kalle/share/emacs/site-scheme/emacs/emacs.scm Thu Mar 16 20:55:59 2000 @@ -7,18 +7,18 @@ ;; This file is part of Guile Emacs. -;; GNU Emacs is free software; you can redistribute it and/or modify +;; Guile Emacs is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. -;; GNU Emacs is distributed in the hope that it will be useful, +;; Guile Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the +;; along with Guile Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. @@ -33,11 +33,29 @@ (define-public (lisp-false? obj) (or (eq (define-public (lisp-true? obj) (not (lisp-false? obj))) (define-public (lisp-variable-ref symbol) + "Return the value of Lisp variable SYMBOL." (lisp-eval symbol)) (define-public (lisp-variable-set! symbol value) - (lisp-eval `(setq ,symbol ',value))) - + "Set the Lisp variable SYMBOL to VALUE." + (lisp-eval `(setq ,symbol ',value)) + ;; In Scheme, *-set! functions return an unspecified value. + *unspecified*) + +;; (import-lisp-variable VARIABLE [SCHEME-NAME]) +;; Import the Lisp variable VARIABLE to Scheme as SCHEME-NAME. +;; Both arguments are unevaluated symbols. +;; If SCHEME-NAME is omitted, it defaults to VARIABLE. +;; +;; The value bound to SCHEME-NAME is actually a procedure. +;; To get the value of the variable, call the procedure: +;; +;; (import-lisp-variable baud-rate) +;; (baud-rate) +;; => 38400 +;; (set! (baud-rate) 115200) +;; (baud-rate) +;; => 115200 (define-macro (import-lisp-variable variable . rest) (let ((name (if (pair? rest) (car rest) variable))) `(define-public ,name @@ -48,6 +66,11 @@ (define-macro (import-lisp-variable vari ptr)))) (export import-lisp-variable) +;; (import-lisp-function FUNCTION [SCHEME-NAME]) +;; Import the Lisp function FUNCTION to Scheme as SCHEME-NAME. +;; Both arguments are unevaluated symbols. +;; If SCHEME-NAME is omitted, it defaults to FUNCTION. +;; The new Scheme function is always public. (define-macro (import-lisp-function func . rest) (if (lisp-true? (lisp-apply 'functionp (list func))) (let ((name (if (pair? rest) (car rest) func))) @@ -55,21 +78,36 @@ (define-macro (import-lisp-function func (lisp-apply 'error (list "No such function: %s" func)))) (export import-lisp-function) +;; (define-variable VAR VAL DOC) +;; Define a Lisp variable VAR with value VAL and docstring DOC. +;; Then import it to Scheme with `import-lisp-variable'. (define-macro (define-variable var val doc) (lisp-eval (list 'defvar var val doc)) `(import-lisp-variable ,var)) (export define-variable) +;; (define-command (COMMAND [ARG...]) [DOCSTRING] INTERACTIVE BODY...) +;; Define COMMAND as an interactive editor command. +;; It can be called from both Scheme and Lisp. +;; [ARG...] is a Scheme argument list. +;; [DOCSTRING] is an optional documentation string. +;; INTERACTIVE is a call of the Lisp function `interactive'. +;; It is only used in the Lisp part of the command. +;; BODY... is a list of Scheme forms to evaluate when the command is run. (define-macro (define-command form . args) - (let ((name (car form)) (iarg (car args))) + (let ((name (car form)) + (iarg (car args)) + (docl '())) (if (string? iarg) - (begin (set! args (cdr args)) + (begin (set! docl (list iarg)) + (set! args (cdr args)) (set! iarg (car args)))) (if (not (and (pair? iarg) (eq? (car iarg) 'interactive))) (lisp-apply 'error (list "Command must begin with (interactive...)"))) `(begin (define-public ,form ,@(cdr args)) (lisp-eval '(defun ,name (&rest args) + ,@docl ,iarg (scheme-eval '(set-current-module the-root-module)) (scheme-apply ',name args)))))) diff -xCVS -bruNF^( /home/kalle/src/FOREIGN-CVS/guile-emacs/emacs/guile.scm /home/kalle/share/emacs/site-scheme/emacs/guile.scm --- /home/kalle/src/FOREIGN-CVS/guile-emacs/emacs/guile.scm Thu Mar 16 05:16:38 2000 +++ /home/kalle/share/emacs/site-scheme/emacs/guile.scm Fri Mar 17 01:17:05 2000 @@ -7,18 +7,18 @@ ;; This file is part of Guile Emacs. -;; GNU Emacs is free software; you can redistribute it and/or modify +;; Guile Emacs is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. -;; GNU Emacs is distributed in the hope that it will be useful, +;; Guile Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the +;; along with Guile Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. @@ -26,7 +26,10 @@ (define-module (emacs guile) :use-module (emacs emacs) - :use-module (emacs import)) + :use-module (emacs import) + :use-module (emacs macro) + :use-module (ice-9 session) + :use-module (ice-9 regex)) (require 'scheme) @@ -55,6 +58,9 @@ (if (lisp-false? (guile-scheme-mode-map) )) (define-command (guile-scheme-mode) + "Major mode for Guile Scheme programs. + +\\{guile-scheme-mode-map}" (interactive) (kill-all-local-variables) (set! (major-mode) 'guile-scheme-mode) @@ -81,7 +87,9 @@ (if (lisp-false? (scheme-interaction-mod )) (define-command (scheme-interaction-mode) - "Scheme Interaction mode." + "Major mode for evaluating Scheme expressions with Guile. + +\\{scheme-interaction-mode-map}" (interactive) (kill-all-local-variables) (use-local-map scheme-interaction-mode-map) @@ -96,14 +104,14 @@ (define-command (scheme-interaction-mode ;;; (define (scheme-set-module) - (let ((pos (point))) + "Evaluate any (define-module ...) form in the buffer." + (save-excursion (goto-char (point-min)) (if (lisp-true? (re-search-forward "^(define-module " nil t)) (let ((start (match-beginning 0))) (goto-char start) (forward-sexp) - (eval-string (buffer-substring start (point))))) - (goto-char pos))) + (eval-string (buffer-substring start (point))))))) (define (scheme-show-result value flag) (set! value (if (unspecified? value) @@ -119,16 +127,22 @@ (define (scheme-show-result value flag) ;;; (define-command (scheme-eval-expression string) + "Evaluate the expressions in STRING and show value in echo area." (interactive "SEval: ") (scheme-set-module) (scheme-show-result (eval-string string) nil)) (define-command (scheme-eval-region start end) + "Execute the region as Scheme code." (interactive "r") (scheme-set-module) (scheme-eval-expression (buffer-substring start end))) (define-command (scheme-eval-last-sexp arg) + ;; The documentation of `eval-last-sexp' talks about printing the + ;; value in the minibuffer, but that's just wrong. + "Evaluate sexp before point; show value in echo area. +With argument, print output into current buffer." (interactive "P") (scheme-set-module) (let ((stab (syntax-table)) (pos (point)) (value #f)) @@ -142,20 +156,61 @@ (define-command (scheme-eval-last-sexp a (scheme-show-result (eval-string value) arg))) (define-command (scheme-eval-print-last-sexp) - (interactive ()) + "Evaluate sexp before point; print value into current buffer." + (interactive) (insert "\n") (scheme-eval-last-sexp t) (insert "\n")) (define-command (scheme-eval-define) - (interactive ()) + (interactive) (scheme-set-module) - (let ((pos (point))) - (scheme-eval-expression (buffer-substring - (begin (beginning-of-defun) (point)) - (begin (end-of-defun) (point)))) - (goto-char pos))) + (scheme-eval-expression + (save-excursion + (buffer-substring (begin (beginning-of-defun) (point)) + (begin (end-of-defun) (point)))))) + +;; This is mostly copied from lisp-complete-symbol in emacs-lisp/lisp.el, +;; (c) 1985, 1986, 1994 FSF. +(define-command (scheme-complete-symbol) + (interactive) + (scheme-set-module) + (let* ((end (point)) + (beg (save-excursion + (save-syntax-table + (set-syntax-table scheme-mode-syntax-table) + (backward-sexp 1) + (skip-syntax-forward "'") + (point)))) + (pattern (buffer-substring beg end)) + (matches (apropos-internal + (string-append "^" (regexp-quote pattern)))) + ;; This is wasteful... + (alist (map (lambda (sym) (list (symbol->string sym))) + matches)) + (completion (try-completion pattern alist))) + (cond ((eq? completion 't)) + ((lisp-false? completion) + (message "Can't find completion for \"%s\"" pattern) + (ding)) + ((not (string=? pattern completion)) + (delete-region beg end) + (insert completion)) + (else + (message "Making completion list...") + ;; No need to call all-completions; the list was already + ;; filtered by apropos. + (with-output-to-temp-buffer "*Completions*" + (display-completion-list + (map (lambda (sym) + (let ((str (symbol->string sym)) + (val (eval sym))) + (cond ((procedure? val) (list str " ")) + ((macro? val) (list str " ")) + (else str)))) + (sort matches string