From mboxrd@z Thu Jan 1 00:00:00 1970 From: John Kitchin Subject: Re: Programmatically handling org files Date: Mon, 12 Sep 2016 14:30:18 -0400 Message-ID: References: <87twdlcpg8.fsf@fastmail.fm> <87fup5f07e.fsf@gmail.com> Mime-Version: 1.0 Content-Type: multipart/alternative; boundary=047d7bea38c42fdc96053c53b0fb Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:44169) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bjW0u-0003pu-BM for emacs-orgmode@gnu.org; Mon, 12 Sep 2016 14:31:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bjW0m-0008BH-HC for emacs-orgmode@gnu.org; Mon, 12 Sep 2016 14:31:23 -0400 Received: from mail-wm0-f50.google.com ([74.125.82.50]:38024) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bjW0m-0008B4-8T for emacs-orgmode@gnu.org; Mon, 12 Sep 2016 14:31:20 -0400 Received: by mail-wm0-f50.google.com with SMTP id 1so160339523wmz.1 for ; Mon, 12 Sep 2016 11:31:20 -0700 (PDT) In-Reply-To: <87fup5f07e.fsf@gmail.com> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: "Emacs-orgmode" To: Thorsten Jolitz Cc: "emacs-orgmode@gnu.org" --047d7bea38c42fdc96053c53b0fb Content-Type: text/plain; charset=UTF-8 indeed! Maybe I misunderstood the OP. You can find more on the API here: http://orgmode.org/worg/dev/org-element-api.html There are also a bunch of functions to do other things, e.g. (org-todo) (org-cut-subtree) (org-entry-put) and many others that let you change properties of headings, cut them, etc... These are documented in the org code. The best way to learn how to use them is to reverse engineer how you would make the change you want manually, e.g. which keys do you press, then use C-h k on those keys to see what commands get run. John ----------------------------------- Professor John Kitchin Doherty Hall A207F Department of Chemical Engineering Carnegie Mellon University Pittsburgh, PA 15213 412-268-7803 @johnkitchin http://kitchingroup.cheme.cmu.edu On Mon, Sep 12, 2016 at 2:21 PM, Thorsten Jolitz wrote: > Joost Kremers writes: > > Hi, > > > I was wondering if there is some sort of (semi)official API for handling > > org files programmatically. That's to say, is there a documented way for > > non-org Emacs packages to manipulate (the contents of) org files? > > > > Specifically, I'm wondering about creating and deleting entries (by > > entries I mean headers with their contents), changing TODO state, moving > > entries, that sort of thing. > > by "non-org Emacs packages" you mean Emacs packages written in Elisp, > but not part of Org-mode? > > The org-mode parser converts an Org document into a nested list and > provides many convenience functions to work on this parse tree. So > org-element.el (and maybe ox.el too) is the core library for converting > an Org text document into an Elisp data structure and working with that, > have a look at these two functions: > > ,---- > | 3965:(defun org-element-parse-buffer (&optional granularity visible-only) > | 4043:(defun org-element-map > `---- > > If you feel you don't need the whole parse tree, but rather want to act > locally on the Org element at point, you might want to look at > org-dp.el with just two core functions (create and rewire an Org > element) and a mapping functions (plus quite a few utilities in > org-dp.el and org-dp-lib.el): > > ,---- > | 523:(cl-defun org-dp-create > | (elem-type &optional contents insert-p affiliated &rest args) > | 642:(cl-defun org-dp-rewire > | (elem-type &optional contents replace affiliated element &rest > args) > | 766:(defun org-dp-map > | (fun-with-args rgxp &optional match-pos backward-search-p beg end > | silent-p) > `---- > > Note that I recently added 4 "Tempo" Templates (a bit like Yasnippets) > to org-dp that make it easy to insert a 'create' or 'rewire' call with > just those parameters the interpreter uses for the element to be created > or rewired: > > ,---- > | M-x tempo-template-org-dp-create > | M-x tempo-template-org-dp-create-with-comments > | M-x tempo-template-org-dp-rewire > | M-x tempo-template-org-dp-rewire-lambda > `---- > > e.g. calling the third one with elem type "headline" enters this template > > #+BEGIN_SRC emacs-lisp > (org-dp-rewire 'headline > "\n" ;cont > t ;ins > nil ;aff > nil ;elem > :level 1 ;1..8 > :priority nil ;65|66|67 > :todo-keyword TODO > :title "" > :tags '( ) > :commentedp nil > :pre-blank 0 > :footnote-section-p nil > ) > #+END_SRC > > while for elem type "example block" its only: > > #+BEGIN_SRC emacs-lisp > (org-dp-rewire 'example-block nil t ;cont ins > nil ;aff > nil ;elem > :switches "" > :preserve-indent "" > :value "" > ) > #+END_SRC > > since example-blocks have no content (:value is their content) and only > 3 parameters that are actually interpreted. > > Using this system, creating or rewiring an Org Element from Elisp > requires only to define the values of the interpreted parameters, all > the low level stuff (actually creating and inserting the new/modified > element in text form) is left to the interpreters (from org-element.el). > > You just declare what you want and don't worry anymore how it is done > (=> dp stands for declarative programming, in this context at least ;-) > > -- > cheers, > Thorsten > > > --047d7bea38c42fdc96053c53b0fb Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
indeed! Maybe I misunderstood the OP.

Y= ou can find more on the API here:


There are also a bunch = of functions to do other things, e.g.=C2=A0

(org-t= odo) (org-cut-subtree) (org-entry-put) and many others

=
that let you change properties of headings, cut them, etc...

These are documented in the org code. The best way to learn= how to use them is to reverse engineer how you would make the change you w= ant manually, e.g. which keys do you press, then use C-h k on those keys to= see what commands get run.

John

-------------------= ----------------
Professor John Kitchin=C2=A0
Doherty Hall A207F
D= epartment of Chemical Engineering
Carnegie Mellon University
Pittsbur= gh, PA 15213
412-268-7803

On Mon, Sep 12, 2016 at 2:21 PM, Thorsten Jo= litz <tjolitz@gmail.com> wrote:
Joost Kremers <joostkr= emers@fastmail.fm> writes:

Hi,

> I was wondering if there is some sort of (semi)official API for handli= ng
> org files programmatically. That's to say, is there a documented w= ay for
> non-org Emacs packages to manipulate (the contents of) org files?
>
> Specifically, I'm wondering about creating and deleting entries (b= y
> entries I mean headers with their contents), changing TODO state, movi= ng
> entries, that sort of thing.

by "non-org Emacs packages" you mean Emacs packages writte= n in Elisp,
but not part of Org-mode?

The org-mode parser converts an Org document into a nested list and
provides many convenience functions to work on this parse tree. So
org-element.el (and maybe ox.el too) is the core library for converting
an Org text document into an Elisp data structure and working with that, have a look at these two functions:

,----
| 3965:(defun org-element-parse-buffer (&optional granularity visible-o= nly)
| 4043:(defun org-element-map
`----

If you feel you don't need the whole parse tree, but rather want to act=
locally on the Org element at point, you might want to look at
org-dp.el with just two core functions (create and rewire an Org
element) and a mapping functions (plus quite a few utilities in
org-dp.el and org-dp-lib.el):

,----
| 523:(cl-defun org-dp-create
|=C2=A0 =C2=A0 =C2=A0 =C2=A0 (elem-type &optional contents insert-p aff= iliated &rest args)
| 642:(cl-defun org-dp-rewire
|=C2=A0 =C2=A0 =C2=A0 =C2=A0 (elem-type &optional contents replace affi= liated element &rest args)
| 766:(defun org-dp-map
|=C2=A0 =C2=A0 =C2=A0 =C2=A0 (fun-with-args rgxp &optional match-pos ba= ckward-search-p beg end
|=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0silent-p)
`----

Note that I recently added 4 "Tempo" Templates (a bit like Yasnip= pets)
to org-dp that make it easy to insert a 'create' or 'rewire'= ; call with
just those parameters the interpreter uses for the element to be created or rewired:

,----
| M-x tempo-template-org-dp-create
| M-x tempo-template-org-dp-create-with-comments
| M-x tempo-template-org-dp-rewire
| M-x tempo-template-org-dp-rewire-lambda
`----

e.g. calling the third one with elem type "headline" enters this = template

#+BEGIN_SRC emacs-lisp
=C2=A0 (org-dp-rewire 'headline
=C2=A0 "\n" ;cont
=C2=A0 t ;ins
=C2=A0 nil ;aff
=C2=A0 nil ;elem
=C2=A0 :level 1 ;1..8
=C2=A0 :priority nil ;65|66|67
=C2=A0 :todo-keyword TODO
=C2=A0 :title ""
=C2=A0 :tags '( )
=C2=A0 :commentedp nil
=C2=A0 :pre-blank 0
=C2=A0 :footnote-section-p nil
=C2=A0 )
#+END_SRC

while for elem type "example block" its only:

#+BEGIN_SRC emacs-lisp
=C2=A0 (org-dp-rewire 'example-block nil t ;cont ins
=C2=A0 nil ;aff
=C2=A0 nil ;elem
=C2=A0 :switches ""
=C2=A0 :preserve-indent ""
=C2=A0 :value ""
=C2=A0 )
#+END_SRC

since example-blocks have no content (:value is their content) and only
3 parameters that are actually interpreted.

Using this system, creating or rewiring an Org Element from Elisp
requires only to define the values of the interpreted parameters, all
the low level stuff (actually creating and inserting the new/modified
element in text form) is left to the interpreters (from org-element.el).
You just declare what you want and don't worry anymore how it is done (=3D> dp stands for declarative programming, in this context at least ;-= )

--
cheers,
Thorsten



--047d7bea38c42fdc96053c53b0fb--