;; open this file with command ;; emacs --no-splash -q -mm how_to_write_a_context_export_backend_v01.el ;; In "emacs-lisp" dropdown menu above, select "evaluate buffer" ;; then, a first Ctrl-c Ctrl-c will compile ;; finally, a second Ctrl-c Ctrl-c will bring you a pdf viewer ;; you can then read this document ;; ETAPE 0 --------------------------------------------------------------------- ;; Minimal cryptic config to use ConTeXt from emacs (cua-mode t) (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (package-initialize) (require 'ox) (setq ConTeXt-Mark-version "IV") (use-package tex :ensure auctex) (use-package context) (setq TeX-view-program-selection '((output-pdf "PDF Viewer"))) (if (eq system-type 'gnu/linux) (setq TeX-view-program-list '(("PDF Viewer" "okular %o")))) (if (eq system-type 'windows-nt) (setq TeX-view-program-list '(("PDF Viewer" "AcroRd32 %o")))) (setq TeX-default-mode 'context-mode) (add-hook 'ConTeXt-mode-hook (lambda() (setq TeX-command-default "ConTeXt Full"))) ;; ETAPE 1 --------------------------------------------------------------------- ;; Create 2 new empty buffers: 1 for org input, 1 for tex output ;; Display them (delete-other-windows) (defun clean_before_demo (buffername) (if (get-buffer buffername) (kill-buffer buffername)) (generate-new-buffer buffername)) (setq demo_name_org "demo_file.org") (setq demo_name_tex "demo_file.tex") (clean_before_demo demo_name_org) (clean_before_demo demo_name_tex) (with-current-buffer demo_name_org (org-mode)) (display-buffer demo_name_org '(display-buffer-in-side-window . ((side . right) (slot . 0) (window-width . 80)))) (with-current-buffer demo_name_tex (context-mode)) (display-buffer demo_name_tex '(display-buffer-in-side-window . ((side . right) (slot . 1) (window-width . 80)))) ;; ETAPE 2 --------------------------------------------------------------------- ;; Write basic content to have org input, and define a style file (with-current-buffer demo_name_org (insert "#+TITLE: Démonstration #+CONTEXT_ENV: my-env #+LANGUAGE: fr * Formatage de texte :PROPERTIES: :CUSTOM_ID: sec:formatage texte :END: Pour mettre en évidence, il est possible de *mettre en gras*. Il est possible aussi de /mettre en italique/. * Images :PROPERTIES: :CUSTOM_ID: sec:images :END: Du texte avant. #+CAPTION: Ceci est un glacier. #+NAME: fig:glacier #+ATTR_ORG: :width 100 [[./glacier.jpg]] Du texte après. * Liens et références :PROPERTIES: :CUSTOM_ID: sec:liens_et_references :END: Une référence à l'image [[fig:glacier]] en espérance que cela fonctionne. Une second vers la section [[#sec:formatage texte]]. #+INCLUDE: \"include.org\" ")) (clean_before_demo "include.org") (with-current-buffer "include.org" (insert "* Include :PROPERTIES: :CUSTOM_ID: sec:include :END: Et voici une seconde référence vers l'image [[fig:glacier]]. ")) (with-current-buffer "include.org" (write-file "include.org")) (clean_before_demo "my-env.tex") (with-current-buffer "my-env.tex" (insert "\setuphead [section] [color=darkred,style=\bfa] \setuptolerance [tolerant] \setupinteraction [state=start] \placebookmarks [chapter,section,subsection] [chapter,section] \setupinteractionscreen [option=bookmark] \setupwhitespace [medium] \setupbodyfont [palatino,12pt] ")) (with-current-buffer "my-env.tex" (write-file "my-env.tex")) ;; ETAPE 3 --------------------------------------------------------------------- ;; Define our export backend (org-export-define-backend 'ox-mycontext ; for each kind of item, we are going to allocate a specific function '((template . ox-mycontext-template) (headline . ox-mycontext-headline) (section . ox-mycontext-section) (paragraph . ox-mycontext-paragraph) (plain-text . ox-mycontext-plain-text) (bold . ox-mycontext-bold) (italic . ox-mycontext-italic) (link . ox-mycontext-link)) ; and we will need tp define specific option at global level :options-alist '((:context-env "CONTEXT_ENV" nil nil newline) (:language "LANGUAGE" nil nil newline))) (defun ox-mycontext-template (contents info) (let* ((context-env (mapconcat #'org-element-normalize-string (list (plist-get info :context-env)))) (language (replace-regexp-in-string "\n$" "" (car (list (plist-get info :language))) ))) (concat "\\environment " context-env "\\mainlanguage [" language "]\n\n" "\\starttext\n\n" contents "\n" "\\stoptext"))) (defun ox-mycontext-headline (headline contents info) "Transcode a HEADLINE element from Org to ConTeXt. CONTENTS holds the contents of the HEADLINE. INFO is a plist holding contextual information." contents) (defun ox-mycontext-section (section contents info) (let* ((parent (org-export-get-parent-element section)) (section_mode (symbol-name (org-element-property :mode section)))) (pcase section_mode ("first-section" (concat "%\n% FIRST SECTION\n%\n")) ("section" (concat "%"))))) (defun ox-mycontext-paragraph (paragraph contents info) (concat "%

")) (defun ox-mycontext-plain-text (text info) (when (member (org-element-type (org-element-property :parent text)) '(bold italic paragraph link)) text)) (defun ox-mycontext-bold (bold contents info) (concat "\\bold{" contents "}")) (defun ox-mycontext-italic (italic contents info) (concat "\\italic{" contents "}")) (defun ox-mycontext-link (link contents info) (let* ((parent_attr_org (org-export-read-attribute :attr_org (org-export-get-parent-element link))) (parent_caption (car (org-export-get-caption (org-export-get-parent-element link)))) (parent_name (org-element-property :name (org-export-get-parent-element link))) (elem_prop_type (org-element-property :type link)) (elem_prop_path (org-element-property :path link)) ) (concat (pcase elem_prop_type ("custom-id" (concat "\\in[" elem_prop_path "]")) ; or \\at{page}[] ("fuzzy" (concat "\\in[" elem_prop_path "]")) ("file" (concat "\\startplacefigure\n" " [title={" parent_caption "},\n" " reference={" parent_name "},\n" " ]\n" "\\externalfigure[" elem_prop_path "]" "[width={" (format "%s" (/ (string-to-number (plist-get parent_attr_org :width )) 100.0 )) "\\textwidth}]" "\n\\stopplacefigure")))))) ;; ETAPE 4 --------------------------------------------------------------------- ;; Define a command and apply to get the tex output buffer (defun ox-mycontext-export () (interactive) (org-export-to-buffer 'ox-mycontext demo_name_tex)) (with-current-buffer demo_name_org (ox-mycontext-export)) (with-current-buffer demo_name_org (write-file demo_name_org)) (with-current-buffer demo_name_tex (write-file demo_name_tex))