Christophe Weblog Wiki Code Publications Music
rework `swank:simple-completions`
authorChristophe Rhodes <csr21@cantab.net>
Sun, 29 Apr 2012 13:15:22 +0000 (14:15 +0100)
committerChristophe Rhodes <csr21@cantab.net>
Sun, 29 Apr 2012 13:15:22 +0000 (14:15 +0100)
In the process, implement looking up foo$bar$baz, and passing those
completions back.  It's not completely robust to somewhat exotic
syntax, as it assumes that the text being completed can be used
directly as character vectors naming objects or fields; it is good
enough to get started, and now a lot less annoying to
use (particularly when lots of fields have underscores in them...)

BUGS.org
swank.R

index 31743fdf8dff1e2590295bf260c67df97f5f8cf8..3e65f0ab255040f1ae653374488d1c94d72028f3 100644 (file)
--- a/BUGS.org
+++ b/BUGS.org
@@ -79,7 +79,7 @@
 
   To reproduce, C-c I globalenv() RET, or hit RET on environment
   presentations in the debugger (if presentations are on).
 
   To reproduce, C-c I globalenv() RET, or hit RET on environment
   presentations in the debugger (if presentations are on).
-* OPEN #22 completion of named list fields                         :WISHLIST:
+* RESOLVED #22 completion of named list fields               :WISHLIST:FIXED:
   It is very nice in ESS to be able to type df$ TAB and get a
   completion list of the data frame's columns.  Supporting it in
   swankr should be really easy.
   It is very nice in ESS to be able to type df$ TAB and get a
   completion list of the data frame's columns.  Supporting it in
   swankr should be really easy.
diff --git a/swank.R b/swank.R
index 979bd8487ceb2532661c5db39e7228782bc6d4cc..3b1f3d78ad29910f51034574f73470ffe6fdd123 100644 (file)
--- a/swank.R
+++ b/swank.R
@@ -455,20 +455,44 @@ computeRestartsForEmacs <- function (sldbState) {
 }
 
 `swank:simple-completions` <- function(slimeConnection, sldbState, prefix, package) {
 }
 
 `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)
   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 {
   } 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)
   }
 }
 
   }
 }