From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eric Schulte Subject: Re: proposal to have ignoreheading tags/properties Date: Mon, 16 Jun 2014 09:29:53 -0400 Message-ID: <87y4wxvv61.fsf@gmail.com> References: <87tx7qxahl.fsf@gmail.com> <87ppie2c2h.fsf@gmail.com> <871tutx4t4.fsf@gmail.com> <87mwdfzmox.fsf@nicolasgoaziou.fr> <87zjhdk63p.fsf@gmail.com> <87oaxtmg36.fsf@nicolasgoaziou.fr> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:55110) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WwX0E-0002BN-BN for emacs-orgmode@gnu.org; Mon, 16 Jun 2014 09:31:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WwX09-0005uN-I2 for emacs-orgmode@gnu.org; Mon, 16 Jun 2014 09:31:14 -0400 Received: from mail-ob0-x22b.google.com ([2607:f8b0:4003:c01::22b]:52314) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WwX09-0005uJ-AP for emacs-orgmode@gnu.org; Mon, 16 Jun 2014 09:31:09 -0400 Received: by mail-ob0-f171.google.com with SMTP id nu7so5721278obb.2 for ; Mon, 16 Jun 2014 06:31:08 -0700 (PDT) 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: Eric Schulte Cc: Mark Edgington , emacs-orgmode , Nicolas Girard --=-=-= Content-Type: text/plain Nicolas Goaziou writes: > Hello, > > Eric Schulte writes: > >> In my opinion the manual interleaving of "noexport" and "export" tags is >> overly cumbersome and is non-obvious. > > It is as non-obvious as the task it achieves. > >> The obscure nature of this solution is evidenced by multiple >> discussions and implementations of filter functions to handle >> situations which could be covered by this noexport/export pattern. > > I don't know what you are referring to, since this "noexport/export" > pattern isn't implemented yet. Do you have an example of such > a discussion that dismissed said pattern? > >> I think the attached patch should be applied to the core. It includes >> the following. >> >> - a single new export function which removes the headlines and contents >> (the "section" element) of headlines tagged "ignoreexport", then >> retains and promotes all sub-headlines contained therein. >> >> - a single new export tag named "ignoreexport" (ignore seems to be the >> crowd favorite, and adding "export" reduces possible conflicts with >> existing personal tags) > > Thank you for the patch. > > Again, my concern is that it introduces another tag for a task that > could be possible without it. "export", "noexport", "ignoreexport": this > all gets confusing. Furthermore, this tag should, at the bare minimum, > be configurable so it also introduces another keyword on par with > SELECT_TAGS and EXCLUDE_TAGS. > > Moreover, that task is highly specific; I'm not convinced we should have > a dedicated keyword for each of them. I'd rather have a simple solution > for selective export problems, even if, as a generic solution, it may > look clumsier. > >> From the included tests, the effect of this patch is to convert a tree >> like the following, >> >> ,---- >> | * H1 >> | Text1 >> | ** H2 :ignoreexport: >> | Text2 >> | *** H3 >> | Text3 >> | **** H4 >> | Text4 >> | *** H5 >> | Text5 >> | **** H6 :ignoreexport: >> | Text6 >> | ***** H7 >> | Text7 >> | ***** H8 >> | Text8 >> `---- > > Note that my suggestion is > > ,---- > | * H1 > | Text1 > | ** H2 :noexport: > | Text2 > | *** H3 :export: > | Text3 > | **** H4 > | Text4 > | *** H5 :export: > | Text5 > | **** H6 :noexport: > | Text6 > | ***** H7 :export: > | Text7 > | ***** H8 :export: > | Text8 > `---- > > In this case, it is more verbose. But the opposite would happen if you > needed to also ignore children within the "ignoreexport" headlines. > In order to get > > * H1 > ** H4 > > compare > > > * H1 > ** H2 :ignoreexport: > *** H3 :noexport: > *** H4 > > with > > * H1 > ** H2 :noexport: > *** H3 > *** H4 :export: > > This time, the brevity of :ignoreexport: is not so clear. Also, it will > not prevent the need to nest tags at some points. IOW, it is only > efficient for one very specific use case. Outside of this case, the new > tag would just be an annoyance and you would fallback > to :noexport:/:export: nesting, if implemented. And if we cannot avoid > tags nesting, I'd take 2 "nesteable" tags over 3 any day. > > Another point to consider is that :noexport:/:export has the advantage > to mark explicitly what will be included in the export process. As such, > I don't find less obvious than your proposal: in both cases, you have to > understand the rules applied behind the keywords anyway. And these rules > are well-known for "export" and "noexport" tags. > This is a specific tag for a specific but common use case. I'll defer to your judgment on the exporting code and instead share a filter function which may be added to personal configurations (I've added this to the FAQ as well [1]). Having looked more closely at my use cases (documented in the attached implementation), including the contents of ignored headlines is required for most practical applications (which may make the parse tree invalid, but which works well for every export backend I've used thus far). --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=ignore-headline.el Content-Transfer-Encoding: quoted-printable ;; During export headlines which have the "ignore" tag are removed ;; from the parse tree. Their contents are retained (leading to a ;; possibly invalid parse tree, which nevertheless appears to function ;; correctly with most export backends) all children headlines are ;; retained and are promoted to the level of the ignored parent ;; headline. ;; ;; This makes it possible to add structure to the original Org-mode ;; document which does not effect the exported version, such as in the ;; following examples. ;; ;; Wrapping an abstract in a headline ;; ;; * Abstract :ignore: ;; #+LaTeX: \begin{abstract} ;; #+HTML:
;; ;; ... ;; ;; #+HTML:
;; #+LaTeX: \end{abstract} ;; ;; Placing References under a headline (using ox-bibtex in contrib) ;; ;; * References :ignore: ;; #+BIBLIOGRAPHY: dissertation plain ;; ;; Inserting an appendix for LaTeX using the appendix package. ;; ;; * Appendix :ignore: ;; #+LaTeX: \begin{appendices} ;; ** Reproduction ;; ... ;; ** Definitions ;; #+LaTeX: \end{appendices} ;; (defun org-export-ignore-headlines (data backend info) "Remove headlines tagged \"ignore\" retaining contents and promoting chil= dren. Each headline tagged \"ignore\" will be removed retaining its contents and promoting any children headlines to the level of the parent." (org-element-map data 'headline (lambda (object) (when (member "ignore" (org-element-property :tags object)) (let ((level-top (org-element-property :level object)) level-diff) (mapc (lambda (el) ;; recursively promote all nested headlines (org-element-map el 'headline (lambda (el) (when (equal 'headline (org-element-type el)) (unless level-diff (setq level-diff (- (org-element-property :level = el) level-top))) (org-element-put-property el :level (- (org-element-property :level el) level-diff))))) ;; insert back into parse tree (org-element-insert-before el object)) (org-element-contents object))) (org-element-extract-element object))) info nil) data) (add-hook 'org-export-filter-parse-tree-functions 'org-export-ignore-headli= nes) --=-=-= Content-Type: text/plain > >> I'm sympathetic to arguments about maintaining simplicity of the core, >> and even more so to arguments about maintaining structural validity of >> trees during export. I believe that this revised patch fully maintains >> valid tree structures, and I'd suggest that the increase in complexity >> of a single keyword is justified by the demonstrated user demand for >> this functionality. > > It mostly preserves tree structure, indeed. More comments about this > below. > > Just to be clear: I'm not against implementing the functionality. We can > implement it without increasing complexity, so the demand is hardly > a justification for this added complexity. > > Making :export: and :noexport: tags symmetrical is a good thing anyway: > why could we add :noexport: within :export: trees but not the other way? > And, as I demonstrated earlier, combination of both permits more > patterns than :ignoreexport:. Therefore, we should implement it in any > case. As a bonus, it provides a solution for the problem at hand. > > If this solution happens to be inadequate, then we can discuss about > better solutions, this time with more options (a user-defined hook, > a macro, a command, even a new tag if we cannot escape it...). > > Anyway, some comments follow about your code. > >> +(defun org-export-ignore-headlines-retain-and-promoting-children (data info) >> + "Remove headlines tagged \"ignoreexport\" retaining sub-headlines. >> +DATA is the parse tree. INFO is a plist containing export >> +options. Each headline tagged \"ignoreexport\" will be removed >> +removing its contents but retaining and promoting any children >> +headlines by a single level." >> + (org-element-map data org-element-all-elements > > Since you're only interested in headlines, org-element-all-elements --> > headline > Done, thanks. > >> + (lambda (object) >> + (when (and (equal 'headline (org-element-type object)) > > This check is not necessary per the suggestion above. > Yes. > >> + (member "ignoreexport" (org-element-property :tags object))) >> + (mapc (lambda (el) >> + ;; recursively promote all nested headlines >> + (org-element-map el 'headline >> + (lambda (el) >> + (when (equal 'headline (org-element-type el)) > > You don't need this `mapc' + `org-element-map' + `org-element-type' > construct. More on this below. > This includes the section contents, and ensures the order in which the children headlines are mapped, so that they are inserted with `org-element-insert-before' in the correct order. This is both because I'm not sure what exactly is guaranteed WRT mapping order by org-element-map, and also so the code is explicit about the ordering of side effects with element insertion. > >> + (org-element-put-property el >> + :level (1- (org-element-property :level el)))))) > > Actually, hard-coding `1-' will not always work, because it assumes that > children differ from their parent by exactly one level. This is not > always the case. > > * 1 > *** 1.0.1 > ***** 1.0.1.0.1 > ***** 1.0.1.0.2 > > Of course, this is a contrived example. Nevertheless, just to make it > robust, promoting children should put the lowest level children to the > level of their parent and preserve relative level differences between > other children. > Good catch. I've made this change. > >> + ;; insert back into parse tree >> + (org-element-insert-before el object)) >> + ;; drop first three elements of headline >> + ;; 1. headline tag >> + ;; 2. properties >> + ;; 3. section >> + (cdddr object)) > > `cddr' is really `org-element-contents'. Also, some headlines do not > have a section, which is not mandatory. In this case `cdddr' would also > remove the first headline, which is wrong. > > This can be solved by replacing `mapc' + `org-element-map' + `cdddr' > with: > > (org-element-map (org-element-contents object) 'headline > (lambda (el) ...)) > Thanks, better to stick with the org-element API. > > > I appreciate your work on this, but let me stress it again: I'm > convinced that :ignoreexport: tag is only a partial solution to the > problem, and, as such, a dead-end. :noexport:/:export: combination is > more versatile, at the price of some verbosity in some cases, but > without the added complexity another tag would introduce. > We disagree here. I think that the particular use case addressed by this functionality is frequent enough to justify the tag, but I understand your points especially given that most useful implementations will require including the content of the ignored headline. Best, > > > Regards, Footnotes: [1] http://orgmode.org/worg/org-faq.html#ignoreheadline -- Eric Schulte https://cs.unm.edu/~eschulte PGP: 0x614CA05D (see https://u.fsf.org/yw) --=-=-=--