From f198b5e4bf8b550c1401ea248f28a515eb3182e1 Mon Sep 17 00:00:00 2001 From: Christophe Rhodes Date: Sun, 29 Apr 2012 14:15:22 +0100 Subject: [PATCH] rework `swank:simple-completions` 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 | 2 +- swank.R | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/BUGS.org b/BUGS.org index 31743fd..3e65f0a 100644 --- 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). -* 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. diff --git a/swank.R b/swank.R index 979bd84..3b1f3d7 100644 --- a/swank.R +++ b/swank.R @@ -455,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) } } -- 2.30.2