EDIT: gave more context for my first approach.
My goal is to search my notes for strings of the form "4/1/2014" to org-mode timestamps "<2014-04-01 Wed>" (that particular day-of-week may be incorrect). I also want querying to be on so I do not accidentally do things like replacing part of a URL this way.
Assuming I already wrote a Day-of-the-week function (complaints welcome, though not part of the main question):
(defun dow (year month day)
(interactive)
(let ((encoded-time (encode-time 1 1 10 day month year)))
(nth (nth 6 (decode-time encoded-time))
'("Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"))))
I seem to be unable to do the rest. Here are my attempts and when they fall short:
- First, I tried to use
query-replace-regexp
:
(defun date-replace ()
(interactive)
(goto-char 1)
(query-replace-regexp "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]\\{4\\}\\)"
"<\\3-\\1-\\2 \\,(dow (string-to-number \\3) (string-to-number \\1) (string-to-number \\2))>"))
I get an "invalid use of '\' in replacement text" error and do not know what to do with that even after googling; it seems the most likely cause is escaping something in the replacement string that's NOT '\', but I do none of that.
By the way, doing
M-x query-replace-regexp RET \([0-9]+\)/\([0-9]+\)/\([0-9]\{4\}\) RET <\3-\1-\2 \,(dow (string-to-number \3) (string-to-number \1) (string-to-number \2))> RET
works, which is why I thought all I had to do was to escape the backslashes.
(another problem with this approach is it does not 0-pad 1-digit numbers in a way that seems clean to me, even if everything else were to work)
- Then, I tried to use
search-forward-regexp
. Here's a clunky solution that works (replacing the relevant portion of above code):
(while (search-forward-regexp "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]\\{4\\}\\)" nil t)
(let* ((ynum (string-to-number (match-string 3)))
(mnum (string-to-number (match-string 1)))
(dnum (string-to-number (match-string 2)))
(dowstr (dow ynum mnum dnum)))
(replace-match (format "<%04d-%02d-%02d %s>" ynum mnum dnum dowstr) t nil)))
The only problem here is that it does not query, and there does not seem to be flags that allow me to do that.
- My final attempt is looking up
query-replace
and the manual suggesting usingperform-replace
. So here I have:
(perform-replace "\\([0-9]+\\)/\\([0-9]+\\)/\\([0-9]\\{4\\}\\)"
((lambda (data numreps)
(format "<%04d-%02d-%02d %s>" (nth 1 data) (nth 2 data) (nth 3 data)
(dow (nth 1 data) (nth 2 data) (nth 3 data))))
.
((string-to-number (match-string 3))
(string-to-number (match-string 1))
(string-to-number (match-string 2))))
t t t)
and I get "Wrong type argument: stringp, nil" that I cannot decipher.
While my immediate goal is to find out which type of solution is the correct way to proceed and to make it work, I am overall more interested in why these bugs occur and how to get better at debugging, as I am new to learning elisp. Thanks!