Christophe Weblog Wiki Code Publications Music
fix null implementation of operator-arglist
[swankr.git] / swank.R
diff --git a/swank.R b/swank.R
index 49f73ff..99012ec 100644 (file)
--- a/swank.R
+++ b/swank.R
@@ -293,6 +293,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(`:encoding`), list(quote(`:coding-systems`), list("utf-8-unix")),
        quote(`:lisp-implementation`), list(quote(`:type`), "R",
                                            quote(`:name`), "R",
@@ -344,7 +345,7 @@ sendReplResultFunction <- sendReplResult
 }
 
 `swank:autodoc` <- function(slimeConnection, sldbState, rawForm, ...) {
-  "No Arglist Information"
+  list("No Arglist Information", TRUE)
 }
 
 `swank:operator-arglist` <- function(slimeConnection, sldbState, op, package) {
@@ -454,20 +455,44 @@ computeRestartsForEmacs <- function (sldbState) {
 }
 
 `swank:simple-completions` <- function(slimeConnection, sldbState, prefix, package) {
+  symbolFieldsCompletion <- function(object, rest) {
+    ## FIXME: this is hacky, ignoring several syntax issues (use of
+    ## and/or necessity for backquoting identifiers: e.g. fields
+    ## containing hyphens)
+    if((dollar <- regexpr("$", rest, fixed=TRUE)) == -1) {
+      matches <- grep(sprintf("^%s", literal2rx(rest)), names(object), value=TRUE)
+      matches <- sprintf("%s$%s", gsub("\\$[^$]*$", "", prefix), matches)
+      returnMatches(matches)
+    } else {
+      if(exists(substr(rest, 1, dollar-1), object)) {
+        symbolFieldsCompletion(get(substr(rest, 1, dollar-1), object), substr(rest, dollar+1, nchar(rest)))
+      } else {
+        returnMatches(character(0))
+      }
+    }
+  }
+  returnMatches <- function(matches) {
+    nmatches <- length(matches)
+    if(nmatches == 0) {
+      list(list(), "")
+    } else {
+      longest <- matches[order(nchar(matches))][1]
+      while(length(grep(sprintf("^%s", literal2rx(longest)), matches)) < nmatches) {
+        longest <- substr(longest, 1, nchar(longest)-1)
+      }
+      list(as.list(matches), longest)
+    }
+  }
   literal2rx <- function(string) {
     ## list of ERE metacharacters from ?regexp
     gsub("([.\\|()[{^$*+?])", "\\\\\\1", string)
   }
   matches <- apropos(sprintf("^%s", literal2rx(prefix)), ignore.case=FALSE)
   nmatches <- length(matches)
-  if(nmatches == 0) {
-    list(list(), "")
+  if((nmatches == 0) && ((dollar <- regexpr("$", prefix, fixed=TRUE)) > -1)) {
+    symbolFieldsCompletion(globalenv(), prefix)
   } else {
-    longest <- matches[order(nchar(matches))][1]
-    while(length(grep(sprintf("^%s", literal2rx(longest)), matches)) < nmatches) {
-      longest <- substr(longest, 1, nchar(longest)-1)
-    }
-    list(as.list(matches), longest)
+    returnMatches(matches)
   }
 }
 
@@ -633,7 +658,7 @@ inspectObject <- function(slimeConnection, object) {
 
 valuePart <- function(istate, object, string) {
   list(quote(`:value`),
-       if(is.null(string)) printToString(object) else string,
+       if(is.null(string)) prin1ToString(object) else string,
        assignIndexInParts(object, istate))
 }
 
@@ -644,7 +669,7 @@ preparePart <- function(istate, part) {
     switch(as.character(part[[1]]),
            `:newline` = list("\n"),
            `:value` = valuePart(istate, part[[2]], part[[3]]),
-           `:line` = list(printToString(part[[2]]), ": ",
+           `:line` = list(prin1ToString(part[[2]]), ": ",
              valuePart(istate, part[[3]], NULL), "\n"))
   }
 }