How to customize org-mode html output to replace emojis? - org-mode

I have added emojis to my org-mode document like this:
bla bla :turtle: bla yadda
When looking at it through the GitHub viewer, they get substituted to the corresponding unicode character entities.
Which hooks I have to pull to get the same effect in org-mode html (esp. ox-reveal) export?

You can use the company-emoji package. Download it and then put the following in your init file:
(require 'company-emoji)
(add-to-list 'company-backends 'company-emoji)
It works for me with org-html-export-to-html. Don't know about ox-reveal though but would assume it will display the emojis as well.

It turns out that there is a customizable variable for this purpose:
org-export-html-protect-char-alist is a variable defined in `org-html.el'.
Its value is (("&" . "&") ("<" . "<") (">" . ">"))
Documentation:
Alist of characters to be converted by `org-html-protect'.
You can customize this variable.
This variable was introduced, or its default value was changed, in
version 24.1 of Emacs.
So for now (not being a hard-core Emacs Lisp user) I just put this in my .emacs:
(defcustom org-export-html-protect-char-alist
'(("&" . "&")
("<" . "<")
(">" . ">")
(":turtle:" . "🐢")
(":dash:" . "💨")
(":-)" . "😊")
(":-(" . "😞"))
"Alist of characters to be converted by `org-html-protect'."
:group 'org-export-html
:version "24.1"
:type '(repeat (cons (string :tag "Character")
(string :tag "HTML equivalent"))))
This works nicely, but maybe there is a better way to just append to the customizable variable?

Related

Org-mode Babels :file with link abbreviations

I have some link-abbreviations in org-mode like this:
(setq org-link-abbrev-alist
'(("dropboxpath" . "~/Dropbox")
("cloudpath" . "~/")
("imgpath" . "~/images")
("gitpath" . "~/git")
))
It works fine and as i am working on different systems and syncing my org-files the paths are different on every system. My problem is the following:
#+BEGIN_SRC plantuml :file gitpath:/test.png
<some plantumlstuff here>
#+END_SRC
This is not working, org-babel does not recognize the link abbreviation.
I also tried the following (where temp is a variable containing the path to the git-directory):
#+BEGIN_SRC plantuml :file (concat temp "/test.png")
This works in principle but gives me the following result:
#+RESULTS:
[[file:~/git/test.png]]
This does not meet my requirements though because i need gitpath in order to make it work over all my machines...
#+RESULTS:
[[gitpath:/test.png]]
Does anybody have a suitable solution to this problem?
You can simply refer to org-link-abbrev-alist. Since that variable is structured as an alist, you can use assoc. It returns the first element of the alist that matches the supplied key.
(concat
(car (assoc "gitpath" org-link-abbrev-alist))
"/test.png")

My Emacs mode does not highlight keywords

I am trying to write an Emacs major mode but it is not working; specifically, my keywords are not being displayed in keyword font face. I have tried to follow the tutorials but I must be doing something wrong. I know a little Lisp but I do not know Emacs scripting.
My Emacs mode script:
;; emacs mode for OldRope
;; does no work for some reason
(setq oldrope-directive-keywords-regexp (regexp-opt '("page" "link" "goto" "act" "end" "div" "span" "include")))
(defvar oldrope-font-lock-defaults '((
(oldrope-directive-keywords-regexp . font-lock-keyword-face))))
(define-derived-mode oldrope-mode fundamental-mode
"oldrope mode"
"Major mode for editing OldRope games"
(setq comment-start "/*")
(setq comment-end "*/")
(setq font-lock-defaults oldrope-font-lock-defaults))
(provide 'oldrope-mode)
Test file:
$[page start]$ Hello $[link]$ Click me $[act]$ That is right. $[end]$
(For context, this is part of https://github.com/martinellison/oldrope but that is not really relevant to the question).
You need this - the rest is OK:
(defvar oldrope-font-lock-defaults
`(((,oldrope-directive-keywords-regexp . font-lock-keyword-face))))
By simply quoting the list you were not evaluating oldrope-directive-keywords-regexp - your quoted list just had that symbol as its car.
Using either backquote (`) plus comma (,) or (list (list (cons oldrope-directive-keywords-regexp 'font-lock-keyword-face))) you evaluate that variable and use its value in the resulting list.

I am confused about how to use a variable in elisp

I try to set the font as below:
(let ((my:font "WenQuanYi Micro Hei Mono"))
(when (member my:font (font-family-list))
(set-face-attribute 'default nil :font my:font :width 'condensed)
(add-to-list 'default-frame-alist
'(font . my:font))))
The set-face-attribute works fine. I can see the font is set to WenQuanYi. But when I check the value of default-frame-alist, it shows as (font . my:font) and when try to create a new frame (emacsclient), I got this error:
*ERROR*: Invalid font: my:font
It looks like it try to use the value name as a font name. So I am not sure what's the right way to do it.
The quoted list '(font . my:font) produces a cons of those two symbols, rather than the value that you want. Instead of quote you can use either backquoting or a call to cons:
`(font ,my:font)
or
(cons 'font my:font)
You might be interested in the info pages (info "(elisp)Quoting") and (info "(elisp)Backquoting"), which explain those constructs in more detail.
On an unrelated note, the emacs lisp lexical conventions for local variables uses hyphens like-this, not colons like:this.

Customizing org-mode exports

So, I have been using org-mode for taking my research notes for some time now. I love how I can seamlessly export to both latex (for my papers) and html (for my blog). However, whenever I define macros with \newcommand with #+LATEX_HEADER, these do not show up in the HTML export at all.
I currently handle this by putting the all these commands as
(\newcommand \newcommand etc. etc.)
at the top and then manually removing the "(" and ")" from the tex file.
What I wish I could do was to keep a drawer for these commands and customize html and latex export of org mode to handle this drawer appropriately.
For example, I would add the following in the org file:
:LATEX_MACROS:
\newcommand{\norm}[1]{\lVert{#1}\rVert}
\newcommand{\abs}[1]{\lvert{#1}\rvert}
\newcommand{\half}{\frac{1}{2}}
:END:
And after export, this shows up in the latex file verbatim in header section
and in the html file as
\(
\newcommand{\norm}[1]{\lVert{#1}\rVert}
\newcommand{\abs}[1]{\lvert{#1}\rvert}
\newcommand{\half}{\frac{1}{2}}
\)
Here's a standalone way that works with Org, pdflatex and MathJax at the time of this writing. Make sure the drawers (or at least the LATEXMACROS drawer) are exported (this is the default), then insert near the top of the Org file:
#+OPTIONS: toc:nil
#+DRAWERS: LATEXMACROS ...
:LATEXMACROS:
##html:<div style="display: none">##
\(
\global\def\mymacro{...}
\global\def\mymacrow2args#1#2{...}
...
\)
##html:</div>##
:END:
#+TOC: headlines
This works around the following problems:
We have to use a math environment (here \( ... \)), otherwise Org escapes the TeX syntax.
We cannot use \newcommand, because LaTeX expects them to be in the preamble and MathJaX does not receive it. \newcommand can be used outside of the preamble, but then LaTeX (unlike MathJax) restricts the defined macros to the current math environment. We usually want to use them anywhere in the file.
We cannot use a plain \def because it behaves like \newcommand in terms of scoping (global for MathJax, local for LaTeX). We cannot use \xdef either because MathJax does not know it.
MathJax does not know \global but that won't prevent it from using \def which is global anyway. However, it will print a red warning for each \global in the web page. To get rid of them, we put the math environment inside an undisplayed HTML section.
For MathJax, the macros won't be defined in time for the table of content in its default location. If you use macros in headlines and want a TOC, disable the default with #+OPTIONS: toc:nil and manually add it after the drawer with #+TOC: headlines.
Caveats:
It's not possible to preview latex fragments which use custom macros, because the small TeX file Org build won't include our environment.
Unlike \newcommand, \def silently replaces anything. Also, its syntax is slightly different.
The math environment takes up some vertical space in the output of pdflatex, so we have to put it where that doesn't matter (e.g. before the first headline).
This is probably really version dependent:
Org mode may get better at exporting LaTeX macros (e.g. sending them to MathJax by being smarter when parsing #+LATEX_HEADER, providing a new export option, not escaping \newcommand and putting those into a correctly handled preamble).
MathJax may start accepting \xdef as an alias of \def or ignoring \global (so that the HTML section trick is not needed anymore).
I figured out how to do it myself. Note that this is perhaps not the most elegant solution since it does not place the latex part in the beginning of the latex file (i.e. outside \begin{document}), but it works well enough for me.
(setq org-export-blocks
(cons '(latexmacro org-export-blocks-latexmacro) org-export-blocks))
(defun org-export-blocks-latexmacro (body &rest headers)
(message "exporting latex macros")
(cond
((eq org-export-current-backend 'html) (concat "\\(" body "\\)"))
((eq org-export-current-backend 'latex) body)
(t nil))
)
Alternative solution (not stand-alone), using Org's dynamic blocks.
It has none of the caveats of my original solution (because it generates what Org actually expects for LaTeX or HTML)
It's possible to edit the macros in LaTeX mode (C-c C-')
Callback
Create a file named org-dblock-write:block-macro.el with the following content and add it to Emacs' load path.
(defun org-dblock-write:block-macro (params)
(let ((block-name (or (plist-get params :from) "macros"))
(org-buf (current-buffer)))
(with-temp-buffer
(let ((tmp-buf (current-buffer)))
(set-buffer org-buf)
(save-excursion
(org-babel-goto-named-src-block block-name)
(org-babel-mark-block)
(let ((mblock-begin (region-beginning))
(mblock-end (region-end)))
(set-buffer tmp-buf)
(insert-buffer-substring org-buf mblock-begin mblock-end)))
(set-buffer org-buf)
(insert "#+BEGIN_HTML\n\\(\n")
(insert-buffer-substring tmp-buf)
(insert "\\)\n#+END_HTML\n")
(set-buffer tmp-buf)
(beginning-of-buffer)
(while (re-search-forward "^" nil t)
(replace-match "#+LATEX_HEADER: " nil nil))
(set-buffer org-buf)
(insert-buffer-substring tmp-buf)))))
Org file
Somewhere in the file, create:
A LaTeX source block named "macros" containing your macros
An empty block-macro dynamic block
You can change the name of the source block, and use a :from <custom-name> header argument in the dynamic block. Also, note the :exports none in the source block (usually you don't want to export the LaTeX source).
#+NAME: macros
#+BEGIN_SRC latex :exports none
\newcommand\a{a}
\def\b{b}
\DeclareMathOperator\c{c}
#+END_SRC
#+BEGIN: block-macro
#+END:
Now use C-c C-c with the point on the dynamic block, and it will update to:
#+BEGIN: block-macro
#+BEGIN_HTML
\(
\newcommand\a{a}
\def\b{b}
\DeclareMathOperator\c{c}
\)
#+END_HTML
#+LATEX_HEADER: \newcommand\a{a}
#+LATEX_HEADER: \def\b{b}
#+LATEX_HEADER: \DeclareMathOperator\c{c}
#+LATEX_HEADER:
#+END:
Do this whenever the macros are modified.
I usually have a file with many custom definitions which I reuse for many documents and I want to use it also in my org documents.
The following is a modification of Blout's answer, so please read his answer for more info.
Define macro
(defun org-dblock-write:insert-latex-macros (params)
(let ((text)
(file (plist-get params :file)))
(with-temp-buffer
(insert-file file)
(setq text (split-string (buffer-string) "\n" t)))
(insert (mapconcat (lambda (str) (concat "#+LATEX_HEADER: " str)) text "\n"))
(insert "\n#+BEGIN_HTML\n\\(\n")
(insert (mapconcat 'identity text "\n"))
(insert "\n\\)\n#+END_HTML")))
Usage
File macros.tex:
\newcommand\a{a}
\def\b{b}
\DeclareMathOperator\c{c}
In org file:
#+BEGIN: insert-latex-macros :file "macros.tex"
#+BEGIN_HTML
\(
\newcommand\a{a}
\def\b{b}
\DeclareMathOperator\c{c}
\)
#+END_HTML
#+LATEX_HEADER: \newcommand\a{a}
#+LATEX_HEADER: \def\b{b}
#+LATEX_HEADER: \DeclareMathOperator\c{c}
#+LATEX_HEADER:
#+END:

Is there a BNF mode for Emacs?

I have to edit lots of grammar files in .bnf format. Is there a mode for this in Emacs?
I've looked at CEDET's semantic package, and it seems that it USED to have a bnf-mode, but not any more. This snippet is googlable, but semantic-bnf-mode doesn't seem to exist:
(autoload 'semantic-bnf-mode "semantic-bnf" "Mode for Bovine Normal Form." t)
(add-to-list 'auto-mode-alist '("\\.bnf$" . semantic-bnf-mode))
Thanks Don. I improved the code very slightly, here's a new version.
(define-generic-mode 'bnf-mode
() ;; comment char: inapplicable because # must be at start of line
nil ;; keywords
'(
("^#.*" . 'font-lock-comment-face) ;; comments at start of line
("^<.*?>" . 'font-lock-function-name-face) ;; LHS nonterminals
("<.*?>" . 'font-lock-builtin-face) ;; other nonterminals
("::=" . 'font-lock-const-face) ;; "goes-to" symbol
("\|" . 'font-lock-warning-face) ;; "OR" symbol
("\{:\\|:\}" . 'font-lock-keyword-face) ;; special pybnf delimiters
)
'("\\.bnf\\'" "\\.pybnf\\'") ;; filename suffixes
nil ;; extra function hooks
"Major mode for BNF highlighting.")
The Semantic bnf mode was for its own internal parser format. The original 'bnf' name was a pun that ended up confusing people.
The existing Semantic modes such as wisent-grammar-mode and bovine-grammar-mode are for the grammars used by CEDET, and the original bnf-mode was similar, and did not represent a real BNF style grammar.
You are probably more interested in ebnf2ps, which translates ebnf grammars (yacc, etc) into syntax charts, though I haven't used it myself.
To be more readable and findable as an answer, jmmcd answered his own question with the following. You can find more in the emacs Help > elisp > 23.2.6 Generic Modes.
"I put this in my .emacs and it seems to work."
(define-generic-mode 'bnf-mode
'("#")
nil
'(("^<.*?>" . 'font-lock-variable-name-face)
("<.*?>" . 'font-lock-keyword-face)
("::=" . 'font-lock-warning-face)
("\|" . 'font-lock-warning-face))
'("\\.bnf\\.pybnf\\'")
nil
"Major mode for BNF highlighting.")
I just created a GNU Emacs major mode for editing BNF grammars.
Currently provides basic syntax and font-locking for BNF files. EBNF and ABNF are in my plans for the near future.