2013-07-27 11 views
5

Sto tentando di mappare su tutte le voci dell'organizzazione in un file e raccogliere una parte dell'intestazione se è stata abbinata a qualche regex.'string-match' non funziona in 'org-map-entries'

Il problema è che stringa-partita restituisce sempre zero. Vedo che tutto il resto funziona correttamente mentre passo a Edebug.

Qui ho ridotto il problema, per quanto posso:

(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)) 

Le 3 linee in test.org:

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

stringa-partita funziona bene altrimenti:

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

Alcune cose ho cercato:
- Rimozione di proprietà di stringa befor e corrispondenza.
- Implementazione attorno a re-search-forward.
- Spostamento della corrispondenza regolare in una funzione separata.
- sostituito "org-map-entries" con "mapcar" e testato su un elenco, funziona correttamente.

sto usando GNU Emacs 24.3.1 (x86_64-unknown-linux-gnu, GTK + versione 3.4.2)

Qualche consiglio sarebbe molto apprezzato.

+0

Quando si passa attraverso di essa con edebug, fa 'heading' presentano il valore atteso? – Malabarba

+0

Sì, 'heading' presenta il valore previsto in edebug. – michaelJohn

risposta

3

Potrebbe essere semplicemente che case-fold-search in qualche modo viene impostata al nil mentre che il codice è in funzione (da qui la "A-Z" non corrisponde a caratteri minuscoli più)? In tal caso, la sostituzione di A-Z0-9 con [:alnum:] dovrebbe risolvere il problema.

+0

Sembra che "org-map-entries" chiami 'org-entry-properties' che imposta' case-fold-search' a 'nil' prima di chiamare' org-back-to-heading' e dà il controllo della funzione applicata . – michaelJohn

2

Suggerimento: utilizzare org-element! Almeno se è possibile utilizzare Org v8 +.

Ecco un esempio giocattolo che si può costruire. Copialo su un buffer Org e valuta i blocchi di codice.

Edit: altri esempi. Fondamentalmente, non posso riprodurre. Vedi l'ultima intestazione per la tua funzione test.

* >>> 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 | 
+0

Wow, vorrei aver trovato 'org-element' un anno fa! Questo funziona, tuttavia voglio ancora sapere perché 'org-map-entries' non è – michaelJohn

+1

Vedere l'esempio aggiornato. "org-map-entries" può anche essere usato, ma è meno potente. 'org-element' ha vissuto in' contrib' per un po ', ma ora fa parte del nucleo 'org-mode'. – Rasmus

0

ho ottenuto un risultato corretto fin dall'inizio. Emacs 24.3.4. Versione org versione 8.0.6. È necessario aggiornare la configurazione.