From: Christophe Rhodes Date: Sun, 29 Apr 2012 13:15:22 +0000 (+0100) Subject: rework `swank:simple-completions` X-Git-Url: http://christophe.rhodes.io/gitweb/?p=swankr.git;a=commitdiff_plain;h=f198b5e4bf8b550c1401ea248f28a515eb3182e1;ds=sidebyside 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...) --- 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) } }