Download
(eval-when-compile (require 'cl))
(require 'erc)
(defvar erc-tex-latex-program "latex"
"Program name for invoking LaTeX.")
(defvar erc-tex-dvipng-program "dvipng"
"Program name for invoking dvipng.")
(defvar erc-tex-image-size 1.2
"Ratio of magnification.")
(put 'erc-tex-bad-expression-error
'error-conditions '(error erc-tex-bad-expression-error))
(defsubst erc-tex-run-latex (&rest arguments)
"Launch LaTeX program with some arguments."
(unless (zerop (apply #'call-process erc-tex-latex-program nil nil nil arguments))
(signal 'erc-tex-bad-expression-error nil)))
(defsubst erc-tex-run-dvipng (&rest arguments)
"Launch dvipng program with some arguments."
(unless (zerop (apply #'call-process erc-tex-dvipng-program nil nil nil arguments))
(signal 'erc-tex-bad-expression-error nil)))
(defun erc-tex-make-image (math-expression fg bg)
(condition-case nil
(let* ((prefix (concat temporary-file-directory (make-temp-name "erc-tex-")))
(tex-file (concat prefix ".tex"))
(dvi-file (concat prefix ".dvi"))
(png-file (concat prefix ".png")))
(with-temp-file tex-file
(insert "\\documentclass{article}\n"
"\\pagestyle{empty}\n"
"\\usepackage{amsmath, amssymb, amsthm}\n"
"\\begin{document}\n"
"\\par\n"
"$" math-expression "$"
"\\end{document}\n"))
(erc-tex-run-latex (concat "-output-directory=" temporary-file-directory) tex-file)
(flet ((colorize (color)
(let ((max (car (color-values "#ffffff"))))
(destructuring-bind (r g b)
(color-values color)
(format "rgb %.02f %.02f %.02f"
(/ (float r) max)
(/ (float g) max)
(/ (float b) max))))))
(erc-tex-run-dvipng "-x" (number-to-string (floor (* 1000 erc-tex-image-size)))
"-T" "tight"
"-fg" (colorize fg)
"-bg" (colorize bg)
"-o" png-file
dvi-file))
(delete-file tex-file)
(delete-file dvi-file)
(create-image png-file 'png nil :margin '(0 . 5) :ascent 'center))
((erc-tex-bad-expression-error)
)))
(defvar erc-tex-image-keymap
(let ((keymap (make-sparse-keymap)))
(define-key keymap (kbd "RET") 'erc-tex-image-edit)
keymap))
(defun erc-tex-image-edit ()
(interactive)
(let* ((start (point))
(i start)
(prop (get-char-property i 'display)))
(while (eq prop (get-char-property i 'display))
(setq i (1+ i)))
(goto-char (point-max))
(insert (buffer-substring-no-properties start i))))
(defun erc-tex-render (&optional fg bg)
(let ((fg (or fg (face-foreground 'default)))
(bg (or bg (face-background 'default))))
(goto-char (point-min))
(while (re-search-forward "\\$[^$]*\\$" nil t)
(let* ((match (match-string-no-properties 0))
(descp (erc-tex-make-image match fg bg)))
(when descp
(let (start end)
(delete-region (match-beginning 0) (match-end 0))
(setq start (point))
(insert-image descp match)
(setq end (point))
(put-text-property start end 'keymap erc-tex-image-keymap)))))))
(defun erc-tex-render-insert ()
(erc-tex-render))
(defun erc-tex-render-send ()
(erc-tex-render
(face-foreground 'erc-input-face)
(face-background 'erc-input-face)))
(define-erc-module tex latex
"Display LaTeX mathematical expressions as images in ERC."
((add-hook 'erc-insert-modify-hook 'erc-tex-render-insert t)
(add-hook 'erc-send-modify-hook 'erc-tex-render-send t))
((remove-hook 'erc-insert-modify-hook 'erc-tex-render-insert)
(remove-hook 'erc-send-modify-hook 'erc-tex-render-send)))
(provide 'erc-tex)