mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-29 19:30:36 +02:00
Merge branch 'ossau-gds-dev'
Conflicts: THANKS
This commit is contained in:
commit
639bf3e507
12 changed files with 712 additions and 61 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -72,6 +72,8 @@ gdb-pre-inst-guile
|
|||
cscope.out
|
||||
cscope.files
|
||||
*.log
|
||||
gds-test.debug
|
||||
gds-test.transcript
|
||||
INSTALL
|
||||
*.aux
|
||||
*.cp
|
||||
|
|
29
AUTHORS
29
AUTHORS
|
@ -206,8 +206,34 @@ In the subdirectory doc, changes to:
|
|||
Many changes throughout.
|
||||
|
||||
Neil Jerram:
|
||||
In the subdirectory emacs, wrote:
|
||||
gds.el gds-scheme.el gds-server.el
|
||||
gds-test.el gds-test.sh gds-test.stdin
|
||||
gds-tutorial.txt gds-faq.txt
|
||||
In the subdirectory ice-9, wrote:
|
||||
buffered-input.scm
|
||||
buffered-input.scm gds-client.scm gds-server.scm
|
||||
In the subdirectory ice-9/debugging, wrote:
|
||||
example-fns.scm ice-9-debugger-extensions.scm
|
||||
steps.scm trace.scm traps.scm
|
||||
trc.scm
|
||||
In the subdirectory lang/elisp, wrote:
|
||||
base.scm example.el interface.scm
|
||||
transform.scm variables.scm
|
||||
In the subdirectory lang/elisp/internals, wrote:
|
||||
evaluation.scm format.scm fset.scm
|
||||
lambda.scm load.scm null.scm
|
||||
set.scm signal.scm time.scm
|
||||
trace.scm
|
||||
In the subdirectory lang/elisp/primitives, wrote:
|
||||
buffers.scm char-table.scm features.scm
|
||||
fns.scm format.scm guile.scm
|
||||
keymaps.scm lists.scm load.scm
|
||||
match.scm numbers.scm pure.scm
|
||||
read.scm signal.scm strings.scm
|
||||
symprop.scm syntax.scm system.scm
|
||||
time.scm
|
||||
In the subdirectory srfi, wrote:
|
||||
srfi-34.scm
|
||||
In the subdirectory doc, wrote:
|
||||
deprecated.texi goops.texi scheme-ideas.texi
|
||||
scheme-reading.texi
|
||||
|
@ -227,6 +253,7 @@ In the subdirectory doc, changes to:
|
|||
scm.texi scripts.texi script-getopt.texi
|
||||
In the subdirectory doc/maint, wrote:
|
||||
docstring.el
|
||||
Many other changes throughout.
|
||||
|
||||
Thien-Thi Nguyen:
|
||||
In the top-level directory, wrote:
|
||||
|
|
3
THANKS
3
THANKS
|
@ -30,6 +30,7 @@ For fixes or providing information which led to a fix:
|
|||
Rob Browning
|
||||
Adrian Bunk
|
||||
Michael Carmack
|
||||
R Clayton
|
||||
Stephen Compall
|
||||
Brian Crowder
|
||||
Christopher Cramer
|
||||
|
@ -95,6 +96,7 @@ For fixes or providing information which led to a fix:
|
|||
Werner Scheinast
|
||||
Bill Schottstaedt
|
||||
Frank Schwidom
|
||||
John Steele Scott
|
||||
Thiemo Seufer
|
||||
Scott Shedden
|
||||
Alex Shinn
|
||||
|
@ -115,6 +117,7 @@ For fixes or providing information which led to a fix:
|
|||
Andreas Vögele
|
||||
Michael Talbot-Wilson
|
||||
Michael Tuexen
|
||||
Thomas Wawrzinek
|
||||
Mark H. Weaver
|
||||
Jon Wilson
|
||||
Andy Wingo
|
||||
|
|
225
emacs/gds-faq.txt
Executable file
225
emacs/gds-faq.txt
Executable file
|
@ -0,0 +1,225 @@
|
|||
|
||||
* Installation
|
||||
|
||||
** How do I install guile-debugging?
|
||||
|
||||
After unpacking the .tar.gz file, run the usual sequence of commands:
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
Then you need to make sure that the directory where guile-debugging's
|
||||
Scheme files were installed is included in your Guile's load path.
|
||||
(The sequence above will usually install guile-debugging under
|
||||
/usr/local, and /usr/local is not in Guile's load path by default,
|
||||
unless Guile itself was installed under /usr/local.) You can discover
|
||||
your Guile's default load path by typing
|
||||
|
||||
$ guile -q -c '(begin (write %load-path) (newline))'
|
||||
|
||||
There are two ways to add guile-debugging's installation directory to
|
||||
Guile's load path, if it isn't already there.
|
||||
|
||||
1. Edit or create the `init.scm' file, which Guile reads on startup,
|
||||
so that it includes a line like this:
|
||||
|
||||
(set! %load-path (cons "/usr/local/share/guile" %load-path))
|
||||
|
||||
but with "/usr/local" replaced by the prefix that you installed
|
||||
guile-debugging under, if not /usr/local.
|
||||
|
||||
The init.scm file must be installed (if it does not already exist
|
||||
there) in one of the directories in Guile's default load-path.
|
||||
|
||||
2. Add this line to your .emacs file:
|
||||
|
||||
(setq gds-scheme-directory "/usr/local/share/guile")
|
||||
|
||||
before the `require' or `load' line that loads GDS, but with
|
||||
"/usr/local" replaced by the prefix that you installed
|
||||
guile-debugging under, if not /usr/local.
|
||||
|
||||
Finally, if you want guile-debugging's GDS interface to be loaded
|
||||
automatically whenever you run Emacs, add this line to your .emacs:
|
||||
|
||||
(require 'gds)
|
||||
|
||||
* Troubleshooting
|
||||
|
||||
** "error in process filter" when starting Emacs (or loading GDS)
|
||||
|
||||
This is caused by an internal error in GDS's Scheme code, for which a
|
||||
backtrace will have appeared in the gds-debug buffer, so please switch
|
||||
to the gds-debug buffer and see what it says there.
|
||||
|
||||
The most common cause is a load path problem: Guile cannot find GDS's
|
||||
Scheme code because it is not in the known load path. In this case
|
||||
you should see the error message "no code for module" somewhere in the
|
||||
backtrace. If you see this, please try the remedies described in `How
|
||||
do I install guile-debugging?' above, then restart Emacs and see if
|
||||
the problem has been cured.
|
||||
|
||||
If you don't see "no code for module", or if the described remedies
|
||||
don't fix the problem, please send the contents of the gds-debug
|
||||
buffer to me at <neil@ossau.uklinux.net>, so I can debug the problem.
|
||||
|
||||
If you don't see a backtrace at all in the gds-debug buffer, try the
|
||||
next item ...
|
||||
|
||||
** "error in process filter" at some other time
|
||||
|
||||
This is caused by an internal error somewhere in GDS's Emacs Lisp
|
||||
code. If possible, please
|
||||
|
||||
- switch on the `debug-on-error' option (M-x set-variable RET
|
||||
debug-on-error RET t RET)
|
||||
|
||||
- do whatever you were doing so that the same error happens again
|
||||
|
||||
- send the Emacs Lisp stack trace which pops up to me at
|
||||
<neil@ossau.uklinux.net>.
|
||||
|
||||
If that doesn't work, please just mail me with as much detail as
|
||||
possible of what you were doing when the error occurred.
|
||||
|
||||
* GDS Features
|
||||
|
||||
** How do I inspect variable values?
|
||||
|
||||
Type `e' followed by the name of the variable, then <RET>. This
|
||||
works whenever GDS is displaying a stack for an error at at a
|
||||
breakpoint. (You can actually `e' to evaluate any expression in the
|
||||
local environment of the selected stack frame; inspecting variables is
|
||||
the special case of this where the expression is only a variable name.)
|
||||
|
||||
If GDS is displaying the associated source code in the window above or
|
||||
below the stack, you can see the values of any variables in the
|
||||
highlighted code just by hovering your mouse over them.
|
||||
|
||||
** How do I change a variable's value?
|
||||
|
||||
Type `e' and then `(set! VARNAME NEWVAL)', where VARNAME is the name
|
||||
of the variable you want to set and NEWVAL is an expression which
|
||||
Guile can evaluate to get the new value. This works whenever GDS is
|
||||
displaying a stack for an error at at a breakpoint. The setting will
|
||||
take effect in the local environment of the selected stack frame.
|
||||
|
||||
** How do I change the expression that Guile is about to evaluate?
|
||||
|
||||
Type `t' followed by the expression that you want Guile to evaluate
|
||||
instead, then <RET>.
|
||||
|
||||
Then type one of the commands that tells Guile to continue execution.
|
||||
|
||||
(Tweaking expressions, as described here, is only supported by the
|
||||
latest CVS version of Guile. The GDS stack display tells you when
|
||||
tweaking is possible by adding "(tweakable)" to the first line of the
|
||||
stack window.)
|
||||
|
||||
** How do I return a value from the current stack frame different to what the evaluator has calculated?
|
||||
|
||||
You have to be at the normal exit of the relevant frame first, so if
|
||||
GDS is not already showing you the normally calculated return value,
|
||||
type `o' to finish the evaluation of the selected frame.
|
||||
|
||||
Then type `t' followed by the value you want to return, and <RET>.
|
||||
The value that you type can be any expression, but note that it will
|
||||
not be evaluated before being returned; for example if you type `(+ 2
|
||||
3)', the return value will be a three-element list, not 5.
|
||||
|
||||
Finally type one of the commands that tells Guile to continue
|
||||
execution.
|
||||
|
||||
(Tweaking return values, as described here, is only supported by the
|
||||
latest CVS version of Guile. The GDS stack display tells you when
|
||||
tweaking is possible by adding "(tweakable)" to the first line of the
|
||||
stack window.)
|
||||
|
||||
** How do I step over a line of code?
|
||||
|
||||
Scheme isn't organized by lines, so it doesn't really make sense to
|
||||
think of stepping over lines. Instead please see the next entry on
|
||||
stepping over expressions.
|
||||
|
||||
** How do I step over an expression?
|
||||
|
||||
It depends what you mean by "step over". If you mean that you want
|
||||
Guile to evaluate that expression normally, but then show you its
|
||||
return value, type `o', which does exactly that.
|
||||
|
||||
If you mean that you want to skip the evaluation of that expression
|
||||
(for example because it has side effects that you don't want to
|
||||
happen), use `t' to change the expression to something else which
|
||||
Guile will evaluate instead.
|
||||
|
||||
There has to be a substitute expression so Guile can calculate a value
|
||||
to return to the calling frame. If you know at a particular point
|
||||
that the return value is not important, you can type `t #f <RET>' or
|
||||
`t 0 <RET>'.
|
||||
|
||||
See `How do I change the expression that Guile is about to evaluate?'
|
||||
above for more on using `t'.
|
||||
|
||||
** How do I move up and down the call stack?
|
||||
|
||||
Type `u' to move up and `d' to move down. "Up" in GDS means to a more
|
||||
"inner" frame, and "down" means to a more "outer" frame.
|
||||
|
||||
** How do I run until the next breakpoint?
|
||||
|
||||
Type `g' (for "go").
|
||||
|
||||
** How do I run until the end of the selected stack frame?
|
||||
|
||||
Type `o'.
|
||||
|
||||
** How do I set a breakpoint?
|
||||
|
||||
First identify the code that you want to set the breakpoint in, and
|
||||
what kind of breakpoint you want. To set a breakpoint on entry to a
|
||||
top level procedure, move the cursor to anywhere in the procedure
|
||||
definition, and make sure that the region/mark is inactive. To set a
|
||||
breakpoint on a particular expression (or sequence of expressions) set
|
||||
point and mark so that the region covers the opening parentheses of
|
||||
all the target expressions.
|
||||
|
||||
Then type ...
|
||||
|
||||
`C-c C-b d' for a `debug' breakpoint, which means that GDS will
|
||||
display the stack when the breakpoint is hit
|
||||
|
||||
`C-c C-b t' for a `trace' breakpoint, which means that the start and
|
||||
end of the relevant procedure or expression(s) will be traced to the
|
||||
*GDS Trace* buffer
|
||||
|
||||
`C-c C-b T' for a `trace-subtree' breakpoint, which means that every
|
||||
evaluation step involved in the evaluation of the relevant procedure
|
||||
or expression(s) will be traced to the *GDS Trace* buffer.
|
||||
|
||||
You can also type `C-x <SPC>', which does the same as one of the
|
||||
above, depending on the value of `gds-default-breakpoint-type'.
|
||||
|
||||
** How do I clear a breakpoint?
|
||||
|
||||
Select a region containing the breakpoints that you want to clear, and
|
||||
type `C-c C-b <DEL>'.
|
||||
|
||||
** How do I trace calls to a particular procedure or evaluations of a particular expression?
|
||||
|
||||
In GDS this means setting a breakpoint whose type is `trace' or
|
||||
`trace-subtree'. See `How do I set a breakpoint?' above.
|
||||
|
||||
* Development
|
||||
|
||||
** How can I follow or contribute to guile-debugging's development?
|
||||
|
||||
guile-debugging is hosted at http://gna.org, so please see the project
|
||||
page there. Feel free to raise bugs, tasks containing patches or
|
||||
feature requests, and so on. You can also write directly to me by
|
||||
email: <neil@ossau.uklinux.net>.
|
||||
|
||||
|
||||
Local Variables:
|
||||
mode: outline
|
||||
End:
|
|
@ -43,25 +43,24 @@
|
|||
:group 'gds
|
||||
:type '(choice (const :tag "nil" nil) directory))
|
||||
|
||||
(defun gds-start-server (procname port-or-path protocol-handler &optional bufname)
|
||||
"Start a GDS server process called PROCNAME, listening on TCP port
|
||||
or Unix domain socket PORT-OR-PATH. PROTOCOL-HANDLER should be a
|
||||
function that accepts and processes one protocol form. Optional arg
|
||||
BUFNAME specifies the name of the buffer that is used for process
|
||||
output; if not specified the buffer name is the same as the process
|
||||
name."
|
||||
(with-current-buffer (get-buffer-create (or bufname procname))
|
||||
(defun gds-start-server (procname unix-socket-name tcp-port protocol-handler)
|
||||
"Start a GDS server process called PROCNAME, listening on Unix
|
||||
domain socket UNIX-SOCKET-NAME and TCP port number TCP-PORT.
|
||||
PROTOCOL-HANDLER should be a function that accepts and processes
|
||||
one protocol form."
|
||||
(with-current-buffer (get-buffer-create procname)
|
||||
(erase-buffer)
|
||||
(let* ((code (format "(begin
|
||||
%s
|
||||
(use-modules (ice-9 gds-server))
|
||||
(run-server %S))"
|
||||
(run-server %S %S))"
|
||||
(if gds-scheme-directory
|
||||
(concat "(set! %load-path (cons "
|
||||
(format "%S" gds-scheme-directory)
|
||||
" %load-path))")
|
||||
"")
|
||||
port-or-path))
|
||||
unix-socket-name
|
||||
tcp-port))
|
||||
(process-connection-type nil) ; use a pipe
|
||||
(proc (start-process procname
|
||||
(current-buffer)
|
||||
|
|
166
emacs/gds-test.el
Normal file
166
emacs/gds-test.el
Normal file
|
@ -0,0 +1,166 @@
|
|||
|
||||
;; Test utility code.
|
||||
(defun gds-test-execute-keys (keys &optional keys2)
|
||||
(execute-kbd-macro (apply 'vector (listify-key-sequence keys))))
|
||||
|
||||
(defvar gds-test-expecting nil)
|
||||
|
||||
(defun gds-test-protocol-hook (form)
|
||||
(message "[protocol: %s]" (car form))
|
||||
(if (eq (car form) gds-test-expecting)
|
||||
(setq gds-test-expecting nil)))
|
||||
|
||||
(defun gds-test-expect-protocol (proc &optional timeout)
|
||||
(message "[expect: %s]" proc)
|
||||
(setq gds-test-expecting proc)
|
||||
(while gds-test-expecting
|
||||
(or (accept-process-output gds-debug-server (or timeout 5))
|
||||
(error "Timed out after %ds waiting for %s" (or timeout 5) proc))))
|
||||
|
||||
(defun gds-test-check-buffer (name &rest strings)
|
||||
(let ((buf (or (get-buffer name) (error "No %s buffer" name))))
|
||||
(save-excursion
|
||||
(set-buffer buf)
|
||||
(goto-char (point-min))
|
||||
(while strings
|
||||
(search-forward (car strings))
|
||||
(setq strings (cdr strings))))))
|
||||
|
||||
(defun TEST (desc)
|
||||
(message "TEST: %s" desc))
|
||||
|
||||
;; Make sure we take GDS elisp code from this code tree.
|
||||
(setq load-path (cons (concat default-directory "emacs/") load-path))
|
||||
|
||||
;; Protect the tests so we can do some cleanups in case of error.
|
||||
(unwind-protect
|
||||
(progn
|
||||
|
||||
;; Visit the tutorial.
|
||||
(find-file "gds-tutorial.txt")
|
||||
|
||||
(TEST "Load up GDS.")
|
||||
(search-forward "(require 'gds)")
|
||||
(setq load-path (cons (concat default-directory "emacs/") load-path))
|
||||
(gds-test-execute-keys "\C-x\C-e")
|
||||
|
||||
;; Install our testing hook.
|
||||
(add-hook 'gds-protocol-hook 'gds-test-protocol-hook)
|
||||
|
||||
(TEST "Help.")
|
||||
(search-forward "(list-ref")
|
||||
(backward-char 2)
|
||||
(gds-test-execute-keys "\C-hg\C-m")
|
||||
(gds-test-expect-protocol 'eval-results 10)
|
||||
(gds-test-check-buffer "*Guile Help*"
|
||||
"help list-ref"
|
||||
"is a primitive procedure in the (guile) module")
|
||||
|
||||
(TEST "Completion.")
|
||||
(re-search-forward "^with-output-to-s")
|
||||
(gds-test-execute-keys "\e\C-i")
|
||||
(beginning-of-line)
|
||||
(or (looking-at "with-output-to-string")
|
||||
(error "Expected completion `with-output-to-string' failed"))
|
||||
|
||||
(TEST "Eval defun.")
|
||||
(search-forward "(display z)")
|
||||
(gds-test-execute-keys "\e\C-x")
|
||||
(gds-test-expect-protocol 'eval-results)
|
||||
(gds-test-check-buffer "*Guile Evaluation*"
|
||||
"(let ((x 1) (y 2))"
|
||||
"Arctangent is: 0.46"
|
||||
"=> 0.46")
|
||||
|
||||
(TEST "Multiple values.")
|
||||
(search-forward "(values 'a ")
|
||||
(gds-test-execute-keys "\e\C-x")
|
||||
(gds-test-expect-protocol 'eval-results)
|
||||
(gds-test-check-buffer "*Guile Evaluation*"
|
||||
"(values 'a"
|
||||
"hello world"
|
||||
"=> a"
|
||||
"=> b"
|
||||
"=> c")
|
||||
|
||||
(TEST "Eval region with multiple expressions.")
|
||||
(search-forward "(display \"Arctangent is: \")")
|
||||
(beginning-of-line)
|
||||
(push-mark nil nil t)
|
||||
(forward-line 3)
|
||||
(gds-test-execute-keys "\C-c\C-r")
|
||||
(gds-test-expect-protocol 'eval-results)
|
||||
(gds-test-check-buffer "*Guile Evaluation*"
|
||||
"(display \"Arctangent is"
|
||||
"Arctangent is:"
|
||||
"=> no (or unspecified) value"
|
||||
"ERROR: Unbound variable: z"
|
||||
"=> error-in-evaluation"
|
||||
"Evaluating expression 3"
|
||||
"=> no (or unspecified) value")
|
||||
|
||||
(TEST "Eval syntactically unbalanced region.")
|
||||
(search-forward "(let ((z (atan x y)))")
|
||||
(beginning-of-line)
|
||||
(push-mark nil nil t)
|
||||
(forward-line 4)
|
||||
(gds-test-execute-keys "\C-c\C-r")
|
||||
(gds-test-expect-protocol 'eval-results)
|
||||
(gds-test-check-buffer "*Guile Evaluation*"
|
||||
"(let ((z (atan"
|
||||
"Reading expressions to evaluate"
|
||||
"ERROR"
|
||||
"end of file"
|
||||
"=> error-in-read")
|
||||
|
||||
(TEST "Stepping through an evaluation.")
|
||||
(search-forward "(for-each (lambda (x)")
|
||||
(forward-line 1)
|
||||
(push-mark nil nil t)
|
||||
(forward-line 1)
|
||||
(gds-test-execute-keys "\C-u\e\C-x")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys " ")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys "o")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys "o")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys "o")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys "o")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys "o")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys "o")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys "o")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys "o")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys "o")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys "o")
|
||||
(gds-test-expect-protocol 'stack)
|
||||
(gds-test-execute-keys "g")
|
||||
(gds-test-expect-protocol 'eval-results)
|
||||
(gds-test-check-buffer "*Guile Evaluation*"
|
||||
"(for-each (lambda"
|
||||
"Evaluating in current module"
|
||||
"3 cubed is 27"
|
||||
"=> no (or unspecified) value")
|
||||
|
||||
;; Done.
|
||||
(message "====================================")
|
||||
(message "gds-test.el completed without errors")
|
||||
(message "====================================")
|
||||
|
||||
)
|
||||
|
||||
(switch-to-buffer "gds-debug")
|
||||
(write-region (point-min) (point-max) "gds-test.debug")
|
||||
|
||||
(switch-to-buffer "*GDS Transcript*")
|
||||
(write-region (point-min) (point-max) "gds-test.transcript")
|
||||
|
||||
)
|
2
emacs/gds-test.sh
Executable file
2
emacs/gds-test.sh
Executable file
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
GUILE_LOAD_PATH=$(pwd) emacs --batch --no-site-file -q -l gds-test.el < gds-test.stdin
|
1
emacs/gds-test.stdin
Normal file
1
emacs/gds-test.stdin
Normal file
|
@ -0,0 +1 @@
|
|||
|
223
emacs/gds-tutorial.txt
Executable file
223
emacs/gds-tutorial.txt
Executable file
|
@ -0,0 +1,223 @@
|
|||
|
||||
;; Welcome to the GDS tutorial!
|
||||
|
||||
;; This tutorial teaches the use of GDS by leading you through a set
|
||||
;; of examples where you actually use GDS, in Emacs, along the way.
|
||||
;; To get maximum benefit, therefore, you should be reading this
|
||||
;; tutorial in Emacs.
|
||||
|
||||
;; ** GDS setup
|
||||
|
||||
;; The first thing to do, if you haven't already, is to load the GDS
|
||||
;; library into Emacs. The Emacs Lisp expression for this is:
|
||||
|
||||
(require 'gds)
|
||||
|
||||
;; So, if you don't already have this in your .emacs, either add it
|
||||
;; and then restart Emacs, or evaluate it just for this Emacs session
|
||||
;; by moving the cursor to just after the closing parenthesis and
|
||||
;; typing `C-x C-e'.
|
||||
|
||||
;; (Note that if you _have_ already loaded GDS, and you type `C-x C-e'
|
||||
;; after this expression, you will see a *Guile Evaluation* window
|
||||
;; telling you that the evaluation failed because `require' is
|
||||
;; unbound. Don't worry; this is not a problem, and the rest of the
|
||||
;; tutorial should still work just fine.)
|
||||
|
||||
;; ** Help
|
||||
|
||||
;; GDS makes it easy to access the Guile help system when working on a
|
||||
;; Scheme program in Emacs. For example, suppose that you are writing
|
||||
;; code that uses list-ref, and need to remind yourself about
|
||||
;; list-ref's arguments ...
|
||||
|
||||
(define (penultimate l)
|
||||
(list-ref
|
||||
|
||||
;; Just place the cursor on the word "list-ref" and type `C-h g RET'.
|
||||
;; Try it now!
|
||||
|
||||
;; If GDS is working correctly, a window should have popped up above
|
||||
;; or below showing the Guile help for list-ref.
|
||||
|
||||
;; You can also do an "apropos" search through Guile's help. If you
|
||||
;; couldn't remember the name list-ref, for example, you could search
|
||||
;; for anything matching "list" by typing `C-h C-g' and entering
|
||||
;; "list" at the minibuffer prompt. Try doing this now: you should
|
||||
;; see a longish list of Guile definitions whose names include "list".
|
||||
;; As usual in Emacs, you can use `M-PageUp' and `M-PageDown' to
|
||||
;; conveniently scroll the other window without having to select it.
|
||||
|
||||
;; The functions called by `C-h g' and `C-h C-g' are gds-help-symbol
|
||||
;; and gds-apropos. They both look up the symbol or word at point by
|
||||
;; default, but that default can be overidden by typing something else
|
||||
;; at the minibuffer prompt.
|
||||
|
||||
;; ** Completion
|
||||
|
||||
;; As you are typing Scheme code, you can ask GDS to complete the
|
||||
;; symbol before point for you, by typing `ESC TAB'. GDS selects
|
||||
;; possible completions by matching the text so far against all
|
||||
;; definitions in the Guile environment. (This may be contrasted with
|
||||
;; the "dabbrev" completion performed by `M-/', which selects possible
|
||||
;; completions from the contents of Emacs buffers. So, if you are
|
||||
;; trying to complete "with-ou", to get "with-output-to-string", for
|
||||
;; example, `ESC TAB' will always work, because with-output-to-string
|
||||
;; is always defined in Guile's default environment, whereas `M-/'
|
||||
;; will only work if one of Emacs's buffers happens to contain the
|
||||
;; full name "with-output-to-string".)
|
||||
|
||||
;; To illustrate the idea, here are some partial names that you can
|
||||
;; try completing. For each one, move the cursor to the end of the
|
||||
;; line and type `ESC TAB' to try to complete it.
|
||||
|
||||
list-
|
||||
with-ou
|
||||
with-output-to-s
|
||||
mkst
|
||||
|
||||
;; (If you are not familiar with any of the completed definitions,
|
||||
;; feel free to use `C-h g' to find out about them!)
|
||||
|
||||
;; ** Evaluation
|
||||
|
||||
;; GDS provides several ways for you to evaluate Scheme code from
|
||||
;; within Emacs.
|
||||
|
||||
;; Just like in Emacs Lisp, a single expression in a buffer can be
|
||||
;; evaluated using `C-x C-e' or `C-M-x'. For `C-x C-e', the
|
||||
;; expression is that which ends immediately before point (so that it
|
||||
;; is useful for evaluating something just after you have typed it).
|
||||
;; For `C-M-x', the expression is the "top level defun" around point;
|
||||
;; this means the balanced chunk of code around point whose opening
|
||||
;; parenthesis is in column 0.
|
||||
|
||||
;; Take this code fragment as an example:
|
||||
|
||||
(let ((x 1) (y 2))
|
||||
(let ((z (atan x y)))
|
||||
(display "Arctangent is: ")
|
||||
(display z)
|
||||
(newline)
|
||||
z))
|
||||
|
||||
;; If you move the cursor to the end of the (display z) line and type
|
||||
;; `C-x C-e', the code evaluated is just "(display z)", which normally
|
||||
;; produces an error, because z is not defined in the usual Guile
|
||||
;; environment. If, however, you type `C-M-x' with the cursor in the
|
||||
;; same place, the code evaluated is the whole "(let ((x 1) (y 2))
|
||||
;; ...)" kaboodle, because that is the most recent expression before
|
||||
;; point that starts in column 0.
|
||||
|
||||
;; Try these now. The Guile Evaluation window should pop up again,
|
||||
;; and show you:
|
||||
;; - the expression that was evaluated (probably abbreviated)
|
||||
;; - the module that it was evaluated in
|
||||
;; - anything that the code wrote to its standard output
|
||||
;; - the return value(s) of the evaluation.
|
||||
;; Following the convention of the Emacs Lisp and Guile manuals,
|
||||
;; return values are indicated by the symbol "=>".
|
||||
|
||||
;; To see what happens when an expression has multiple return values,
|
||||
;; try evaluating this one:
|
||||
|
||||
(values 'a (begin (display "hello world\n") 'b) 'c)
|
||||
|
||||
;; You can also evaluate a region of a buffer using `C-c C-r'. If the
|
||||
;; code in the region consists of multiple expressions, GDS evaluates
|
||||
;; them sequentially. For example, try selecting the following three
|
||||
;; lines and typing `C-c C-r'.
|
||||
|
||||
(display "Arctangent is: ")
|
||||
(display z)
|
||||
(newline)
|
||||
|
||||
;; If the code in the region evaluated isn't syntactically balanced,
|
||||
;; GDS will indicate a read error, for example for this code:
|
||||
|
||||
(let ((z (atan x y)))
|
||||
(display "Arctangent is: ")
|
||||
(display z)
|
||||
(newline)
|
||||
|
||||
;; Finally, if you want to evaluate something quickly that is not in a
|
||||
;; buffer, you can use `C-c C-e' and type the code to evaluate at the
|
||||
;; minibuffer prompt. The results are popped up in the same way as
|
||||
;; for code from a buffer.
|
||||
|
||||
;; ** Breakpoints
|
||||
|
||||
;; Before evaluating Scheme code from an Emacs buffer, you may want to
|
||||
;; set some breakpoints in it. With GDS you can set breakpoints in
|
||||
;; Scheme code by typing `C-x SPC'.
|
||||
;;
|
||||
;; To see how this works, select the second line of the following code
|
||||
;; (the `(format ...)' line) and type `C-x SPC'.
|
||||
|
||||
(for-each (lambda (x)
|
||||
(format #t "~A cubed is ~A\n" x (* x x x)))
|
||||
(iota 6))
|
||||
|
||||
;; The two opening parentheses in that line should now be highlighted
|
||||
;; in red, to show that breakpoints have been set at the start of the
|
||||
;; `(format ...)' and `(* x x x)' expressions. Then evaluate the
|
||||
;; whole for-each expression by typing `C-M-x' ...
|
||||
;;
|
||||
;; In the upper half of your Emacs, a buffer appears showing you the
|
||||
;; Scheme stack.
|
||||
;;
|
||||
;; In the lower half, the `(format ...)' expression is highlighted.
|
||||
;;
|
||||
;; What has happened is that Guile started evaluating the for-each
|
||||
;; code, but then hit the breakpoint that you set on the start of the
|
||||
;; format expression. Guile therefore pauses the evaluation at that
|
||||
;; point and passes the stack (which encapsulates everything that is
|
||||
;; interesting about the state of Guile at that point) to GDS. You
|
||||
;; can then explore the stack and decide how to tell Guile to
|
||||
;; continue.
|
||||
;;
|
||||
;; - If you move your mouse over any of the identifiers in the
|
||||
;; highlighted code, a help echo (or tooltip) will appear to tell
|
||||
;; you that identifier's current value. (Note though that this only
|
||||
;; works when the stack buffer is selected. So if you have switched
|
||||
;; to this buffer in order to scroll down and read these lines, you
|
||||
;; will need to switch back to the stack buffer before trying this
|
||||
;; out.)
|
||||
;;
|
||||
;; - In the stack buffer, the "=>" on the left shows you that the top
|
||||
;; frame is currently selected. You can move up and down the stack
|
||||
;; by pressing the up and down arrows (or `u' and `d'). As you do
|
||||
;; this, GDS will change the highlight in the lower window to show
|
||||
;; the code that corresponds to the selected stack frame.
|
||||
;;
|
||||
;; - You can evaluate an arbitrary expression in the local environment
|
||||
;; of the selected stack frame by typing `e' followed by the
|
||||
;; expression.
|
||||
;;
|
||||
;; - You can show various bits of information about the selected frame
|
||||
;; by typing `I', `A' and `S'. Feel free to try these now, to see
|
||||
;; what they do.
|
||||
;;
|
||||
;; You also have control over the continuing evaluation of this code.
|
||||
;; Here are some of the things you can do - please try them as you
|
||||
;; read.
|
||||
;;
|
||||
;; - `g' tells Guile to continue execution normally. In this case
|
||||
;; that means that evaluation will continue until it hits the next
|
||||
;; breakpoint, which is on the `(* x x x)' expression.
|
||||
;;
|
||||
;; - `SPC' tells Guile to continue until the next significant event in
|
||||
;; the same source file as the selected frame. A "significant
|
||||
;; event" means either beginning to evaluate an expression in the
|
||||
;; relevant file, or completing such an evaluation, in which case
|
||||
;; GDS tells you the value that it is returning. Pressing `SPC'
|
||||
;; repeatedly is a nice way to step through all the details of the
|
||||
;; code in a given file, but stepping over calls that involve code
|
||||
;; from other files.
|
||||
;;
|
||||
;; - `o' tells Guile to continue execution until the selected stack
|
||||
;; frame completes, and then to show its return value.
|
||||
|
||||
;; Local Variables:
|
||||
;; mode: scheme
|
||||
;; End:
|
27
emacs/gds.el
27
emacs/gds.el
|
@ -36,10 +36,11 @@
|
|||
;; The subprocess object for the debug server.
|
||||
(defvar gds-debug-server nil)
|
||||
|
||||
(defvar gds-socket-type-alist '((tcp . 8333)
|
||||
(unix . "/tmp/.gds_socket"))
|
||||
"Maps each of the possible socket types that the GDS server can
|
||||
listen on to the path that it should bind to for each one.")
|
||||
(defvar gds-unix-socket-name (format "/tmp/.gds-socket-%d" (emacs-pid))
|
||||
"Name of the Unix domain socket that GDS will listen on.")
|
||||
|
||||
(defvar gds-tcp-port 8333
|
||||
"The TCP port number that GDS will listen on.")
|
||||
|
||||
(defun gds-run-debug-server ()
|
||||
"Start (or restart, if already running) the GDS debug server process."
|
||||
|
@ -47,10 +48,14 @@ listen on to the path that it should bind to for each one.")
|
|||
(if gds-debug-server (gds-kill-debug-server))
|
||||
(setq gds-debug-server
|
||||
(gds-start-server "gds-debug"
|
||||
(cdr (assq gds-server-socket-type
|
||||
gds-socket-type-alist))
|
||||
gds-unix-socket-name
|
||||
gds-tcp-port
|
||||
'gds-debug-protocol))
|
||||
(process-kill-without-query gds-debug-server))
|
||||
(process-kill-without-query gds-debug-server)
|
||||
;; Add the Unix socket name to the environment, so that Guile
|
||||
;; clients started from within this Emacs will be able to use it,
|
||||
;; and thereby ensure that they connect to the GDS in this Emacs.
|
||||
(setenv "GDS_UNIX_SOCKET_NAME" gds-unix-socket-name))
|
||||
|
||||
(defun gds-kill-debug-server ()
|
||||
"Kill the GDS debug server process."
|
||||
|
@ -137,7 +142,13 @@ listen on to the path that it should bind to for each one.")
|
|||
|
||||
;;;; Debugger protocol
|
||||
|
||||
(defcustom gds-protocol-hook nil
|
||||
"Hook called on receipt of a protocol form from the GDS client."
|
||||
:type 'hook
|
||||
:group 'gds)
|
||||
|
||||
(defun gds-debug-protocol (client form)
|
||||
(run-hook-with-args 'gds-protocol-hook form)
|
||||
(or (eq client '*)
|
||||
(let ((proc (car form)))
|
||||
(cond ((eq proc 'name)
|
||||
|
@ -610,7 +621,7 @@ you would add an element to this alist to transform
|
|||
:group 'gds)
|
||||
|
||||
(defcustom gds-server-socket-type 'tcp
|
||||
"What kind of socket the GDS server should listen on."
|
||||
"This option is now obsolete and has no effect."
|
||||
:group 'gds
|
||||
:type '(choice (const :tag "TCP" tcp)
|
||||
(const :tag "Unix" unix)))
|
||||
|
|
|
@ -163,23 +163,20 @@
|
|||
|
||||
(define (connect-to-gds . application-name)
|
||||
(or gds-port
|
||||
(begin
|
||||
(let ((gds-unix-socket-name (getenv "GDS_UNIX_SOCKET_NAME")))
|
||||
(set! gds-port
|
||||
(or (let ((s (socket PF_INET SOCK_STREAM 0))
|
||||
(SOL_TCP 6)
|
||||
(TCP_NODELAY 1))
|
||||
(setsockopt s SOL_TCP TCP_NODELAY 1)
|
||||
(catch #t
|
||||
(lambda ()
|
||||
(connect s AF_INET (inet-aton "127.0.0.1") 8333)
|
||||
s)
|
||||
(lambda _ #f)))
|
||||
(let ((s (socket PF_UNIX SOCK_STREAM 0)))
|
||||
(catch #t
|
||||
(lambda ()
|
||||
(connect s AF_UNIX "/tmp/.gds_socket")
|
||||
s)
|
||||
(lambda _ #f)))
|
||||
(or (and gds-unix-socket-name
|
||||
(false-if-exception
|
||||
(let ((s (socket PF_UNIX SOCK_STREAM 0)))
|
||||
(connect s AF_UNIX gds-unix-socket-name)
|
||||
s)))
|
||||
(false-if-exception
|
||||
(let ((s (socket PF_INET SOCK_STREAM 0))
|
||||
(SOL_TCP 6)
|
||||
(TCP_NODELAY 1))
|
||||
(setsockopt s SOL_TCP TCP_NODELAY 1)
|
||||
(connect s AF_INET (inet-aton "127.0.0.1") 8333)
|
||||
s))
|
||||
(error "Couldn't connect to GDS by TCP or Unix domain socket")))
|
||||
(write-form (list 'name (getpid) (apply client-name application-name))))))
|
||||
|
||||
|
|
|
@ -36,38 +36,31 @@
|
|||
|
||||
(define connection->id (make-object-property))
|
||||
|
||||
(define (run-server port-or-path)
|
||||
(define (run-server unix-socket-name tcp-port)
|
||||
|
||||
(or (integer? port-or-path)
|
||||
(string? port-or-path)
|
||||
(error "port-or-path should be an integer (port number) or a string (file name)"
|
||||
port-or-path))
|
||||
(let ((unix-server (socket PF_UNIX SOCK_STREAM 0))
|
||||
(tcp-server (socket PF_INET SOCK_STREAM 0)))
|
||||
|
||||
(let ((server (socket (if (integer? port-or-path) PF_INET PF_UNIX)
|
||||
SOCK_STREAM
|
||||
0)))
|
||||
;; Bind and start listening on the Unix domain socket.
|
||||
(false-if-exception (delete-file unix-socket-name))
|
||||
(bind unix-server AF_UNIX unix-socket-name)
|
||||
(listen unix-server 5)
|
||||
|
||||
;; Initialize server socket.
|
||||
(if (integer? port-or-path)
|
||||
(begin
|
||||
(setsockopt server SOL_SOCKET SO_REUSEADDR 1)
|
||||
(bind server AF_INET INADDR_ANY port-or-path))
|
||||
(begin
|
||||
(catch #t
|
||||
(lambda () (delete-file port-or-path))
|
||||
(lambda _ #f))
|
||||
(bind server AF_UNIX port-or-path)))
|
||||
|
||||
;; Start listening.
|
||||
(listen server 5)
|
||||
;; Bind and start listening on the TCP socket.
|
||||
(setsockopt tcp-server SOL_SOCKET SO_REUSEADDR 1)
|
||||
(false-if-exception (bind tcp-server AF_INET INADDR_ANY tcp-port))
|
||||
(listen tcp-server 5)
|
||||
|
||||
;; Main loop.
|
||||
(let loop ((clients '()) (readable-sockets '()))
|
||||
|
||||
(define (do-read port)
|
||||
(cond ((eq? port (current-input-port))
|
||||
(do-read-from-ui))
|
||||
((eq? port server)
|
||||
(accept-new-client))
|
||||
((eq? port unix-server)
|
||||
(accept-new-client unix-server))
|
||||
((eq? port tcp-server)
|
||||
(accept-new-client tcp-server))
|
||||
(else
|
||||
(do-read-from-client port))))
|
||||
|
||||
|
@ -86,7 +79,7 @@
|
|||
(trc "client not found")))
|
||||
clients)
|
||||
|
||||
(define (accept-new-client)
|
||||
(define (accept-new-client server)
|
||||
(let ((new-port (car (accept server))))
|
||||
;; Read the client's ID.
|
||||
(let ((name-form (read new-port)))
|
||||
|
@ -122,8 +115,10 @@
|
|||
;;(trc 'readable-sockets readable-sockets)
|
||||
|
||||
(if (null? readable-sockets)
|
||||
(loop clients (car (select (cons (current-input-port)
|
||||
(cons server clients))
|
||||
(loop clients (car (select (cons* (current-input-port)
|
||||
unix-server
|
||||
tcp-server
|
||||
clients)
|
||||
'()
|
||||
'())))
|
||||
(loop (do-read (car readable-sockets)) (cdr readable-sockets))))))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue