emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* accessing properties in org-element-parse-buffer tree
@ 2014-08-30 18:03 Eike
  2014-08-30 19:07 ` Eike
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Eike @ 2014-08-30 18:03 UTC (permalink / raw)
  To: org-mode


Hello list,

I want to ask for help regarding elisp and org-elements. I like to
access the properties of all my headlines and I created the following
function (tree is the parsed tree) that collects them into an a-list:

#+begin_src emacs-lisp
  (defun collect-props (tree)
    (car (org-element-map tree 'headline
           (lambda (hl)
             (when (eq 2 (org-element-property :level hl)) ; want only level-2 properties
               (org-element-map hl 'node-property
                 (lambda (np)
                   (cons (org-element-property :key np)
                         (org-element-property :value np)))))))))
#+end_src

I'm not very confident about this, is this ok? Is there a better way?
For example, the first car looks strange, and I don't know how to get
rid of it.

Thanks you very much in advance!!!
Kind regards
Eike

--
gpg: AD7AC35E
finger print: 137F BB0B 1639 D25F DC5D  E59C B412 C5F5 AD7A C35E

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: accessing properties in org-element-parse-buffer tree
  2014-08-30 18:03 accessing properties in org-element-parse-buffer tree Eike
@ 2014-08-30 19:07 ` Eike
  2014-08-30 19:41 ` Thorsten Jolitz
  2014-08-31  2:08 ` Eric Abrahamsen
  2 siblings, 0 replies; 7+ messages in thread
From: Eike @ 2014-08-30 19:07 UTC (permalink / raw)
  To: org-mode


Hello again

it seems that I messed up my testing variables… I always had just one
headline and thus the list of lists had always one element that I then
extracted with `car'. So `car' must be removed:

#+begin_src emacs-lisp
  (defun collect-props (tree)
    (org-element-map tree 'headline
      (lambda (hl)
        (when (eq 2 (org-element-property :level hl)) ; want only level-2 properties
          (org-element-map hl 'node-property
            (lambda (np)
              (cons (org-element-property :key np)
                    (org-element-property :value np))))))))
#+end_src

I'd still be curious if there are other/better ways to do that; or is
this idiomatic usage of provided org functions?

Thanks again and kind regards
Eike

Eike writes:

> Hello list,
>
> I want to ask for help regarding elisp and org-elements. I like to
> access the properties of all my headlines and I created the following
> function (tree is the parsed tree) that collects them into an a-list:
>
> #+begin_src emacs-lisp
>   (defun collect-props (tree)
>     (car (org-element-map tree 'headline
>            (lambda (hl)
>              (when (eq 2 (org-element-property :level hl)) ; want only level-2 properties
>                (org-element-map hl 'node-property
>                  (lambda (np)
>                    (cons (org-element-property :key np)
>                          (org-element-property :value np)))))))))
> #+end_src
>
> I'm not very confident about this, is this ok? Is there a better way?
> For example, the first car looks strange, and I don't know how to get
> rid of it.
>
> Thanks you very much in advance!!!
> Kind regards
> Eike

--
gpg: AD7AC35E
finger print: 137F BB0B 1639 D25F DC5D  E59C B412 C5F5 AD7A C35E

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: accessing properties in org-element-parse-buffer tree
  2014-08-30 18:03 accessing properties in org-element-parse-buffer tree Eike
  2014-08-30 19:07 ` Eike
@ 2014-08-30 19:41 ` Thorsten Jolitz
  2014-08-30 20:20   ` Eike
  2014-08-31  2:08 ` Eric Abrahamsen
  2 siblings, 1 reply; 7+ messages in thread
From: Thorsten Jolitz @ 2014-08-30 19:41 UTC (permalink / raw)
  To: emacs-orgmode

Eike <eike@eknet.org> writes:

Hello,

> I want to ask for help regarding elisp and org-elements. I like to
> access the properties of all my headlines and I created the following
> function (tree is the parsed tree) that collects them into an a-list:
>
> #+begin_src emacs-lisp
>   (defun collect-props (tree)
>     (car (org-element-map tree 'headline
>            (lambda (hl)
>              (when (eq 2 (org-element-property :level hl)) ; want only level-2 properties
>                (org-element-map hl 'node-property
>                  (lambda (np)
>                    (cons (org-element-property :key np)
>                          (org-element-property :value np)))))))))
> #+end_src
>
> I'm not very confident about this, is this ok? Is there a better way?
> For example, the first car looks strange, and I don't know how to get
> rid of it.

* Answer
  :PROPERTIES:
  :CUSTOM_ID: abc123
  :foo:      bar
  :END:

There are several options, here a few examples, some using my new
function 'org-dp-filter-node-props' from org-dp-lib.el which is very
good at filtering out only those node-properties you are really
interested in. 'org-entry-properties' does some filtering too, but its
less generic.

#+NAME: ex1
#+BEGIN_SRC emacs-lisp :results raw
(org-map-entries
(lambda () (org-entry-properties nil nil "foo")))
#+END_SRC

#+results:
(((CATEGORY . 989)) ((CUSTOM_ID . abc123) (foo . bar) (CATEGORY . 989)))

#+NAME: ex2
#+BEGIN_SRC emacs-lisp :results raw
(require 'org-dp-lib)
(org-map-entries
  (lambda () (org-dp-filter-node-props 'org t t)))
#+END_SRC

#+results:
(nil ((foo . bar)))

#+NAME: ex3
#+BEGIN_SRC emacs-lisp :results raw
  (org-element-map (org-element-parse-buffer 'headline) 'headline
    (lambda (hl)
      (when (eq 1 (org-element-property :level hl)) ; want only level-2 properties
      (org-element-property :FOO hl))))
#+END_SRC

#+results: ex3
(bar)

#+NAME: ex4
#+BEGIN_SRC emacs-lisp :results raw
  (let (props)
    (save-excursion
      (goto-char (point-min))
      (while (re-search-forward "^\\*+ " nil t)
        (save-excursion
          (beginning-of-line)
          (setq props
                (cons
                 (org-dp-filter-node-props
                  '("FOO" "CUSTOM_ID") nil t)
                 props))))
      (delq nil props)))
#+END_SRC

#+results: ex4
(((foo . bar) (CUSTOM_ID . abc123)))


PS 1

Strange behaviour in src-block ex1. 

Neither the example given nor

(org-entry-properties nil "foo")
(org-entry-properties nil "foo" "foo")

return what I would expect. 

PS 2

Without the :results header-arg I get the following error when running
src-block ex2:

Debugger entered--Lisp error: (args-out-of-range 0 1)
  orgtbl-to-orgtbl((nil (("foo" . "bar"))) (:fmt (lambda (cell) (format "%s" cell))))
  org-babel-insert-result((nil (("foo" . "bar"))) ("replace") ("emacs-lisp" "(require 'org-dp-lib)\n(org-map-entries (lambda () (org-dp-filter-node-props 'org t t)))" ((:comments . "") (:shebang . "") (:cache . "no") (:padline . "") (:noweb . "no") (:tangle . "no") (:exports . "code") (:results . "replace") (:session . "none") (:hlines . "no") (:result-type . value) (:result-params "replace") (:rowname-names) (:colname-names)) "" nil 0 #<marker at 1263 in *outorg-edit-buffer*>) nil 0 "emacs-lisp")
  org-babel-execute-src-block(nil)
  org-babel-execute-src-block-maybe()
  org-babel-execute-maybe()
  org-babel-execute-safely-maybe()
  run-hook-with-args-until-success(org-babel-execute-safely-maybe)
  org-ctrl-c-ctrl-c(nil)
  call-interactively(org-ctrl-c-ctrl-c nil nil)


-- 
cheers,
Thorsten

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: accessing properties in org-element-parse-buffer tree
  2014-08-30 19:41 ` Thorsten Jolitz
@ 2014-08-30 20:20   ` Eike
  2014-08-30 22:10     ` Thorsten Jolitz
  0 siblings, 1 reply; 7+ messages in thread
From: Eike @ 2014-08-30 20:20 UTC (permalink / raw)
  To: emacs-orgmode


Thanks a lot for the examples, they are very helpful! I first thought to
parse the org buffer and then work with the resulting tree. But your
examples now makes me think to work directly on the buffer. Well, I will
play with a few different ways now…

Regards
Eike


Thorsten Jolitz writes:

> Eike <eike@eknet.org> writes:
>
> Hello,
>
>> I want to ask for help regarding elisp and org-elements. I like to
>> access the properties of all my headlines and I created the following
>> function (tree is the parsed tree) that collects them into an a-list:
>>
>> #+begin_src emacs-lisp
>>   (defun collect-props (tree)
>>     (car (org-element-map tree 'headline
>>            (lambda (hl)
>>              (when (eq 2 (org-element-property :level hl)) ; want only level-2 properties
>>                (org-element-map hl 'node-property
>>                  (lambda (np)
>>                    (cons (org-element-property :key np)
>>                          (org-element-property :value np)))))))))
>> #+end_src
>>
>> I'm not very confident about this, is this ok? Is there a better way?
>> For example, the first car looks strange, and I don't know how to get
>> rid of it.
>
> * Answer
>   :PROPERTIES:
>   :CUSTOM_ID: abc123
>   :foo:      bar
>   :END:
>
> There are several options, here a few examples, some using my new
> function 'org-dp-filter-node-props' from org-dp-lib.el which is very
> good at filtering out only those node-properties you are really
> interested in. 'org-entry-properties' does some filtering too, but its
> less generic.
>
> #+NAME: ex1
> #+BEGIN_SRC emacs-lisp :results raw
> (org-map-entries
> (lambda () (org-entry-properties nil nil "foo")))
> #+END_SRC
>
> #+results:
> (((CATEGORY . 989)) ((CUSTOM_ID . abc123) (foo . bar) (CATEGORY . 989)))
>
> #+NAME: ex2
> #+BEGIN_SRC emacs-lisp :results raw
> (require 'org-dp-lib)
> (org-map-entries
>   (lambda () (org-dp-filter-node-props 'org t t)))
> #+END_SRC
>
> #+results:
> (nil ((foo . bar)))
>
> #+NAME: ex3
> #+BEGIN_SRC emacs-lisp :results raw
>   (org-element-map (org-element-parse-buffer 'headline) 'headline
>     (lambda (hl)
>       (when (eq 1 (org-element-property :level hl)) ; want only level-2 properties
>       (org-element-property :FOO hl))))
> #+END_SRC
>
> #+results: ex3
> (bar)
>
> #+NAME: ex4
> #+BEGIN_SRC emacs-lisp :results raw
>   (let (props)
>     (save-excursion
>       (goto-char (point-min))
>       (while (re-search-forward "^\\*+ " nil t)
>         (save-excursion
>           (beginning-of-line)
>           (setq props
>                 (cons
>                  (org-dp-filter-node-props
>                   '("FOO" "CUSTOM_ID") nil t)
>                  props))))
>       (delq nil props)))
> #+END_SRC
>
> #+results: ex4
> (((foo . bar) (CUSTOM_ID . abc123)))
>
>
> PS 1
>
> Strange behaviour in src-block ex1.
>
> Neither the example given nor
>
> (org-entry-properties nil "foo")
> (org-entry-properties nil "foo" "foo")
>
> return what I would expect.
>
> PS 2
>
> Without the :results header-arg I get the following error when running
> src-block ex2:
>
> Debugger entered--Lisp error: (args-out-of-range 0 1)
>   orgtbl-to-orgtbl((nil (("foo" . "bar"))) (:fmt (lambda (cell) (format "%s" cell))))
>   org-babel-insert-result((nil (("foo" . "bar"))) ("replace") ("emacs-lisp" "(require 'org-dp-lib)\n(org-map-entries (lambda () (org-dp-filter-node-props 'org t t)))" ((:comments . "") (:shebang . "") (:cache . "no") (:padline . "") (:noweb . "no") (:tangle . "no") (:exports . "code") (:results . "replace") (:session . "none") (:hlines . "no") (:result-type . value) (:result-params "replace") (:rowname-names) (:colname-names)) "" nil 0 #<marker at 1263 in *outorg-edit-buffer*>) nil 0 "emacs-lisp")
>   org-babel-execute-src-block(nil)
>   org-babel-execute-src-block-maybe()
>   org-babel-execute-maybe()
>   org-babel-execute-safely-maybe()
>   run-hook-with-args-until-success(org-babel-execute-safely-maybe)
>   org-ctrl-c-ctrl-c(nil)
>   call-interactively(org-ctrl-c-ctrl-c nil nil)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: accessing properties in org-element-parse-buffer tree
  2014-08-30 20:20   ` Eike
@ 2014-08-30 22:10     ` Thorsten Jolitz
  0 siblings, 0 replies; 7+ messages in thread
From: Thorsten Jolitz @ 2014-08-30 22:10 UTC (permalink / raw)
  To: emacs-orgmode

Eike <eike@eknet.org> writes:

> Thanks a lot for the examples, they are very helpful! I first thought to
> parse the org buffer and then work with the resulting tree. 
 
Thats the obvious thing to do in this case, and you can do everything
you want this way, but there are some alternatives too.

> But your examples now makes me think to work directly on the
> buffer. Well, I will play with a few different ways now…

I wrote 'org-dp-filter-node-props' based on 'org-dp-contents', so only
the property-drawer of the current entry is parsed and its content (the
node-properties) filtered. This is meant mostly for local usage (in
contrast to the global parse-tree), but can be used as function argument
for org-map-entries too. 

The big advantage is that it becomes really easy to filter out all the
system properties, or all properties that do not belong to a specific
application. I use it quite often now because I like the database
functionality of Org properties.

-- 
cheers,
Thorsten

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: accessing properties in org-element-parse-buffer tree
  2014-08-30 18:03 accessing properties in org-element-parse-buffer tree Eike
  2014-08-30 19:07 ` Eike
  2014-08-30 19:41 ` Thorsten Jolitz
@ 2014-08-31  2:08 ` Eric Abrahamsen
  2014-08-31  9:12   ` Eike
  2 siblings, 1 reply; 7+ messages in thread
From: Eric Abrahamsen @ 2014-08-31  2:08 UTC (permalink / raw)
  To: emacs-orgmode

Eike <eike@eknet.org> writes:

> Hello list,
>
> I want to ask for help regarding elisp and org-elements. I like to
> access the properties of all my headlines and I created the following
> function (tree is the parsed tree) that collects them into an a-list:

You could also take a look at org-collector, in contrib. It might give
you some ideas, or even solve your problem directly.

> #+begin_src emacs-lisp
>   (defun collect-props (tree)
>     (car (org-element-map tree 'headline
>            (lambda (hl)
>              (when (eq 2 (org-element-property :level hl)) ; want only level-2 properties
>                (org-element-map hl 'node-property
>                  (lambda (np)
>                    (cons (org-element-property :key np)
>                          (org-element-property :value np)))))))))
> #+end_src
>
> I'm not very confident about this, is this ok? Is there a better way?
> For example, the first car looks strange, and I don't know how to get
> rid of it.
>
> Thanks you very much in advance!!!
> Kind regards
> Eike
>
> --
> gpg: AD7AC35E
> finger print: 137F BB0B 1639 D25F DC5D  E59C B412 C5F5 AD7A C35E

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: accessing properties in org-element-parse-buffer tree
  2014-08-31  2:08 ` Eric Abrahamsen
@ 2014-08-31  9:12   ` Eike
  0 siblings, 0 replies; 7+ messages in thread
From: Eike @ 2014-08-31  9:12 UTC (permalink / raw)
  To: emacs-orgmode



Eric Abrahamsen writes:
> Eike <eike@eknet.org> writes:
>
>> Hello list,
>>
>> I want to ask for help regarding elisp and org-elements. I like to
>> access the properties of all my headlines and I created the following
>> function (tree is the parsed tree) that collects them into an a-list:
>
> You could also take a look at org-collector, in contrib. It might give
> you some ideas, or even solve your problem directly.

Yes, that looks really interesting! Thanks for the tip!

Kind regards
Eike

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-08-31  9:16 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-30 18:03 accessing properties in org-element-parse-buffer tree Eike
2014-08-30 19:07 ` Eike
2014-08-30 19:41 ` Thorsten Jolitz
2014-08-30 20:20   ` Eike
2014-08-30 22:10     ` Thorsten Jolitz
2014-08-31  2:08 ` Eric Abrahamsen
2014-08-31  9:12   ` Eike

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).