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))))
Related
In bash if I do "foo.sh x", then x can be used in bash by calling $1.
If I want to do the same with lisp, "script.lisp x" what can I use/call to get x as a param instead of $1.
Example
#!/usr/local/bin/sbcl --script
(if (eql intp $1)
(+ $1 $1)
(format t "~¬ a valid int")))
The answer to this question depends on your particular Lisp implementation. For SBCL, as you can find in the User Manual, the variable sb-ext:*posix-argv* contains the command line. So eg. (nth 1 sb-ext:*posix-argv*) would give you the first parameter.
I am currently dealing with a problem, where I have to read a zipped file line by line, and further on process each line and do something with it.
I managed to read from stdin using the following code:
(defun process ()
(princ (split-sequence:split-sequence #\Space (read-line))))
(defun main (args)
(process))
*this will be a command line tool
Where I ran it as:
cat file.txt | ./executable
this works fine, but it prints only the first line. I assume I must insert some form of loop in the first part, yet I am not sure how this is to be done.
Thank you for any help!
I solved this using:
(loop for line = (read-line) ; stream, no error, :eof value
until (eq line :eof)
do (princ line))
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)
I am writing some code in Emacs Lisp where I want to start a subprocess using start-process or a similar function. However, when the parent emacs process exits, I don't want the subprocess to exit. However, it seems that exiting the parent emacs process always kills all the subprocesses as well. The following code snippet demonstrates this:
(require 'async)
(async-sandbox
(lambda ()
(require 'package)
(package-initialize)
(require 'async)
(shell-command "{ echo -n 'SPAWNING: '; date; } > ~/temp/ASYNC_LOG")
(start-process-shell-command "subproc" nil
"{ echo -n 'STARTED: '; date; } >> ~/temp/ASYNC_LOG;
sleep 5;
{ echo -n 'FINISHED: '; date; } >> ~/temp/ASYNC_LOG;")
(shell-command "{ echo -n 'SPAWNED: '; date; } >> ~/temp/ASYNC_LOG")
(shell-command "sleep 2")
(shell-command "{ echo -n 'FINISHED WAITING: '; date; } >> ~/temp/ASYNC_LOG")
))
This code spawns one emacs process synchronously (async-sandbox (lambda () ...) so that we can quit that process to trigger the problem. That process then spawns a subprocess asynchronously (start-process-shell-command ...). The parent process sleeps for 2 seconds, while the subprocess sleeps for 5, so the parent process will exit first. When I run this code, I never see the "FINISHED" line in the log file, indicating that the subprocess is killed after 2 seconds. If I change the parent to wait for 7 seconds, then I see the FINISHED line in the output.
So is there any similar way to start a subprocess so that it won't be killed when its parent exits?
Here's how I start stuff from dired:
(require 'dired-aux)
(setq dired-guess-shell-alist-user
'(("\\.pdf\\'" "evince")
("\\.eps\\'" "evince")
("\\.jpe?g\\'" "eog")
("\\.png\\'" "eog")
("\\.gif\\'" "eog")
("\\.tex\\'" "pdflatex" "latex")
("\\.\\(?:mp4\\|mkv\\|avi\\|flv\\)\\'" "vlc")))
(defvar dired-filelist-cmd
'(("vlc" "-L")))
(defun dired-start-process (cmd &optional file-list)
(interactive
(let ((files (dired-get-marked-files t current-prefix-arg)))
(list
(dired-read-shell-command "& on %s: " current-prefix-arg files)
files)))
(apply
#'start-process
(list cmd nil shell-file-name shell-command-switch
(format "nohup 1>/dev/null 2>/dev/null %s \"%s\""
(if (> (length file-list) 1)
(format "%s %s"
cmd
(cadr (assoc cmd dired-filelist-cmd)))
cmd)
(mapconcat #'expand-file-name file-list "\" \"")))))
What Emacs does upon termination is to send a signal to its spawned processes (I assume they are those present in process-list). This behavior is hardcoded in Emacs C code (you could try to hack process-list removing the process you want to outlive Emacs, but I am not sure about the side effects of that; possibly they will be ugly)
You can find out what signal Emacs sends easily (just write a signal handler for one of your processes). I would guess it is SIGHUP, so the processes know that connection to the user (Emacs) has been lost.
What you can do is to make your process to handle SIGHUP in such a way it does not die, by adding a handler for that signal for instance. If you have zero control over that process code, you may wrap it with a "nohup" (this is what #abo-abo is basically doing; see abo-abo other answer for implementation details)
Try using call-process-shell-command with the destination argument set to 0.
From the documentation of call-process:
The argument destination says where to put the process output. Here are the possibilities:
…
0
Discard the output, and return nil immediately without waiting for the subprocess to finish.
In this case, the process is not truly synchronous, since it can run in parallel with Emacs; but you can think of it as synchronous in that Emacs is essentially finished with the subprocess as soon as this function returns.
MS-DOS doesn’t support asynchronous subprocesses, so this option doesn’t work there.
(From an answer by dalanicolai on https://emacs.stackexchange.com/questions/22363/possible-to-detach-a-child-process/65040#65040)