Christophe Weblog Wiki Code Publications Music
fix multibyte decoding protocol bug
[swankr.git] / swank.R
diff --git a/swank.R b/swank.R
index d84582491c0396a8f1a4099d0ec135c297b507fd..901f1c16a5bc7f1af0015a73b7bd352c4adf36b3 100644 (file)
--- a/swank.R
+++ b/swank.R
@@ -141,19 +141,27 @@ readPacket <- function(io) {
   header <- readChunk(io, 6)
   len <- strtoi(header, base=16)
   payload <- readChunk(io, len)
-  readSexpFromString(payload)
+  sexp <- readSexpFromString(payload)
+  sexp
 }
 
 readChunk <- function(io, len) {
-  buffer <- readChar(io, len)
+  buffer <- readChar(io, len, useBytes=TRUE)
   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")
-  }
+  ## FIXME: with the useBytes argument to readChar, it is normal for
+  ## the buffer returned to be fewer character than bytes were read,
+  ## given the possibility of multibyte characters.  However, that
+  ## means we can’t detect at all the case where there is actually a
+  ## short read (though empirically the readChar call blocks rather
+  ## than returning early).
+  ##
+  ## if(nchar(buffer) != len) {
+  ##   stop("short read in readChunk")
+  ## }
   buffer
 }
 
@@ -293,7 +301,7 @@ printToString <- function(val) {
 `swank:connection-info` <- function (slimeConnection, sldbState) {
   list(quote(`:pid`), Sys.getpid(),
        quote(`:package`), list(quote(`:name`), "R", quote(`:prompt`), "R> "),
-       quote(`:version`), "2012-04-23",
+       quote(`:version`), "2014-09-13",
        quote(`:encoding`), list(quote(`:coding-systems`), list("utf-8-unix")),
        quote(`:lisp-implementation`), list(quote(`:type`), "R",
                                            quote(`:name`), "R",
@@ -314,6 +322,8 @@ printToString <- function(val) {
   list("R", "R")
 }
 
+`swank-repl:create-repl` <- `swank:create-repl`
+
 makeReplResult <- function(value) {
   string <- printToString(value)
   list(quote(`:write-string`), string,
@@ -344,6 +354,12 @@ sendReplResultFunction <- sendReplResult
   list()
 }
 
+`swank-repl:listener-eval` <- `swank:listener-eval`
+
+`swank:clear-repl-variables` <- function(slimeConnection, sldbState) {
+  list()
+}
+
 `swank:autodoc` <- function(slimeConnection, sldbState, rawForm, ...) {
   list("No Arglist Information", TRUE)
 }
@@ -377,6 +393,25 @@ helpFilesWithTopicString <- function(value) {
   helpFilesWithTopicString(value)
 }
 
+`swank:apropos-list-for-emacs` <- function(slimeConnection, sldbState, name, onlyExternal, package, caseSensitive) {
+  x <- help.search(name, fields="alias", package=.packages())$matches
+  brieflyDescribe <- function(name, title) {
+    if (exists(name, globalenv())) {
+      val <- get(name, globalenv())
+      kind <- if("function" %in% class(val)) quote(`:function`) else quote(`:variable`)
+      list(quote(`:designator`), name, kind, title)
+    } else {
+      ## maybe
+      list(quote(`:designator`), name, quote(`:type`), title)
+    }
+  }
+  mapply(brieflyDescribe, x[,"name"], x[,"title"], SIMPLIFY=FALSE)
+}
+
+`swank:describe-definition-for-emacs` <- function(slimeConnection, sldbState, name, kind) {
+  `swank:describe-symbol`(slimeConnection, sldbState, name, NULL)
+}
+
 `swank:throw-to-toplevel` <- function(slimeConnection, sldbState) {
   condition <- simpleCondition("Throw to toplevel")
   class(condition) <- c("swankTopLevel", class(condition))