[ESS] Easy argument list: r-autoyas

Vitalie Spinu spinuvit.list at gmail.com
Thu Mar 10 17:28:16 CET 2011


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



More information about the ESS-help mailing list