1

I am trying to write a small function where I extract two sub-strings from a cite-key, e.g. cite:rammstein2017paris.

(defun citekey-get-author-and-year ()
          "Get the _author_ and _YEAR_ from a cite:authorYEARtitle key."
          (interactive) ; allow this to be user-callable
          (let
              ((regexp ":\(.*\)\([0-9]*\)[a-z]") ; the regex to parse
               author
               year
               (citekey (buffer-substring (line-beginning-position) (line-end-position)))))
        
          (when (string-match 'regexp 'citekey)
            (setq author (match-string 1 string)
                  year (match-string 2 string)))
          )

The above code gives me a "Wrong type argument: stringp, regexp" error. I came up with it after reading the manual. If I do it without the 'regexp 'citekey line, I get the error "Symbols value as a variable is void: regexp".

Based on the error description, the function doesn't know what regexp and citekey are, but why?


I tried debugging it with debug-on-entry, as described here. Unfortunately I did not really see or understand where the error is.

My code is inspired by the string-match documentation, and it confuses me very much that it doesn't work.


Demos
#+BEGIN_SRC elisp
(let ((string "Today is <2018-11-07>."))
  (when (string-match "<\\([-0-9]+\\)>" string)
    (match-string 1 string)))
#+END_SRC

When searching online for the error code, there are a bunch of results, but as the error seems very generic I didn't find anything that solved my problem.


I believe that the mistake is really basic and obvious, it is just that my understanding of elisp is lacking, as this is the first function I write.

3
  • To many questions - this essentially amounts to Please fix my code. There's the quote of regexp (which you removed in your own answer), and the wrong regexp, and... Please submit only one, specific question per question. Thx.
    – Drew
    Feb 25 at 0:24
  • Interesting, so it is true what they say about stackoverflow and stackexchange. I am a new user, I read the on-boarding, I tag my question, I get a badge, and the first thing I get as feedback is that everything I did was wrong.
    – jsteinbach
    Feb 25 at 1:02
1

Here's the corrected incantation:

(defun my-citekey-get-author-and-year ()
  "Get the AUTHOR and YEAR from a cite:AUTHORYEARtitle key."
  (interactive) ; allow this to be user-callable
  (let ((regexp ":\\(.*\\)\\([0-9]*\\)[a-z]") ; the regex to parse
        (citekey (buffer-substring (line-beginning-position)
                                   (line-end-position)))
        author year)
    (when (string-match regexp citekey)
      (setq author (match-string 1 citekey)
            year (match-string 2 citekey)))))

Note the fixed parentheses around let's bindings, regexp backslash syntax, variable referencing, and second argument to match-string, which needs to be the same string passed to string-match.

In brief, the value of 'foo is the canonical symbol with the name foo, whereas the value of foo is the value stored in the variable whose name is the symbol foo.

For example, (setq foo 1) is actually shorthand for (set 'foo 1).

3
  • How do I have to understand the "canonical symbol"? I never head that term. Can I say that "$" is the canonical symbol for dollar?
    – jsteinbach
    Feb 24 at 23:01
  • @jsteinbach What I meant by "canonical" is "unique interned", i.e. writing 'foo creates a single unique symbol in the global obarray called foo. Similarly for the dollar symbol: (eq (intern "$") '$)
    – Basil
    Feb 24 at 23:37
  • For more on symbols, see (info "(elisp) Symbol Type") and (info "(elisp) Symbols").
    – Basil
    Feb 24 at 23:38
0

I think I solved it myself. Apparently I have to run my code inside the let(), not outside.

The following works (= does not throw an error). Note the brackets.

(defun citekey-get-author-and-year ()
  "Get the _author_ and _YEAR_ from a cite:authorYEARtitle key."
  (interactive) ; allow this to be user-callable
  (let
      ((regexp ":\(.*\)\([0-9]*\)[a-z]") ; the regex to parse
       author
       year
       (citekey (buffer-substring (line-beginning-position) (line-end-position))))
    ; body
    (message regexp)
    (message citekey)
    (when (string-match ":\(.*\)\([0-9]*\)[a-z]" citekey)
      (when (string-match regexp 'citekey)
        (setq author (match-string 1 string)
              year (match-string 2 string))))
    (message "---")
    (message author)
    (message year)
    ))

Now I only got to fix the regexp! :)


E2: This is what I came up with myself.

(defun citekey-get-author-and-year ()
  "Get the _author_ and _YEAR_ from a cite:authorYEARtitle key."
  (interactive) ; allow this to be user-callable
  (let
      (
       ;; (regexp ":\(.*\)\([0-9]*\)[a-z]") ; the regex to parse
       (regexp (rx ":"
                   (group (zero-or-more letter))
                   (group (one-or-more digit))
                   (one-or-more letter)
                   ))
       author
       year
       (citekey (buffer-substring (line-beginning-position) (line-end-position))))
                                        ; body
    (message regexp)
    (message citekey)
    (when (string-match regexp citekey)
      (setq author (match-string 1 citekey)
            year (match-string 2 citekey)))
    (message "---")
    (message (concat author " + " year))
    ))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.