emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [patch][ox-latex] context-aware subscript
@ 2013-08-18  1:29 Rasmus
  2013-08-19  8:26 ` Nicolas Goaziou
  0 siblings, 1 reply; 10+ messages in thread
From: Rasmus @ 2013-08-18  1:29 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1957 bytes --]

Hi,

Currently one can't write something like \beta_t and get a nice result
in org when exporting to LaTeX (where nice result := $\beta_t$).  This
patch tries to fix it.

Nicolas, you might consider this a "can of worms", but since I'd
already worked on it a while ago I'll try my luck.  I'd appreciate if
you'd let me know something like this would be acceptable before I put
more work into it.

With this patch the following document

--8<---------------cut here---------------start------------->8---
#+TITLE:
#+OPTIONS: toc:nil num:nil
#+LATEX:\Huge
* Math entity
1. \(\alpha\)\(\beta\)\(_\text{t}\)
2.  \(\alpha\)\(\beta\)\(_t\)
3. \alpha\beta_t
4. \alpha\times\beta_t\gamma
5. foo_bar
6. \beta_bar
--8<---------------cut here---------------end--------------->8---

translates to something like

--8<---------------cut here---------------start------------->8---
\begin{enumerate}
\item \(\alpha\)\(\beta\)\(_t\)
\item $\alpha\beta_t$
\item $\alpha$\texttimes{}$\beta_{t\gamma}$
\item foo$_{\text{bar}}$
\item $\beta_{bar}$
\end{enumerate}
--8<---------------cut here---------------end--------------->8---

For the reference, this is the output with the current HEAD

--8<---------------cut here---------------start------------->8---
\begin{enumerate}
\item \(\alpha\)\(\beta\)\(_\text{t}\)
\item \(\alpha\)\(\beta\)\(_t\)
\item $\alpha$$\beta$$_{\text{t}}$
\item $\alpha$\texttimes{}$\beta$$_{\text{t}\gamma}$
\item foo$_{\text{bar}}$
\item $\beta$$_{\text{bar}}$
\end{enumerate}
--8<---------------cut here---------------end--------------->8---

As is evident from the pdf output

  $\alpha$$\beta$$_{\text{t}}$ ≠ $\alpha$$\beta$$_{{t}}$ ≠ $\alpha\beta_{t}$

There seems to be no difference between $\alpha$$\beta$ and
$\alpha\beta$ in the pdf, but the latter is more aesthetically
pleasing in the source.

I (currently) don't see much use in trying to be context aware outside
of the entity case (e.g. \(x\)_t?), but I could be wrong.

–Rasmus


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Improved-subscript-handling-in-ox-latex.patch --]
[-- Type: text/x-diff, Size: 4256 bytes --]

From eefe696de67bd4c9baefe928a58648c75adec41e Mon Sep 17 00:00:00 2001
From: rasmus <rasmus@gmx.us>
Date: Sat, 13 Jul 2013 15:59:23 +0200
Subject: [PATCH] Improved subscript handling in ox-latex.

	* ox-latex.el (org-latex-subscript-format): Controls the
	format of subscripts.
	(org-latex-entity): Collects multiple math entities into one
	math fragment.
	(org-latex-entity): Collect proceeding subscripts into same
	math fragment.
	(org-latex--script-size): Better collection of subscripts into
	math-fragments.  Allows for different handling of
	math-subscripts and text subscripts.

In the above "subscripts" refers to subscripts and superscripts.
---
 lisp/ox-latex.el | 55 +++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 45 insertions(+), 10 deletions(-)

diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 1fe918a..183c89a 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -552,6 +552,20 @@ returned as-is."
   :options '(bold code italic strike-through underline verbatim))
 
 
+(defcustom org-latex-subscript-format '("\\text{%s}" . "%s")
+  "Formatting string or strings used for sub- and super-scripts.
+
+If `org-latex-subscript-format' is a cons of two strings, the first
+element will be used when a subscript is plain text,
+e.g. foo_bar, and the second will be used when a subscript is
+math, e.g. beta_t.
+
+If `org-latex-subscript-format' is a string this is used in both
+cases.
+
+The string should contain \"%s\", which is then replaced by the
+actual subscript.")
+
 ;;;; Drawers
 
 (defcustom org-latex-format-drawer-function nil
@@ -1234,8 +1248,23 @@ holding contextual information.  See `org-export-data'."
   "Transcode an ENTITY object from Org to LaTeX.
 CONTENTS are the definition itself.  INFO is a plist holding
 contextual information."
-  (let ((ent (org-element-property :latex entity)))
-    (if (org-element-property :latex-math-p entity) (format "$%s$" ent) ent)))
+  (let ((ent (org-element-property :latex entity))
+	(prev (org-export-get-previous-element entity info))
+	(next (org-export-get-next-element entity info))
+	(post-blanks-p (= (or (org-element-property :post-blank entity) 1) 0))
+	(pre-blanks-p (= (or (org-element-property :post-blank
+						   (org-export-get-previous-element
+						    entity info)) 1) 0))
+	(scripts '(subscript superscript)))
+    (if (not (org-element-property :latex-math-p entity)) ent
+      (concat
+       (if (and pre-blanks-p
+		(or (org-element-property :latex-math-p prev)
+		    (memq (org-element-type prev) scripts))) "" "$")
+       ent
+       (if (and post-blanks-p
+		(or (org-element-property :latex-math-p next)
+		    (memq (org-element-type next) scripts))) "" "$")))))
 
 
 ;;;; Example Block
@@ -2217,8 +2246,12 @@ channel."
 			   (let ((blank (org-element-property :post-blank obj)))
 			     (and blank (> blank 0) "\\ "))))))
 	  (plain-text
-	   (setq output
-		 (format "%s\\text{%s}" output (org-export-data obj info))))
+	   (let* ((mathp (org-element-property :latex-math-p (org-export-get-previous-element (org-export-get-parent obj) info)))
+		  (format (cond ((stringp org-latex-subscript-format) org-latex-subscript-format)
+				((consp org-latex-subscript-format) (funcall (if mathp 'cdr 'car) org-latex-subscript-format))
+				(t "\\text{%s}"))))
+	     (setq output
+		   (format (concat "%s" format) output (org-export-data obj info)))))
 	  (otherwise
 	   (setq output
 		 (concat output
@@ -2232,12 +2265,14 @@ channel."
     ;; superscript into the same math snippet.
     (concat (and (not in-script-p)
 		 (let ((prev (org-export-get-previous-element object info)))
-		   (or (not prev)
-		       (not (eq (org-element-type prev)
-				(if (eq type 'subscript) 'superscript
-				  'subscript)))
-		       (let ((blank (org-element-property :post-blank prev)))
-			 (and blank (> blank 0)))))
+		   (and
+		    (not (org-element-property :latex-math-p prev))
+		    (or (not prev)
+			(not (eq (org-element-type prev)
+				 (if (eq type 'subscript) 'superscript
+				   'subscript)))
+			(let ((blank (org-element-property :post-blank prev)))
+			  (and blank (> blank 0))))))
 		 "$")
 	    (if (eq (org-element-type object) 'subscript) "_" "^")
 	    (and (> (length output) 1) "{")
-- 
1.8.3.4


[-- Attachment #3: Type: text/plain, Size: 27 bytes --]



--
Need more coffee. . .

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [patch][ox-latex] context-aware subscript
  2013-08-18  1:29 [patch][ox-latex] context-aware subscript Rasmus
@ 2013-08-19  8:26 ` Nicolas Goaziou
  2013-08-28 11:55   ` Rasmus
  0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Goaziou @ 2013-08-19  8:26 UTC (permalink / raw)
  To: Rasmus; +Cc: emacs-orgmode

Hello,

Thanks for the patch. Here are some comments about it.

Rasmus <rasmus@gmx.us> writes:

> Currently one can't write something like \beta_t and get a nice result
> in org when exporting to LaTeX (where nice result := $\beta_t$).  This
> patch tries to fix it.

Translating \beta_t into $\beta$$_\text{t}$ and \beta_bar into
$\beta$$ \text{bar}$ is intended.

Unless you explicitly ask for math mode, Org defaults to text mode. The
fact that it needs to go through math mode to insert some entities is
not relevant. IOW, there's a difference between \beta_{$t$} and \beta_t.

Also, merging consecutive subscript and superscript is fragile (and the
code in `org-latex--script-size' could be improved in that area), as it
also depends on user's filters. Here is a contrived example:

Let's assume I have a filter which removes any subscript with the letter
"a" in it. With the following code:

  \beta_a

Trying to merge both the entity and the subscript will return

  $\beta

which is wrong.

> As is evident from the pdf output
>
>   $\alpha$$\beta$$_{\text{t}}$ ≠ $\alpha$$\beta$$_{{t}}$ ≠ $\alpha\beta_{t}$
>
> There seems to be no difference between $\alpha$$\beta$ and
> $\alpha\beta$ in the pdf, but the latter is more aesthetically
> pleasing in the source.

Beautifying LaTeX code is fine, unless it means adding yet another
variable, and making some assumptions about user's configuration. If it
ain't broken, don't fix it.


Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch][ox-latex] context-aware subscript
  2013-08-19  8:26 ` Nicolas Goaziou
@ 2013-08-28 11:55   ` Rasmus
  2013-08-28 13:38     ` Nicolas Goaziou
  0 siblings, 1 reply; 10+ messages in thread
From: Rasmus @ 2013-08-28 11:55 UTC (permalink / raw)
  To: n.goaziou; +Cc: emacs-orgmode

Hi Nicolas,

Nicolas Goaziou <n.goaziou@gmail.com> writes:

> Thanks for the patch. Here are some comments about it.

Sorry about the late reply

> Rasmus <rasmus@gmx.us> writes:
>
>> Currently one can't write something like \beta_t and get a nice
>> result
>> in org when exporting to LaTeX (where nice result := $\beta_t$).
>> This
>> patch tries to fix it.
>
> Translating \beta_t into $\beta$$_\text{t}$ and \beta_bar into
> $\beta$$ \text{bar}$ is intended.

I know it's intended but I dislike it.  In earlier version of
ox-latex.el it didn't use the \text-macro.

> Unless you explicitly ask for math mode, Org defaults to text
> mode. The
> fact that it needs to go through math mode to insert some entities is
> not relevant. 

I disagree that it is irrelevant.  Even so, the spacing is wrong
cf. below.

> IOW, there's a difference between \beta_{$t$} and \beta_t.

No doubt.

> Also, merging consecutive subscript and superscript is fragile (and
> the
> code in `org-latex--script-size' could be improved in that area), as
> it
> also depends on user's filters. Here is a contrived example:
>
> Let's assume I have a filter which removes any subscript with the
> letter
> "a" in it. With the following code:
>
>   \beta_a
>
> Trying to merge both the entity and the subscript will return
>
>   $\beta
>
> which is wrong.

OK.  Perhaps it can be made less fragile.

>> As is evident from the pdf output
>>
>>   $\alpha$$\beta$$_{\text{t}}$ ≠ $\alpha$$\beta$$_{{t}}$ ≠
>> $\alpha\beta_{t}$
>>
>> There seems to be no difference between $\alpha$$\beta$ and
>> $\alpha\beta$ in the pdf, but the latter is more aesthetically
>> pleasing in the source.
>
> Beautifying LaTeX code is fine, unless it means adding yet another
> variable, and making some assumptions about user's configuration. If
> it ain't broken, don't fix it.

But it is broken, since even 

(*)    $\beta$$_{\text{t}}$

doesn't produce the correct output (spacing is wrong; compare to
$\beta_{\text{t}}$).  In LaTeX, (*) represents two "math elements",
although the intention was to get only one.

To sum up, my (implicit) claim and what I intended to fix with the
patch, was

  1. Fixing the bug that subscripts produce wrong output.
  2. Try to make the type of subscript configurable.  Previously,
     "math subscripts" were forced, now \text subscripts are forced.
     
Please let me know whether either 1. or 2. is up for discussion or
whether the current state is to be accepted.

–Rasmus

-- 
⠠⠵

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch][ox-latex] context-aware subscript
  2013-08-28 11:55   ` Rasmus
@ 2013-08-28 13:38     ` Nicolas Goaziou
  2013-08-28 13:46       ` Rasmus
  0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Goaziou @ 2013-08-28 13:38 UTC (permalink / raw)
  To: Rasmus; +Cc: emacs-orgmode

Hello,

Rasmus <rasmus@gmx.us> writes:

> I know it's intended but I dislike it.  In earlier version of
> ox-latex.el it didn't use the \text-macro.

Earlier versions were broken in many ways. They didn't handle spaces,
unicode characters and nested sub/superscript like \text does.

>> Also, merging consecutive subscript and superscript is fragile (and
>> the
>> code in `org-latex--script-size' could be improved in that area), as
>> it
>> also depends on user's filters. Here is a contrived example:
>>
>> Let's assume I have a filter which removes any subscript with the
>> letter
>> "a" in it. With the following code:
>>
>>   \beta_a
>>
>> Trying to merge both the entity and the subscript will return
>>
>>   $\beta
>>
>> which is wrong.
>
> OK.  Perhaps it can be made less fragile.

That's not an easy task. I think it would involve adding implicit
pseudo-objects (i.e. object types specific to `latex' back-end).
Unfortunately, there's no API for that in either org-element or ox.

For now, I think we can put it aside.

> But it is broken, since even 
>
> (*)    $\beta$$_{\text{t}}$
>
> doesn't produce the correct output (spacing is wrong; compare to
> $\beta_{\text{t}}$).

Correct. Then, fixing it is more important than caring about some user
filter.

> To sum up, my (implicit) claim and what I intended to fix with the
> patch, was
>
>   1. Fixing the bug that subscripts produce wrong output.

OK.

>   2. Try to make the type of subscript configurable.  Previously,
>      "math subscripts" were forced, now \text subscripts are forced.

I think filters are good enough for the job. No need for another
configuration variable.

Also, entering math mode is easy enough in Org, whereas exiting math
mode isn't (if it is forced). I often use constructs like \(I_n\) since
I want the "I" char to be in the same font as "n".



Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch][ox-latex] context-aware subscript
  2013-08-28 13:38     ` Nicolas Goaziou
@ 2013-08-28 13:46       ` Rasmus
  2013-08-28 19:21         ` Nicolas Goaziou
  0 siblings, 1 reply; 10+ messages in thread
From: Rasmus @ 2013-08-28 13:46 UTC (permalink / raw)
  To: emacs-orgmode


Hi Nicolas, 

Nicolas Goaziou <n.goaziou@gmail.com> writes:

>> I know it's intended but I dislike it.  In earlier version of
>> ox-latex.el it didn't use the \text-macro.
>
> Earlier versions were broken in many ways. They didn't handle spaces,
> unicode characters and nested sub/superscript like \text does.

OK.

>>> Also, merging consecutive subscript and superscript is fragile 
>>> [...]
>> OK.  Perhaps it can be made less fragile.
>
> That's not an easy task. I think it would involve adding implicit
> pseudo-objects (i.e. object types specific to `latex' back-end).
> Unfortunately, there's no API for that in either org-element or ox.
>
> For now, I think we can put it aside.

I'll just go ahead and trust you on that one.

>> But it is broken, since even 
>>
>> (*)    $\beta$$_{\text{t}}$
>>
>> doesn't produce the correct output (spacing is wrong; compare to
>> $\beta_{\text{t}}$).
>
> Correct. Then, fixing it is more important than caring about some user
> filter.

OK, can I help?  Or do you already have something in mind?

>>   2. Try to make the type of subscript configurable.  Previously,
>>      "math subscripts" were forced, now \text subscripts are forced.
>
> I think filters are good enough for the job. No need for another
> configuration variable.

I can settle for that.  One day we'll (as in I'll) have to grog up a
Worg page for sharing "useful" filters.

> Also, entering math mode is easy enough in Org, whereas exiting math
> mode isn't (if it is forced). I often use constructs like \(I_n\) since
> I want the "I" char to be in the same font as "n".

That's what I use as well, but I'd like to save the $'s around
constructs like \(\beta_t\).  I'll try to fix it via a filter.

–Rasmus

-- 
The Kids call him Billy the Saint

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch][ox-latex] context-aware subscript
  2013-08-28 13:46       ` Rasmus
@ 2013-08-28 19:21         ` Nicolas Goaziou
  2013-08-29 10:50           ` Rasmus
  0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Goaziou @ 2013-08-28 19:21 UTC (permalink / raw)
  To: Rasmus; +Cc: emacs-orgmode

Rasmus <rasmus@gmx.us> writes:

>> Correct. Then, fixing it is more important than caring about some user
>> filter.
>
> OK, can I help?

Sure, please go ahead.

> That's what I use as well, but I'd like to save the $'s around
> constructs like \(\beta_t\).  I'll try to fix it via a filter.

A good filter could be to remove "\text{ }" around single characters.
With the previous fix, \beta_t would eventually become $\beta_t$.


Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch][ox-latex] context-aware subscript
  2013-08-28 19:21         ` Nicolas Goaziou
@ 2013-08-29 10:50           ` Rasmus
  2013-08-31  8:11             ` Nicolas Goaziou
  0 siblings, 1 reply; 10+ messages in thread
From: Rasmus @ 2013-08-29 10:50 UTC (permalink / raw)
  To: n.goaziou; +Cc: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 2073 bytes --]

Nicolas Goaziou <n.goaziou@gmail.com> writes:

> Rasmus <rasmus@gmx.us> writes:
>
>>> Correct. Then, fixing it is more important than caring about some user
>>> filter.
>>
>> OK, can I help?
>
> Sure, please go ahead.

I've just enclosed a quick patch (as in doesn't contain proper commit
msg), but it's basically the previous patch minus the removal of \text
in math plus some quick checks towards potential nasty filters.

It works with the following test file, but let me know about more
hair-pulling test cases, and/or filters.

#+BEGIN_SRC Org
* filters                                                          :noexport:

#+begin_src emacs-lisp
  (defun test-filter (script backend info)
    (when (org-export-derived-backend-p backend 'latex)
      (if  (string-match "a" script) "" script)))
  
  (defun test-filter2 (script backend info)
    (when (org-export-derived-backend-p backend 'latex)
      (replace-regexp-in-string "zz" "" script)))
  
  (add-to-list 'org-export-filter-subscript-functions
                 'test-filter)
  (add-to-list 'org-export-filter-subscript-functions
                 'test-filter2)
  
#+end_src

* test 
|                      | mathp | text |
|----------------------+-------+------|
| merge maybe          | \beta_t    | \times_t   |
| long merge maybe     | \beta_tb   | \times_tb  |
| filter drop          | \beta_abc  | \times_abc |
| filter replace all   | \beta_zz   | \times_zz  |
| filter replace parts | \beta_zzx  | \times_zzx  |

#+END_SRC

The output is something like this (hline removed)

                     & mathp               & text                       \\
                     %%%%%%%%%%%%%%%%%%%%%   %%%%%%%%%%%%%%%%%%%%%%%%%%
merge maybe          & $\beta_{\text{t}}$  & \texttimes{}$_{\text{t}}$  \\
long merge maybe     & $\beta_{\text{tb}}$ & \texttimes{}$_{\text{tb}}$ \\
filter drop          & $\beta$             & \texttimes{}               \\
filter replace all   & $\beta_{\text{}}$   & \texttimes{}$_{\text{}}$   \\
filter replace parts & $\beta_{\text{x}}$  & \texttimes{}$_{\text{x}}$  \\




[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-maybe-merge-subscript-and-mathp-entity-with-some-che.patch --]
[-- Type: text/x-diff, Size: 2406 bytes --]

From b59c60eb7df5b1ff927aff9f4442b1d226d24ceb Mon Sep 17 00:00:00 2001
From: rasmus <rasmus@gmx.us>
Date: Thu, 29 Aug 2013 12:18:00 +0200
Subject: [PATCH] maybe merge subscript and mathp entity with some checks

---
 lisp/ox-latex.el | 35 +++++++++++++++++++++++++++--------
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 1fe918a..91ab912 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -1234,8 +1234,25 @@ holding contextual information.  See `org-export-data'."
   "Transcode an ENTITY object from Org to LaTeX.
 CONTENTS are the definition itself.  INFO is a plist holding
 contextual information."
-  (let ((ent (org-element-property :latex entity)))
-    (if (org-element-property :latex-math-p entity) (format "$%s$" ent) ent)))
+  (let ((ent (org-element-property :latex entity))
+	(prev (org-export-get-previous-element entity info))
+	(next (org-export-get-next-element entity info))
+	(no-post-blanks-p (= (or (org-element-property :post-blank entity) 1) 0))
+	(no-pre-blanks-p (= (or (org-element-property :post-blank
+						   (org-export-get-previous-element
+						    entity info)) 1) 0))
+	(scripts '(subscript superscript)))
+    (if (not (org-element-property :latex-math-p entity)) ent
+      (concat
+       (if (and no-pre-blanks-p
+		(memq (org-element-type prev) scripts)
+		(not (eq (org-export-data prev info) "")))
+	   "" "$")
+       ent
+       (if (and no-post-blanks-p
+		(memq (org-element-type next) scripts)
+		(not (eq (org-export-data next info) "")))
+	   "" "$")))))
 
 
 ;;;; Example Block
@@ -2232,12 +2249,14 @@ channel."
     ;; superscript into the same math snippet.
     (concat (and (not in-script-p)
 		 (let ((prev (org-export-get-previous-element object info)))
-		   (or (not prev)
-		       (not (eq (org-element-type prev)
-				(if (eq type 'subscript) 'superscript
-				  'subscript)))
-		       (let ((blank (org-element-property :post-blank prev)))
-			 (and blank (> blank 0)))))
+		   (and
+		    (not (org-element-property :latex-math-p prev))
+		    (or (not prev)
+			(not (eq (org-element-type prev)
+				 (if (eq type 'subscript) 'superscript
+				   'subscript)))
+			(let ((blank (org-element-property :post-blank prev)))
+			  (and blank (> blank 0))))))
 		 "$")
 	    (if (eq (org-element-type object) 'subscript) "_" "^")
 	    (and (> (length output) 1) "{")
-- 
1.8.4


[-- Attachment #3: Type: text/plain, Size: 29 bytes --]



-- 
When in doubt, do it!


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [patch][ox-latex] context-aware subscript
  2013-08-29 10:50           ` Rasmus
@ 2013-08-31  8:11             ` Nicolas Goaziou
  2013-08-31 13:59               ` Rasmus
  0 siblings, 1 reply; 10+ messages in thread
From: Nicolas Goaziou @ 2013-08-31  8:11 UTC (permalink / raw)
  To: Rasmus; +Cc: emacs-orgmode

Hello,

Rasmus <rasmus@gmx.us> writes:

> I've just enclosed a quick patch (as in doesn't contain proper commit
> msg), but it's basically the previous patch minus the removal of \text
> in math plus some quick checks towards potential nasty filters.
>
> It works with the following test file, but let me know about more
> hair-pulling test cases, and/or filters.

Thanks for the patch. Here are a few comments.

> filter replace all   & $\beta_{\text{}}$   & \texttimes{}$_{\text{}}$   \\

We might be able to handle it more nicely, i.e. by skipping \text when
contents are empty.

> +	(prev (org-export-get-previous-element entity info))
> +	(next (org-export-get-next-element entity info))
> +	(no-post-blanks-p (= (or (org-element-property :post-blank entity) 1) 0))
> +	(no-pre-blanks-p (= (or (org-element-property :post-blank
> +						   (org-export-get-previous-element
> +						    entity info)) 1) 0))

A nil :post-blank property means 0, not 1. Also, you don't re-use PREV
in NO-PRE-BLANKS-P.

> +	(scripts '(subscript superscript)))
> +    (if (not (org-element-property :latex-math-p entity)) ent
> +      (concat
> +       (if (and no-pre-blanks-p
> +		(memq (org-element-type prev) scripts)
> +		(not (eq (org-export-data prev info) "")))
> +	   "" "$")
> +       ent
> +       (if (and no-post-blanks-p
> +		(memq (org-element-type next) scripts)
> +		(not (eq (org-export-data next info) "")))
> +	   "" "$")))))

I think this is problematic: if an entity needs to export both the
previous and the next object, what happens when we have two consecutive
entities? An infloop?

This is the difficult part of the problem.

> +		    (not (org-element-property :latex-math-p prev))

Sure, but I'd rather make a stricter check and also test PREV's type.


Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [patch][ox-latex] context-aware subscript
  2013-08-31  8:11             ` Nicolas Goaziou
@ 2013-08-31 13:59               ` Rasmus
  2013-08-31 14:46                 ` Nicolas Goaziou
  0 siblings, 1 reply; 10+ messages in thread
From: Rasmus @ 2013-08-31 13:59 UTC (permalink / raw)
  To: n.goaziou; +Cc: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 4484 bytes --]

Hi,

> Thanks for the patch. Here are a few comments.

Thanks for the comments.

>> filter replace all   & $\beta_{\text{}}$   & \texttimes{}$_{\text{}}$   \\
>
> We might be able to handle it more nicely, i.e. by skipping \text when
> contents are empty.

Right, these should be removed due to spacing issues, it seems.
However, in this case the change is induced by a filter.  As such, Ox
doesn't know the final output when in the subscript function.  It's
not easy to predict the outcome of a filter before it's been applied.

What I do in the patch is that I apply the filters within the
function.  I don't like this approach as the doc says that filters are
applied ex post so it seems like cheating...  Also, filters using a
regexp with "\text{whatever}" wouldn't work.

So I'm not too optimistic about this particular apporach.

>> +	(prev (org-export-get-previous-element entity info))
>> +	(next (org-export-get-next-element entity info))
>> +	(no-post-blanks-p (= (or (org-element-property :post-blank entity) 1) 0))
>> +	(no-pre-blanks-p (= (or (org-element-property :post-blank
>> +						   (org-export-get-previous-element
>> +						    entity info)) 1) 0))
>
> A nil :post-blank property means 0, not 1. Also, you don't re-use PREV
> in NO-PRE-BLANKS-P.

Right.  I wanted to check for the case where there is no next/previous
element.  But I was wrong.  Thanks.

>> +	(scripts '(subscript superscript)))
>> +    (if (not (org-element-property :latex-math-p entity)) ent
>> +      (concat
>> +       (if (and no-pre-blanks-p
>> +		(memq (org-element-type prev) scripts)
>> +		(not (eq (org-export-data prev info) "")))
>> +	   "" "$")
>> +       ent
>> +       (if (and no-post-blanks-p
>> +		(memq (org-element-type next) scripts)
>> +		(not (eq (org-export-data next info) "")))
>> +	   "" "$")))))
>
> I think this is problematic: if an entity needs to export both the
> previous and the next object, what happens when we have two consecutive
> entities? An infloop?

I agree, but I haven't been able to cause any nasty behavior. I've
probably neglected some case.  These works fine

  1. \alpha\beta_t : \alpha is not a subscript
  2. \alpha\beta_\xi\nu : runs OK recursively. 

On 2.: on my system I've tried with many entities (around 500).  It
works, but obviously it's slow due to the recursiveness.  This is very
nasty.  I don't know if some other mechanism can be derived, tho. . .


>> +		    (not (org-element-property :latex-math-p prev))
>
> Sure, but I'd rather make a stricter check and also test PREV's type.

OK.

–Rasmus


Test file

#+BEGIN_SRC Org
* filters                                                          :noexport:

#+begin_src emacs-lisp
  (defun test-filter (script backend info)
    (when (org-export-derived-backend-p backend 'latex)
      (if  (string-match "a" script) "" script)))

  (defun test-filter2 (script backend info)
    (when (org-export-derived-backend-p backend 'latex)
      (replace-regexp-in-string "zz" "" script)))

  (add-to-list 'org-export-filter-subscript-functions
                 'test-filter)
  (add-to-list 'org-export-filter-subscript-functions
                 'test-filter2)

#+end_src

#+RESULTS:
| test-filter2 | test-filter |

* test 1

|                      | mathp             | text               |
|----------------------+-------------------+--------------------|
| merge maybe          | \alpha\beta_t     | \alpha\times_t     |
| long merge maybe     | \alpha\beta_tv\xi | \alpha\times_tv\xi |
| filter drop          | \alpha\beta_abc   | \alpha\times_abc   |
| filter replace all   | \alpha\beta_zz    | \alpha\times_zz    |
| filter replace parts | \alpha\beta_zz\xi | \alpha\times_zz\xi |
#+END_SRC

Approximate output

                     & mathp                           & text                              
=============================================================================================
merge maybe          & $\alpha$$\beta_{\text{t}}$      & $\alpha$\texttimes{}$_{\text{t}}$ 
long merge maybe     & $\alpha$$\beta_{\text{tv}\xi}$  & $\alpha$\texttimes{}$_{\text{tv}\xi}$
filter drop          & $\alpha$$\beta$                 & $\alpha$\texttimes{}              
filter replace all   & $\alpha$$\beta$                 & $\alpha$\texttimes{}              
filter replace parts & $\alpha$$\beta_{\xi}$           & $\alpha$\texttimes{}$_{\xi}$      


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-maybe-merge-subscript-and-mathp-entity-with-some-che.patch --]
[-- Type: text/x-diff, Size: 3440 bytes --]

From ebb7eb32b8ff18b9ff2c9d8686df1cdc6ed28bfb Mon Sep 17 00:00:00 2001
From: rasmus <rasmus@gmx.us>
Date: Thu, 29 Aug 2013 12:18:00 +0200
Subject: [PATCH] maybe merge subscript and mathp entity with some checks

---
 lisp/ox-latex.el | 51 +++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 39 insertions(+), 12 deletions(-)

diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index 1fe918a..cc8ac80 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -1234,9 +1234,26 @@ holding contextual information.  See `org-export-data'."
   "Transcode an ENTITY object from Org to LaTeX.
 CONTENTS are the definition itself.  INFO is a plist holding
 contextual information."
-  (let ((ent (org-element-property :latex entity)))
-    (if (org-element-property :latex-math-p entity) (format "$%s$" ent) ent)))
-
+  (let* ((ent (org-element-property :latex entity))
+	 (prev (org-export-get-previous-element entity info))
+	 (next (org-export-get-next-element entity info))
+	 (no-post-blanks-p (= (or (org-element-property :post-blank entity) 0) 0))
+	 (no-pre-blanks-p (= (or (org-element-property :post-blank prev) 0) 0))
+	 (scripts '(subscript superscript)))
+
+    (if (not (org-element-property :latex-math-p entity)) ent
+      (concat
+       (if (and no-pre-blanks-p
+		(memq (org-element-type prev) scripts)
+		;; check if nil
+		(org-export-data prev info))
+	   "" "$")
+       ent
+       (if (and no-post-blanks-p
+		(memq (org-element-type next) scripts)
+		;; check if nil
+		(org-export-data next info))
+	   "" "$")))))
 
 ;;;; Example Block
 
@@ -2217,8 +2234,14 @@ channel."
 			   (let ((blank (org-element-property :post-blank obj)))
 			     (and blank (> blank 0) "\\ "))))))
 	  (plain-text
-	   (setq output
-		 (format "%s\\text{%s}" output (org-export-data obj info))))
+	   (let ((out (or (org-export-filter-apply-functions
+			   org-export-filter-subscript-functions
+			   (org-export-data obj info)
+			   info) "")))
+	     (setq output
+		   (if (not (eq out ""))
+		       (format "%s\\text{%s}" output out)
+		     output))))
 	  (otherwise
 	   (setq output
 		 (concat output
@@ -2230,14 +2253,18 @@ channel."
     ;; or superscript.  Do not wrap into curly brackets if OUTPUT is
     ;; a single character.  Also merge consecutive subscript and
     ;; superscript into the same math snippet.
+    (if (not (eq output ""))
     (concat (and (not in-script-p)
 		 (let ((prev (org-export-get-previous-element object info)))
-		   (or (not prev)
-		       (not (eq (org-element-type prev)
-				(if (eq type 'subscript) 'superscript
-				  'subscript)))
-		       (let ((blank (org-element-property :post-blank prev)))
-			 (and blank (> blank 0)))))
+		   (and
+		    (not (and (eq (org-element-type prev) 'entity)
+			      (org-element-property :latex-math-p prev)))
+		    (or (not prev)
+			(not (eq (org-element-type prev)
+				 (if (eq type 'subscript) 'superscript
+				   'subscript)))
+			(let ((blank (org-element-property :post-blank prev)))
+			  (and blank (> blank 0))))))
 		 "$")
 	    (if (eq (org-element-type object) 'subscript) "_" "^")
 	    (and (> (length output) 1) "{")
@@ -2250,7 +2277,7 @@ channel."
 			       (org-export-get-next-element object info))
 			      (if (eq type 'subscript) 'superscript
 				'subscript))))
-		 "$"))))
+		 "$")))))
 
 (defun org-latex-subscript (subscript contents info)
   "Transcode a SUBSCRIPT object from Org to LaTeX.
-- 
1.8.4


[-- Attachment #3: Type: text/plain, Size: 27 bytes --]



--
Need more coffee. . .

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [patch][ox-latex] context-aware subscript
  2013-08-31 13:59               ` Rasmus
@ 2013-08-31 14:46                 ` Nicolas Goaziou
  0 siblings, 0 replies; 10+ messages in thread
From: Nicolas Goaziou @ 2013-08-31 14:46 UTC (permalink / raw)
  To: Rasmus; +Cc: emacs-orgmode

Rasmus <rasmus@gmx.us> writes:

> What I do in the patch is that I apply the filters within the
> function

Why is that? `org-export-data' already takes care of filters. These
calls are redundant.

> Also, filters using a regexp with "\text{whatever}" wouldn't work.

I don't get it.

>>> +	(scripts '(subscript superscript)))
>>> +    (if (not (org-element-property :latex-math-p entity)) ent
>>> +      (concat
>>> +       (if (and no-pre-blanks-p
>>> +		(memq (org-element-type prev) scripts)
>>> +		(not (eq (org-export-data prev info) "")))
>>> +	   "" "$")
>>> +       ent
>>> +       (if (and no-post-blanks-p
>>> +		(memq (org-element-type next) scripts)
>>> +		(not (eq (org-export-data next info) "")))
>>> +	   "" "$")))))
>>
>> I think this is problematic: if an entity needs to export both the
>> previous and the next object, what happens when we have two consecutive
>> entities? An infloop?
>
> I agree, but I haven't been able to cause any nasty behavior. I've
> probably neglected some case.  These works fine
>
>   1. \alpha\beta_t : \alpha is not a subscript
>   2. \alpha\beta_\xi\nu : runs OK recursively.

There's still some infloop smell around this code. Perhaps with
something like the following (untested):

  A_b^c

> On 2.: on my system I've tried with many entities (around 500).  It
> works, but obviously it's slow due to the recursiveness.This is very
> nasty.  I don't know if some other mechanism can be derived, tho. . .

`org-export-data' caches its results, so calling it more than once on
the same object/element isn't really costly.

> +  (let* ((ent (org-element-property :latex entity))
> +	 (prev (org-export-get-previous-element entity info))
> +	 (next (org-export-get-next-element entity info))
> +	 (no-post-blanks-p (= (or (org-element-property :post-blank entity) 0) 0))

aka `zerop' (slightly easier to read).

> +	 (no-pre-blanks-p (= (or (org-element-property :post-blank prev) 0) 0))


Ditto.

> +	 (scripts '(subscript superscript)))
> +
> +    (if (not (org-element-property :latex-math-p entity)) ent
> +      (concat
> +       (if (and no-pre-blanks-p
> +		(memq (org-element-type prev) scripts)
> +		;; check if nil
> +		(org-export-data prev info))
> +	   "" "$")
> +       ent
> +       (if (and no-post-blanks-p
> +		(memq (org-element-type next) scripts)
> +		;; check if nil
> +		(org-export-data next info))

You don't need to check for nil. `org-export-data' returns nil when the
element or object is ignored. But `org-export-get-previous-element'
never returns ignored objects or elements.

> +	   (let ((out (or (org-export-filter-apply-functions
> +			   org-export-filter-subscript-functions
> +			   (org-export-data obj info)
> +			   info) "")))

See above.

Thanks again.


Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2013-08-31 14:46 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-18  1:29 [patch][ox-latex] context-aware subscript Rasmus
2013-08-19  8:26 ` Nicolas Goaziou
2013-08-28 11:55   ` Rasmus
2013-08-28 13:38     ` Nicolas Goaziou
2013-08-28 13:46       ` Rasmus
2013-08-28 19:21         ` Nicolas Goaziou
2013-08-29 10:50           ` Rasmus
2013-08-31  8:11             ` Nicolas Goaziou
2013-08-31 13:59               ` Rasmus
2013-08-31 14:46                 ` Nicolas Goaziou

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).