Comments (15)
This part has been finally done. There are now two fully featured exporters (M-n e
) one for ESS and one for Rscript standalone. Thanks for your patience.
from polymode.
@biocyberman - I think would be satisfied if the snippet ran Rscript ...
not on localhost but rather on the host associated with tramp session through which you are editing the file.
Try this:
(defun rmarkdown-render ()
"Reformat the current (presumed) markdown formatted buffer into
another format (i.e. html) by running rmarkdown::render() on
it (which in turn calls pandoc and friends).
Display trace or error results in buffer *rmarkdown-render Output*
When underlying file is remote (i.e. tramp), perform conversion
on remote host (where Rscript must be on path and rmarkdown must
be installed/configured (i.e. including pandoc)).
"
;; TODO: recover when assumptions not met (e.g. RStudio offers to
;; install rmarkdown if needed).
(interactive)
(let ((render-command (read-string "render command:"
(format "render('%s',%s);"
(shell-quote-argument (file-name-nondirectory (buffer-file-name)))
"'all'"
))))
(get-buffer-create "*rmarkdown-render Output*")
(start-file-process
"rmarkdown-render" "*rmarkdown-render Output*"
"Rscript"
"-e" (message "withCallingHandlers({library(rmarkdown); %s}, clean=FALSE, error = function(e) {print(sys.calls())})"
render-command)
)))
from polymode.
I have implemented a temporary workaround, with the assumption that it will be done more formally and more correctly later.
I initially tried to create a custom pm-weaver/rmarkdown
, but I had trouble getting it to work, so I just modified pm-weaver/knitR
in-place. Since I am using render()
instead of knit()
, this does not pose a problem for me.
I have tested it weakly (it works on the two files I've tested so far), and only knitR-ESS
(I haven't played with dynamically putting Rscript.exe
in my path, similar to how ESS finds all versions of R.) Perhaps somebody better at lisp could improve on this.
--- modes/poly-R.el.orig 2014-08-07 09:10:51.835450100 -0700
+++ modes/poly-R.el 2014-08-07 09:10:19.166581500 -0700
@@ -301,13 +301,13 @@
(defcustom pm-weaver/knitR-ESS
(pm-callback-weaver "knitR-ESS"
:from-to
- '(("latex" "\\.\\(tex\\|rnw\\)\\'" "tex" "LaTeX" "library(knitr); knit('%i', output='%o')")
- ("html" "\\.x?html?\\'" "html" "HTML" "library(knitr); knit('%i', output='%o')")
- ("markdown" "\\.r?md\\'" "md" "Markdown" "library(knitr); knit('%i', output='%o')")
- ("rst" "\\.rst\\'" "rst" "ReStructuredText" "library(knitr); knit('%i', output='%o')")
- ("brew" "\\.r?brew\\'" "brew" "Brew" "library(knitr); knit('%i', output='%o')")
- ("asciidoc" "\\.asciidoc\\'" "txt" "AsciiDoc" "library(knitr); knit('%i', output='%o')")
- ("textile" "\\.textile\\'" "textile" "Textile" "library(knitr); knit('%i', output='%o')"))
+ '(("latex" "\\.\\(tex\\|rnw\\)\\'" "tex" "LaTeX" "library(rmarkdown); render('%i')")
+ ("html" "\\.x?html?\\'" "html" "HTML" "library(rmarkdown); render('%i')")
+ ("markdown" "\\.r?md\\'" "md" "Markdown" "library(rmarkdown); render('%i')")
+ ("rst" "\\.rst\\'" "rst" "ReStructuredText" "library(rmarkdown); render('%i')")
+ ("brew" "\\.r?brew\\'" "brew" "Brew" "library(rmarkdown); render('%i')")
+ ("asciidoc" "\\.asciidoc\\'" "txt" "AsciiDoc" "library(rmarkdown); render('%i')")
+ ("textile" "\\.textile\\'" "textile" "Textile" "library(rmarkdown); render('%i')"))
:function 'pm--run-command-in-ESS
:callback 'pm--ESS-callback)
"ESS knitR weaver."
NB: I chose to remove the output
argument, instead relying on render()
to infer the output document from the YAML header instead of relying on polymode to force it, mostly because I do not consistently tell polymode what format to weave/export and prefer to just hit M-n w
to knit/compile into a PDF or HTML in one step.
from polymode.
I will get around to this and other issued at the end of this week. Sorry for the delays.
from polymode.
No need to apologize! It's your effort helping us. Thank you!
from polymode.
What do you think about simply:
(defun rmarkdown-render ()
"run rmarkdown::render on the current file"
(interactive)
(shell-command
(format "Rscript -e 'library(rmarkdown); render(\"%s\")'"
(shell-quote-argument (buffer-file-name)))))
(define-key polymode-mode-map [(meta n) (r)] 'rmarkdown-render)
from polymode.
I modified your code slightly, since generally I'm not concerned about the pandoc output:
(defun rmarkdown-render ()
"run rmarkdown::render on the current file"
(interactive)
(let* ((out (shell-command-to-string
(format "c:/R/R-3.1.1/bin/x64/Rscript.exe -e \"rmarkdown::render('%s')\""
(shell-quote-argument (buffer-file-name)))))
(rstr (reverse (split-string out "\n")))
(last3 (mapconcat 'identity (subseq rstr 0 3) "")))
(message last3)))
(define-key polymode-mode-map [(meta n) (r)] 'rmarkdown-render)
It's not great elisp, but it's currently sufficient for my needs. If I were to extend it (and were more fluent in elisp), I'd extend it in a couple of ways:
- capture the shell-command output into a temp buffer instead of a string;
- search for "Output created" in the last few lines ... if found, "(message ...)" that line and delete the temp buffer, else show the temp buffer; and
- Offer an optional argument (e.g., "C-u M-n r") to do one of the following:
- change the current output format, where rmarkdown::render currently defaults to the first (or only) output format in the YAML section; or
- add
clean = FALSE
in order to keep intermediate files created during rendering
Thanks, @malcook, that was helpful.
from polymode.
Hi - glad it helped.
In light of some of the same issues, I've slightly changed my approach as follows:
(defun rmarkdown-render ()
"run rmarkdown::render() on the current file and display results in buffer *Shell Command Output*"
(interactive)
(let ((render-command (read-string "render command:"
(format "render('%s',%s);"
(shell-quote-argument (buffer-file-name))
"'all'"
))))
(shell-command
(message
"Rscript -e \"withCallingHandlers({library(rmarkdown); library(pander); %s}, error = function(e) print(sys.calls()))\""
render-command
))
))
... which gives the chance to add additional options (like clean=FALSE) to the call to render and handles shell output better.
Also, the withCallingHandlers business gets me a backtrace in case the call to render errors out, which happens.
Anyone else improving on this snippet?
~Malcolm
from polymode.
Excellent snippet @malcook !
For me, however, the output is display both in the Shell Command Output buffer and the Messages buffer, which is quite annoying.
I resolved this by putting a & at the end of the shell command, which executes the rendering asynchronously and only outputs to the Async Shell Command buffer
from polymode.
Another technique I switched to is using smart-compile
to automatically default to the correct Rscript call (instead of the default make -k
), and just use compile
to render the document. It does color-ify the output meaningfully, though admittedly it doesn't know enough about the output to be able to jump to the source document line for an error.
from polymode.
@malcook Could you change the function so that it works for files open through ssh connection with Tramp? I tried to render a file like that and the fuction does not understand the ssh protocol and the colons :
from polymode.
@malcook With only a typo with three additional ))) at the very end, the functions now works like a charm over tramp 👍
from polymode.
Glad it helped.
About those trailing parens, I think I lost them to an emacs core dump while coding for my master thesis over 30 years ago - glad to have 'em back - thanks for the alert!
from polymode.
My approach. Renders Rmd to html and opens in browser. Derived from: delhey.info/inc/ess-rmarkdown.pdf
(define-key polymode-mode-map (kbd "M-n r") 'ess-render-rmarkdown)
(defun ess-render-rmarkdown ()
"Compile R markdown (.Rmd). Should work for any output type."
(interactive)
;; Check if attached R-session
(condition-case nil
(ess-get-process)
(error
(ess-switch-process)))
(let* ((rmd-buf (current-buffer)))
(save-excursion
(let* ((sprocess (ess-get-process ess-current-process-name))
(sbuffer (process-buffer sprocess))
(buf-coding (symbol-name buffer-file-coding-system))
(buffer-file-name-html (concat (file-name-sans-extension buffer-file-name) ".html"))
(R-cmd
(format "library(rmarkdown); rmarkdown::render(\"%s\"); browseURL(\"%s\")"
buffer-file-name buffer-file-name-html)))
(message "Running rmarkdown on %s" buffer-file-name)
(ess-execute R-cmd 'buffer nil nil)
(switch-to-buffer rmd-buf)
(ess-show-buffer (buffer-name sbuffer) nil)))))
from polymode.
@kwstat - big difference with your approach is that it (re)-uses current R process which may have some state (i.e. variables set) which would not be present when starting a new R process, such as my approach. "You get what you asked for"
from polymode.
Related Issues (20)
- can't find polymode via package-install? HOT 1
- electric-indent-mode
- How to run a function is indirect buffers with the same major mode only?
- Typescript-xml polymode
- Setting mode file local variable to polymode applies itself recursively infinitely until cancelled
- Background Adjustment when Background Unspecified
- polymode creates additional [web] buffer
- Interaction with nix-mode: font-lock broken HOT 4
- Chunks not following automatic Emacs switch to light/dark theme HOT 5
- Polymode, Poly-COMEEGA and COMEEGA (Collaborative Org Mode Enhanced Emacs Generalized Authorship)
- inner mode indentation not works on the first line after head mark
- org-mode links become invisible HOT 3
- Polymode does not work in org-edit-special
- eglot sees the whole outer buffer content HOT 3
- hs-hide-all gives unbalanced parentheses error when it shouldn't in some Rnw buffers
- Inconsistent font size in heads
- Beginning of the Polymode buffer is ignored by flymake HOT 1
- quoted backslash in polymode chunks breaks font-locking
- how to activate AucTeX in poly-R for Rnw files
- Extra buffers popping up all over the place when switch-to-buffer-obey-display-actions is non-nil
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from polymode.