From mboxrd@z Thu Jan 1 00:00:00 1970 From: John Kitchin Subject: Re: creating new #+KEYWORD: variables Date: Thu, 15 Nov 2018 14:51:55 -0500 Message-ID: References: <87h8gpcs86.fsf@nicolasgoaziou.fr> <87r2fsbvz2.fsf@nicolasgoaziou.fr> Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="000000000000c597f7057ab96263" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:33123) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gNNgR-00008R-FY for emacs-orgmode@gnu.org; Thu, 15 Nov 2018 14:52:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gNNgQ-0004Vd-73 for emacs-orgmode@gnu.org; Thu, 15 Nov 2018 14:52:11 -0500 Received: from mail-wr1-x433.google.com ([2a00:1450:4864:20::433]:45270) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gNNgP-0004VD-NA for emacs-orgmode@gnu.org; Thu, 15 Nov 2018 14:52:10 -0500 Received: by mail-wr1-x433.google.com with SMTP id v6so635785wrr.12 for ; Thu, 15 Nov 2018 11:52:09 -0800 (PST) In-Reply-To: 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: Matt Price Cc: org-mode-email --000000000000c597f7057ab96263 Content-Type: text/plain; charset="UTF-8" I have used something like this: (defun gb-set-filetag (tag value) "Set filetag TAG to VALUE. If VALUE is nil, remove the filetag." (save-excursion (goto-char (point-min)) (if (re-search-forward (format "#\\+%s:" tag) (point-max) 'end) ;; replace existing filetag (progn (beginning-of-line) (kill-line) (when value (insert (format "#+%s: %s" tag value)))) ;; add new filetag (if (looking-at "^$") ;empty line ;; at beginning of line (when value (insert (format "#+%s: %s" tag value))) ;; at end of some line, so add a new line (when value (insert (format "\n#+%s: %s" tag value))))))) I am not sure what you mean by the end of the headers. This code ends up putting new keywords at the end of the file. You could add some code I guess that jumps back to the top, and puts it at the next line after the last #+ or something. 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 Thu, Nov 15, 2018 at 7:14 AM Matt Price wrote: > > > On Sat, Nov 10, 2018 at 1:58 PM Nicolas Goaziou > wrote: > >> Hello, >> >> John Kitchin writes: >> >> > You can retrieve keywords in the org-file like this: >> > >> > (defun get-keyword (key) >> > (org-element-map (org-element-parse-buffer) 'keyword >> > (lambda (k) >> > (when (string= key (org-element-property :key k)) >> > (org-element-property :value k))) >> > nil t)) >> >> As a minor addendum, >> >> (org-element-parse-buffer 'element) >> >> is more efficient in this case. >> >> An even more efficient way to retrieve keywords, assuming buffer is not >> already parsed, would be: >> >> (org-with-point-at 1 >> (let ((case-fold-search t) >> (regexp (format "^[ \t]*#\\+%s:" key)) >> (result nil)) >> (while (re-search-forward regexp nil t) >> (let ((element (org-element-at-point))) >> (when (eq 'keyword (org-element-type element)) >> (push (org-element-property :value element) result)))) >> result)) >> >> This is very helpful, Nicolas and John. > > What about *setting* a global keyword? I would like to write something > like this: > > (defun org-lms-set-global-prop-value (key value) > "Add or update keyword KEY in the org file header." > (save-excursion > (goto-char (point-min)) > (insert (format "#+%s: %" (upcase key) value)))) > > But > (a) insert the value at the *end* of the headers section, not the > beginning. > (b) preferably replace any existing values of the keyword rather than > write a whole new line. > > (b) I guess could be achieved with something like > > (replace-regexp (format "\(^[ \t]*#\\+%s: \)\(.*\)" key) (concat "\1" > value)) > But what about (a)? I thought org already had a couple of functions that > performed this kind of serach but now I'm not so sure. > > > > >> Regards, >> >> -- >> Nicolas Goaziou >> > --000000000000c597f7057ab96263 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
I have used something like this:

=
= (defun gb-set-f= iletag (tag value)
"Set filetag TAG to VALUE.
If VALUE is nil, remove the filetag.&q= uot;
(save-excursion
(goto-char (point-min= ))
(if = (re-search-forward (format "#\\+%s:" tag) (point-max= ) 'end)
;; replace existing fileta= g
(progn
(beginnin= g-of-line)
(kill-line)
(when value
(insert (format "#+%s: %s" tag value))))
= ;; add new filetag
(if (looking-at &qu= ot;^$") ;empty line
;; at beginning of line
(when value
(insert (format "#+%s: %s" tag value)= ))
;; at end of some line, so add a new line
(when value
(insert (format "\n#+%s: %s" tag = value)))))))
I am not sure what you mean by the end of t= he headers. This code ends up putting new keywords at the end of the file. = You could add some code I guess that jumps back to the top, and puts it at = the next line after the last #+ or something.

John

--= ---------------------------------
Professor John Kitchin=C2=A0
Dohert= y Hall A207F
Department of Chemical Engineering
Carnegie Mellon Unive= rsity
Pittsburgh, PA 15213
412-268-7803

On Thu, Nov 1= 5, 2018 at 7:14 AM Matt Price <moptop99@gmail.com> wrote:


On Sat, Nov 10, 2018 at 1:58 PM Nicolas Goaziou &l= t;mail@nicolasg= oaziou.fr> wrote:
Hello,

John Kitchin <jkitchin@andrew.cmu.edu> writes:

> You can retrieve keywords in the org-file like this:
>
> (defun get-keyword (key)
>=C2=A0 =C2=A0(org-element-map (org-element-parse-buffer) 'keyword >=C2=A0 =C2=A0 =C2=A0(lambda (k)
>=C2=A0 =C2=A0 =C2=A0 =C2=A0(when (string=3D key (org-element-property := key k))
> (org-element-property :value k)))
>=C2=A0 =C2=A0 =C2=A0nil t))

As a minor addendum,

=C2=A0 =C2=A0 (org-element-parse-buffer 'element)

is more efficient in this case.

An even more efficient way to retrieve keywords, assuming buffer is not
already parsed, would be:

=C2=A0 =C2=A0 (org-with-point-at 1
=C2=A0 =C2=A0 =C2=A0 (let ((case-fold-search t)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (regexp (format "^[ \t]*#\\+= %s:" key))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (result nil))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 (while (re-search-forward regexp nil t)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (let ((element (org-element-at-point)))<= br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (when (eq 'keyword (org-eleme= nt-type element))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (push (org-element-propert= y :value element) result))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 result))

This is very helpful, Nicolas and John.=C2=A0

What about *setting* a global keyword? I would like = to write something like this:

(defun org-lms-= set-global-prop-value (key value)
=C2=A0 "Add or update keyword KEY= in the org file header."
=C2=A0 (save-excursion
=C2=A0=C2=A0=C2= =A0 (goto-char (point-min))
=C2=A0=C2=A0=C2=A0 (insert (format "#+%= s: %" (upcase key) value))))

But
(a) insert the value at the *end* of the headers section, not the beginn= ing.
(b) preferably replace any existing values of the keywo= rd rather than write a whole new line.

(b) I guess= could be achieved with something like

(repla= ce-regexp (format "\(^[ \t]*#\\+%s: \)\(.*\)" key) (concat "= \1" value))
But what about (a)? I thought org already h= ad a couple of functions that performed this kind of serach but now I'm= not so sure.=C2=A0


=C2=A0
Regards,

--
Nicolas Goaziou
--000000000000c597f7057ab96263--