Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'string-match' does not work in 'org-map-entries'

I am attempting to map over all org entries in a file and collect a part of the heading if it is matched by some regex.

The problem is that string-match always returns nil. I can see that everything else is working correctly as I step through with edebug.

Here I have reduced the problem as far as I can:

(defun test ()
  (let ((found nil))
    (org-map-entries (lambda ()
               (let ((heading (org-get-heading t t)))
             (when (string-match "[ \t]*>>>[ \t]*\\([A-Z0-9_-]+\\)"
                         heading)
               (push (match-string 1 heading) found))))

             nil '("test.org"))
    found))

The 3 lines in test.org:

* >>> one
* two
* >>> three

string-match works fine otherwise:

(string-match "[ \t]*>>>[ \t]*\\([A-Z0-9_-]+\\)" ">>> one")
=> 0

Some things I have attempted:
- Removing string properties before matching.
- Implementing around re-search-forward instead.
- Moving the regex matching to a separate function.
- replaced 'org-map-entries' with 'mapcar' and tested it over a list, works fine.

I'm using GNU Emacs 24.3.1 (x86_64-unknown-linux-gnu, GTK+ Version 3.4.2)

Any tips would be much appreciated.

like image 263
michaelJohn Avatar asked Jul 27 '13 20:07

michaelJohn


2 Answers

Could it simply be that case-fold-search somehow gets set to nil while that code is running (hence the "A-Z" doesn't match lower case characters any more)? If so, replacing A-Z0-9 with [:alnum:] should fix it.

like image 64
Stefan Avatar answered Oct 03 '22 02:10

Stefan


Tip: Use org-element! At least if using Org v8+ is feasible.

Here's a toy example that you can build upon. Copy it to an Org buffer and evaluate the code blocks.

Edit: more examples. Basically, I can't reproduce. See the last heading for your test function.

* >>> one
#+begin_src emacs-lisp :file test2.org
  (save-excursion (find-file "test2.org")
                  (delete-region (point-min) (point-max))
                  (insert "* >>> one2\n* two2"))
#+end_src

#+RESULTS:
[[file:test2.org]]

A function
#+begin_src emacs-lisp
  (defun my/tagged-headings (&optional regexp file full-element)
    "Return headings matching regexp.  If simple is t return only the headline.  Else return the element.  Requires Org-Element (Org>8)"
    (require 'org-element)
    (save-excursion
      (when (and file (file-exists-p file))
        (find-file file))
      (let (found
            (regexp (if regexp regexp "^>>>")))
        (org-element-map
            (org-element-parse-buffer)
            'headline
          '(lambda (h)
             (when  (string-match "^>>>" (org-element-property :raw-value h))
               (push (if full-element h (org-element-property :raw-value h)) found))))
        found)))
#+end_src

#+begin_src emacs-lisp
(my/tagged-headings)
#+end_src

#+RESULTS:
| >>> three | >>> one |

#+begin_src emacs-lisp
(my/tagged-headings nil "test2.org")
#+end_src

#+RESULTS:
| >>> one2 |

* two

#+begin_src emacs-lisp
  (defun my/tagged-headings2 ()
    (let (found)
      (org-map-entries (lambda () 
                         (save-excursion
                           (when (search-forward-regexp "^*+[[:space:]]*>+" (point-at-eol) t)
                             (push (org-get-heading t t) found)
                             ))))
      found))
#+end_src


#+begin_src emacs-lisp 
(my/tagged-headings2)
#+end_src

#+RESULTS:
| >>> three | >>> one |


* >>> three 



#+begin_src emacs-lisp
  (defun test (&optional file)
    (save-excursion
      (when (and file (file-exists-p file)) (find-file file))
      (let ((found nil))
        (org-map-entries (lambda ()
                           (let ((heading (org-get-heading t t)))
                             (when (string-match "[ \t]*>>>[ \t]*\\([A-Z0-9_-]+\\)"
                                                 heading)
                               (push (match-string 1 heading) found)))))
        found)))
#+end_src

#+begin_src emacs-lisp
(test)
#+end_src

#+RESULTS:
| three | one |

#+begin_src emacs-lisp
(test "test2.org")
#+end_src

#+RESULTS:
| one2 |
like image 28
Rasmus Avatar answered Oct 03 '22 00:10

Rasmus