Christophe Weblog Wiki Code Publications Music
escape names when searching for completions
authorChristophe Rhodes <csr21@cantab.net>
Tue, 13 Sep 2011 21:26:12 +0000 (22:26 +0100)
committerChristophe Rhodes <csr21@cantab.net>
Tue, 13 Sep 2011 21:26:12 +0000 (22:26 +0100)
otherwise extended regexp metacharacters, particularly ".", get
interpreted as those metacharacters rather than literals.  (bug #12)

BUGS.org
swank.R

index 24cd075174228f79450ef6e0402050bbfdc12323..a91d7b841a7b83120ec26f57dd8e492c97e0ca2b 100644 (file)
--- a/BUGS.org
+++ b/BUGS.org
@@ -42,7 +42,7 @@
   Logged here so that I don't forget it if I sort out #9 first: we
   need to be able to indicate "no repl result please" if we open a new
   temporary buffer to display the result.
-* OPEN #12 need to be more careful when searching for completions    :NORMAL:
+* RESOLVED #12 escaping when searching for completions         :NORMAL:FIXED:
   Gets thoroughly confused on completing "read." because the "." is
   treated as a regexp "any character" pattern.
 * COMMENT:
diff --git a/swank.R b/swank.R
index b5c79c78204695667f421bbceb3b3e83664971c1..f0c0d15373ff150a29f291f56d89b23f9050c276 100644 (file)
--- a/swank.R
+++ b/swank.R
@@ -430,14 +430,17 @@ computeRestartsForEmacs <- function (sldbState) {
 }
 
 `swank:simple-completions` <- function(slimeConnection, sldbState, prefix, package) {
-  ## fails multiply if prefix contains regexp metacharacters
-  matches <- apropos(sprintf("^%s", prefix), ignore.case=FALSE)
+  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(), "")
   } else {
     longest <- matches[order(nchar(matches))][1]
-    while(length(grep(sprintf("^%s", longest), matches)) < nmatches) {
+    while(length(grep(sprintf("^%s", literal2rx(longest)), matches)) < nmatches) {
       longest <- substr(longest, 1, nchar(longest)-1)
     }
     list(as.list(matches), longest)