* [New exporter] custom emphasis in org-emphasis-alist
@ 2013-02-10 0:32 Gregor Kappler
2013-02-10 0:55 ` François Pinard
2013-02-10 8:37 ` Nicolas Goaziou
0 siblings, 2 replies; 5+ messages in thread
From: Gregor Kappler @ 2013-02-10 0:32 UTC (permalink / raw)
To: emacs-orgmode
Cudos for all the work that has been done on migrating to the new
exporter. I so welcome that exporting now is approaching a clean
design!
I am currently migrating my system and contribute my first stop:
custom emphasis characters that I use extensively:
- "!" is used for exclamations,
- "?" for questions, and
- "#" for in-text comments that I do not want exported.
This is my org-emphasis-alist configuration:
#+BEGIN_SRC emacs-lisp
(setq org-emphasis-alist
(quote (("*" bold "<b>" "</b>")
("/" italic "<i>" "</i>")
("_" underline "<span style=\"text-decoration:underline;\">" "</span>")
("=" (:box t :foreground "#AAF") "<code>" "</code>" verbatim)
("~" org-headline-done "<u>" "</u>" verbatim)
("+" (:strike-through t) "<del>" "</del>")
("?" gk-org-question "<span class=\"org-question\">" "</span>")
("!" gk-org-exclamation "<span class=\"org-exclamation\">" "</span>")
("#" font-lock-comment-face "<!--" "-->"))))
#+END_SRC
These emphases are currently not working . During debugging I found
the following to be the reason: Though
org-element-text-markup-successor recognizes emphasis by using
org-emph-re, it returns only one of a set of hard-coded symbols
(`bold', `italic', `underline', `strike-through', `code' and
`verbatim').
IMHO org-element-text-markup-successor should recognize
org-emphasis-alist. Maybe return the face configured in the cadr of
the respective org-emphasis-alist element. However, the drawback
would be that this would disenable "quick-and-dirty" face
specification as with (:box t :foreground "#AAF") above.
On the other hand, I do not know how plans with org-emphasis-alist
are, as caddr,... for html export and org-export-latex-emphasis-alist
probably are obsolete with the new exporter.
With the following setup, the following test case worked. However,
changing deconsts and defuns in org-element surely is not a good
approach. Do you have any suggestions?
Thank you all for your amazing work on orgmode,
Gregor
* Test Case
With these settings these work: the test *bold*, (invisible comment?!), and .
But these still do not work: *bold*, (\leftarrow invisible comment?!), !exclamation! and ?question?. These examples stop working after the comment.
: (org-export-to-file 'my-html "test.html")
* Changes
I played around further by adding lines to
org-element-text-markup-successor
#+BEGIN_SRC emacs-lisp
(defun org-element-text-markup-successor (limit)
"Search for the next text-markup object.
LIMIT bounds the search.
Return value is a cons cell whose CAR is a symbol among `bold',
`italic', `underline', `strike-through', `code' and `verbatim'
and CDR is beginning position."
(save-excursion
(unless (bolp) (backward-char))
(when (re-search-forward org-emph-re limit t)
(let ((marker (match-string 3)))
(cons (cond
((equal marker "*") 'bold)
((equal marker "/") 'italic)
((equal marker "_") 'underline)
((equal marker "+") 'strike-through)
((equal marker "~") 'code)
((equal marker "=") 'verbatim)
((equal marker "#") 'emph-comment)
((equal marker "?") 'emph-question)
((equal marker "!") 'emph-exclamation)
(t (error "Unknown marker at %d" (match-beginning 3))))
(match-beginning 2))))))
#+END_SRC
and then trying to define org-element-emph-comment-parser copy-pasting
org-element-italic-parser:
#+BEGIN_SRC emacs-lisp
(defun org-element-emph-comment-parser ()
"Parse comment object at point.
Return a list whose CAR is `italic' and CDR is a plist with
`:begin', `:end', `:contents-begin' and `:contents-end' and
`:post-blank' keywords.
Assume point is at the first # marker."
(save-excursion
(unless (bolp) (backward-char 1))
(looking-at org-emph-re)
(let ((begin (match-beginning 2))
(contents-begin (match-beginning 4))
(contents-end (match-end 4))
(post-blank (progn (goto-char (match-end 2))
(skip-chars-forward " \t")))
(end (point)))
(list 'emph-comment
(list :begin begin
:end end
:contents-begin contents-begin
:contents-end contents-end
:post-blank post-blank)))))
(defun org-element-emph-comment-interpreter (italic contents)
"Interpret ITALIC object as Org syntax.
CONTENTS is the contents of the object."
(format "#%s#" contents))
(defun org-element-emph-exclamation-parser ()
"Parse exclamation object at point.
Return a list whose CAR is `italic' and CDR is a plist with
`:begin', `:end', `:contents-begin' and `:contents-end' and
`:post-blank' keywords.
Assume point is at the first # marker."
(save-excursion
(unless (bolp) (backward-char 1))
(looking-at org-emph-re)
(let ((begin (match-beginning 2))
(contents-begin (match-beginning 4))
(contents-end (match-end 4))
(post-blank (progn (goto-char (match-end 2))
(skip-chars-forward " \t")))
(end (point)))
(list 'emph-exclamation
(list :begin begin
:end end
:contents-begin contents-begin
:contents-end contents-end
:post-blank post-blank)))))
(defun org-element-emph-exclamation-interpreter (italic contents)
"Interpret ITALIC object as Org syntax.
CONTENTS is the contents of the object."
(format "?%s?" contents))
(defun org-element-emph-question-parser ()
"Parse question object at point.
Return a list whose CAR is `italic' and CDR is a plist with
`:begin', `:end', `:contents-begin' and `:contents-end' and
`:post-blank' keywords.
Assume point is at the first # marker."
(save-excursion
(unless (bolp) (backward-char 1))
(looking-at org-emph-re)
(message "%s" (match-string 4))
(let ((begin (match-beginning 2))
(contents-begin (match-beginning 4))
(contents-end (match-end 4))
(post-blank (progn (goto-char (match-end 2))
(skip-chars-forward " \t")))
(end (point)))
(list 'emph-question
(list :begin begin
:end end
:contents-begin contents-begin
:contents-end contents-end
:post-blank post-blank)))))
(defun org-element-emph-question-interpreter (italic contents)
"Interpret ITALIC object as Org syntax.
CONTENTS is the contents of the object."
(format "?%s?" contents))
#+END_SRC
(Considering that I only changed the defun name and emph-comment, to me this seems a lot of duplicate code. I am a mere elisp novice without knowledge of macros - but would this not be a case to use macros or similar in order to ease things?)
Stealing from org-html-italic
#+BEGIN_SRC emacs-lisp
(add-to-list 'org-html-text-markup-alist '(emph-comment . ""))
(add-to-list 'org-html-text-markup-alist '(emph-exclamation . "<span class=\"org-exclamation\">%s</span>"))
(add-to-list 'org-html-text-markup-alist '(emph-question . "<span class=\"org-question\">%s</span>"))
(defun my-emph-comment (text contents info)
"Transcode a comment emphasis element from Org to latex.
CONTENTS is nil. INFO is a plist used as a communication
channel."
(message "comment %s" contents)
(format (or (cdr (assq 'emph-comment org-html-text-markup-alist)) "%s") contents))
(defun my-emph-exclamation (text contents info)
"Transcode a comment emphasis element from Org to latex.
CONTENTS is nil. INFO is a plist used as a communication
channel."
(message "exclamation %s" contents)
(format (or (cdr (assq 'emph-exclamation org-html-text-markup-alist)) "%s") contents))
(defun my-emph-question (text contents info)
"Transcode a comment emphasis element from Org to latex.
CONTENTS is nil. INFO is a plist used as a communication
channel."
;;(fux)
(message "question %s" contents)
(format (or (cdr (assq 'emph-question org-html-text-markup-alist)) "%s") contents))
(org-export-define-derived-backend my-html html
:translate-alist ((emph-comment . my-emph-comment)
(emph-exclamation . my-emph-exclamation)
(emph-question . my-emph-question)))
#+END_SRC
(again, this seems a lot of duplicate code...)
With this change, contents always was passed nil...
So I digged further into org-element.el - and finally by experimenting found that adding my new elements to
#+BEGIN_SRC emacs-lisp
(defconst org-element-recursive-objects
'(emph-question emph-exclamation emph-comment bold italic link subscript radio-target strike-through superscript
table-cell underline)
"List of recursive object types.")
#+END_SRC
resulted in a (partly) working solution. Yet, bold and italic occur quite often hard-coded in org-element.el.
--
Dr. Gregor Kappler
Fakultät für Psychologie
Institut für Angewandte Psychologie: Gesundheit,
Entwicklung, Förderung
Universität Wien
Liebiggasse 5
A-1010 Wien
http://www.univie.ac.at/Psychologie
tel: +43 1 4277 47276
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [New exporter] custom emphasis in org-emphasis-alist
2013-02-10 0:32 [New exporter] custom emphasis in org-emphasis-alist Gregor Kappler
@ 2013-02-10 0:55 ` François Pinard
2013-02-10 8:37 ` Nicolas Goaziou
1 sibling, 0 replies; 5+ messages in thread
From: François Pinard @ 2013-02-10 0:55 UTC (permalink / raw)
To: emacs-orgmode
Gregor Kappler <g.kappler@gmx.net> writes:
> Cudos for all the work that has been done on migrating to the new
> exporter. I so welcome that exporting now is approaching a clean
> design!
Let me join my voice to the chorus! Munch congratulations, and thanks!
There is an impressive amount of work in all this, it has been a major
undertaking. I'm very glad to see that is now in the process of falling
back into place in a definitive way. Very good news for us all!
François
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [New exporter] custom emphasis in org-emphasis-alist
2013-02-10 0:32 [New exporter] custom emphasis in org-emphasis-alist Gregor Kappler
2013-02-10 0:55 ` François Pinard
@ 2013-02-10 8:37 ` Nicolas Goaziou
2013-02-10 9:45 ` Nicolas Goaziou
2013-02-14 17:42 ` Gregor Kappler
1 sibling, 2 replies; 5+ messages in thread
From: Nicolas Goaziou @ 2013-02-10 8:37 UTC (permalink / raw)
To: Gregor Kappler; +Cc: emacs-orgmode
Hello,
Gregor Kappler <g.kappler@gmx.net> writes:
> I am currently migrating my system and contribute my first stop:
> custom emphasis characters that I use extensively:
> - "!" is used for exclamations,
> - "?" for questions, and
> - "#" for in-text comments that I do not want exported.
Emphasis characters are now hard-coded. You cannot change them, though,
you can change how each back-end interprets them.
We are solidifying Org syntax for parsing purposes. Allowing variable
markup is asking for trouble. The plan is to make `org-emphasis-alist'
a defconst.
On the other hand, you may be able to parse custom markup with the help
of a filter:
#+begin_src emacs-lisp
(defun my-special-markup (text backend info)
(when (and (org-export-derived-backend-p backend 'html)
(string-match "\\([ ('\"{]\\|^\\)\\(\\([?!#]\\)\\([^
,\"']\\|[^
,\"'].*?\\(?:
.*?\\)\\{0,1\\}[^
,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"
text))
(format (cond ((equal (match-string 3 text) "?")
"<span class=\"org-question\">%s</span>")
((equal (match-string 3 text) "#") "<!--%s-->")
(t "<span class=\"org-exclamation\">%s</span>"))
(match-string 4 text))))
(add-to-list 'org-export-filter-plain-text-functions 'my-special-markup)
#+end_src
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [New exporter] custom emphasis in org-emphasis-alist
2013-02-10 8:37 ` Nicolas Goaziou
@ 2013-02-10 9:45 ` Nicolas Goaziou
2013-02-14 17:42 ` Gregor Kappler
1 sibling, 0 replies; 5+ messages in thread
From: Nicolas Goaziou @ 2013-02-10 9:45 UTC (permalink / raw)
To: Gregor Kappler; +Cc: emacs-orgmode
Completing myself,
> On the other hand, you may be able to parse custom markup with the help
> of a filter:
>
> #+begin_src emacs-lisp
> (defun my-special-markup (text backend info)
> (when (and (org-export-derived-backend-p backend 'html)
> (string-match "\\([ ('\"{]\\|^\\)\\(\\([?!#]\\)\\([^
> ,\"']\\|[^
> ,\"'].*?\\(?:
> .*?\\)\\{0,1\\}[^
> ,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"
> text))
> (format (cond ((equal (match-string 3 text) "?")
> "<span class=\"org-question\">%s</span>")
> ((equal (match-string 3 text) "#") "<!--%s-->")
> (t "<span class=\"org-exclamation\">%s</span>"))
> (match-string 4 text))))
> (add-to-list 'org-export-filter-plain-text-functions 'my-special-markup)
> #+end_src
This solution will not work but in the simplest cases (no special
markup allowed within the tags).
For additional syntax, a better option would be to define a macro:
#+MACRO: excl @@html:<span class="org-exclamation">@@$1@@html:</span>@@
Then use it within the buffer:
A paragraph and {{{excl(some *bold* text within a special
container)}}}.
This allow for some flexibility. You can even define a babel block and
call it within a paragraph for more complicated (i.e. conditional)
stuff.
Regards,
--
Nicolas Goaziou
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [New exporter] custom emphasis in org-emphasis-alist
2013-02-10 8:37 ` Nicolas Goaziou
2013-02-10 9:45 ` Nicolas Goaziou
@ 2013-02-14 17:42 ` Gregor Kappler
1 sibling, 0 replies; 5+ messages in thread
From: Gregor Kappler @ 2013-02-14 17:42 UTC (permalink / raw)
To: Nicolas Goaziou; +Cc: emacs-orgmode
Hi Nicolas,
thanks for your replies. I can see that for org syntax stability and to prevent parsing hassle using a variety of characters for emphasis is not desireable. On the other hand, org-emphasis-alist had several advantages that seem not possible with your suggestions.
When writing, I frequently mark up and fontify text for review or important text parts (each, ? and ! used ~1000 times in my org files). The fontification in org provided a perfect overview of what still needs attention.
> For additional syntax, a better option would be to define a macro:
>
> #+MACRO: excl @@html:<span class="org-exclamation">@@$1@@html:</span>@@
>
> Then use it within the buffer:
>
> A paragraph and {{{excl(some *bold* text within a special
> container)}}}.
This solution is charactery/wordy but I could work with some editing sugar (abbrevs, remove-macro-keys,...). Yet I loose the fontification feature that I appreciate highly.
For now, I took the road of adding a filter as you suggested, and made it configurable with format strings for latex and html. Also, I implemented org highlighting (borrowing from `org-set-emph-re' and `org-do-emphasis-faces').
This solution now works for me. If anyone else has custom emphasis markers, and wants to keep them (like I did) the following code might be usable.
Thank you very much for your help!
Gregor
Your markup filter code did not replace multiple occurences and had hard-coded regexps, so I adapted your markup code:
#+begin_src emacs-lisp
(require 'ox)
(defun gk-emphasis-markup (text backend info)
(let ((formats (assoc backend gk-org-export-emphasis)))
(when formats
(let ((start 0) (result ""))
(while (string-match gk-org-emph-re text start)
(setq result
(concat result
(substring text start (match-beginning 2))
(format (cadr (assoc (match-string 3 text) formats))
(match-string 4 text))))
(setq start (- (match-end 0) 1)))
(concat result
(if
(substring text start (length text))
""))))))
(add-to-list 'org-export-filter-plain-text-functions 'gk-emphasis-markup)
#+end_src
The formating strings are configured
#+begin_src emacs-lisp
(setq gk-org-export-emphasis
'((html . (("?" "<span class=\"org-question\">%s</span>")
("!" "<span class=\"org-exclamation\">%s</span>")
("#" "")))
(latex . (("?" "\\mycheck{%s}")
("!" "\\myexcl{%s}")
("#" "")))))
#+end_src
Org highlighting for the custom emphasis list (adapted from `org-set-emph-re')
#+BEGIN_SRC emacs-lisp :tangle "~/Documents/Programme/elisp/my-org-mode.el"
(setq gk-org-emphasis-alist
(quote (
("?" gk-org-question)
("!" gk-org-exclamation)
("#" font-lock-comment-face))))
(setq gk-org-emph-re
(let* ((e org-emphasis-regexp-components)
(pre (car e))
(post (nth 1 e))
(border (nth 2 e))
(body (nth 3 e))
(nl (nth 4 e))
(body1 (concat body "*?"))
(markers (mapconcat 'car gk-org-emphasis-alist ""))
(vmarkers (mapconcat
(lambda (x) (if (eq (nth 4 x) 'verbatim) (car x) ""))
gk-org-emphasis-alist "")))
;; make sure special characters appear at the right position in the class
(if (string-match "\\^" markers)
(setq markers (concat (replace-match "" t t markers) "^")))
(if (string-match "-" markers)
(setq markers (concat (replace-match "" t t markers) "-")))
(if (string-match "\\^" vmarkers)
(setq vmarkers (concat (replace-match "" t t vmarkers) "^")))
(if (string-match "-" vmarkers)
(setq vmarkers (concat (replace-match "" t t vmarkers) "-")))
(if (> nl 0)
(setq body1 (concat body1 "\\(?:\n" body "*?\\)\\{0,"
(int-to-string nl) "\\}")))
;; Make the regexp
(concat "\\([" pre "]\\|^\\)"
"\\("
"\\([" markers "]\\)"
"\\("
"[^" border "]\\|"
"[^" border "]"
body1
"[^" border "]"
"\\)"
"\\3\\)"
"\\([" post "]\\|$\\)")))
#+END_SRC
The emphasis function (adapted `org-do-emphasis-faces') then is added as font-lock
#+BEGIN_SRC emacs-lisp :tangle "~/Documents/Programme/elisp/my-org-mode.el"
(defun gk-org-do-emphasis-faces (limit)
"Run through the buffer and add overlays to emphasized strings."
(let (rtn a)
(while (and (not rtn) (re-search-forward gk-org-emph-re limit t))
(if (not (= (char-after (match-beginning 3))
(char-after (match-beginning 4))))
(progn
(setq rtn t)
(setq a (assoc (match-string 3) gk-org-emphasis-alist))
(font-lock-prepend-text-property (match-beginning 2) (match-end 2)
'face
(nth 1 a))
(and (nth 4 a)
(org-remove-flyspell-overlays-in
(match-beginning 0) (match-end 0)))
(add-text-properties (match-beginning 2) (match-end 2)
'(font-lock-multiline t org-emphasis t))
(when org-hide-emphasis-markers
(add-text-properties (match-end 4) (match-beginning 5)
'(invisible org-link))
(add-text-properties (match-beginning 3) (match-end 3)
'(invisible org-link)))))
(backward-char 1))
rtn))
(font-lock-add-keywords
'org-mode '(gk-org-do-emphasis-faces))
#+END_SRC
Maybe the duplication of code could be prevented by including functions `org-set-emph-re' and `org-do-emphasis-faces' with dynamical scoping?
Nicolas Goaziou <n.goaziou@gmail.com> writes:
> Hello,
>
> Gregor Kappler <g.kappler@gmx.net> writes:
>
>> I am currently migrating my system and contribute my first stop:
>> custom emphasis characters that I use extensively:
>> - "!" is used for exclamations,
>> - "?" for questions, and
>> - "#" for in-text comments that I do not want exported.
>
> Emphasis characters are now hard-coded. You cannot change them, though,
> you can change how each back-end interprets them.
>
> We are solidifying Org syntax for parsing purposes. Allowing variable
> markup is asking for trouble. The plan is to make `org-emphasis-alist'
> a defconst.
>
> On the other hand, you may be able to parse custom markup with the help
> of a filter:
>
> #+begin_src emacs-lisp
> (defun my-special-markup (text backend info)
> (when (and (org-export-derived-backend-p backend 'html)
> (string-match "\\([ ('\"{]\\|^\\)\\(\\([?!#]\\)\\([^
> ,\"']\\|[^
> ,\"'].*?\\(?:
> .*?\\)\\{0,1\\}[^
> ,\"']\\)\\3\\)\\([- .,:!?;'\")}\\]\\|$\\)"
> text))
> (format (cond ((equal (match-string 3 text) "?")
> "<span class=\"org-question\">%s</span>")
> ((equal (match-string 3 text) "#") "<!--%s-->")
> (t "<span class=\"org-exclamation\">%s</span>"))
> (match-string 4 text))))
> (add-to-list 'org-export-filter-plain-text-functions 'my-special-markup)
> #+end_src
>
>
> Regards,
>
> --
> Nicolas Goaziou
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-02-14 17:50 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-10 0:32 [New exporter] custom emphasis in org-emphasis-alist Gregor Kappler
2013-02-10 0:55 ` François Pinard
2013-02-10 8:37 ` Nicolas Goaziou
2013-02-10 9:45 ` Nicolas Goaziou
2013-02-14 17:42 ` Gregor Kappler
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).