select has a handy tool for dealing with these situations where you can negate the one_of result. However, this requires getting the variables names into a character string.
After to_drop <- rlang::quos(...), getting the character strings is easy enough with as.character, but you have an extraneous ~ character. A quick sub can drop it, and you use
select_not <- function(d, ...){
to_drop <- rlang::quos(...)
to_drop <- sub("^~", "", as.character(to_drop))
dplyr::select(d, -dplyr::one_of(to_drop))
}
Personally, I find the following maintains the look and feel of a tidyverse function, but gets to the heart of the issue more efficiently.
select_not <- function(d, ...){
# get expressions in ... as characters
to_drop <-
vapply(substitute(list(...)),
as.character,
character(1))[-1] # the first one ends up being "list", and we don't need it
d[!names(d) %in% to_drop]
}