I'm using this method of creating a column:
http://orgmode.org/worg/org-tutorials/org-spreadsheet-lisp-formulas.html
I have a spreadsheet with 9 columns and column 8 contains filenames which have dollar signs in them, such as:
product_name $500.00.jpg
So I want column 9 to state whether or not the file actually exists, so my org TBLFM is as follows:
#+TBLFM: $9='(file-exists-p (concat "/import/" $8))
So the issue is, whether or not I use the ;L flag at the end of the TBLFM, when applying the formula I immediately get "Invalid Field Specifier: "$500"" because there is no column numbered 500.
Any thoughts as to how I can get this working? I've tried $8 in quotes and not in quotes, with and without the literal flag, and I've tried escaping the dollar sign in the actual columns all with no luck.
Edit: It's important to note that changing my column values to something like: product_name $\ 500.00.jpg does in fact work, however the file-exists-p value returned is obviously incorrect.
Edit: An example org-mode table triggering the error:
| foo | bar | /some/file with $500 in it.jpg | | baz |
| | | | | |
#+TBLFM: $4='(or (file-exists-p $3) "f")
This is the bit of Org code, which handles this case of the formula:
;; Insert the references to fields in same row
(while (string-match "\\$\\(\\([-+]\\)?[0-9]+\\)" form)
(setq n (+ (string-to-number (match-string 1 form))
(if (match-end 2) n0 0))
x (nth (1- (if (= n 0) n0 (max n 1))) fields))
(unless x (error "Invalid field specifier \"%s\""
(match-string 0 form)))
(setq form (replace-match
(save-match-data
(org-table-make-reference x nil numbers lispp))
t t form)))
As you see, there's no way for you to sidestep this bit, however, you could've patched the org-table-eval-formula near that place to allow you some kind of escape sequence to insert the literal sigil, I could get it this far:
;; Insert the references to fields in same row
(while (string-match "\\(^\\|[^\\$]\\)\\$\\(\\([-+]\\)?[0-9]+\\)" form)
(setq n (+ (string-to-number (match-string 2 form))
(if (match-end 3) n0 0))
x (nth (1- (if (= n 0) n0 (max n 1))) fields))
(unless x (error "Invalid field specifier \"%s\""
(match-string 0 form)))
(setq form (replace-match
(save-match-data
(org-table-make-reference x nil numbers lispp))
t t form)))
This will skip $$, unfortunately, this function calls itself recursively until all $ are replaced (I didn't know that). What you could do later: in eLisp code replace double sigils with singles... This worked in my case:
| foo | bar | /some/file with $$500 in it.jpg | f | /some/file with $500 in it.jpg |
| | | | t | |
#+TBLFM: $4='(or (file-exists-p $3) "f")::$5='(format "%s" (replace-regexp-in-string "\\$\\$" "$" $3))
Try escaping the $8 with a dollar char, that is as $$8.
Related
I am trying to write a LaTeX export filter that should replace all table rows with cells having entries such as <3cid4> by \cmidrule{lr}{3-4}
The idea is to have a table row of this kind
| <2cid3> | <4cid5> | <6cid7> | | | | |
Which should be exported to
\cmidrule(lr){2-3} \cmidrule(lr){4-5} \cmidrule(lr){6-7}
This is as far as I have gone.
(defun org-export-cmidrule-filter-latex (row backend info)
(while (string-match "\\(<\\([0-9]+\\)cid\\([0-9]+\\)?>[[:blank:]]*\\([^&]+\\)\\)" row)
(let ((start (string-to-number (match-string 2 row)))
(end (or (match-string 3 row) "l")))
(setq row (replace-match (format "\\\\cmidrule(lr){%s-%s}" start end) nil nil row 1))
(while (string-match "& \\| \\\\\\\\" row 0)
(setq row (replace-match "" nil nil row))
(decf start))))
row)
(add-to-list 'org-export-filter-table-row-functions
'org-export-cmidrule-filter-latex)
The above filter works if I have only one or two <[0-9]cid[0-9]> strings in a row. It does not pick up the third <[0-9]cid[0-9]> string.
The problem seems to be in this part of the code:
(while (string-match "& \\| \\\\\\\\" row 0)
(setq row (replace-match "" nil nil row))
(decf start))
If I comment it out, I get three \cmidrule latex commands, but with &s and \\
Somehow, the above lines replace more than just &s and \\.
Would much appreciate if anyone could help improve this filter.
Is there a way to configure org-mode spreadsheets to show thousand separators? I would like 1000 to be shown as 1,000.
Here is a solution. First define the function group-number:
(defun group-number (num &optional size char)
"Format NUM as string grouped to SIZE with CHAR."
;; Based on code for `math-group-float' in calc-ext.el
(let* ((size (or size 3))
(char (or char ","))
(str (if (stringp num)
num
(number-to-string num)))
;; omitting any trailing non-digit chars
;; NOTE: Calc supports BASE up to 36 (26 letters and 10 digits ;)
(pt (or (string-match "[^0-9a-zA-Z]" str) (length str))))
(while (> pt size)
(setq str (concat (substring str 0 (- pt size))
char
(substring str (- pt size)))
pt (- pt size)))
str))
from: Emacs Cookbook - put commas in numbers
Next, use it in your formula:
| | | |
|-----------+-------+-------------|
| 2000 | 3100 | 5,100 |
| 11 | 22 | 33 |
| 111221212 | 29996 | 111,251,208 |
| | | 0 |
#+TBLFM: $3='(group-number (+ $1 $2));N
Here we are using the group-number function to format the result of an emacs lisp form - rather than using the calc formula syntax.
I have this:
(format *standard-output* "~v#a ~a ~%" (* 5 indent) "End of Parent" (* 5 indent))
The curious issue is that (* 5 indent) is added as a debug item, and it is correct in the printout. However, the text is not indented when called inside my function, even though it prints out the correct indent value. If I just perform this line at the REPL, it prints out correctly, with indentation. My entire function is this:
(defun print-object-and-children-data (object indent)
"Recursively prints a chart object and its children,
with each child level indented further."
(let ((children (get-chart-children object)))
;; This indents correctly.
(format *standard-output* "~v#a Level: ~a~%"
(* 5 indent) object indent)
(mapc (lambda (x)
(when x (print-object-and-children-data x (+ 1 indent))))
children)
;; This does not.
(format *standard-output* "~v#a ~a ~%"
(* 5 indent) "End of Parent" (* 5 indent))))
All text content is correct. Also, whether that final format is part of the let makes no difference (it doesn't need anything from children). Something in this function is somehow affecting the indentation of the format call, but since the format prints out the correct indent value, what could be the cause of no indentation?
The v in ~v#A does not specify indentation. It specifies field width. Try this:
(dolist (i '(5 10 15))
(dolist (x '(1 123 12345))
(format t ">~v#A< (i=~D)~%" i x i)))
Note how the output is not aligned to the left.
Here's one possible way to have indented output:
(dolist (i '(5 10 15))
(dolist (x '(1 123 12345))
(format t ">~vA~A< (i=~D)~%" i " " x i)))
(Fixing the bug here is left as an exercise.)
In order to get indented output, you could also use format's tabulate (~t) directive:
(dolist (i '(0 5 10 15 20))
(format t "~&~vt~a~%" i i))
The #modifier may be used if you want relative tabulation instead of absolute tabulation.
Is there a simple way to align on the decimal dot a column of floats? In other words, I would like an output like the one of (vertical bars '|' are there only for clarity purpose)
(format t "~{|~16,5f|~%~}" '(798573.467 434.543543 2.435 34443.5))
which is
| 798573.44000|
| 434.54355|
| 2.43500|
| 34443.50000|
but with trailing spaces instead of zeros, as follows:
| 798573.44 |
| 434.54355|
| 2.435 |
| 34443.5 |
I do not think that this can easily be done with format's inbuilt control characters, but you could pass your own function to it:
(defun my-f (stream arg colon at &rest args)
(declare (ignore colon at))
(destructuring-bind (width digits &optional (pad #\Space)) args
(let* ((string (format nil "~v,vf" width digits arg))
(non-zero (position #\0 string :test #'char/= :from-end t))
(dot (position #\. string :test #'char= :from-end t))
(zeroes (- (length string) non-zero (if (= non-zero dot) 2 1)))
(string (nsubstitute pad #\0 string :from-end t :count zeroes)))
(write-string string stream))))
You can use it like this:
CL-USER> (format t "~{|~16,5/my-f/|~%~}" '(798573.467 434.543543 2.435 34443.5 10))
| 798573.44 |
| 434.54355|
| 2.435 |
| 34443.5 |
| 10.0 |
NIL
The padding character defaults to #\Space, and may be given as a third argument like this: "~16,5,' /my-f/".
An alternative implementation using loop:
(defun my-f (stream arg colon at &rest args)
(declare (ignore colon at))
(loop with string = (format nil "~v,vf" (car args) (cadr args) arg)
and seen-non-zero = nil
for i from (1- (length string)) downto 0
as char = (char string i)
if (char/= char #\0) do (setq seen-non-zero t)
collect (if (and (not seen-non-zero)
(char= char #\0)
(not (char= #\. (char string (1- i)))))
(or (caddr args) #\Space)
char) into chars
finally (write-string (nreverse (coerce chars 'string)) stream)))
(Disclaimer: Maybe I overlooked something easier in the documentation of format.)
It seems one is not supposed to quote KEYMAP when using define-key.
(define-key org-remember-mode-map "\C-c\C-r" 'org-remember-kill)
I'm confused because I think that all arguments of a function that is not quoted are evaluated, and according to the help, define-key is a function, not a macro. I don't see why the value of KEYMAP can be modified after a call of define-key.
(defun increment-value (a)
(setq a (+ 1 a)))
(setq my-num 10)
(increment-value my-num)
my-num ; ===> 10
Update: The answers explain everything, but for those still confused, let me clear up with more examples.
My increment-value example above is equivalent to this:
(let ((n 0))
(print n) ; prints 0
(let ((a n))
(setq a (+ 1 a))
(print a) ; prints 1
)
(print n) ; prints 0
)
What's going on above is, I think, similar to what's going on in this some-map example:
(let ((some-map '(1 2)))
(print some-map) ; prints (1 2)
(let ((a some-map))
(setq a (list 4 (second a)))
(print a) ; prints (4 2)
)
(print some-map) ; prints (1 2)
)
What's going on in define-key is similar to this second some-map example:
(let ((some-map '(1 2)))
(print some-map) ; prints (1 2)
(let ((a some-map))
(setcar a 4)
(print a) ; prints (4 2)
)
(print some-map) ; prints (4 2)
)
Now read the answers again with these three examples in mind and you will get it. Read also http://www.emacswiki.org/emacs/ListModification
You aren't actually changing what 'org-remember-map is (a pointer to a particular list structure), you are modifying the actual structure. Read this info page for details on modifying lists.
Specificially, if you take a look at the documentation for 'make-keymap:
(make-keymap &optional string)
Construct and return a new keymap, of
the form (keymap CHARTABLE . ALIST).
CHARTABLE is a char-table that holds
the bindings for all characters
without modifiers. All entries in it
are initially nil, meaning "command
undefined". ALIST is an assoc-list
which holds bindings for function
keys, mouse events, and any other
things that appear in the input
stream. Initially, ALIST is nil.
You'll see that keymap is a list with three elements. Let me draw that for you (yay M-x artist-mode):
org-remember-map
|
|
v
+----+----+ +----+----+
| | | --+--->+ / | \ |
+-+--+----+ +-/--+--\-+
| | |
v v v
keymap CHARTABLE ALIST
So, the value of the 'org-remember-map is something like the above structure, and when you define a key, what you are doing is changing what is pointed to in the ALIST blob part of the structure.
you're confusing value and name-value mapping.
in your increment-value function, you're not changing a's value as much as changing the mapping of the name a to a new value.
Fundamentally, there is no way to change the value of 10. 10 is 10!
But in the first case, you can either modify the mapping of the name org-remember-mode-map to a fully different map (set a new value), or you can alter the map pointed by that name (its current value). This is what define-key does.
Illustration:
(setq a '(1 2)) -> (1 2)
(setcar a 4) -> 4
a -> (4 2)
Everything you write is completely correct. The thing you are missing is that lists (keymaps are represented as lists) are not values themselves, but containers of values. Thus, you can pass a list to a function and have that function change the values of the list, but the list you have is still the same list.
All the details are in the Cons Cell Type section of the elisp manual.