emacs-orgmode
[Top][All Lists]
Advanced

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

Re: [O] [New exporter] custom emphasis in org-emphasis-alist


From: Gregor Kappler
Subject: Re: [O] [New exporter] custom emphasis in org-emphasis-alist
Date: Thu, 14 Feb 2013 18:42:12 +0100
User-agent: Notmuch/0.15.1+13~g7264732 (http://notmuchmail.org) Emacs/24.3.50.1 (i686-pc-linux-gnu)

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 <address@hidden> writes:

> Hello,
>
> Gregor Kappler <address@hidden> 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




reply via email to

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