Org Emacs Project Template

Table of Contents

HOME

1 What is it?

Defines a create_orgMode_project bash script to quickly generate an OrgMode project structure.

createOrgProject MyProject

1.1 Features

The framework provides some functionalities like:

  • org publish configuration
  • bibliography file with its configuration
  • pdf export configuration luaTeX + biber + minted (utf8 support)
  • org templates (also org protocol) configuration

2 Quick starter

2.1 Emacs init.el configuration

To use the project (template) simply run this code.

Note: if you want to use this configure in a regular basis, simply add this function to your Emacs init.el

2.1.1 Required packages

(require 'project)
(require 'org-ref)
(require 'htmlize)

2.1.2 my-new-project-configuration function

(defun my-new-project-configuration ()
  "Sets my-project-root as root project directory and load
my-project-root/setup/setup.el project configuration file "
  (interactive)
  (setq my-project-root (expand-file-name (car (project-roots (project-current)))))

  (if my-project-root
      (let ((my-project-setup-file (concat my-project-root "setup/setup.el")))
        (if (file-exists-p my-project-setup-file)
            (load my-project-setup-file nil t t nil)
          (error "Project %s setup file not found" my-project-setup-file)))
    (error "Project root dir not found (missing .git ?)")))

Its role is to found the project root (= the directory containing the .git directory) and to load the project configuration setup/setup.el.

2.2 New project creation

Use the provided shell script:

createorgproject MyProject

Please note that by default, this script will never overwrite anything. If to want to overwrite, use the -f option.

Important: if you just created a fresh new project be sure that there is a .git directory as it is used to locate the project root. If you simply want to do a quick test you can do

cd MyProject
echo >> .git

as an alternative.

Once that the script has been run you can use Emacs as usual:

emacs MyProject/page_example.org &

Then load your project configuration M-x my-new-project-configuration

Then you can do whatever you want, for instance publish your project with C-c C-e P p and visit the generated pages:

firefox  MyProject/index.html

Note: you can also try C-c C-e l o to check PDF exports.

3 Project structure

:header-args: :mkdirp yes

3.1 project root

Create files at project root

3.1.1 theindex_org

This file includes the generated index

#+CALL: Setup()
#+TITLE: Index
#+CALL: HomeUp()


#+INCLUDE: "theindex.inc"

3.1.2 todo.org

#+CALL: Setup()
#+TITLE: TODO list 
#+CALL: HomeUp()

3.1.3 journal.org

#+CALL: Setup()
#+TITLE: Journal
#+CALL: HomeUp()

3.1.4 www_links.org

#+CALL: Setup()
#+TITLE: External web links
#+CALL: HomeUp()

3.2 setup/

This directory contains the configuration files.

3.2.1 setup/library-of-babel.org

This file contains function definitions, that are loaded with org-babel-lob-ingest.

  1. The Setup() command

    <Sat May 23 2020 12:07> <- Use minted for listings

    The #+CALL: Setup() has to be set at the beginning of your org file (see: file:example/example.org).

    The latex package verbatim is required by the bibliography trick in Bibliography() to support both html and pdf export.

    The minted package is used for code listings

    #+NAME: Setup
    #+BEGIN_SRC emacs-lisp :results drawer
    (concat 
     "#+OPTIONS: H:3 toc:t num:t \\n:nil ::t |:t ^:{} -:t f:t *:t tex:t d:t tags:not-in-toc \n"
    
     "#+PROPERTY: header-args :mkdirp yes \n"
    
     "#+HTML_HEAD_EXTRA: <style type=\"text/css\"> blockquote {background:#EEEEEE; padding: 3px 13px}    </style> \n"
     "#+HTML_HEAD_EXTRA: <style type=\"text/css\"> pre {background:#EEEEEE; padding: 3px 13px}    </style> \n"
    
     "#+LATEX_HEADER: \\usepackage[backend=biber, bibencoding=utf8 ]{biblatex}\n" 
     "#+LATEX_HEADER: \\usepackage{verbatim}\n" 
     "#+LATEX_HEADER: \\usepackage{minted}\n"
     "#+LATEX_HEADER: \\hypersetup{colorlinks=true}\n"
     "#+LATEX_HEADER: \\addbibresource{" my-project-root "bibliography/bibliography.bib}\n"
    
     "#+BEGIN_EXPORT latex \n"
     "% from: https://github.com/SublimeText/LaTeXTools/issues/657#issuecomment-188188632 \n"
     "\\renewcommand{\\MintedPygmentize}{/usr/bin/pygmentize} \n"
     "\\definecolor{bg}{rgb}{0.95,0.95,0.95} \n"
     "\\setminted{bgcolor=bg} \n"
     "\\setminted{fontsize=\\footnotesize}   \n"
     "\\setminted{breaklines} \n"
     "\\setminted{breakautoindent=false} \n"
     "\\setminted{mathescape} \n"
     "\\setminted{xleftmargin=0pt} \n"
     "#+END_EXPORT \n"
     )
    #+END_SRC
    
  2. The Bibliography() command

    The #+CALL: Bibliography() has to be set where you want to insert your bilbliography (see: file:example/example.org).

    #+NAME: Bibliography
    #+BEGIN_SRC emacs-lisp :results drawer
    (concat "#+BEGIN_EXPORT latex\n\\printbibliography\n"
            "\\begin{comment}\n#+END_EXPORT\n"
            "bibliography:" my-project-root "bibliography/bibliography.bib\n"
            "#+BEGIN_EXPORT latex\n\\end{comment}\n#+END_EXPORT\n")
    #+END_SRC
    
  3. Automatic Home/Up

    This one took me some time and I still do not understand why I must use relative path for links

    #+NAME: HomeUp
    #+BEGIN_SRC emacs-lisp :results drawer
    (let* ((my-project-root
            (expand-file-name (car (project-roots (project-current)))))
           (my-buffer-dir
            (expand-file-name (file-name-directory buffer-file-name)))
           (my-up
            (expand-file-name (concat my-buffer-dir "../index.org")))
           (my-home
            (expand-file-name (concat my-project-root "index.org")))
           (my-can-go-up (string< my-project-root my-buffer-dir))
           )
      (concat
       "#+begin_export latex\n\\begin{comment}\n#+end_export\n"
       (if (file-exists-p my-home)
           (format "[[file:%s][*HOME*]] " (file-relative-name my-home my-buffer-dir)))
       (if (and my-can-go-up (file-exists-p my-up))
           (format "[[file:%s][*UP*]] " (file-relative-name my-up my-buffer-dir)))
       "\n#+begin_export latex\n\\end{comment}\n#+end_export\n"
       )
      )
    #+END_SRC
    

3.2.2 setup/setup.el

This file contains code executed by the my-new-project-configuration function. At this point there is only one variable my-project-root containing the project root.

  1. Configuration message

    Print a message

    ;; Configuration message
    (message (format "Configuring %s" my-project-root))
    
  2. Use minted for listings

    See Setup()

    ;; use =minted= for listings
    (setq org-latex-listings 'minted)
    
  3. Load library-of-babel.org

    <Sat May 23 2020 12:23> <- setup/library-of-babel.org

    ;; Load =library-of-babel.org=
    (org-babel-lob-ingest (concat my-project-root "setup/library-of-babel.org"))
    

    See: library-of-babel.org

  4. org-publish-project-alist definition

    The first task is to define how to publish the project:

    ;; =org-publish-project-alist= definition
    (setq my-publish-dir (concat my-project-root "docs"))
    
    (defun my-org-publish-sitemap (title list)
      "Create my own index.org instead of the default one"
      (concat
       "#+CALL: Setup()\n"
       "#+INCLUDE: \"setup/index_preamble.org\"\n"
       "#+OPTIONS: toc:nil\n\n"
       "* My Sitemap\n\n"
       (org-list-to-org list)
       "\n\n"))
    
    (setq org-publish-project-alist
          `(
            ("My_Project_Name-org-files",
             :base-directory ,my-project-root
             :base-extension "org"
             :recursive t
             :publishing-directory ,my-publish-dir
             :publishing-function org-html-publish-to-html
             :sitemap-function my-org-publish-sitemap
             :htmlize-source t
             :sitemap-sort-files anti-chronologically
             :exclude "setup/*\\|docs/*\\|subprojects/*"
             ;; Generates theindex.org + inc files
             :makeindex t
             ;; Creates index.org, calls my-org-publish-sitemap to fill it
             :auto-sitemap t
             :sitemap-filename "index.org"
             )
    
            ("My_Project_Name-data-files",
             :base-directory ,my-project-root
             :base-extension "nb\\|?pp\\|png"
             :recursive t
             :publishing-directory ,my-publish-dir
             :publishing-function org-publish-attachment
             :exclude "setup/*\\|docs/*\\|subprojects/*"
             )
    
            ;; Main
            ("My_Project_Name",
             :components ("My_Project_Name-org-files" "My_Project_Name-data-files")
             )
            )
          )
    
  5. Feed org-agenda-files with org files

    Then we use the find command to feed the org-agenda-files variable:

    (setq org-agenda-files
          (split-string
           (shell-command-to-string (format "find \"$(cd %s; pwd)\"  -name '*.org' ! -name 'index.org'  ! -name 'agenda.org'  ! -name '.#*' ! -path './setup/*'" my-project-root)
                                    )))
    
  6. Some captures with their files

    CAVEAT: these files, "www_links.org", "journal.org", "todo.org" must exist.

    (setq my-www-links-filename (concat my-project-root "www_links.org"))
    (setq my-journal-filename (concat my-project-root "journal.org"))
    (setq my-todo-filename (concat my-project-root "todo.org"))
    
    (setq-default org-display-custom-times t)
    (setq org-time-stamp-custom-formats '("<%a %b %e %Y>" . "<%a %b %e %Y %H:%M>"))
    
    (setq org-capture-templates
          `(
            ("A"
             "Agenda/Meeting" entry (file+headline "~/GitLab/PVBibliography/agenda.org" "Agenda")
             "* %^{Title?} %^G\n:PROPERTIES:\n:Created: %U\n:END:\n\n%?"
             :empty-lines 1  
             :create t
             )
    
            ("K" "Log Time" entry (file+datetree "~/GitLab/PVBibliography/activity.org" "Activity")
             "* %U - %^{Activity}  :TIME:"
             )
            
    
            ;;----------------
            
            ("t"
             "Todo" entry (file+olp+datetree ,my-todo-filename)
             "* TODO %^{Title?} [/] %^G\n:PROPERTIES:\n:Created: %U\n:END:\n\n - [ ] %?"
             :empty-lines 1  
             :create t
             )
            
            ("T"
             "Todo with file link" entry (file+olp+datetree ,my-todo-filename)
             "* TODO %^{Title|%f} [/] %^G\n:PROPERTIES:\n:Created: %U\n:END:\n\nBack link: %a\n\n#+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n - [ ] %?"
             :empty-lines 1  
             :create t
             )
            
            ("j" "Journal" entry (file+olp+datetree ,my-journal-filename)
             "* %^{Title} %^G\n\n%?"
             :empty-lines 1  
             :create t
             )
            ("J" 
             "Journal with file link" entry (file+olp+datetree ,my-journal-filename)
             "* %^{Title|%f} %^G\n\nBack link: %a\n\n#+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n%?"
             :empty-lines 1  
             :create t
             )
            ;;
            ;; See: https://github.com/sprig/org-capture-extension for further details
            ;;
            ("L" 
             "Protocol Link" entry (file ,my-www-links-filename)
             "* [[%:link][%(transform-square-brackets-to-round-ones \"%:description\")]] \
                    %^G\n:PROPERTIES:\n:Created: %U\n:END:\n\n%?"
             :empty-lines 1  
             :create t
             )
            
            ("p" 
             "Protocol" entry (file ,my-www-links-filename)
             "* [[%:link][%(transform-square-brackets-to-round-ones \"%:description\")]] \
                     %^G\n:PROPERTIES:\n:Created: %U\n:END:\n#+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n%?"
             :empty-lines 1  
             :create t
             )
            ))
    
  7. org-ref configuration
    (setq my-bibtex-filename 
          (concat my-project-root "bibliography/bibliography.bib"))
    (if (file-exists-p my-bibtex-filename)
        ;; If bibliography.bib exists 
        (setq reftex-default-bibliography  `(,my-bibtex-filename)
              bibtex-completion-notes-extension "-notes.org"
              bibtex-completion-notes-template-multiple-files "#+CALL: Setup()\n#+TITLE: ${author-or-editor} (${year}): ${title}\n\n* Personal Notes\n  :PROPERTIES:\n  :NOTER_DOCUMENT: ~/AnnotatedPDF/${=key=}.pdf\n  :END:\n\n[[file:~/AnnotatedPDF/${=key=}.pdf][${title}]]\n"
              bibtex-completion-bibliography my-bibtex-filename
              bibtex-completion-library-path (file-name-directory my-bibtex-filename)
              bibtex-completion-notes-path (file-name-directory my-bibtex-filename)
              
              org-ref-default-bibliography  `(,my-bibtex-filename)
              org-ref-pdf-directory (file-name-directory my-bibtex-filename)
              )
      ;; otherwise unbound meaningless my-bibtex-filename
      (makunbound 'my-bibtex-filename)
      )
    
  8. PDF generation
    ;; defines how to generate the pdf file using lualatex + biber
    (setq org-latex-pdf-process
          '("lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"
            "biber %b"
            "lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"
            "lualatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
    

3.2.3 setup/index_preamble.org

This is file included in sitemap.org. Note: no need for Setup(), it is already declared in the template.

#+TITLE: My_Project_Name

# add what you want

3.3 bibliography/

This directory contains the bibliography.bib file.

3.3.1 bibliography.bib

To be used as example here is our bibliography.bib example file. I found convenient to provide a directory and not only the bibliography.bib as I can annotate my reference here.

@book{dominik16_org_mode_ref_manual,
  author =	 {Dominik, C.},
  title =	 {ORG MODE 9 REF MANUAL},
  year =	 2016,
  publisher =	 {ARTPOWER International PUB},
  isbn =	 9789888406852,
}

@Book{lewis00_gnu_emacs_lisp,
  author =	 {Lewis, Bil},
  title =	 {The GNU Emacs Lisp reference manual : for Emacs
                  Version 21, Revision 2.6, May 2000},
  year =	 2000,
  publisher =	 {Free Software Foundation},
  address =	 {Boston, MA},
  isbn =	 {978-1882114733},
}

3.4 example/

3.4.1 example/example.org

This is a page demo to check it works.

  1. File header

    To be properly configured the org mode file can begin as follows:

    #+CALL: Setup()
    #+TITLE: One example file
    #+CALL: HomeUp()
    

    For explanations: https://emacs.stackexchange.com/q/58633/13563.

    • [ ] another possibility is to use yasnippet
  2. Equation example

    Check if equations are processed with mathjax

    * An equation
    
      Do GitHub pages support equation rendering?
      \begin{equation*}
      \int \cos{x} dx = \sin{x}
      \end{equation*}
    
  3. A figure example
    * A figure example
      file:./figures/sg_d1.png
    
  4. Code block example

    We then add a code block to see that background is gray colored

    * A code block example 
      #+BEGIN_SRC cpp 
    #include <iostream>
    int main()
    {
      std::cout << "Hello world!" << std:endl;
      return 0;
    }
      #+END_SRC
    
    
  5. Bibliographic reference example
    * A bibliographic reference
      Test bibliography: cite:lewis00_gnu_emacs_lisp
    * Another section
    
      # put the bibliography here
      #+CALL: Bibliography()
    

Author: picaud

Created: 2020-07-17 Fri 08:13

Validate