[O] org-latex-classes with functions, incomplete doc

2013-02-10 Thread Florian Beck
Hi,

the docstring for `org-latex-classes' says:

Instead of a list of sectioning commands, you can also specify
a function name.  That function will be called with two
parameters, the (reduced) level of the headline, and a predicate
non-nil when the headline should be numbered.  It must return
a format string in which the section title will be added.

This is wrong. The way this function is called in `org-latex-headline'
requires it to return a string with TWO format specifiers, e.g.
\section{%%s}%%s\n, the second where the CONTENT of the section is
being added. Maybe `org-latex-headline' should add %%s\n itself – as
it does for other cases?

Also, I'm using this to add an optional argument to my sections. Can I
expect this to work? (i.e. being called in a context where the variables
`info' and `headline' are defined?)

#+BEGIN_SRC emacs-lisp
(defun fb/latex-sections (level numbered)
(let* ((level (1- level))
   (sec-name (nth level fb/latex-section-names))
   (sec (when sec-name
  (format \\%s%s%s{%%s}\n%%s
  sec-name
  (if numbered  *)
  ;; 
  (or (when (plist-get info :toc-title)
(let ((toc-title (org-element-property 
:toc-title headline)))
  (when toc-title (format [%s] toc-title
   )
  
  sec))
#+END_SRC


Org-mode version 7.9.3e (7.9.3e-961-g521d47 @ /home/flo/.emacs.d/org-mode/lisp/)
-- 
Florian Beck



Re: [O] org-latex-classes with functions, incomplete doc

2013-02-10 Thread Nicolas Goaziou
Hello,

Florian Beck f...@miszellen.de writes:

 the docstring for `org-latex-classes' says:

 Instead of a list of sectioning commands, you can also specify
 a function name.  That function will be called with two
 parameters, the (reduced) level of the headline, and a predicate
 non-nil when the headline should be numbered.  It must return
 a format string in which the section title will be added.

 This is wrong. The way this function is called in `org-latex-headline'
 requires it to return a string with TWO format specifiers, e.g.
 \section{%%s}%%s\n, the second where the CONTENT of the section is
 being added. Maybe `org-latex-headline' should add %%s\n itself – as
 it does for other cases?

Indeed. It's now the case. Thanks for reporting this.

 Also, I'm using this to add an optional argument to my sections. Can I
 expect this to work? (i.e. being called in a context where the variables
 `info' and `headline' are defined?)

 #+BEGIN_SRC emacs-lisp
 (defun fb/latex-sections (level numbered)
 (let* ((level (1- level))
(sec-name (nth level fb/latex-section-names))
(sec (when sec-name
   (format \\%s%s%s{%%s}\n%%s
   sec-name
   (if numbered  *)
   ;; 
   (or (when (plist-get info :toc-title)
 (let ((toc-title (org-element-property 
 :toc-title headline)))
   (when toc-title (format [%s] toc-title
)
   
   sec))
 #+END_SRC

Actually, the proper way to do this is to define a derived back-end with
a custom headline translation function.

#+begin_src emacs-lisp
(org-export-define-derived-backend my-latex latex
  :translate-alist ((headline . fb/my-latex-headline)))

(defun fb/my-latex-headline (headline contents info)
  ...
  Do whatever you want here)
#+end_src

Also, you can use `org-export-with-backend' as a fallback case for your
custom function.

From there you can use:

  (org-export-to-buffer 'my-latex *My own export*)

or,

  (org-export-to-file 'my-latex some-file.tex)

You may wrap the previous calls into an interactive command (just copy
and adapt from those in ox-latex.el). For example:

#+begin_src emacs-lisp
(defun fb/my-latex-export-to-latex
  (optional async subtreep visible-only body-only ext-plist)
  (interactive)
  (let ((outfile (org-export-output-file-name .tex subtreep)))
(if async
(org-export-async-start
(lambda (f) (org-export-add-to-stack f 'my-latex))
  `(expand-file-name
(org-export-to-file
 'my-latex ,outfile ,subtreep ,visible-only ,body-only 
',ext-plist)))
  (org-export-to-file
   'my-latex outfile subtreep visible-only body-only ext-plist
#+end_src

Optionally, you can add an entry in the dispatcher for your new command:

#+begin_src emacs-lisp
(org-export-define-derived-backend my-latex latex
  :translate-alist ((headline . fb/my-latex-headline))
  :menu-entry
  (?l 2 ((?m With my special extension fb/my-latex-export-to-latex
#+end_src


Regards,

-- 
Nicolas Goaziou



Re: [O] org-latex-classes with functions, incomplete doc

2013-02-10 Thread Florian Beck
Thanks for your explanations, very much appreciated.

Nicolas Goaziou n.goaz...@gmail.com writes:

 the proper way to do this is to define a derived back-end with
 a custom headline translation function.

Ok, I tried this. There is a problem, however. This is what I came up
with:

#+BEGIN_SRC emacs-lisp
(defun fb/org-latex-headline (headline contents info)
  (let* ((full-section (org-latex-headline headline contents info))
 (toc-title (if (plist-get info :toc-title)
(org-element-property :toc-title headline)))
 (section-regex \\`\\(sub\\)*\\(section\\|paragraph\\){)
 (new-section
  (when (and toc-title
 (string-match section-regex full-section))
(let ((subs (match-string 1 full-section))
  (section (match-string 2 full-section))
  (rest (substring full-section (match-end 0
  (concat
   \\ subs section [
   ;; replace brackets (from `org-latex-headline')
   (replace-regexp-in-string
\\[ (
(replace-regexp-in-string
 \\] )
 toc-title))
   ]{ rest)
(or new-section
full-section)))
#+END_SRC

As you can see, the solution is much more convoluted.

The reason is that I have to parse the string returned by
`org-latex-headline' or am I missing something? I ran into a similar
problem while adding padding (\n - [0.4em]\n) to table
rows.

IMO, the probem is this: the translation is (mostly) application of
content to a template (a format string), but these templates are build
(mostly, sectioning is actually an exception) inside the default
translation functions. It would be much easier, when this template would
be accessible from outside, like this:

#+BEGIN_SRC emacs-lisp
(defun my-org-latex-headline (headline contents info)
  (let ((sec-format 
 (plist-get info :sec-format))) ;; or something like that
[modify sec-format]
(plist-put info :sec-format sec-format)
(org-latex-headline)))
#+END_SRC

The same goes for other functions.

--
Florian Beck



Re: [O] org-latex-classes with functions, incomplete doc

2013-02-10 Thread Nicolas Goaziou
Florian Beck f...@miszellen.de writes:

 Ok, I tried this. There is a problem, however. This is what I came up
 with:

 #+BEGIN_SRC emacs-lisp
 (defun fb/org-latex-headline (headline contents info)
   (let* ((full-section (org-latex-headline headline contents info))

I suggest (org-export-with-backend 'latex headline contents info) to not
depend on the actual name of the translator.

(toc-title (if (plist-get info :toc-title)
   (org-element-property :toc-title headline)))

There's no :toc-title property in the communication channel. The
exhaustive list of its properties is written in ox.el, at The
Communication Channel section.

(section-regex \\`\\(sub\\)*\\(section\\|paragraph\\){)
(new-section
 (when (and toc-title
(string-match section-regex full-section))
   (let ((subs (match-string 1 full-section))
 (section (match-string 2 full-section))
 (rest (substring full-section (match-end 0
 (concat
  \\ subs section [
  ;; replace brackets (from `org-latex-headline')
  (replace-regexp-in-string
   \\[ (
   (replace-regexp-in-string
\\] )
toc-title))
  ]{ rest)
 (or new-section
   full-section)))
 #+END_SRC

 As you can see, the solution is much more convoluted.

Because you're not using the proper tool. If you just want to modify the
string returned by the `latex' back-end, use a filter. You will have
access to the transcoded headline (in LaTeX format, as a string) and the
communication channel.

#+begin_src emacs-lisp
(defun fb/my-headline-transformation (headline backend info)
  (when (eq backend 'latex)
;; Here HEADLINE is the output from `latex' back-end, as a string.
...
))

(add-to-list 'org-export-filter-headline-functions
 'fb/my-headline-transformation)
#+end_src

What I suggest gives you access to the headline as parsed data. This is
much more powerful, but a completely different task.

 IMO, the probem is this: the translation is (mostly) application of
 content to a template (a format string), but these templates are build
 (mostly, sectioning is actually an exception) inside the default
 translation functions. It would be much easier, when this template would
 be accessible from outside, like this:

There are already many ways to alter output from a back-end. It's just
a matter of using the right tool.


Regards,

-- 
Nicolas Goaziou



Re: [O] org-latex-classes with functions, incomplete doc

2013-02-10 Thread Florian Beck
Nicolas Goaziou n.goaz...@gmail.com writes:

   (toc-title (if (plist-get info :toc-title)
  (org-element-property :toc-title headline)))

 There's no :toc-title property in the communication channel. The
 exhaustive list of its properties is written in ox.el, at The
 Communication Channel section.

Obviouly, I defined it, otherwise it wouldn't work.

  :options-alist ((:toc-title TOC_TITLE nil nil t) ... )

 As you can see, the solution is much more convoluted.

 Because you're not using the proper tool. If you just want to modify the
 string returned by the `latex' back-end, use a filter. You will have
 access to the transcoded headline (in LaTeX format, as a string) and the
 communication channel.

But not to the element properties, which is what I need.

 There are already many ways to alter output from a back-end. It's just
 a matter of using the right tool.

So, which is it? I'm a bit confused right now.

-- 
Florian Beck



Re: [O] org-latex-classes with functions, incomplete doc

2013-02-10 Thread Nicolas Goaziou
Florian Beck f...@fbeck.net writes:

 Nicolas Goaziou n.goaz...@gmail.com writes:

  (toc-title (if (plist-get info :toc-title)
 (org-element-property :toc-title headline)))

 There's no :toc-title property in the communication channel. The
 exhaustive list of its properties is written in ox.el, at The
 Communication Channel section.

 Obviouly, I defined it, otherwise it wouldn't work.

   :options-alist ((:toc-title TOC_TITLE nil nil t) ... )

 As you can see, the solution is much more convoluted.

 Because you're not using the proper tool. If you just want to modify the
 string returned by the `latex' back-end, use a filter. You will have
 access to the transcoded headline (in LaTeX format, as a string) and the
 communication channel.

 But not to the element properties, which is what I need.

 There are already many ways to alter output from a back-end. It's just
 a matter of using the right tool.

 So, which is it? I'm a bit confused right now.

I now get what you intend to do (or so I think).

I didn't implement this feature in ox-latex.el, mainly because a proper
implementation needs to be done at the ox.el level.

Anyway, we're back to step one: if you want to handle headlines
differently (i.e. by adding your own properties), you need to fork
`latex' back-end, as explained before. If you encounter problems, you
can post back here.


Regards,

-- 
Nicolas Goaziou