How can I specify external-format (for example (:crlf :|cp932|)) on ECL?
I want to write string to file with some encoding.
So I type in my REPL like this:
(with-open-file (out "test.txt"
:direction :output
:external-format '(:crlf :|cp932|))
(write-string "some string" out))
Then invoked debugger and it show this:
The function EXT:MAKE-ENCODING is undefined.
[Condition of type UNDEFINED-FUNCTION]
This is an wrong way...?
When the external-format is :utf-8, successfully written...
ECL version -- 15.3.7
OS -- Ubuntu 14.04
Based on §19.1.3. External formats in the manual, it looks like the appropriate symbol is actually named "CP819" and is in the package named by "EXT", so you'd use ext:cp819, not :|cp819|. You'd be able to use (:crlf ext:cp819), e.g.:
(with-open-file (out "test.txt"
:direction :output
:external-format '(:crlf ext:cp932))
(write-string "some string" out))
Please fallback to ECL 15.2.21 or use git head - this is a bug introduced in 15.3.7
Related
I want to sent some data from my program to a process executed via uiop:run-program.
The following works:
(require :asdf)
(asdf:load-system :uiop)
(uiop:with-temporary-file (:stream dot-program-stream
:pathname dot-program-file)
(format dot-program-stream "digraph g { n1 -> n2; }")
(finish-output dot-program-stream)
:close-stream
(uiop:with-temporary-file (:pathname png-data)
(uiop:run-program '("/usr/bin/dot" "-Tpng") :input dot-program-file
:output png-data)
(uiop:launch-program '("/usr/bin/display") :input png-data)))
It seems rather convoluted.
A simpler version, where I used only a stream did not finish-output and did not use the :close-stream label resulted in dot producung an empty 0 byte file.
How to execute a process and pass it data generated by my lisp program as standard input?
Take a closer look at the documentation of uiop:launch-program and uiop:run-program, especially the options for the :input and :output keys.
You can call launch-program with :input :stream. Launch-program returns a process info object that contains the stream connected to that program's standard input behind the accessor process-info-input, so you can print to that.
If you have a different program that produces output that should go into that input stream, you have several options:
create a temporary file, then read it and print it to the second program's input stream (that seems to be your current approach)
use run-program with :output :string for the first call, then use launch-program with :input :stream for the second and write the output of the first to that stream
use launch-program also for the first call, in this case with :output :stream, then read from that output and print it to the second program's input
You can either read everything first, then write everything, or you can do buffered reading and writing, which might be interesting for long running processes.
Instead of this in-process buffering, you could also use a fifo (named pipe) from your OS.
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 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))))
When edit .emacs.el in emacs, I have run Alt + X eval-buffer command.
My os is windows.
And when I restart emacs it display following warning:
Warning (initialization): An error occurred while loading
`.../.emacs.el':
error: Non-hex digit used for Unicode escape
To ensure normal operation, you should investigate and remove the
cause of the error in your initialization file. Start Emacs with the
`--debug-init' option to view a complete error backtrace.
.emacs.el is:
;;Open all fine in one running instance
;;Ref:http://www.johndcook.com/blog/2010/07/28/miscellaneous-emacs-adventures/
;;(server-start)
;;TEST
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
`(ansi-color-names-vector ["#242424" "#e5786d" "#95e454" "#cae682" "#8ac6f2" "#333366" "#ccaa8f" "#f6f3e8"])
`(custom-enabled-themes (quote (wheatgrass))))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
;;Set auto save backup location, failed with following warning
(setq backup-directory-alist
`((".*" . ,"D:\Unix-Tmp")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\Unix-Tmp" t)))
(require 'recentf)
(recentf-mode 1)
(setq inhibit-startup-screen t)
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)
;;Aspell install failed
;;(setq-default ispell-program-name "C:/bin/Aspell/bin/aspell.exe")
;;(setq text-mode-hook '(lambda() (flyspell-mode t) ))
How I can resolve it?
The problem is these lines:
(setq backup-directory-alist
`((".*" . ,"D:\Unix-Tmp")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\Unix-Tmp" t)))
The \U introduces a unicode escape ... and has to be followed by hex digits.
What you actually appear to want is a literal backslash character, so you need to escape it; i.e.
(setq backup-directory-alist
`((".*" . ,"D:\\Unix-Tmp")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\\Unix-Tmp" t)))
Reference: http://www.gnu.org/software/emacs/manual/html_node/elisp/Basic-Char-Syntax.html#Basic-Char-Syntax
UPDATE
However, this appears to lead to another problem. A better solution would be to do what #Stefan suggests. Use "/" instead of "\" as the pathname separator. (It should work even on Windows ...)
Error is caused by D:\Unix-Tmp, \U introduces unicode escape as Stephen stated.
But when I change to :
(setq backup-directory-alist
`((".*" . ,"D:\\Unix-Tmp")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\\Unix-Tmp" t)))
It will throw another:
Loading d:/git_root_tfs/WorkStation/Unix-Home/.recentf...done Cleaning
up the recentf list...done (0 removed) For information about GNU Emacs
and the GNU system, type C-h C-a. make-auto-save-file-name: Invalid
use of `\' in replacement text
At last I change the path to D:\Tmp-Unix and it works.
(setq backup-directory-alist
`((".*" . ,"D:\Tmp-Unix")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\Tmp-Unix" t)))
Total .eamcs.el is
;;Open all fine in one running instance
;;Ref:http://www.johndcook.com/blog/2010/07/28/miscellaneous-emacs-adventures/
;;(server-start)
;;TEST
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
`(ansi-color-names-vector ["#242424" "#e5786d" "#95e454" "#cae682" "#8ac6f2" "#333366" "#ccaa8f" "#f6f3e8"])
`(custom-enabled-themes (quote (wheatgrass))))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
;;Set auto save backup location, failed with following warning
(setq backup-directory-alist
`((".*" . ,"D:\Tmp-Unix")))
(setq auto-save-file-name-transforms
`((".*" ,"D:\Tmp-Unix" t)))
(require 'recentf)
(recentf-mode 1)
(setq inhibit-startup-screen t)
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)
;;Aspell install failed
;;(setq-default ispell-program-name "C:/bin/Aspell/bin/aspell.exe")
;;(setq text-mode-hook '(lambda() (flyspell-mode t) ))
Always use forward slashes rather than backward slashes for file names in Emacs. Windows usually prefers backward slashes, but other than in a few rare exceptions, Windows actually accepts forward slashes just as well.
Emacs in Windows treats forward slashes (/) as backslashes (\). When you are specifying any type of path, you should always use forward slashes. Emacs will interpret them correctly. This allows you to control the escape sequence use to times where that is the intended effect.
C:/Users/username/AppData/Roaming/.emacs is a perfectly valid path/filename in Emacs.
ess-mode is "Emacs speaks statistics." This mode is useful for editing programs for R or Splus (two separate statistics packages).
In my buffer, when ever I type _ the character is replaced with <-, which is very frustrating. Is there an emacs lisp statement to turn off this behavior?
emacs: 22.1.1
ess-mode release (unknown)
From ESS's manual (look under "Changes/New Features in 5.2.0"):
ESS[S]: Pressing underscore ("_") once inserts " <- " (as before); pressing underscore twice inserts a literal underscore. To stop this smart behaviour, add "(ess-toggle-underscore nil)" to your .emacs after ess-site has been loaded
Since the feature is useful. You can assign it to other key which is less used by you in R it will automatically unassign it from underscore. I personally assign it to ";" by adding following line in .emacs file.
(setq ess-smart-S-assign-key ";")
My version of emacs is 24.3 All-in-one installation file by Vincent Goulet.(Installed on windows 7)
hope this helps
Edit
In emacs 25.2 above do not work instead add following in the .emacs file
(setq ess-smart-S-assign-key ";")
(ess-toggle-S-assign nil)
(ess-toggle-S-assign nil)
A more recent version which seemed to work for me, and is a lot less verbose (you essentially keep normal underscores, but can set your own key for this smart behaviour!):
(global-set-key (kbd "C-;") (lambda () (interactive) (insert " <- ")))
(ess-toggle-underscore nil)
Insert your shortkey choice instead of C-;.
From http://www.r-bloggers.com/a-small-customization-of-ess/ and
How to change smart assign key ("_" to "<-") binding in ESS
To assign ":" to "<-" and to stop the assignment of underscore (underbar) "_" to "<-" put the following in .emacs (yes, the repeated line is correct)
(setq ess-smart-S-assign-key ":")
(ess-toggle-S-assign nil)
(ess-toggle-S-assign nil)
(ess-toggle-underscore nil) ; leave underscore key alone!
Like Michał Marczyk and this R mailing list thread suggested, add this line to ~/.emacs:
(ess-toggle-underscore nil)
Then reload it with M-x load-file and type ~/.emacs.
But if you load the file again, e.g. if you add another customization, then it toggles it back to the original state. So toggle it twice, the first one forcing it to the default:
(ess-toggle-underscore t)
(ess-toggle-underscore nil)
That being said, I like Drummermean's solution better, but it also reverts back to default if you add it to ~/.emacs and load it twice. So force a toggle to the default before:
(ess-toggle-underscore t)
(global-set-key (kbd "M--") (lambda () (interactive) (insert " <- ")))
(ess-toggle-underscore nil)
I bound the smart assignment to Opt-[minus] like RStudio (on a Mac).
As a follow-up on #mmorin answer. To set keybinding for the assignment operator the same way as in Rstudio add the following in your .emacs file
(ess-toggle-underscore t)
(ess-toggle-underscore nil)
(define-key ess-mode-map (kbd "M--") (lambda () (interactive) (just-one-space 1) (insert "<-") (just-one-space 1)))
(define-key inferior-ess-mode-map (kbd "M--") (lambda () (interactive) (just-one-space 1) (insert "<-") (just-one-space 1)))