Christophe Weblog Wiki Code Publications Music
log and fix bug #20: infinite errors on disconnect.
authorChristophe Rhodes <csr21@cantab.net>
Thu, 15 Dec 2011 21:13:57 +0000 (21:13 +0000)
committerChristophe Rhodes <csr21@cantab.net>
Thu, 15 Dec 2011 21:13:57 +0000 (21:13 +0000)
Check for a zero-element character vector return from readChar.  (This
is not documented as the EOF return value, no, but it makes sense).

Also commit bug reports #18 and #19, and some README rearrangement.

BUGS.org
README
swank.R

index f4c5bf103eb3a19894e4b64558790b24f1785703..46fcb4ece21d8df1307f0850c5f0326e77f833a3 100644 (file)
--- a/BUGS.org
+++ b/BUGS.org
   (Almost certainly not; I suspect we naïvely use nchar() in places).
   We could either declare our encoding as latin1-unix, or make the
   server utf8ly correct.  To reproduce, simply type "ë" at the repl.
+* OPEN #18 ess-help needs to be loaded automatically                  :MINOR:
+  to reproduce: in a fresh emacs, type ?help
+* OPEN #19 base graphics don't work automatically                    :NORMAL:
+  They can be made to by passing --interactive to R on startup, but
+  I'm not sure what else that does.
+* RESOLVED #20 closing the connection causes infinite R errors    :IMPORTANT:
+  reported by "Philipp Marek" <philipp@marek.priv.at> by private mail.
 * COMMENT:
 Local Variables:
 mode: org;
diff --git a/README b/README
index ce8005c3f3037eebf4bdb7d1b7c2d92b8d4fd1bc..d7dc564c2934987fe45c141f5659292c3438396a 100644 (file)
--- a/README
+++ b/README
    SLIME is to ILISP.  At present, ESS mode remains active in R source
    buffers, providing font-locking functionality among other things.
 * Installation
-** Running
-   To begin using swankr:
-
-   1. start R;
-   2. load the swank.R file:
-#+BEGIN_SRC R
-      source("swank.R")
-#+END_SRC
-   3. at the R prompt, run
-#+BEGIN_SRC R
-      swank();
-#+END_SRC
-   4. within emacs, load and initialize slime;
-#+BEGIN_SRC emacs-lisp
-      (require 'slime)
-      (slime-setup '(slime-repl))
-#+END_SRC
-   5. run =M-x slime-connect=, accepting the default host and port,
-      and acknowledging the protocol version mismatch.
+** Emacs configuration
+*** Installing SLIME
+    SLIME is required separately from swankr.  To install slime,
+    perhaps the simplest is to pull the CVS sources into a
+    user-specific site directory, and arrange for that to be on the
+    emacs =load-path=; I did
+#+begin_src sh
+mkdir -p ~/.emacs.d/site-lisp
+cd ~/.emacs.d/site-lisp
+cvs -z3 -d:pserver:anonymous:anonymous@common-lisp.net:/project/slime/cvsroot co slime
+#+end_src
 
-   At this point, an R REPL should appear.
-** Emacs customization
-   At a minimum, slime needs to be set up to function.  I've
-   used the following forms in my =~/.emacs=
-#+BEGIN_SRC emacs-lisp
-   (require 'slime)
-   (slime-setup '(slime-repl slime-scratch slime-media))
-#+END_SRC
-   The =slime-media= contrib is new and (at present) R-specific,
-   allowing for image results to be embedded in the REPL.
+    Following that, I have in my =~/.emacs= (you will need to adjust
+    paths to executables and source files):
+#+begin_src emacs-lisp
+;;; ~/.emacs.d/
+(let ((default-directory (concat user-emacs-directory (convert-standard-filename "site-lisp/"))))
+  (normal-top-level-add-subdirs-to-load-path))
 
+;;; SLIME
+(require 'slime)
+(setq slime-net-coding-system 'utf-8-unix)
+(slime-setup '(slime-asdf slime-repl slime-scratch slime-presentations slime-media))
+(setq slime-lisp-implementations
+      '((sbcl ("sbcl" "--dynamic-space-size" "2048" "--load" "/home/csr21/src/lisp/quicklisp/setup.lisp"))
+        (git-sbcl ("sh" "/home/csr21/src/lisp/sbcl/run-sbcl.sh" "--dynamic-space-size" "2048"))
+        (R ("R" "--no-save" "--max-vsize=4096M")
+           :init (lambda (port-filename coding-system) 
+                   (format
+                    "source('/home/csr21/src/R/swankr/swank.R', keep.source=TRUE, chdir=TRUE)\nstartSwank('%s')\n" port-filename)))))
+(global-set-key (kbd "s-s") 'slime-selector)
+#+end_src
+*** Additional refinements
    In addition, for keybindings like =C-c C-c= to work properly, emacs
    needs to be told how to guess where a function definition begins.
    This can be achieved with /e.g./
                      1 font-lock-function-name-face t))
              ess-R-mode-font-lock-keywords)))
 #+END_SRC
+*** Running
+    After performing the installation steps above, =M-- M-x slime RET R
+    RET= should start swank.  You will be prompted to accept a version
+    mismatch -- simply accept -- then the SLIME REPL should start up,
+    giving a prompt.  Enjoy!
+** Proof-of-concept (OBSOLETE)
+   [ The instructions here are for the seriously impatient, and do not
+   give as good an experience ]
+
+   To begin using swankr:
+
+   1. start R;
+   2. load the swank.R file:
+#+BEGIN_SRC R
+      source("swank.R")
+#+END_SRC
+   3. at the R prompt, run
+#+BEGIN_SRC R
+      swank();
+#+END_SRC
+   4. within emacs, load and initialize slime;
+#+BEGIN_SRC emacs-lisp
+      (require 'slime)
+      (slime-setup '(slime-repl slime-presentations slime-media))
+#+END_SRC
+   5. run =M-x slime-connect=, accepting the default host and port,
+      and acknowledging the protocol version mismatch.
+
+   At this point, an R REPL should appear.
 * Development
   swankr's primary development repository is a git repository,
   accessible through
   <http://common-lisp.net/r/users/crhodes/swankr.git> and
-  git://common-lisp.net/crhodes/swankr/swankr.git; a web view of the
+  git://common-lisp.net/users/crhodes/swankr.git; a web view of the
   development history is [[http://common-lisp.net/gitweb?p=users/crhodes/swankr.git][available through gitweb]].  You can also view
   the current lists of [[file:BUGS.org]] and [[file:TODO.org]] items.
 * Acknowledgments
diff --git a/swank.R b/swank.R
index dea28cf99f2f72cec6ccadc13d1266b88b571c78..20311847afef86a62468a50c58b0f1962cc7dc9b 100644 (file)
--- a/swank.R
+++ b/swank.R
@@ -33,9 +33,10 @@ acceptConnections <- function(port, portFile) {
     cat(port, file=f)
     close(f)
   }
+  ## FIXME: maybe we should support dontClose here?
   s <- socketConnection(host="localhost", server=TRUE, port=port, open="r+b")
   on.exit(close(s))
-  serve(s)
+  tryCatch(serve(s), endOfFile=function(c) NULL)
 }
 
 serve <- function(io) {
@@ -145,6 +146,11 @@ readPacket <- function(io) {
 
 readChunk <- function(io, len) {
   buffer <- readChar(io, len)
+  if(length(buffer) == 0) {
+    condition <- simpleCondition("End of file on io")
+    class(condition) <- c("endOfFile", class(condition))
+    signalCondition(condition)
+  }
   if(nchar(buffer) != len) {
     stop("short read in readChunk")
   }