fixed version of the attachment
;; 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 "%<S section org ======================================\n"
               "\\startsection\n"
               " [title={" (org-element-property :raw-value parent) "},\n"
               "  reference={" (org-element-property :CUSTOM_ID parent) "},\n"
               " ]\n"
               contents
               "\\stopsection\n"
               "%====================================== section org S>")))))

(defun ox-mycontext-paragraph (paragraph contents info)
  (concat "%<P paragraphe org\n" contents "%P>"))

(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))

Reply via email to