;;; build-doc-config --- Pugs' doc generation helper
;;; Commentary:
;;; configuration piochee sur le net
;;; Code:

(setq max-lisp-eval-depth 10000)
(setq max-specpdl-size 10000)

(require 'package)
(package-initialize)
(setq package-enable-at-startup nil)

(add-to-list 'package-archives
	     '("melpa" . "http://melpa.org/packages/"))
(add-to-list 'package-archives
	     '("gnu" . "http://elpa.gnu.org/packages/"))
(add-to-list 'package-archives
	     '("org" . "https://orgmode.org/elpa/"))

;; Bootstrap `use-package'
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(package-initialize)

(use-package auto-async-byte-compile
  :ensure t
  :hook
  (emacs-lisp-mode-hook  . 'enable-auto-async-byte-compile-mode))

(setq auto-save-default nil)

(use-package tex
  :ensure auctex)

(use-package org
  :ensure t
  :pin org)

(use-package htmlize
  :ensure t)

(custom-set-variables
 '(org-export-html-postamble nil)
 '(org-latex-minted-langs '((pugs "Pugs") (pugs-error "Pugs")))
 '(org-confirm-babel-evaluate nil)
 '(org-html-validation-link nil)
 '(org-src-fontify-natively t)
 '(org-html-htmlize-output-type 'css)
 )

(defun org-export-output-file-name-modified (orig-fun extension &optional subtreep pub-dir)
  (unless pub-dir
    (setq pub-dir (substitute-in-file-name "${PUGS_BINARY_DIR}/doc"))
    (unless (file-directory-p pub-dir)
      (make-directory pub-dir)))
  (apply orig-fun extension subtreep pub-dir nil))
(advice-add 'org-export-output-file-name :around #'org-export-output-file-name-modified)

(setq org-latex-listings 'minted
      org-latex-pdf-process
      '("cd ${PUGS_BINARY_DIR}/doc; ./build-userdoc-pdf.sh"))

(setq python-indent-guess-indent-offset-verbose nil)

(setq org-babel-python-command "python3")
(add-hook 'org-babel-after-execute-hook
          'org-redisplay-inline-images)

(load-library "${HOME}/share/pugs.el")
(require 'pugs-mode)
;; allow to use pugs mode when dealing with invalid examples
(define-derived-mode pugs-error-mode pugs-mode "pugs-error"
  "pugs-error mode "
  )

(add-to-list 'auto-mode-alist '("\\.pgs?\\'" . pugs-mode))
(load-library "${HOME}/share/ob-pugs.el")
(require 'ob-pugs)
(load-library "${HOME}/share/ob-pugs-error.el")
(require 'ob-pugs-error)

(org-babel-do-load-languages
 'org-babel-load-languages
 '((python . t)
   (emacs-lisp . t)
   (shell . t)
   (pugs . t)
   (pugs-error . t)
   (C . t)
   (gnuplot . t)
   (js . t)
   (ditaa . t)
   (dot . t)
   (org . t)
   (latex . t )))

(use-package gnuplot
  :ensure t)

(eval-when-compile
  (require 'easy-mmode)
  (require 'ox))

(use-package ox
  :config
  (define-minor-mode unpackaged/org-export-html-with-useful-ids-mode
    "Attempt to export Org as HTML with useful link IDs.
  Instead of random IDs like \"#orga1b2c3\", use heading titles,
  made unique when necessary."
    :global t
    (if unpackaged/org-export-html-with-useful-ids-mode
        (advice-add #'org-export-get-reference :override #'unpackaged/org-export-get-reference)
      (advice-remove #'org-export-get-reference #'unpackaged/org-export-get-reference)))

  (defun unpackaged/org-export-get-reference (datum info)
    "Like `org-export-get-reference', except uses heading titles instead of random numbers."
    (let ((cache (plist-get info :internal-references)))
      (or (car (rassq datum cache))
          (let* ((crossrefs (plist-get info :crossrefs))
                 (cells (org-export-search-cells datum))
                 ;; Preserve any pre-existing association between
                 ;; a search cell and a reference, i.e., when some
                 ;; previously published document referenced a location
                 ;; within current file (see
                 ;; `org-publish-resolve-external-link').
                 ;;
                 ;; However, there is no guarantee that search cells are
                 ;; unique, e.g., there might be duplicate custom ID or
                 ;; two headings with the same title in the file.
                 ;;
                 ;; As a consequence, before re-using any reference to
                 ;; an element or object, we check that it doesn't refer
                 ;; to a previous element or object.
                 (new (or (cl-some
                           (lambda (cell)
                             (let ((stored (cdr (assoc cell crossrefs))))
                               (when stored
                                 (let ((old (org-export-format-reference stored)))
                                   (and (not (assoc old cache)) stored)))))
                           cells)
                          (when (org-element-property :raw-value datum)
                            ;; Heading with a title
                            (unpackaged/org-export-new-title-reference datum cache))
                          ;; NOTE: This probably breaks some Org Export
                          ;; feature, but if it does what I need, fine.
                          (org-export-format-reference
                           (org-export-new-reference cache))))
                 (reference-string new))
            ;; Cache contains both data already associated to
            ;; a reference and in-use internal references, so as to make
            ;; unique references.
            (dolist (cell cells) (push (cons cell new) cache))
            ;; Retain a direct association between reference string and
            ;; DATUM since (1) not every object or element can be given
            ;; a search cell (2) it permits quick lookup.
            (push (cons reference-string datum) cache)
            (plist-put info :internal-references cache)
            reference-string))))

  (defun unpackaged/org-export-new-title-reference (datum cache)
    "Return new reference for DATUM that is unique in CACHE."
    (cl-macrolet ((inc-suffixf (place)
                               `(progn
                                  (string-match (rx bos
                                                    (minimal-match (group (1+ anything)))
                                                    (optional "--" (group (1+ digit)))
                                                    eos)
                                                ,place)
                                  ;; HACK: `s1' instead of a gensym.
                                  (-let* (((s1 suffix) (list (match-string 1 ,place)
                                                             (match-string 2 ,place)))
                                          (suffix (if suffix
                                                      (string-to-number suffix)
                                                    0)))
                                    (setf ,place (format "%s--%s" s1 (cl-incf suffix)))))))
      (let* ((title (org-element-property :raw-value datum))
             (ref (url-hexify-string (substring-no-properties title)))
             (parent (org-element-property :parent datum)))
        (while (--any (equal ref (car it))
                      cache)
          ;; Title not unique: make it so.
          (if parent
              ;; Append ancestor title.
              (setf title (concat (org-element-property :raw-value parent)
                                  "--" title)
                    ref (url-hexify-string (substring-no-properties title))
                    parent (org-element-property :parent parent))
            ;; No more ancestors: add and increment a number.
            (inc-suffixf ref)))
        ref))))

(defun org-export-deterministic-reference (references)
    (let ((new 0))
       (while (rassq new references) (setq new (+ new 1)))
       new))
 (advice-add #'org-export-new-reference :override #'org-export-deterministic-reference)

;;; Local Variables:
;;; byte-compile-warnings: (not free-vars)
;;; End: (provide 'build-doc-config)
;;; build-doc-config.el ends here