I use the following function to run shell commands:
(defun sh (cmd)
#+clisp (shell cmd)
#+ecl (si:system cmd)
#+sbcl (sb-ext:run-program "/bin/sh" (list "-c" cmd) :input nil :output*standard-output*)
#+clozure (ccl:run-program "/bin/sh" (list "-c" cmd) :input nil :output*standard-output*)))
For example, How to specify the current directory for command python -m CGIHTTPServer ?
Sincerely!
In ECL you can use EXT:CHDIR before SYSTEM, which changes both default-pathname-defaults and the value of the current directory, as understood by the operating system and C library.
BTW: If possible use (EXT:RUN-PROGRAM "command" list-of-args) instead
A more portable way would be to use pathnames and dynamically binding *default-pathname-defaults*, which would effectively set your current working directory. I had the same problem today. Here is a working adaptation of dot->png from Land of Lisp text by Conrad Barski, that specifies the current working directory:
(defun dot->png (filespec thunk)
"Save DOT information generated by a thunk on a *STANDARD-OUTPUT* to a FILESPEC file. Then use FILESPEC to create a corresponding png picture of a graph."
;; dump DOT file first
(let ((*default-pathname-defaults*
(make-pathname :directory (pathname-directory (pathname filespec)))))
;; (format t "pwd (curr working dir): ~A~%" *default-pathname-defaults*)
(with-open-file (*standard-output*
filespec
:direction :output
:if-exists :supersede)
(funcall thunk))
#+sbcl
(sb-ext:run-program "/bin/sh"
(list "-c" (concatenate 'string "dot -Tpng -O " filespec))
:input nil
:output *standard-output*)
#+clozure
(ccl:run-program "/bin/sh"
(list "-c" (concatenate 'string "dot -Tpng -O" filespec))
:input nil
:output *standard-output*)))
Posted in the hope that this could be useful to someone in a similar situation & running across this thread.
Related
Basically,
(uiop:run-program "echo hello" :output *standard-output*)
outputs hello, while none of
(uiop:launch-program "echo hello" :output *standard-output*)
(uiop:launch-program "echo hello" :output #.*standard-output*)
(uiop:launch-program "echo hello" :output :interactive)
output anything; however, if I do run
(uiop:run-program "echo hello" :output *standard-output*)
after them, I do get hello 4 times indicating echo hello did run. Why is this the case? ((force-output) doesn't change anything either.)
Edit: I am using SBCL with SLIME. And as suggested in the comments, this works as-expected (I get the output) on running it from the terminal.
When you look at the implementations of run-program and launch-program, you see that the former (in this caseā¦) does a wait-process.
If you issue a uiop:wait-process on the process-info returned by launch-program, your output appears.
I guess that it is a kind of race condition where swank or slime doesn't get to pick up the output before it does something else. I think that this is inherent in the asynchronous behaviour of launch-program.
I think that the clearest way to get the output is to specify :output :stream and then use the stream available from calling process-info-output on the return value of launch-program.
I really want to switch from RStudio to Spacemacs with ess layer. However I can't get it to work. I have the following in my dotfile:
dotspacemacs-configuration-layers
'(
html
;; ----------------------------------------------------------------
;; Example of useful layers you may want to use right away.
;; Uncomment some layer names and press <SPC f e R> (Vim style) or
;; <M-m f e R> (Emacs style) to install them.
;; ----------------------------------------------------------------
markdown
helm
ess
auto-completion
better-defaults
emacs-lisp
git
polymode
mu4e
;; markdown
;; (shell :variables
org
;; shell-default-height 30
;; shell-default-position 'bottom)
spell-checking
syntax-checking
;; version-control
)
I have the following packages.el in my .emacs.d private folder copied with thanks from github.
;;; packages.el --- polymode layer packages file for Spacemacs.
;;
;; Copyright (c) 2012-2016 Sylvain Benner & Contributors
;;
;; Author: Walmes Zeviani & Fernando Mayer
;; URL: https://github.com/syl20bnr/spacemacs
;;; Code:
(defconst polymode-packages
'(polymode))
(defun polymode/init-polymode ()
(use-package polymode
:mode (("\\.Rmd" . Rmd-mode))
:init
(progn
(defun Rmd-mode ()
"ESS Markdown mode for Rmd files"
(interactive)
(require 'poly-R)
(require 'poly-markdown)
(R-mode)
(poly-markdown+r-mode))
))
)
;;; packages.el ends here
Syntax highlighting and code completeion etc are working fine but if I try and send code chunks to REPL i get 'wrong type argument stringp nil' error with both Rmd and Rmv files.
emacs 25.2.1 with spacemacs
fresh install on both mac and linux with no other config loaded. Own .emacs has been deleted
some functions seem to work but not like they should e.g. eval-buffer will just send the current code chunk to REPL
Very grateful for any help.
It was a bit tricky to me to make it works with Rmd. Have you try with a simple .R file to see if it works?
This is what I currently have in mi .emacs file for the Rmd files
;; MARKDOWN
(add-to-list 'auto-mode-alist '("\\.md" . poly-markdown-mode))
;; R modes
(add-to-list 'auto-mode-alist '("\\.Snw" . poly-noweb+r-mode))
(add-to-list 'auto-mode-alist '("\\.Rnw" . poly-noweb+r-mode))
(add-to-list 'auto-mode-alist '("\\.Rmd" . poly-markdown+r-mode))
;; polymode
(setq load-path (append '("/home/fer/.emacs.d/elpa/polymode-20170307.322"
"/home/farce/.emacs.d/polymode/modes") load-path))
(require 'poly-R)
(require 'poly-markdown)
(add-to-list 'auto-mode-alist '("\\.Rmd" . poly-markdown+r-mode))
I want to have the ability to execute statements on R's REPL with the option to pipe it to a buffer so I can quickly refer back to it later.
To run a shell command and output to *shell command buffer* I can use M-! as per this question. What would the equivalent be for R's REPL without resorting to write.csv()?
You can use ess-command from ess-inf to redirect the output to another buffer. An example could look like the following,
(defun redirect-ess-output (command &optional buffer process)
(interactive (list (read-from-minibuffer "Command: ")))
(let ((buff (get-buffer-create (or buffer "*r-output*")))
;; 'ess-get-process' defaults to process local to current
;; buffer, so to call from anywhere default to "R"
(proc (ess-get-process (or process "R"))))
;; send a trailing newline to process
(unless (string-match-p "\n$" command)
(setq command (concat command "\n")))
(ess-command command buff 'sleep nil nil proc)
(with-current-buffer buff
;; process stuff
(pop-to-buffer buff))))
Recently I find a run-program hang issue of sbcl 1.2.7 (32bits, linux). The code as following
(progn
(with-open-file (s "test.out" :direction :output :if-exists :supersede)
(loop repeat 900 do (write-line (make-string 76 :initial-element #\x) s)))
(run-program "/bin/bash" (list "-c" "cat test.out") :output :stream))
That is when the "cat test.out" produce many lines of output to the process-output stream of process object, the `run-program' call hang forever. On my test machine, when the number of lines larger than 900, this issue happens. Otherwise just fine. I doubt this issue caused by some kind of block (maybe buffer is full?) when the output data written to the process-output stream. If we change the code as following (avoid data written to the process-output stream), the run-program call returns immediately:
(length
(with-output-to-string (s)
(run-program "/bin/bash" (list "-c" "cat test.out")
:output s)))
;;=> 69300
I don't know whether that's a bug. Is there method by which we can make the call just return when the hang issue happens?
There is also a similar question: how-to-read-from-large-process-output-correctly , but I don't get the answer why the run-program call hang there.
I also think that could be some buffer problem. However, if you read from :stream line by line, that works fine:
(let ((process
(run-program "/bin/bash" (list "-c" "cat test.out") :output :stream :wait nil)))
(loop for line = (read-line (process-output process) nil :eof)
until (eq line :eof)
do (print line)))
When using ESS[R] in inferior mode I can retrieve the most recent command output using C-c C-p which moves the cursor to the previous command output. Alternatively I can use C-up which essentially copies the most recently entered command from the inferior process (similar to how readline works). I prefer the C-up approach but unfortunately it does not retrieve commands that were entered from a script using any of the ess-eval commads. Is there to get the functionality of C-up for commands entered in both inferior mode and by ess-eval?
Your solution works fine for single line commands, but needs a small tweak to handle multi-line statements:
(defun ess-readline ()
"Move to previous command entered from script *or* R-process and copy
to prompt for execution or editing"
(interactive)
;; See how many times function was called
(if (eq last-command 'ess-readline)
(setq ess-readline-count (1+ ess-readline-count))
(setq ess-readline-count 1))
;; Move to prompt and delete current input
(comint-goto-process-mark)
(end-of-buffer nil) ;; tweak here
(comint-kill-input)
;; Copy n'th command in history where n = ess-readline-count
(comint-previous-prompt ess-readline-count)
(comint-copy-old-input)
;; Below is needed to update counter for sequential calls
(setq this-command 'ess-readline)
)
(global-set-key (kbd "\C-cp") 'ess-readline)
This enables you to move up through the previous commands; the following function enables you to move back down again, so you can go up and down to find the command you're after:
(defun ess-readnextline ()
"Move to next command after the one currently copied to prompt and copy
to prompt for execution or editing"
(interactive)
;; Move to prompt and delete current input
(comint-goto-process-mark)
(end-of-buffer nil)
(comint-kill-input)
;; Copy (n - 1)'th command in history where n = ess-readline-count
(setq ess-readline-count (max 0 (1- ess-readline-count)))
(when (> ess-readline-count 0)
(comint-previous-prompt ess-readline-count)
(comint-copy-old-input))
;; Update counter for sequential calls
(setq this-command 'ess-readline)
)
(global-set-key (kbd "\C-cn") 'ess-readnextline)
It doesn't seem that there is any built in function to do this so I wrote the function below. Essentially this function automates the process of using the keystokes C-c C-p to move the cursor to a previous command in the R-process buffer followed by C-c RET to copy that command to the prompt for editing
(defun ess-readline ()
"Move to previous command entered from script *or* R-process and copy
to prompt for execution or editing"
(interactive)
;; See how many times function was called
(if (eq last-command 'ess-readline)
(setq ess-readline-count (1+ ess-readline-count))
(setq ess-readline-count 1))
;; Move to end of buffer and delete current input
(end-of-buffer nil)
(comint-kill-input)
;; Copy n'th command in history where n = ess-readline-count
(comint-previous-prompt ess-readline-count)
(comint-copy-old-input)
;; Below is needed to update counter for sequential calls
(setq this-command 'ess-readline)
)
(global-set-key (kbd "\C-cp") 'ess-readline)