Common Lisp's multiline comments make it easier to include multiline shebangs:
#!/bin/bash
#|
exec clisp -q -q $0 $0 ${1+"$#"}
exit
|#
;;; Usage: ./scriptname.lisp
(defun main (args)
(let ((program (car args)))
(format t "Program: ~a~%" program)
(quit)))
Without this syntax, only very simple shebangs can be used. Is there a pound-based multiline comment for Smalltalk that would facilitate multiline shebangs?
It doesn't NEED to be multi-line; as long as bash can see "into" the Smalltalk comment, you should be okay. I'd be more worried about Smalltalk seeing past the #!
How about something based on:
"exec" "/usr/bin/gst" "--foo" "$0" "--bar" "$#"
There's no need for exit unless you expect the exec ever to fail. Make sure your Smalltalk is where you expect it to be! If you do want the safety valve:
"exec" ...
"exit"
Having to double-quote arguments can get in the way, of course. Double-quoting shell operators breaks their specialness, for example.
"echo" "hello" ">" "/dev/null"
just prints "hello > /dev/null"
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.
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))
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))))
I hope this isn't a really dumb question, but I've used emacs in the past with ESS to edit R files and run them in an R process. I'd like to do the same with spacemacs. As far as I can read and grasp, it just means I have to enable the ess layer in the .spacemacs file, and that's it.
So in my .spacemacs I have the following:
'(
;; ----------------------------------------------------------------
;; 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.
;; ----------------------------------------------------------------
;; auto-completion
;; better-defaults
emacs-lisp
;; git
markdown
javascript
colors
haskell
c-c++
ess
html
;; org
;; (shell :variables
;; shell-default-height 30
;; shell-default-position 'bottom)
;; spell-checking
;; syntax-checking
;; version-control
)
But if I close spacemacs then, and reboot, and try to create say an R file, there's no ess or formatting/colours or anything like that. The same for something like markdown too. All files are just opened in Fundamental mode. I thought spacemacs had layers so you can just add them and it work out of the box. So what am I missing or what should I check? I'm on OSX.
Thanks,
Ben.