X-Git-Url: http://christophe.rhodes.io/gitweb/?p=swankr.git;a=blobdiff_plain;f=swank.R;h=38160edd339acda845dbb40a40b5d3c15eaeca2c;hp=d91c35fdbd3663c3d8312a2a204a3e6a0ec73af7;hb=04218c0c1af88835d1d2e68d97c6e644b7afae35;hpb=24bb738d87a1636b9b86850e14c59b608fe61fb9 diff --git a/swank.R b/swank.R index d91c35f..38160ed 100644 --- 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", @@ -343,12 +344,41 @@ sendReplResultFunction <- sendReplResult list() } +`swank:clear-repl-variables` <- function(slimeConnection, sldbState) { + list() +} + `swank:autodoc` <- function(slimeConnection, sldbState, rawForm, ...) { - "No Arglist Information" + list("No Arglist Information", TRUE) } `swank:operator-arglist` <- function(slimeConnection, sldbState, op, package) { - list() + if(!exists(op, envir = globalenv())) { + return(list()) + } + funoid <- get(op, envir = globalenv()) + if(is.function(funoid)) { + args <- formals(funoid) + paste(sprintf("%s=%s", names(args), args), collapse=", ") + } else { + list() + } +} + +`swank:describe-function` <- function(slimeConnection, sldbState, op, package) { + ## FIXME: maybe not the best match? + `swank:operator-arglist`(slimeConnection, sldbState, op, package) +} + +helpFilesWithTopicString <- function(value) { + output <- capture.output(tools:::Rd2txt(utils:::.getHelpFile(value), + options=list(underline_titles=FALSE))) + paste(output, collapse="\n") +} + +`swank:describe-symbol` <- function(slimeConnection, sldbState, op, package) { + value <- help(op) + helpFilesWithTopicString(value) } `swank:throw-to-toplevel` <- function(slimeConnection, sldbState) { @@ -444,12 +474,24 @@ computeRestartsForEmacs <- function (sldbState) { list()) } -`swank:simple-completions` <- function(slimeConnection, sldbState, prefix, package) { - literal2rx <- function(string) { - ## list of ERE metacharacters from ?regexp - gsub("([.\\|()[{^$*+?])", "\\\\\\1", string) +symbolFieldsCompletion <- function(object, prefix, 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), prefix, substr(rest, dollar+1, nchar(rest))) + } else { + returnMatches(character(0)) + } } - matches <- apropos(sprintf("^%s", literal2rx(prefix)), ignore.case=FALSE) +} + +returnMatches <- function(matches) { nmatches <- length(matches) if(nmatches == 0) { list(list(), "") @@ -462,6 +504,21 @@ computeRestartsForEmacs <- function (sldbState) { } } +literal2rx <- function(string) { + ## list of ERE metacharacters from ?regexp + gsub("([.\\|()[{^$*+?])", "\\\\\\1", string) +} + +`swank:simple-completions` <- function(slimeConnection, sldbState, prefix, package) { + matches <- apropos(sprintf("^%s", literal2rx(prefix)), ignore.case=FALSE) + nmatches <- length(matches) + if((nmatches == 0) && ((dollar <- regexpr("$", prefix, fixed=TRUE)) > -1)) { + symbolFieldsCompletion(globalenv(), prefix, prefix) + } else { + returnMatches(matches) + } +} + `swank:compile-string-for-emacs` <- function(slimeConnection, sldbState, string, buffer, position, filename, policy) { lineOffset <- charOffset <- colOffset <- NULL for(pos in position) { @@ -480,6 +537,23 @@ computeRestartsForEmacs <- function (sldbState) { ifelse(x[3]==1, x[6]+colOffset-1, x[6])))) } transformSrcrefs <- function(s) { + ## horrendous KLUDGE: we need to short-circuit here for "name" + ## objects, rather than having a nice uniform behaviour, because + ## for expressions of the form x[y,] there is an empty "name" + ## which ends up becoming a `missing' object when passed through + ## the switch; why, I do not know, but it is then impossible to + ## return it, because returning it attempts to evaluate it and + ## evaluating it is an error. Fortunately it appears that names + ## don't have srcrefs attached. + if(mode(s) == "name") { + return(s) + } + if(is(s, "srcref")) { + ## more monumental KLUDGE: parsing (in 2.14, at least) appears + ## to put srcrefs directly in `length 2' objects, which we need + ## to frob directly. + return(frob(list(s))[[1]]) + } srcrefs <- attr(s, "srcref") attribs <- attributes(s) new <- @@ -491,6 +565,9 @@ computeRestartsForEmacs <- function (sldbState) { if(!is.null(attr(s, "srcref"))) { attr(new, "srcref") <- frob(srcrefs) } + if(!is.null(attr(s, "wholeSrcref"))) { + attr(new, "wholeSrcref") <- frob(list(attr(s, "wholeSrcref")))[[1]] + } new } withRestarts({ @@ -624,7 +701,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)) } @@ -635,7 +712,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")) } }