Fetching contributors…
Cannot retrieve contributors at this time
188 lines (144 sloc) 6.2 KB
;;; pander.el --- ESS integration of pander (R) package
;; Copyright (C) 2012 Gergely Daróczi
;; Author: Gergely Daróczi <>
;; Version: 0.1
;; Package-Requires: ((ess))
;; Keywords: ESS, R, report
;; X-URL:
;; This file is not part of GNU Emacs.
;; This "program" is free software; you can redistribute it and/or
;; modify it under the terms of the Affero General Public License
;; as published by the Free Software Foundation; version 3.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; AGPL for more details:
;;; Installation and load
;; This file can be found on your filesystem if pander R package
;; is installed. If you do not know where it is, run the following
;; command in *R*:
;; system.file('pander.el', package='pander')
;; To use this minor, simply add the above firectory to your path
;; and load pander.el, e.g.:
;; (add-to-list 'load-path "/usr/lib/R/library/pander/")
;; (require 'pander)
;;; Feedback
;; This minor-mode is under heavy development. Any suggestion/feedback
;; really welcomed at GH issue tracker:
;;; TODO:
;; * escaping issue (now changing all double quotes to single quotes in selection)
;;; Code:
;; minor mode
(defgroup pander nil
"ESS integration of pander R package"
:group 'ess)
(defvar pander-mode-map
(let ((keymap (make-sparse-keymap)))
(define-key keymap (kbd "C-c p b") 'pander-brew)
(define-key keymap (kbd "C-c p B") 'pander-brew-export)
(define-key keymap (kbd "C-c p e") 'pander-eval)
"Keymap for pander-mode.")
(define-minor-mode pander-mode
"Toggle pander mode.
With no argument, this command toggles the mode.
Non-null prefix argument turns on the mode.
Null prefix argument turns off the mode.
When pander mode is enabled, some keybindigs
are activated for pander functions."
:lighter " pander"
:group 'pander
;; Define key-bindings for calling above functions
;; (global-set-key (kbd "C-c p e") 'pander-evals-region)
;; (global-set-key (kbd "C-c p r") 'pander-region)
;; (global-set-key (kbd "C-c p c") 'pander-chunk)
;; (global-set-key (kbd "C-c p p") 'pander-region-or-chunk)
;; (global-set-key (kbd "C-c p R") 'pander-region-export)
;; (global-set-key (kbd "C-c p C") 'pander-chunk-export)
;; (global-set-key (kbd "C-c p P") 'pander-region-or-chunk-export)
(defcustom pander-clipboard nil
"If non-nil then the result of pander-* functions would be copied to clipboard."
:type 'boolean
:group 'pander)
(defcustom pander-show-source nil
"If non-nil then the source of R commands would also show up in generated documents while running 'pander-eval'. This would not affect 'brew' function ATM."
:type 'boolean
:group 'pander)
;; functions
(defun pander-postprocess-output ()
"Prettify results in *ess-output* and optionally copy to clipboard."
;; remove possible "+" chars at the beginning of the result
(set-buffer "*ess-output*")
(while (re-search-forward "\\+ " (min (point-at-eol)) 'go)
(replace-match ""))
;; copy to clipboard
(if pander-clipboard
(clipboard-kill-ring-save (point-min) (point-max))
(defun pander-brew ()
"Run Pandoc.brew on current buffer or region (if mark is active), show results in *ess-output* and (optionally) copy results to clipboard while setting working directory to tempdir() temporary."
(if mark-active
(let (
(selection (buffer-substring-no-properties (region-beginning) (region-end))))
(ess-execute (format "require(pander, quietly=T);wd<-getwd();setwd(tempdir());Pandoc.brew(text=\"%s\");setwd(wd)\n" (replace-regexp-in-string "\"" "'" selection)))
(ess-execute (format "require(pander, quietly=T);wd<-getwd();setwd(tempdir());Pandoc.brew(\"%s\");setwd(wd)\n" buffer-file-name))
(defun pander-brew-export ()
"Run Pandoc.brew on current buffer or region (if mark is active) and export results to specified (auto-complete in minibuffer) format. Also tries to open exported document."
(let ((output-format (completing-read "Output format: "
'(("html" 1) ("pdf" 2) ("odt" 3) ("docx" 4)) nil nil "html")))
(if mark-active
(let (
(selection (buffer-substring-no-properties (region-beginning) (region-end))))
(ess-command (format "require(pander, quietly=T);wd<-getwd();setwd(tempdir());Pandoc.brew(text=\"%s\",output=tempfile(),convert=\"%s\" );setwd(wd)\n" (replace-regexp-in-string "\"" "'" selection) output-format))
(ess-command (format "require(pander, quietly=T);wd<-getwd();setwd(tempdir());Pandoc.brew(\"%s\",output=tempfile(),convert=\"%s\");setwd(wd)\n" buffer-file-name output-format))
(defun pander-eval ()
"Run pander on (automatically evaluated) region *or* current chunk (if marker is not set), show results (of last returned R object) in *ess-output* and (optionally) copy those to clipboard while setting working directory to tempdir() temporary. Chunk is recognized by opening '<%' or '<%=', and closing '%>' tags."
(let ((show-src
(if pander-show-source
(concat "TRUE")
(concat "FALSE"))
(if mark-active
(let (
(selection (buffer-substring-no-properties (region-beginning) (region-end))))
(if (= (length selection) 0)
(message "Nothing selected in region.")
(ess-execute (format "pander:::ess.pander.evals(\"%s\", show.src=%s)\n" (replace-regexp-in-string "\"" "'" selection) show-src))))
(let (p1 p2)
(skip-chars-backward "^<%[=]+") (setq p1 (point))
(skip-chars-forward "^%>") (setq p2 (point))
(let (
(selection (buffer-substring-no-properties p1 p2)))
(if (= (length selection) 0)
(message "Pointer is not inside a chunk!")
(ess-execute (format "pander:::ess.pander.evals(\"%s\", show.src=%s)\n" (replace-regexp-in-string "\"" "'" selection) show-src))))))
(provide 'pander)