I need to generate a space-padded string with a variable string length. The not-so-clever solution that works involved nesting of format:
(format nil (format nil "~~~d,,a" 10) "asdf")
Now, I wanted to make it a bit more clever by using format's ~? for recursive processing. I would expect that something like this should do what I want:
(format nil "~#?" "~~~d,,a" 10 "asdf")
but what I get is just the formatting string, i.e. ~10,,a, not the padded asdf string. Perhaps I misunderstood the word 'recursive' here, but I would expect that having formed the inner format string, CL should proceed to actually use it. Am I missing something?
Variable arguments to format directives
FORMAT allows you to use v as an argument to a directive in the control string to pop arguments from the argument list.
CL-USER> (format nil "~va" 10 "asdf")
"asdf "
There may be multiple vs used.
CL-USER> (format nil "~v,,,va" 10 #\- "asdf")
"asdf------"
Recursive processing with ~?
The recursive processing directive is meant for embedding a different "call" to FORMAT inside a control string. For example, a function to prompt for a yes or no answer might be implemented with it.
(defun y-or-n-prompt (control-string &rest args)
(format t "~&~? [y/n]: " control-string args)
;;...
)
The caller can now format a prompt with this as they would with FORMAT without having to worry about the details of what the prompt should look like to the user (adding a new line at the beginning or the [y/n]: prompt at the end).
CL-USER> (y-or-n-prompt "foo ~d bar" 12)
foo 12 bar [y/n]:
NIL
The result of ~? will not be processed by FORMAT, so it cannot be used to build a control string. In general, building control strings at run time is a bad idea, because it's error prone (for example, you must escape any unwanted tildes in the string) and prevents the implementation from processing the control string at compile time.
Related
I would like to export the agenda view to separate file with a unique name based on the current date. Based on this example code:
(setq org-agenda-custom-commands
'(("X" agenda "" nil ("agenda.ps")))
)
The last argument is the file name so I thought I can put the output of the concat function, e.g.:
(setq org-agenda-custom-commands
'(("X" agenda "" nil (concat (format-time-string "%Y-%m-%d") "-agenda.html")))
)
Unfortunately, this approach fails since the interpreter takes the concat literally, and a string (expected data type) is not generated. I’m not very familiar with LISP, so any help is greatly appreciated.
First of all the last argument is not a filename but rather a list of names, so you must add some extra parentheses.
As you already noted, because of the quote the list is not evaluated, and it's fine since you don't want to evaluate it, except the last element (concat function). To do so you can use backquote:
(setq org-agenda-custom-commands
`(("X" agenda "" nil (,(concat (format-time-string "%Y-%m-%d") "-agenda.html"))))
)
As a side note, I'm not a specialist of the org-mode and I'm just answering the question you asked, but I have a feeling that it is possible to achieve your goal in a more simple way. Not sure how, but maybe you can dig in the documentation of org-mode and probably you'll find something interesting.
I'm trying to create an Org mode capture template that writes each entry to a time-based filename.
First, there is a helper function that works in the scratch buffer:
;; Example input: (capture-date-based-file "~/path/to/logs/" "log")
;; Expected output: "~/path/to/logs/2017-11-27-monday-log.org"
(defun capture-date-based-file (path entry-type)
"Create a date-based file name based on the given type."
(downcase (concat path (format-time-string "%Y-%m-%d-%A-") entry-type ".org")))
Then, it's used in the capture templates list:
(setq org-capture-templates
'(("l" "Log" entry (file+headline ,(capture-date-based-file "~/path/to/logs/" "log"))
"* %?\n%U\n" :clock-in t :clock-resume t) ))
I get an error: Symbol's function definition is void: \,
It's difficult to find an answer in Google, because of the comma character. I've looked over the docs, and I'm not sure what I'm doing wrong.
The comma suggests that you're wanting to evaluate the call to capture-date-based-file, but the surrounding form is quoted rather than backquoted, so that won't work.
i.e. these are two quite different things:
'(foo ,(bar) baz)
`(foo ,(bar) baz)
See C-hig (elisp)Backquote RET
In a backquoted form, the comma causes the form which follows to be evaluated immediately, and the result of that evaluation is then substituted into the backquoted form. In a quoted form, ,(bar) simply remains as a literal ,(bar).
The reason for the specific error you saw is that the lisp reader produces the following:
ELISP> (read ",(bar)")
(\, (bar))
Therefore any attempt to evaluate ,(bar) is actually calling the non-existent function \,
(One of the less-obvious errors you'll encounter, FWIW.)
In your scenario I presume that org pulls that particular form out of the template structure and evaluates it. M-x toggle-debug-on-error would most likely show you exactly where and when this happens.
I have a feeling the answer to my question is something to do with Clojure's lazy evaluation (which I am still fuzzy on...)
So I have a function:
(defn fix-str-old [string]
(let [words (->> string
(clojure.string/split-lines)
(map #(clojure.string/replace % #"\W" "")))]
(apply str (interleave words (repeat " ")))))
Basically it just takes a wacky sentence with non-alphanumeric chars, chars, return characters, line feeds etc in place of a space and turns it into a regular sentence. The reason for this if you're curious is that whenever I try to copy out of certain PDFs, it puts line feeds and other mysterious characters in between the words.
Here is an example:
(fix-str "A
block
of
SQL
statements
that
must
all
complete
successfully
before
returning
or
changing
anything ")
==> "A block of SQL statements that must all complete successfully before returning or changing anything"
It works fine in the REPL but when it is evaluated inside of a little swing gui you get this:
"AblockofSQLstatementsthatmustallcompletesuccessfullybeforereturningorchanginganything "
(note the space at the end of the string)
I was pretty sure that this was because of some gap in my understanding of how Clojure handles lazy seqs so I whipped up this function that just does regex operations.
(defn fix-str [string]
(-> string
(clojure.string/replace #"[ \t\n\r]+" " ")
(clojure.string/replace #"[^a-zA-Z0-9 ]" "")
(clojure.string/trimr)))
which isn't lazy and works fine in both the REPL and in the GUI.
Note: I also tried putting doall statements in various places in the original function that I though might make sense to make sure it forced evaluation of the lazy seqs but I couldn't get it to work either.
So my question isn't really if the first way is a good way to fix the strings, but rather why am I getting a different result in the REPL and in my GUI.
Laziness should not be your problem here, because (apply str ...) forces the output from map to be realized (and because there's no bindings here, which is usually your first clue that laziness is the culprit).
Looks to me like there's something funky going on with the line-endings coming from the GUI, and that split-lines is not splitting anything. That function splits on \n or \r\n - maybe somehow you're getting \r as line-endings from the GUI? You can verify this by adding this to the beginning of your fix-str function:
(doseq [c string] (println (int c)))
I'm trying to convert hexadecimal number to hexadecimal number presentation.
for example is below.
CL-USER> (foo 0D)
#x0D
Should i use macro function?
0D is a symbol (by default). Get its name with SYMBOL-NAME as a string. Use PARSE-INTEGER with :RADIX 16 to get the number.
If you don't have any reason for it, representing hex numbers as symbols is nothing I would do.
Are you saying that you want to format a number as a hexadecimal string? If so, you would want something like this: (format nil "~x" #x0D)
As phrased your question makes no sense. There is no such thing as a "hexadecimal number"; "hexadecimal" is the name of a number-presentation system. In your example, the input appears to be a symbol, as Rainer says, but not every such "hexadecimal" is a symbol. Presumably you want the output of (foo 10) to be #x10, and here the input is a number. So if the input is interpreted by the Lisp reader as a (base-10) number, then it should be converted to the number you would get if reread base 16.
Another point that Rainer overlooked is that if 0D is understood as a symbol, then (foo 0D) would cause an UNBOUND-VARIABLE error. You would have to write (foo '0D) to make 0D an input to foo.
On the output side, I don't think there is any native Lisp object that prints as "#x..." . If you want numbers to print in base 16, then you bind print-base to 16, but you won't see any sharpsign-x in front of it.
That suggests a somewhat different approach to your problem. We define a new datatype that does print starting with #x, and have foo construct such an object:
(defstruct (pseudo-hex (:print-object pseudo-hex-print))
thing)
(defun pseudo-hex-print (h srm)
(format srm "#x~a" (pseudo-hex-thing h)))
(defun foo (x)
(make-pseudo-hex :thing x))
Now we get the following:
cl-user(162): (foo 38)
#x38
cl-user(163): (foo '0D)
#x0D
I have a funny feeling this is not what Rafael was asking!
Let's say I need to check if hello.el file is read or not.
(defun hello ()
"Test"
(interactive)
(message "Hello, world"))
(format "hello")
(provide 'smcho)
I used the (format "hello") to show something, but it doesn't seem to work.
How can I know if an elisp module is read.
You should use message instead:
(message "hello")
format simply generates a formatted string, much like if you had
(+ 1 2)
which would result in adding two numbers. Nothing is done with the result, which is why you didn't see it. If you're familiar with C, it's much like having a line
sprintf(s, "hello"); /* this produces no output */
Note: If you have lots of these, you might need to customize the variable message-log-max.