[ESS] Easy argument list: r-autoyas
Vitalie Spinu
spinuvit.list at gmail.com
Mon Mar 14 14:23:54 CET 2011
Ista Zahn <izahn at psych.rochester.edu> writes:
> Dear Sven and Vitalie,
> r-autoyas is fantastic. You've made me very happy, and I'm sure many
> others feel the same. Thank you!
>
> I'm actually running it as Vitalie suggested, (including binding
> r-autoyas-expand to the "(" key) and it works quite well. I do have a
> sort of feature request though; support for nested function calls. For
> example:
>
> dat <- data.frame(x=rnorm(10, mean=0, sd=1, row.names=NULL,
> check.rows=FALSE, check.names=TRUE,
> stringsAsFactors=default.stringsAsFactors()
>
> OK, now imagine I've just finished typing 10 as the argument to rnorm.
> I'd like to exit the rnorm yasnippet, but not the data.frame snippet.
This modification of 'r-autoyas-exit-snippet-delete-remaining' seems to work
quite well with recursive snippets:
(defun r-autoyas-exit-snippet-delete-remaining ()
"Exit yas snippet and delete the remaining argument list."
(interactive "*")
(let ((deletefrom (point)))
(yas/exit-snippet (car (yas/snippets-at-point)))
(yas/check-commit-snippet)
(delete-region deletefrom (point))
))
> I would also like to bind a function to exit the snippet to the ")"
> key.
You have to use yas/keymap to get this work:
(defun r-autoyas-exit-snippet-with-paren ()
(interactive)
(if (member major-mode '(ess-mode inferior-ess-mode))
(progn
(r-autoyas-exit-snippet-delete-remaining)
(insert ")") ;;<-delete this if not needed
)
(insert ")")
))
(define-key yas/keymap (kbd ")") 'r-autoyas-exit-snippet-with-paren)
You seem to be using skeleton-pair; in that case you should delete the
(insert ")") line since last ")" is already inserted.
I find this ")" behavior quite nice, what does Sven think of including it as
a feature?
Vitalie.
>
> (defun r-autoyas-exit-snippet-delete-one ()
> "Exit this snippet."
> (interactive "*")
> (let ((deletefrom (point)))
> (ad-Orig-yas/abort-snippet)))
>
> (define-key ess-mode-map (kbd ")")
> '(lambda () (interactive)
> (skeleton-pair-insert-maybe nil)
> (r-autoyas-exit-snippet-delete-one)))
>
> But as you can probably tell I really don't know the first thing about
> lisp. The above almost works, except that it doesn't delete the
> remaining rnorm( arguments. I'd appreciate any tips for getting that
> to work.
>
> Thanks again, this is already an incredibly useful tool, especially
> for functions with many arguments.
>
> Best,
> Ista
> On Thu, Mar 10, 2011 at 5:40 PM, Sven Hartenstein
> <lists at svenhartenstein.de> wrote:
>> Hi Vitalie,
>>
>> great - looks like in you I finally found a lisp teacher! :-)
>>
>> Thanks very much for your ideas and (quick!) coding. I will find time
>> on the weekend to try to understand it and update r-autoyas on my
>> website.
>>
>> Best,
>>
>> Sven
>>
>>
>> * Vitalie Spinu wrote:
>>> Sven Hartenstein <lists at svenhartenstein.de> writes:
>>>
>>>
>>> > Here is the code:
>>> > http://www.svenhartenstein.de/Software/R-autoyas>> >
>>> > I'd love to receive your honest feedback!
>>>
>>> Hi Sven,
>>>
>>> A very nice attempt indeed. It can become a very useful addition to ESS.
>>> One further step would be to have an option to scroll through methods
>>> arguments, but that would take some considerable thinking.
>>>
>>> Here are a couple of points of how to improve on what you did. The complete
>>> code follows.
>>>
>>> First, it would be probably more convenient if "(" key would directly invoke
>>> the yas/expand. This is what I have in my .emacs:
>>>
>>> (define-key ess-mode-map (kbd "(") '(lambda () (interactive)
>>> (skeleton-pair-insert-maybe nil)
>>> (r-autoyas-expand nil t))))
>>>
>>> Second, it is nice to have C-g to delete all the remaining arguments (as
>>> you've already suggested on your site). The easiest way I could find is to
>>> advise yas/abort-snippet. Please see below.
>>>
>>> Third, it is inconvenient to maintain both .emacs and .Rprofile, one way of
>>> avoiding it is to "inject" the necessary commands each time R-session starts
>>> by means of ess-post-run-hook.
>>>
>>> This is the complete r-autoyas code which I have got in my .emacs:
>>>
>>> ;;;_ autoyas
>>>
>>> (defun r-autoyas-exit-snippet-delete-remaining ()
>>> "Exit yas snippet and delete the remaining argument list."
>>> (interactive "*")
>>> (let ((deletefrom (point)))
>>> (yas/exit-all-snippets)
>>> (delete-region deletefrom (point))))
>>>
>>> (defun r-autoyas-expand (&optional funname no-paren)
>>> "Insert argument list (in parentheses) of R function before the
>>> point as intelligent yas snippets and expand the snippets."
>>> (interactive "*")
>>> (if (null funname)
>>> (setq funname (ess-r-args-current-function)))
>>> (ess-command (concat "r.autoyas.create('" funname "')\n")
>>> (get-buffer-create "*r-autoyas*"))
>>> (unless (null funname)
>>> (let (snippet)
>>> (with-current-buffer "*r-autoyas*"
>>> (if (< (length (buffer-string)) 10);; '[1] " "' if no valid fun
>>> (message "No valid function!")
>>> (delete-region 1 6)
>>> (goto-char (point-max))
>>> (delete-backward-char 2)
>>> (goto-char (point-min))
>>> (replace-string "\\\"" "\"")
>>> (goto-char (point-min))
>>> (replace-string "\\\\" "\\")
>>> (setq snippet (buffer-string))
>>> (when no-paren
>>> (setq snippet (substring snippet 1 -1)))
>>> ))
>>> (when snippet
>>> (yas/expand-snippet snippet)
>>> ))))
>>>
>>> (defun r-autoyas-inject-commands ()
>>> (process-send-string (get-process ess-current-process-name)
>>> "r.autoyas.esc <- function(str) {
>>> str <- gsub('$', '\\\\$', str, fixed=TRUE)
>>> str <- gsub('`', '\\\\`', str, fixed=TRUE)
>>> return(str)
>>> };
>>> r.autoyas.create <- function(funname) {
>>> if (!existsFunction(funname)) return(' ')
>>> formals <- formals(funname)
>>> nr <- 0
>>> closebrackets <- 0
>>> str <- NULL
>>> for (field in names(formals)) {
>>> type <- typeof(formals[[field]])
>>> if (type=='symbol' & field!='...') {
>>> nr <- nr+1
>>> str <- append(str, paste(', ${',nr,':',field,'}', sep=''))
>>> } else if (type=='symbol' & field=='...') {
>>> nr <- nr+2
>>> str <- append(str, paste('${',nr-1,':, ${',nr,':',field,'}}', sep=''))
>>> } else if (type=='character') {
>>> nr <- nr+2
>>> str <- append(str, paste('${',nr-1,':, ',field,'=${',nr,':\\'',gsub('\\'', '\\\\\\'', r.autoyas.esc(encodeString(formals[[field]])), fixed=TRUE),'\\'}}', sep=''))
>>> } else if (type=='logical') {
>>> nr <- nr+2
>>> str <- append(str, paste('${',nr-1,':, ',field,'=${',nr,':',as.character(formals[[field]]),'}}', sep=''))
>>> } else if (type=='double') {
>>> nr <- nr+2
>>> str <- append(str, paste('${',nr-1,':, ',field,'=${',nr,':',as.character(formals[[field]]),'}}', sep=''))
>>> } else if (type=='NULL') {
>>> nr <- nr+2
>>> str <- append(str, paste('${',nr-1,':, ',field,'=${',nr,':NULL}}', sep=''))
>>> } else if (type=='language') {
>>> nr <- nr+2
>>> str <- append(str, paste('${',nr-1,':, ',field,'=${',nr,':',r.autoyas.esc(deparse(formals[[field]])),'}}', sep=''))
>>> }
>>> }
>>> str <- paste(str, sep='', collapse='')
>>> if (grepl(', ', str, fixed=TRUE)) str <- sub(', ', '', str) # remove 1st ', ' (from 1st field)
>>> str <- paste('(',str,')', sep='')
>>> str
>>> }\n")
>>> )
>>>
>>>
>>> (defadvice yas/abort-snippet (around r-delete-remaining)
>>> (if (member major-mode '(ess-mode inferior-ess-mode))
>>> (r-autoyas-exit-snippet-delete-remaining)
>>> ad-do-it)
>>> )
>>>
>>> (ad-activate 'yas/abort-snippet)
>>> (add-hook 'ess-post-run-hook 'r-autoyas-inject-commands)
>>>
>>> (define-key ess-mode-map (kbd "C-M-<tab>")
>>> '(lambda ()(interactive)(r-autoyas-expand nil t)))
>>>
>>> (define-key ess-mode-map (kbd "(") '(lambda () (interactive)
>>> (skeleton-pair-insert-maybe nil)
>>> (r-autoyas-expand nil t)))
>>>
>>>
>>> Best,
>>> Vitalie.
>>>
>>> >
>>> > Sven
>>> >
>>> > ______________________________________________
>>> > ESS-help at r-project.org mailing list
>>> > https://stat.ethz.ch/mailman/listinfo/ess-help>
>> ______________________________________________
>> ESS-help at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/ess-help>
More information about the ESS-help
mailing list