I would like to start a LaTeX after knitting an .Rnw file. The meta code shoudl be something like:
(defun knit ()
(interactive)
(setq rproc (ess-get-process ess-current-process-name))
(setq c "knit('foo.rnw')\n")
(process-send-string rproc c)
;; Wait for ESS to finish
(shell-command-to-string "cd foo/path & pdflatex foo"))
The main problem is to have Emacs to wait for the inferior buffer to finish knitting and only after to start latexing. I found a couple of interesting functions: (ess-wait-for-process ...) and (inferior-ess-mark-as-busy ...)`, which could possibly work, but I am unable to understand how.
Note that (shell-command-to-string ... is only illustrative. The final choice might be:
(TeX-command "LaTeX" 'rnw-to-tex-ext -1))
knit2pdf() might be a different path to go, but I will lose the benefit of AUCTeX.
PS: My question is considered "subjective and likely to be closed" by the SE robot!?
I use texi2pdf and have R do it after the knit, but that's apparently the equivalent of knit2pdf. I wonder though if you could use system to call whatever tex command you want from within R, after the knit command, similar to how I use texi2pdf.
I'm not an emacs expert whatsoever but for what it's worth here's the function I have in my .emacs file.
; use knitr (was Sweave) script as compile function for Rnw files
(defun ess-swv-SweaveSh ()
"Use knitr script to knit an Rnw file and create a pdf."
(interactive)
(let
((compilation-buffer-name-function (function (lambda(ign)(concat "*" (buffer-file-name) "*")))))
(compile (concat "Rscript -e \".n <- '" (buffer-file-name) "'; library(knitr); knit(.n); library(tools); texi2pdf(sub('Rnw$','tex',.n))\"" ))
)
)
A possible solution is to check the 'busy property of the inferior ESS process.
The while loop waiting for it to be nil blocks command echo. This is why you see (redisplay). To avoid stressing your dear one, I set also a refresh delay (sleep-for .5).
Just in case ESS gets stuck the loop exists after 60 seconds. Adjust it, if you have heavy weight code.
Finally I attached latexing to AUCTeX. Therefore you can customise LaTeX-command-style with the help of TeX-expand-list documentation.
The function automatically sets the proper name for files to knit and latex, and sets R working dir to the .Rnw file to be knitted, so you can source other scripts or load data.
So you can run it everywhere with M-x knit or perhaps associate it with a shortcut.
The function saves the buffer with last changes before knitting and opens an inferior R buffer if there is none available; otherwise it uses the existing one.
(defun knit ()
"Save the buffer, knit and latex"
(interactive) ; You will associate this to you favourite key
(let* (
;; Get names & path
(cur-dir (file-name-directory (buffer-file-name)))
(rnw-name (file-name-nondirectory (buffer-file-name)))
(tex-name (concat (file-name-base (buffer-file-name)) ".tex"))
;; Create knit command
(cmd (format "require(knitr); setwd('%s'); knit('%s')" cur-dir rnw-name))
;; Time the knitting
(start-time (float-time))
(wait 60) ; Lifeboat to exit loop if smt wrong
)
;; Save rnw buffer... you are lazy, I know)
(save-buffer)
;; Send string to R at low-level
;;(setq rproc (ess-get-process ess-current-process-name))
;;(process-send-string rproc c)
;; or Send line with the ESS wrapper
(ess-eval-linewise cmd)
;; While loop to check when
(setq start-time (float-time)
wait 60) ; Lifeboat to exit loop after x secs
;; Wait for 'busy property nil, nut not more than wait seconds
(setq rproc (ess-get-process ess-current-process-name))
(while (< (- (float-time) start-time) wait)
(sleep-for .5)
;; (accept-process-output rproc .5) ;alt. way for process-send-string
(redisplay)
(if (not (process-get rproc 'busy))
(setq wait 0)
(message "Knitting... ")))
(message "Knitting finished, starting latexing")
;; Set LaTeX your fav options. See TeX-expand-list for % pars
(setq LaTeX-command-style '(("" "%(PDF)%(latex) -file-line-error %S%(PDFout)")))
;; TeX-command requires a 'file function (anonymous here) returning the filename.
;; TeX-command/TeX-expand-list say 'file has one opt arg: extension.
;; Actually they are 2, despite the second seems always passed true.
(TeX-command "LaTeX" (lambda (&optional ext dummy) tex-name))))
Related
I don't understand why this code behaves differently in different implementations:
(format t "asdf")
(setq var (read))
In CLISP it behaves as would be expected, with the prompt printed followed by the read, but in SBCL it reads, then outputs. I read a bit on the internet and changed it:
(format t "asdf")
(force-output t)
(setq var (read))
This, again, works fine in CLISP, but in SBCL it still reads, then outputs. I even tried separating it into another function:
(defun output (string)
(format t string)
(force-output t))
(output "asdf")
(setq var (read))
And it still reads, then outputs. Am I not using force-output correctly or is this just an idiosyncrasy of SBCL?
You need to use FINISH-OUTPUT.
In systems with buffered output streams, some output remains in the output buffer until the output buffer is full (then it will be automatically written to the destination) or the output buffer is explicity emptied.
Common Lisp has three functions for that:
FINISH-OUTPUT, attempts to ensure that all output is done and THEN returns.
FORCE-OUTPUT, starts the remaining output, but IMMEDIATELY returns and does NOT wait for all output being done.
CLEAR-OUTPUT, tries to delete any pending output.
Also the T in FORCE-OUTPUT and FORMAT are unfortunately not the same.
force-output / finish-output: T is *terminal-io* and NIL is *standard-output*
FORMAT: T is *standard-output*
this should work:
(format t "asdf")
(finish-output nil) ; note the NIL
(setq var (read))
I was hoping to experiment with cl-async to run a series of external programs with a large combinations of command line arguments. However, I can't figure out how to read the stdout of the processes launched with as:spawn.
I would typically use uiop which makes it easy to capture the process output:
(let ((p (uiop:launch-program ... :output :stream)))
(do-something-else-until-p-is-done)
(format t "~a~%" (read-line (uiop:process-info-output p))))
I've tried both :output :pipe and :output :stream options to as:spawn and executing (as:process-output process-object) in my exit-callback shows the appropriate pipe or async-stream objects but I can't figure out how to read from them.
Can anyone with experience with this library tell how to accomplish this?
So you go to your repl and type:
CL-USER> (documentation 'as:spawn 'function)
And you read whatever comes out (or put your point on the symbol and hit C-c C-d f). If you read it you’ll see that the format for the :input, etc arguments is either :pipe, (:pipe args...), :stream, or (:stream args...) (or some other options). And that :stream behaves similarly to :pipe but gives output of a different type and that for details of args one should look at PIPE-CONNECT so you go and look up the documentation for that. Well it tells you what the options are but it isn’t very useful. What’s the documentation/description of PIPE or STREAM? Well it turns out that pipe is a class and a subclass of STREAMISH. What about PROCESS that’s a class too and it has slots (and accessors) for things like PROCESS-OUTPUT. So what is a good plan for how to figure out what to do next? Here’s a suggestion:
Spawn a long running process (like cat foo.txt -) with :output :stream :input :pipe say
Inspect the result (C-c C-v TAB)
Hopefully it’s an instance of PROCESS. What is it’s output? Inspect that
Hopefully the output is a Gray stream (ASYNC-STREAM). Get it into your repl and see what happens if you try to read from it?
And what about the input? See what type that has and what you can do with it
The above is all speculation. I’ve not tried running any of this but you should. Alternatively go look at the source code for the library. It’s already on your computer and if you can’t find it it’s on GitHub. There are only about half a dozen source files and they’re all small. Just read them and see what you can learn. Or go to the symbol you want to know about and hit M-. to jump straight to its definition. Then read the code. Then see if you can figure out what to do.
I found the answer in the test suite. The output stream can only be processed asynchronously via a read call-back. The following is simple example for posterity
(as:start-event-loop
(lambda ()
(let ((bytes (make-array 0 :element-type '(unsigned-byte 8))))
(as:spawn "./test.sh" '()
:exit-cb (lambda (proc exit-status term-signal)
(declare (ignore proc exit-status term-signal))
(format t "proc output:~%~a"
(babel:octets-to-string bytes)))
:output (list :stream
:read-cb (lambda (pipe stream)
(declare (ignore pipe))
(let ((buf (make-array 128 :element-type '(unsigned-byte 8))))
(loop for n = (read-sequence buf stream)
while (plusp n) do
(setf bytes
(concatenate '(vector (unsigned-byte 8))
bytes
(subseq buf 0 n)))))))))))
with
$ cat test.sh
#!/bin/bash
sleep_time=$((1+$RANDOM%10))
echo "Process $$ will sleep for $sleep_time"
sleep $sleep_time
echo "Process $$ exiting"
yields the expected output
I try to get a practical development environment for R in Emacs, hoping to get auto-completion working as shown in http://www.emacswiki.org/emacs/ESSAuto-complete.
However, even in a minimal configuration, I can't get it working.
See what I get on http://screencast.com/t/qcyVwkECX. In fact, while AC does work (see completion menu appearing), it's like if there was no info from the R language itself, while ac-source-R is WELL added to ac-sources.
Do you understand what's happening?
Best regards.
PS- Here is my minimal Emacs configuration file for the demo:
;; Auto Completion
(add-to-list 'load-path "~/.emacs.d/elpa/auto-complete-20140824.1658/")
(add-to-list 'load-path "~/.emacs.d/elpa/popup-20140815.629/")
(when (require 'auto-complete-config)
(ac-config-default)
;; use `C-n/C-p' to select candidates
(setq ac-use-menu-map t)
(define-key ac-menu-map (kbd "C-n") 'ac-next)
(define-key ac-menu-map (kbd "C-p") 'ac-previous)
;; unbind some keys (inconvenient in iESS buffers)
(define-key ac-completing-map (kbd "M-n") nil)
(define-key ac-completing-map (kbd "M-p") nil)
;; set default sources
(setq ac-sources
(append '(ac-source-features
ac-source-functions
ac-source-yasnippet
ac-source-variables
ac-source-symbols)
ac-sources))
(setq ac-delay 0) ; faster than default 0.1
(setq ac-auto-show-menu 0.2)
(setq ac-quick-help-delay 0.5)
(setq ac-quick-help-height 10)
(setq ac-candidate-limit 100)
;; completion by TAB
(define-key ac-completing-map
(kbd "<tab>") 'ac-complete)
;; avoid Flyspell processes when auto completion is being started
(ac-flyspell-workaround))
;; ESS: Emacs Speaks Statistics
(add-to-list 'load-path "~/.emacs.d/elpa/ess-20140824.1452/lisp/")
(setq shell-file-name "zsh.exe")
(add-to-list 'auto-mode-alist '("\\.[rR]\\'" . R-mode))
(autoload 'R "ess-site" "Call 'R', the 'GNU S' system from the R Foundation." t)
(autoload 'R-mode "ess-site" "Major mode for editing R source." t)
(setq ess-ask-for-ess-directory nil)
(setq inferior-ess-same-window nil)
(setq ess-default-style 'DEFAULT)
(with-eval-after-load "ess-site"
;; use eldoc to report R function names
(require 'ess-eldoc)
(add-hook 'inferior-ess-mode-hook 'ess-use-eldoc))
PPS- In fact, ElDoc does not seem to work either!
UPDATE
I just discovered it almost works when the iESS buffer gets created, not when just editing R code in its own buffer. See http://screencast.com/t/fKRjLmIC6K0.
What would explain that iESS must be run first before it finally works?
Still, something that does not work is the completion on function arguments (like with the cat function on the page http://www.emacswiki.org/emacs/ESSAuto-complete).
Why does that not work?
After opening a R file with emacs, if you have this mode described into your emacs status bar:
(ESS[S] [none] ElDoc AS)
You can run this shortcut C-c C-s to attach a R session to you ESS[S] editor mode.
If you already have one or some R session open, emacs will ask you to choose the R session you want to use. Otherwise if you have not already open a R session then emacs will open a new one for you.
Next, you should have this information inside your status bar:
(ESS[S] [R db -] ElDoc AS)
and the completion should work.
I have tried to put the following in my .emacs file.
(defun clear-shell ()
(interactive)
(let ((old-max comint-buffer-maximum-size))
(setq comint-buffer-maximum-size 0)
(comint-truncate-buffer)
(setq comint-buffer-maximum-size old-max)))
(global-set-key (kbd "\C-x c") 'clear-shell)
It worked, but it also remove all the command I have typed before. So it is not what I want. I just want the current prompt > at the top of the buffer and not to delete any command I typed before.
Does anyone know?
For me Esc-0 Ctr-l seems to work.
`Ctrl-h k' output is:
C-l runs the command recenter-top-bottom,
which is an interactive compiled Lisp function in window.el'.
According to this page from the Emacs manual:
Scroll the selected window so the current line is the
center-most text line; on subsequent consecutive invocations,
make the current line the top line, the bottom line, and so on in
cyclic order. Possibly redisplay the screen too (recenter-top-bottom).
This seems to get the job done (though I am actually not really sure if this is what you are after):
(defun clean-shell ()
(interactive)
; if you call this from your .r script, it will switch to the next window
(when (eq major-mode 'ess-mode) (other-window 1))
(mark-whole-buffer)
(exchange-point-and-mark)
(move-beginning-of-line 1)
(delete-region (region-beginning) (region-end))
(end-of-line)
)
EDIT: Or maybe this?
(defun clean-shell ()
(interactive)
(when (eq major-mode 'ess-mode) (other-window 1))
(mark-whole-buffer)
(exchange-point-and-mark)
(move-beginning-of-line 0)
(delete-region (region-beginning) (region-end))
(end-of-line)
)
What is wrong with C-l C-l? It works in any buffer.
In a Sweave document, code chunks in R are set off from the main text like so:
Catz are well known for their fur & pur.
<<echo = false>>=
catz <- 1 + 2
#
I'd like to run spell check for the LaTeX part (and flag "Catz") but have it skip the code chunks (not flag "catz"). In a long document, hitting "SPC" for each "misspelling" in the code section gets tedious.
Try adding this to your emacs init file:
(add-to-list 'ispell-skip-region-alist '("^<<.*>>=" . "^#"))
Edit (Re Michael Hoffman's comments):
If Flyspell is enabled, these two additional expressions will also be needed:
(defun flyspell-eligible ()
(let ((p (point)))
(save-excursion
(cond ((re-search-backward (ispell-begin-skip-region-regexp) nil t)
(ispell-skip-region (match-string-no-properties 0))
(< (point) p))
(t)))))
(put 'latex-mode 'flyspell-mode-predicate 'flyspell-eligible)
For other modes, replace the latex-mode in the last expression with the appropriate major mode names.