emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [O] proposal to have ignoreheading tags/properties


From: Eric Schulte
Subject: Re: [O] proposal to have ignoreheading tags/properties
Date: Mon, 16 Jun 2014 09:29:53 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)

Nicolas Goaziou <address@hidden> writes:

> Hello,
>
> Eric Schulte <address@hidden> 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).

Attachment: ignore-headline.el
Description: application/emacs-lisp

>
>> 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)

reply via email to

[Prev in Thread] Current Thread [Next in Thread]