Skip to content

tab-complete for non-syntactic names could attempt backtick-wrapping

7 messages · Ivan Krylov, Michael Chirico, Deepayan Sarkar +1 more

#
Consider:

x <- list(`a b` = 1)
x$a<tab>

(i.e., press the 'tab' key after typing 'x$a')

The auto-complete mechanism will fill the buffer like so:
x$a b

This is not particularly helpful because this is now a syntax error.

It seems to me there's a simple fix -- in
utils:::specialCompletions(), we can wrap the result of
utils:::specialOpCompletionsHelper() with backticks for non-syntactic
names ([1]):

comps <- specialOpCompletionsHelper(op, suffix, prefix)
if (length(comps) == 0L) comps <- ""
+non_syntactic <- make.names(comps) != comps
+comps[non_syntactic] <- paste0("`", comps[non_syntactic], "`")
sprintf("%s%s%s", prefix, op, comps)

I'm somewhat surprised this hasn't come up before (I searched for
'completeToken', 'specialCompletions', and
'specialOpCompletionsHelper' here and on Bugzilla), so I'm checking
with the list first if I'm missing anything before filing a patch.

Mike C

[1] https://github.com/r-devel/r-svn/blob/4657f65a377cb5ef318c6548bc264e3b0f9517a0/src/library/utils/R/completion.R#L536-L538
#
? Wed, 1 Mar 2023 01:36:02 -0800
Michael Chirico via R-devel <r-devel at r-project.org> ?????:
There are a few more corner cases. For example, comps could contain
backticks (which should be escaped with backslashes) and backslashes
(which should also be escaped). Thankfully, \uXXXX-style Unicode escape
sequences are not currently supported inside backticks, and "escape the
backslash" rule already takes care of them.

The deparse() function already knows these rules:

name <- 'hello world ` \\uFF'
cat(deparse1(as.name(name), backtick=TRUE), '\n')
# `hello world \` \\uFF`
`hello world \` \\uFF` <- 'hello'
`hello world \` \\uFF`
# [1] "hello"
#
Great suggestion! I've started a patch:
https://bugs.r-project.org/show_bug.cgi?id=18479
On Wed, Mar 1, 2023 at 1:56 AM Ivan Krylov <krylov.r00t at gmail.com> wrote:
#
There turn out to be a few more things to fix.

One problem is easy to solve: vapply() needs a third argument
specifying the type of the return value. (Can we have unit tests for
tab completion?)

The other problem is harder: `comps` defaults to an empty string, and
you can't have a symbol consisting of an empty string, because this
value is internally reserved for missing function arguments. I think
you can return(paste0(prefix, op)) if length(comps) == 0L, but this is
still somewhat worrying. R tries to prevent empty names, so I wouldn't
expect specialOpCompletionsHelper() to return an empty string, but I
can't prove it right now.

On the other hand, x$'a string' is the same as x$`a string`. Could we
just drop as.name() and keep the return value being a string literal?
I'm not sure about this, either.
#
On Thu, Mar 2, 2023 at 2:09?PM Ivan Krylov <krylov.r00t at gmail.com> wrote:
There are tests in

src/library/utils/tests/completion.R

which should get run by make check-devel (which runs R CMD check on
all base packages).
See my just-posted response on bugzilla for other issues to look out for.

Best,
-Deepayan
#
I personally wouldn't like using a string, and this comment makes me
think it's against the r-core preference as well:

https://bugs.r-project.org/show_bug.cgi?id=18429#c1

Thanks both for catching the sloppy mistake in vapply() :)

Let's continue discussion on the bug/PR.
On Thu, Mar 2, 2023 at 12:39 AM Ivan Krylov <krylov.r00t at gmail.com> wrote:
#
x$`string` is not the same as x$'string'.  They may act similarly now, but
they do not parse the same.
[1] "symbol" "symbol" "symbol"
[1] "symbol"    "symbol"    "character"
[1] "symbol"    "symbol"    "character"

Single and double quoted character sequences do parse to the same thing
(character) but backquoted ones parse to symbols (aka names).

-Bill
On Thu, Mar 2, 2023 at 12:39?AM Ivan Krylov <krylov.r00t at gmail.com> wrote: