Elisp close *Async Shell Command* window after the command finishes - asynchronous

I made a function, that runs pdflatex compiler to produce a pdf file for the currently edited tex file:
(defun latex-compile ()
"Runs pdflatex on current file"
(interactive)
(let ((file-name (shell-quote-argument (buffer-file-name))))
(async-shell-command (concat "pdflatex " file-name))))
Is it possible to close the window *Async Shell Command* after the process exits, if it exited successfully?

If you want to run asynchronous process programmatically go for it.
That is, use the lower level functions.
(set-process-sentinel (start-process "pdflatex"
"*async pdflatex*"
"pdflatex" filename)
(lambda (process event)
(cond ((string-match-p "finished" event)
(kill-buffer "*async pdflatex*"))
((string-match-p "\\(exited\\|dumped\\)" event)
(message "Something wrong happened while running pdflatex")
(when (yes-or-no-p "Something wrong happened while running pdflatex, see the errors?")
(switch-to-buffer "*async pdflatex*"))))))
start-process starts a process asynchronously and set-process-sentinel defines the function triggered when the process status changes.

Here is the working code:
(defun latex-sentinel (process event)
(message event)
(cond ((string-match-p "finished" event)
(progn
(kill-buffer "*async pdflatex*")
(message "pdflatex done")))))
(defun latex-compile ()
"Runs pdflatex on current file"
(interactive)
(let* ((file-name (shell-quote-argument (buffer-file-name)))
(process (start-process-shell-command
"pdflatex"
"*async pdflatex*"
(concat "pdflatex " file-name))))
(set-process-sentinel process 'latex-sentinel)))

Related

uiop:launch-program and nodejs

I'm trying to launch node, write JS and read back the answer. Why does the following code not work but hangs at the read-line? echo "console.log(1+1)" | node works fine.
(defvar node-process (uiop:launch-program '("/usr/local/bin/node")
:input :stream
:output :stream
:error-output :stream))
(defvar node-stream (make-two-way-stream (uiop:process-info-output node-process)
(uiop:process-info-input node-process)))
(write-line "console.log(1+1)" node-stream)
(force-output node-stream)
(format t "~s~%" (read-line node-stream))
It appears that node only emit output after EOF is read when in non-interactive mode, so you need to close the input stream before reading.
Add
(close (two-way-stream-input-stream node-stream))
after force-output and before read-line.

async clojure http-kit client with callback writing to database sqlite3

I am stucked with http-kit async behavior when it comes to write to an sqlite table.
The i/o to the database depends on whether I send the code to a boot repl or run it as a boot script. The i/o proceed only in the repl case. What am I missing? Here 's my code:
#!/usr/bin/env boot
(defn deps [new-deps]
(boot.core/merge-env! :dependencies new-deps))
(deps '[
[http-kit "2.2.0"]
[org.clojure/core.async "0.2.395"]
[org.clojure/java.jdbc "0.7.0-alpha1"]
[org.xerial/sqlite-jdbc "3.16.1"]
[org.slf4j/slf4j-nop "1.7.22"]
])
(require
'[org.httpkit.client :as http]
'[clojure.java.jdbc :as jdbc]
)
(def db-spec
{:classname "org.sqlite.JDBC"
:subprotocol "sqlite"
:subname "sqlite.db"})
;(jdbc/db-do-commands
;db-spec
;(jdbc/create-table-ddl "test" [[:msg :text]]))
(def ins! (partial jdbc/insert! db-spec "test"))
(http/get "http://locahost" {} (fn [_] (ins! {:msg "repl"})))
(defn -main []
(println (System/getProperty "user.dir"))
(http/get "http://locahost" {} (fn [_] (ins! {:msg "exec"}))))
Thanks
The issue with the script not working from command line is that http-kit asynchronous callbacks are handled by daemon threads and the only non-daemon thread is the main thread running your script.
When your -main function ends after submitting HTTP request to http-kit for async processing, the main thread terminates and causes that the JVM shutdowns before daemon threads processing your async callback get a chance to run.
You can check that by adding a sleep expression in the end of -main function to see that your callback is executed:
(defn -main []
(println (System/getProperty "user.dir"))
(http/get "http://locahost" {} (fn [_] (ins! {:msg "exec"})))
(Thread/sleep 60000))
The best way to make sure that the -main function will wait for the result to be processed is to keep the promise returned by http/get call. The promise eventually will contain the result produced by your callback function:
(let [result-promise (http/get "https://www.google.com" {} (fn [_] "Result"))]
#result-promise)
#result-promise is a reader macro/shortcut for (deref result-promise).
The full form might be better when you would like to not block indefinitely - just call deref with timeout-ms and timeout-value arguments:
(deref result-promise 5000 "Didn't get response in 5 seconds. Giving up")

Clojure - core.async interface for apache kafka

I am using clj-kafka, and I am trying to make a core.async interface to it in the REPL.
I am getting some messages, but my structure feels wrong : I either cannot stop receiving messages, or have to launch the go routine again to receive more messages.
Here is my attempt :
(defn consume [topic]
(let [consume-chan (chan)]
(with-resource [c (consumer config)]
shutdown
(go (doseq [m (messages c "test")]
(>! chan message) ;; should I check the return value?
)))
consume-chan)) ;; is it the right place to return a channel ?
(def consume-chan (consume "test"))
;;(close! consume-chan)
(go (>! consume-chan "hi")) ;; manual test, but I have some messages in Kafka already
(def cons-ch (go
(with-resource [c (consumer config)]
shutdown
(doseq [m (messages c "test")]
(>! consume-chan m))))) ;; should I check something here ?
;;(close! cons-ch)
(def go-ch
(go-loop []
(if-let [km (<! consume-chan)]
(do (println "Got a value in this loop:" km)
(recur))
(do (println "Stop recurring - channel closed")))))
;;(close! go-ch)
How do I consume a lazy-sequence of messages with a core.async interface ?
Here's what I would do:
>! and <! return nil if the channel is closed, so make sure that the loop exits when this happens - that way you can easily end the loop from the outside by closing the channel.
Use a try/catch to check for exceptions inside the go block, and make any exception the return value so that they don't get lost.
Check for exceptions on read values, to catch anything from inside the channel.
The go blocks return a channel, and the return value of the code inside the block (like the exceptions from above) will be put on the channel. Check these channels for exceptions, possibly to rethrow.
You can now write to a channel like this:
(defn write-seq-to-channel
[channel
values-seq]
(a/go
(try
(loop [values values-seq]
(when (seq values)
(when (a/>! channel (first values))
(recur (rest values)))))
(catch Throwable e
e))))
and you read like this:
(defn read-from-channel-and-print
[channel]
(a/go
(try
(loop []
(let [value (a/<! channel)]
(when value
(when (instance? Throwable value)
(throw value))
(println "Value read:" value)
(recur))))
(catch Throwable e
e))))
You will now have two channels, so use something like alts! or alts!! to check for your loops exiting. Close the channel when you are done.

Clojurescript async <? macro

I keep seeing this macro <?, in swanodette's code which looks really useful :
In this gist :
;; BOOM!!! we can convert async errors into exceptions
(go (try
(let [x (<? (run-task (.-readFile fs) "foo.txt" "utf8"))]
(.log js/console "Success" x))
(catch js/Error e
(.log js/console "Oops" e))))
In this blog post :
(go (try
(let [tweets (<? (get-tweets-for "swannodette"))
first-url (<? (expand-url (first (parse-urls tweets))))
response (<? (http-get first-url))]
(. js/console (log "Most recent link text:" response)))
(catch js/Error e
(. js/console (error "Error with the twitterverse:" e)))))
<? is just a touch of macro sugar that expands into something like
(throw-err (<! [expr])). In core.async <! serves the same purpose as
ES6's yield operator. If an asynchronous process writes an error onto
its channel we will convert it into an exception.
But I can't find a definition for it. How is it implemented in Clojure{Script} ?
Alright so here is what I am using so far. There is probably room for improvement.
In Clojure :
(defn throw-err [e]
(when (instance? Throwable e) (throw e))
e)
(defmacro <? [ch]
`(throw-err (<! ~ch)))
In ClojureScript :
(defn error? [x]
(instance? js/Error x))
(defn throw-err [e]
(when (error? e) (throw e))
e)
(defmacro <? [ch]
`(throw-err (<! ~ch)))
I am completely unsure about the readability of my solution though (throw-err looks like it should throw an error, but it doesn't. At least not every time).

How to get the shell function's output in slime?

In REPL, we can get its output normally:
(shell "head -3 ~/misc.lisp")
(asdf:make-build 'stumpwm :type :program :monolithic t
:move-here "."
:name-suffix ""
However, we get nil from (shell "head -3 ~/misc.lisp") in slime.
Sincerely!
I don't know which Lisp implementation you're using, but normally you should need a package to run shell command like:
trivial-shell
inferior-shell
clesh (build on top of trivial-shell)
use #'run-shell-command instead of shell:
(let ((str (ext:run-shell-command cmd :output :stream)))
(loop for line = (read-line str nil)
until (null line)
do (print line)))
it works now.

Resources