From mboxrd@z Thu Jan 1 00:00:00 1970 From: Aaron Ecay Subject: Re: Lexical binding bug in org-list.el? Date: Sun, 08 Nov 2015 19:55:09 +0000 Message-ID: <87pozks1uq.fsf@gmail.com> References: <87wptuua9n.fsf@gmail.com> <87ziyq7j8t.fsf@nicolasgoaziou.fr> <87r3k2t46z.fsf@gmail.com> <87twox92nx.fsf@nicolasgoaziou.fr> <87a8qpts31.fsf@gmail.com> <878u688rov.fsf@nicolasgoaziou.fr> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:54532) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZvW3X-0003CC-KQ for emacs-orgmode@gnu.org; Sun, 08 Nov 2015 14:55:17 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZvW3U-0002dF-B7 for emacs-orgmode@gnu.org; Sun, 08 Nov 2015 14:55:15 -0500 Received: from mail-wm0-x22a.google.com ([2a00:1450:400c:c09::22a]:34673) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZvW3U-0002dA-1r for emacs-orgmode@gnu.org; Sun, 08 Nov 2015 14:55:12 -0500 Received: by wmnn186 with SMTP id n186so82427934wmn.1 for ; Sun, 08 Nov 2015 11:55:11 -0800 (PST) In-Reply-To: <878u688rov.fsf@nicolasgoaziou.fr> 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-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Nicolas Goaziou , emacs-org list --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Hi Nicolas, 2015ko azaroak 8an, Nicolas Goaziou-ek idatzi zuen: [...] > Anyway, this we're really nitpicking. There's nothing fundamentally > wrong in either choice. You=E2=80=99re right, and I=E2=80=99m not trying to be quarrelsome. At lea= st for me, it=E2=80=99s helpful to understand the perspective on things like this, so = I can try to model what is normative guidance and what is not. Thanks for humoring me. >=20 >>> - change `org-list-parse-list' to provide a simpler output and update >>> Babel should to use that new output. >=20 > So the new output could be [...] details elided >=20 > WDYT? LGTM. I=E2=80=99ve probably met my quota of org-related fun for the day (s= ee below...), but implementing this in terms of elements will be my next org-list related task. >=20 >>> - re-implement `org-list-to-subtree' using directly Elements, or even >>> string massaging. It=E2=80=99s obvious to me that string-massaging causes friction in parts of org=E2=80=99s code, so I=E2=80=99d like to try a different approach here. = The attached patch makes a stab at doing the reimplementation in terms of elements. I think it came out rather nicely, but I=E2=80=99d really value hearing your opinion on it. It=E2=80=99s very lightly tested so far. I basically just used the followi= ng snippet as a test case: put it in an org-mode buffer, put your cursor somewhere inside the list, and M-: (org-list-to-subtree2) - foo - *bar* blorfle - [X] baz - quux - 123 > Having slept over the idea, I think we could simply update > `org-list-to-generic' to be more robust and be done with it. I can > implement it in a couple of hours (and debug it in a couple of > months...). OK. Don=E2=80=99t hesitate to ask if there=E2=80=99s some way we can help,= of course. Thanks, --=20 Aaron Ecay --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0001-draft-implementation-of-org-list-to-subtree-in-terms.patch >From 2c41ae7704c133086a772b8651a1c3cd67feab78 Mon Sep 17 00:00:00 2001 From: Aaron Ecay Date: Sun, 8 Nov 2015 19:37:22 +0000 Subject: [PATCH] draft implementation of org-list-to-subtree in terms of org-element --- lisp/org-list.el | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/lisp/org-list.el b/lisp/org-list.el index 19d5b03..1612e4e 100644 --- a/lisp/org-list.el +++ b/lisp/org-list.el @@ -3263,6 +3263,110 @@ syntax. Return converted list as a string." (require 'ox-texinfo) (org-export-string-as list 'texinfo t)) +(defun org-list--partial-parse-contents (parse) + "Get the actual contents of a partial org-mode parse. + +Specifically, when parsing a piece of text smaller than a +headline, `org-element-parse-buffer' wraps its result with a +dummy `section' element, as well as the standard `org-data' +wrapper. This function removes these, returning a list of +org-elements. + +TODO: maybe this needs a more general name." + (org-element-contents + ;; strip the org-data element + (nth 0 (org-element-contents + ;; and the section element + parse)))) + +(defun org-list--split-first-line (contents) + "Remove the first line of text from an org-element item. + +CONTENTS are the contents of the item org-element: at least a +paragraph followed by zero or more other elements. + +Returns a cons of the first textual line and a list of +org-elements representing the structure of the item minus this +line. + +TODO: is the first daughter of an item always a paragraph?" + (let ((graf (nth 0 contents))) + (unless (eq (org-element-type graf) 'paragraph) + (error "`org-list--split-first-line' got confused")) + (goto-char (org-element-property :begin graf)) + (let* ((eol (point-at-eol)) + (end (org-element-property :end graf)) + (first-line (buffer-substring-no-properties (point) eol))) + (if (> (1+ eol) end) + ;; One line paragraph: it becomes the entirety of the + ;; headline, and we remove it from contents + (setq contents (cdr contents)) + ;; Multi-line paragraph: narrow the buffer to lines 2-N, parse + ;; them, and set them as the contents of the paragraph. + (save-restriction + (widen) + (narrow-to-region (1+ eol) end) + (org-element-set-contents graf + (org-list--partial-parse-contents + ;; TODO: We're playing a trick on + ;; the parser here. AFAICT, the + ;; parse does not rely on the + ;; cache. But maybe we should + ;; let org-element-use-cache to + ;; nil around this call, in case + ;; that changes in the future. + (org-element-parse-buffer))))) + (cons first-line contents)))) + +(defun org-list--item-to-headline (item level) + "Convert an org-element list item to a headline. + +The first line of the list item becomes the " + (unless (eq (car item) 'item) + (error "`org-list--item-to-headline' expects an item argument")) + (let* ((r (org-list--split-first-line (org-element-contents item))) + (title (car r)) + (other-contents (cdr r))) + (list 'headline + `(:level ,level + ,@(when (eq (org-element-property :checkbox item) 'on) + (list :todo-keyword + ;; TODO: how to fish the approporiate + ;; value out of org-todo-keywords? + "TODO")) + :title ,title) + (mapcar (lambda (x) (if (eq (org-element-type x) 'plain-list) + (org-list--to-headlines x (1+ level)) + x)) + other-contents)))) + +(defun org-list--to-headlines (list level) + (unless (eq (car list) 'plain-list) + (error "`org-list-to-subtree' expects a plain-list argument")) + (mapcar (lambda (x) (org-list--item-to-headline x level)) + (org-element-contents list))) + +(defun org-list-to-subtree2 () + (let* ((e (org-element-at-point)) + (l (org-element-lineage e)) + (list (cl-find-if (lambda (x) (eq (org-element-type x) 'plain-list)) + (nreverse l))) + (level (org-reduced-level (or (org-current-level) 0))) + (begin (org-element-property :begin list)) + (end (org-element-property :end list)) + (parse (save-restriction + (widen) + (narrow-to-region begin end) + (org-element-parse-buffer))) + (new-subtree (org-list--to-headlines + (nth 0 (org-list--partial-parse-contents parse)) + level))) + (goto-char end) + ;; Don't eat the blank lines after the list. + (skip-chars-backward " \n\t\f") + (delete-region begin (point)) + (insert (org-element-interpret-data new-subtree)))) + (defun org-list-to-subtree (list &optional params) "Convert LIST into an Org subtree. LIST is as returned by `org-list-parse-list'. PARAMS is a property list -- 2.6.2 --=-=-=--