0

It must be something obvious but I cannot find information on this issue.

When reftex-mode is enabled, I can type ~C-c )~ and for the following piece of code

\begin{equation}
2x=4
\label{Eq:A}
\end{equation}
 
\begin{equation}
a=b
\label{Eq:B}
\end{equation}

a pretty list of labelled blocks is generated (label + equation formula), so I can easily navigate and choose the right label to insert.

How can I achieve similar functionality when working in org-mode approach? I'd like to get all #+NAME tags in the document when labeling equations as follows:

 #+NAME: Eq:simpleEq
 \begin{equation}
 2x=4
 \end{equation}

 #+NAME: Eq:simplerEq
 \begin{equation}
 a=b
 \end{equation}

I don't expect the solution to be as comfortable as in ~reftex-mode~. Well, it'd be perfect if someone provided it, but simple list of all +NAME tags would do... ;)

1 Answers1

1

You can use org-element-map to apply a function that gets the #+NAME of each matched element. Here's a function that does that:

#+begin_src elisp
  (defun my/get-name (e)
    (org-element-property :name e))

  (defun my/latex-environment-names ()
    (org-element-map (org-element-parse-buffer) 'latex-environment #'my/get-name))

#+end_src

We parse the whole buffer, select the latex-environment elements and map over them the function my/get-name which gets the name of each such environment, accumulating them into a list and returning that.

You call it with M-: (my/latex-environment-names). But you probably want to write a wrapper command that calls it and deals with the list of names however it wants to. Here's a simple-minded example of that:

#+begin_src elisp
  (defun my/report-latex-environment-names ()
    (interactive)
    (message (format "%S" (my/latex-environment-names))))

  (define-key org-mode-map (kbd "C-c z") #'my/report-latex-environment-names)
#+end_src

Then C-c z will invoke the report function which will print the result of my/latex-environment-names in the echo area.


Here is the enhanced version as requested in a comment. Given the hint, I found out that the :value property holds the text of the environment, so we need to do some string manipulations to get only the part we want. string-split splits the string on newlines (\n) and returns the lines as a list; we then use nth to get the equation which is the second element of the list (remember, nth starts numbering the elements of the list from 0), and string-trim trims off leading and trailing whitespace. We call both the name and the value function at each matching element and we concatenate the results into a single string. Overall, it's very similar to the code block above:

#+begin_src elisp
  (defun my/get-name (e)
    (org-element-property :name e))

  (defun my/get-value (e)
    (string-trim (nth 1 (string-split (org-element-property :value e) "\n"))))

  (defun my/get-both (e)
    (concat (my/get-name e) " " (my/get-value e)))
  
  (defun my/latex-environment-names-values ()
    (org-element-map (org-element-parse-buffer) 'latex-environment #'my/get-both))

#+end_src
NickD
  • 27,023
  • 3
  • 23
  • 42
  • Thanks. I just needed to change keybinding in order to avoid `sequence starts with non-prefix key` error (this probably has something to do with [this](https://www.emacspeak.org/VCCS-archive/2016/msg00074.html)), but anyway, it works as required. Wouldn't it be too much if I asked you to extend the code (or at least, give a hint how to do this) to display the name of the equation next to the equation itself? (In the example above it would be `Eq:simpleEq 2x=4` RET `Eq:simplerEq` a=b) – martinoidar May 24 '23 at 09:18
  • Yes, the keybinding is arbitrary: `C-c z` is (usually) undefined so I tend to use it as an example - you should use your own keybinding (interesting link BTW - thanks! I take it you use `emacspeak` then?). As for the RFE, it should not be too hard except for one problem: in your case the body of the environment is the single equation, but in general there may be many lines (either of a single equation or many equations or other things). What do you want to do in that case? Is the first line of the body of the equation environment enough? If I find some time, I'll try to add the enhancement... – NickD May 24 '23 at 15:31
  • ... but no promises. You might try it yourself, mimicking the code above. Go to the beginning of the equation environment (the backslash of `\begin`) and type `M-: (org-element-at-point)`. The value of that is the parse tree of the element: see if you can figure out how to get the text using `org-element-property` and then manipulate the text (it's just a string so you can use the elisp string functions or perhaps the enhanced ones in `s.el` - available from MELPA) until you get just the part you want. – NickD May 24 '23 at 15:34