I'm trying to create a simple input loop in Clojure. The idea is to read in a line of text like so:
> look
You see nothing, as this game hasn't actually been written.
The method I'm using to attempt this is below:
(defn get-input []
(print "> ")
(string/trim-newline (read-line)))
However, the input loop instead looks like this:
look
> You see nothing, as this game hasn't actually been written.
How would one go about getting the angle quote to print before user input rather than after it?
This is a buffering issue. "> " is only a small amount of text, and doesn't contain a newline (and one isn't automatically added since you aren't using println), so it gets stuck in the outstream buffer. You just need to do a flush after printing.
When I need a print/flush combo like this in multiple places, I usually create a little helper function to neaten things up:
(defn print-fl [& messages]
(apply print messages) ; Pass the strings to print to be printed
(flush)) ; Then flush the buffer manually so small strings don't get stuck
(defn get-input []
(print-fl "> ")
(string/trim-newline (read-line)))
(get-input)
> look
"look"
Related
I have a following EDN file
:abc #request/builder/abc {
"def" #request/builder/def {
"someVector" ["sample1", "sample2"]
}
}
I have defined custom tag reader in Clojure, which internally calls java code
(defn custom-readers []
{
#request/builder/def defBuilder
#request/builder/abc abcBuilder
}
)
(defn defBuilder [params]
(.defBuilder (someJavaUtilityClass.) params)
)
(defn abcBuilder [params]
(.abcBuilder (someJavaUtilityClass.) params)
)
When I read EDN using edn/read-string, defBuilder executes first and its value gets passed to abcBuilder.
I want to reverse the order of execution without modifying EDN. I want to modify abcBuilder code such that if java call in abcBuilder returns some value then only execute defBuilder. How can I achieve this.
I tried by modifying code as below
(defn defBuilder [params]
'(.defBuilder (someJavaUtilityClass.) params)
)
(defn abcBuilder [params]
if((.abcBuilder (someJavaUtilityClass.) params)
(eval (get params "def"))
)
)
But this throws error like it "Unable to resolve someJavaUtilityClass and params". Is there a better way to solve this?
I'm afraid that's not possible. That isn't how EDN's tagged literals work. The tag handler is called after reading the form, which includes calling the tag handlers for any tagged literals in the form. In other words, the tag handlers are called inside-out.
If this weren't the case, then what a tag means will depend on where that tagged literal is situated, which is needlessly context dependent.
Check out: https://github.com/edn-format/edn#tagged-elements
Here's the relevant part:
Upon encountering a tag, the reader will first read the next element (which may itself be or comprise other tagged elements), then pass the result to the corresponding handler for further interpretation, and the result of the handler will be the data value yielded by the tag + tagged element, i.e. reading a tag and tagged element yields one value.
Also check out: https://clojure.org/reference/reader#tagged_literals
This is about the Clojure reader. And again, here is the relevant bit:
by invoking the Var #'my.project.foo/bar on the vector [1 2 3]. The data reader function is invoked on the form AFTER it has been read as a normal Clojure data structure by the reader.
Also, symbols can only contain one /, delimiting the namespace and the name. Check out: https://github.com/edn-format/edn#symbols
I'm new to Clojure and found there's a piece of code like following
user=> (def to-english (partial clojure.pprint/cl-format nil
"~#(~#[~R~]~^ ~A.~)"))
#'user/to-english
user=> (to-english 1234567890)
"One billion, two hundred thirty-four million, five hundred sixty-seven
thousand, eight hundred ninety"
at https://clojuredocs.org/clojure.core/partial#example-542692cdc026201cdc326ceb. I know what partial does and I checked clojure.pprint/cl-format doc but still don't understand how it translates an integer to English words. Guess secret is hidden behind "~#(~#[~R~]~^ ~A.~)" but I didn't find a clue to read it.
Any help will be appreciated!
The doc mentions it, but one good resource is A Few FORMAT Recipes from Seibel's Practical Common Lisp.
Also, check §22.3 Formatted Output from the HyperSpec.
In Common Lisp:
CL-USER> (format t "~R" 10)
ten
~#(...~^...) is case conversion, where the # prefix means to capitalize (upcase only the first word). It contains an escape upward operation ~^, which in this context marks the end of what is case-converted. It also exits the current context when there are no more argument available.
~#[...] is conditional format: the inner format is applied on a value only if it is non nil.
The final ~A means that the function should be able to accept one more argument and print it.
In fact, your example looks like the one in §22.3.9.2:
If ~^ appears within a ~[ or ~( construct, then all the commands up to
the ~^ are properly selected or case-converted, the ~[ or ~(
processing is terminated, and the outward search continues for a ~{ or
~< construct to be terminated. For example:
(setq tellstr "~#(~#[~R~]~^ ~A!~)")
=> "~#(~#[~R~]~^ ~A!~)"
(format nil tellstr 23) => "Twenty-three!"
(format nil tellstr nil "losers") => " Losers!"
(format nil tellstr 23 "losers") => "Twenty-three losers!"
I know there are a lot of questions out there with this headline, but I can't glean my answer from them, so here goes.
I'm an experienced programmer, but fairly new to Clojure. I'm trying to parse a RTF file by converting it to a HTML file then calling the html parser.
The converter I'm using (unrtf) always prints to stdout, so I need to capture the output and write the file myself.
(defn parse-rtf
"Use unrtf to parse a rtf file"
[#^java.io.InputStream istream charset]
(let [rtffile (File/createTempFile "parse" ".rtf" (File. "/vault/tmp/"))
htmlfile (File/createTempFile "parse" ".ohtml" (File. "/vault/tmp/"))
command (str "/usr/bin/unrtf "
(.getPath rtffile)
)
]
(try
(with-open [rtfout (FileOutputStream. rtffile)]
(IOUtils/copy istream rtfout))
(let [ proc (.exec (Runtime/getRuntime) command)
ostream (.getInputStream proc)
result (.waitFor proc)]
(if (> result 0)
(
(println "unrtf failed" command result)
; throwing an exception causes a parse failure to be logged
(throw (Exception. (str "RTF to HTML conversion failed")))
)
(
(with-open [htmlout (FileOutputStream. htmlfile)]
(IOUtils/copy ostream htmlout))
; since we now have html, run it through the html parser
(parse-html (FileInputStream. htmlfile) charset)
)
)
)
(finally
(.delete rtffile)
(.delete htmlfile)
)
)))
The exception points to the line with
(IOUtils/copy ostream htmlout))
which really confuses me, since I used that form earlier (just after the try:) and it seems to be OK there. I can't see the difference.
Thanks for any help you can give.
As others have correctly pointed out, you can't just add extra parentheses for code organization to group forms together. Parentheses in a Clojure file are tokens that delimit a list in the corresponding code; lists are evaluated as s-expressions - that is, the first form is evaluated and the result is invoked as a function (unless it names a special form such as if or let).
In this case you have the following:
(
(with-open [htmlout (FileOutputStream. htmlfile)]
(IOUtils/copy ostream htmlout))
; since we now have html, run it through the html parser
(parse-html (FileInputStream. htmlfile) charset)
)
The IOUtils/copy function has an integer return value (the number of bytes copied). This value is then returned when the surrounding with-open macro is evaluated. Since the with-open form is the first in a list, Clojure will then try to invoke the integer return value from IOUtils/copy as a function, resulting in the exception that you see.
To evaluate multiple forms for side-effects without invoking the result from the first one, wrap them in a do form; this is a special form that evaluates each expression and returns the result of the final expression, discarding the result from all others. Many core macros and special forms such as let, when, and with-open (among many others) accept multiple expressions and evaluate them in an implicit do.
I didnt try to run your code, just had a look at it, and after the if (> result 0) you have ((println ...)(throw ...)) without a do. Having an extra parens causes the returned value from the inner parens to be treated as a function and get executed.
try to include it, like this (do (println ...) (throw ...))
In practice I usually encounter below situation:
statement_line /*..some comments..*/
Sometimes I need to jump to just pass the end of the statement_line to: add some code, or delete the entire comment region.
Is there a keyboard shortcut to do it? (I know C-s ; Ret works for statement_line ending with a ";" but this is not all the case. e.g. if(...) /*...comments...*/)
Thanks in advance.
Try this code:
(defun end-of-statement ()
(interactive)
(beginning-of-line)
(if (comment-search-forward (line-end-position) t)
(re-search-backward "//\\|/\\*")
(end-of-line))
(skip-chars-backward " \t"))
I just wrote it, so it might require some tweaks, but it looks
fine at the moment.
Not a full answer to your question, but for the case where you want to remove the comment, you can use C-u M-; (aka comment-kill).
I have a command to bounce between the end of line and end of code. It works in most programming modes.
(defun end-of-line-code ()
(interactive "^")
(require 'newcomment)
(if comment-start-skip
(save-match-data
(let* ((bolpos (line-beginning-position)))
(end-of-line)
(if (comment-search-backward bolpos 'noerror)
(search-backward-regexp comment-start-skip bolpos 'noerror))
(skip-syntax-backward " " bolpos)))
(end-of-line)))
(defun end-of-line-or-code ()
"Move to EOL, or if already there, to EOL sans comments."
(interactive "^")
(if (eolp) ;; test me here
(end-of-line-code)
(end-of-line)))
(put 'end-of-line-or-code 'CUA 'move)
(defun jpk/prog-mode-hook ()
...
(local-set-key (kbd "C-e") 'end-of-line-or-code)
...
)
(add-hook 'prog-mode-hook 'jpk/prog-mode-hook)
I have a similar command that bounces between the beginning of line and beginning of text, which I can post if you're interested.
I am trying to print a sequence such that neither the whole sequence is printed on one line, nor is each element of the sequence printed on its own line. E.g.
[10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29]
I found pprint-newline in the documentation which indicates that allows me to determine how the newline gets printed. Unfortunately, I cannot find any examples on how it is to be used in conjunction with pprint, and the doc string doesn't to offer much insight:
-------------------------
clojure.pprint/pprint-newline
([kind])
Print a conditional newline to a pretty printing stream. kind specifies if the
newline is :linear, :miser, :fill, or :mandatory.
This function is intended for use when writing custom dispatch functions.
Output is sent to *out* which must be a pretty printing writer.
pprint specifies an optional second argument for the writer, which is by default set to *out*. However, I am not sure how to 'send' pprint-writer to *out* in this case, e.g. something like the example below doesn't appear to work
(clojure.pprint/pprint [1 2 3 4] (*out* (clojure.pprint/pprint-newline :miser)))
While Guillermo explained how to change the dispatch for pretty-printing in general, if all you want to do is printing one collection differently, that's possible, too.
For example, using cl-format (after (use '[clojure.pprint :as pp)):
(binding [pp/*print-pretty* true
pp/*print-miser-width* nil
pp/*print-right-margin* 10]
(pp/cl-format true "~<[~;~#{~a~^ ~:_~}~;]~:>~%" '[foo bar baz quux]))
Set *print-right-margin* as you wish.
You don't have to use format for this. The format directives can be translated to their respective pretty-printer functions, if you want. Explanation of the format string: ~< and ~:> establish a logical block. Inside the block, there are three sections separated by ~;. The first and last section are your prefix and suffix, while the elements are printed in the middle section, using ~#{ and ~}. For each element, the element is printed using ~a, followed by a space, if needed, and a conditional fill-style newline.
(In CL, the format string could be simplified to "~<[~;~#{~a~^ ~}~;]~:#>~%", but that doesn't seem to work in Clojure 1.5.)
As the help says, the function is intended for use for custom dispatch functions.
In order to change the behavior of the pprint for sequences you need to provide a new dispatch function for clojure.lang.ISeq.
The current dispatch function for sequences you can find in clojure/pprint/dispatch.clj
(use-method simple-dispatch clojure.lang.ISeq pprint-list)
...
(defn- pprint-simple-list [alis]
(pprint-logical-block :prefix "(" :suffix ")"
(print-length-loop [alis (seq alis)]
(when alis
(write-out (first alis))
(when (next alis)
(.write ^java.io.Writer *out* " ")
(pprint-newline :linear)
(recur (next alis)))))))
Since printing is dispatched according to data type overriding seems to be the way to go.
See the source code for ideas.