Написание технической документации с использованием Emacs Org mode.

Обзор

Разработчики обычно не любят документацию. Однако вам неизбежно придется тратить время на документирование разработанных вами приложений, библиотек или SDK. Для проектной документации у нас есть такие инструменты, как MkDocs, Jekyll, Sphinx, Hugo, Gatsby и многие другие, которые можно использовать.

Однако одна из основных проблем с использованием этих инструментов заключается в том, что код вашего приложения и документация разделены. Например. если вам нужно задокументировать фрагмент кода, вы должны запустить его отдельно, а затем вставить код и результаты в документ. Со временем это станет проблемой обслуживания, чтобы обновлять вашу документацию.

В своей предыдущей статье я говорил о грамотном программировании с помощью Jupyter Notebook. При таком подходе ваш код и документация всегда будут синхронизированы. В этой статье я собираюсь использовать Emacs Org mode для написания технической документации.

Настраивать

Emacs поставляется по умолчанию с установленным Org mode. Однако, если вы хотите использовать последнюю версию, просто введите M-x package-install RET org RET (убедитесь, что вы настроили Org ELPA в качестве одного из ваших репозиториев пакетов). В этой статье я буду использовать Org mode 9.3. Вы можете проверить свою Org mode версию, набрав M-x org-version RET.

Если вы только начали работать с Emacs, прочтите мои предыдущие статьи. Вы можете обратиться к моим dotfiles в этом репозитории.







Орг-Вавилон

Начнем с создания файла с расширением .org . Ниже я создаю файл с именем writing_tech_docs.org со следующим содержимым.

#+TITLE: Writing Technical Documentation using Emacs
* Shell
#+begin_src shell
echo "Writing technical documentation using Emacs"
#+end_src

Теперь либо нажмите

  • M-x org-export-dispatch
  • C-c C-e

и вы должны увидеть следующий экран.

Нажмите h (экспортировать в HTML), а затем o (как файл HTML и открыть).

Организационные HTML-темы

Сгенерированный HTML не так привлекателен. Давайте изменим это сейчас.

Создайте файл с именем setup.conf со следующим содержимым.

# -*- mode: org; -*-
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="https://fniessen.github.io/org-html-themes/src/readtheorg_theme/css/htmlize.css"/>
#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="https://fniessen.github.io/org-html-themes/src/readtheorg_theme/css/readtheorg.css"/>
#+HTML_HEAD: <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
#+HTML_HEAD: <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
#+HTML_HEAD: <script type="text/javascript" src="https://fniessen.github.io/org-html-themes/src/lib/js/jquery.stickytableheaders.min.js"></script>
#+HTML_HEAD: <script type="text/javascript" src="https://fniessen.github.io/org-html-themes/src/readtheorg_theme/js/readtheorg.js"></script>
#+HTML_HEAD: <style type="text/css">
#+HTML_HEAD:   pre.src:hover:before { display: none; }
#+HTML_HEAD: </style>

Я собираюсь использовать тему HTML из этого репозитория.

Я тоже не хочу убирать нумерацию в шапках. Давайте добавим строки ниже в начало файла.

#+TITLE: Writing Technical Documentation using Emacs
#+OPTIONS: num:nil
#+SETUPFILE: setup.conf

Теперь нажмите C-c C-e, чтобы экспортировать файл в HTML.

Изменить экспорт и рабочий каталог

Теперь экспортированный HTML находится в том же каталоге, что и наш файл org. Изменим рабочий каталог, а также укажем имя экспортируемого файла.

#+TITLE: Writing Technical Documentation using Emacs
#+OPTIONS: num:nil
#+SETUPFILE: setup.conf
#+PROPERTY: header-args :mkdirp yes :dir ~/output
#+EXPORT_FIle_NAME: ~/output/writing_tech_docs.html

Теперь снова выполните экспорт, и файл должен быть экспортирован в указанный каталог.

Сценарий запуска

Для рабочего каталога я хочу очистить файлы перед их созданием. Давайте определим функцию для удаления всех файлов в выходной папке.

Создайте файл с именем code.inc

# -*- mode: org; -*-
#+NAME: init
#+BEGIN_SRC shell :exports none
rm -rf ~/output
#+END_SRC

Теперь добавьте заголовки в файл org.

#+TITLE: Writing Technical Documentation using Emacs
#+OPTIONS: num:nil
#+SETUPFILE: setup.conf
#+PROPERTY: header-args :mkdirp yes :dir ~/output
#+EXPORT_FIle_NAME: ~/output/writing_tech_docs.html
#+INCLUDE: code.inc
#+CALL: init()

Вызов блока кода в тексте

Давайте добавим оболочку и блок кода Python в code.inc

# -*- mode: org; -*-
#+NAME: init
#+BEGIN_SRC shell :exports none
rm -rf ~/output
#+END_SRC
#+NAME: today
#+BEGIN_SRC shell :exports both :results output
echo `date`
#+END_SRC
#+NAME: increment
#+begin_src python :noweb yes :var num=0
def incr(num):
   return num + 1
   
return incr(num)
#+end_src

Затем в файле org я могу вызвать функцию.

* Evaluating Code Block
Today is “call_today[:results raw]()”
Increment of 87 is "call_increment[:results raw](num=87)"
#+CALL: today()
#+CALL: increment(167)

Многоразовый блок кода

Я также могу определить повторно используемый блок кода, а затем внедрить его с помощью noweb.

* Reusable function
#+NAME: init_block
#+BEGIN_SRC python
  PI=3.142
  def some_function(r):
    return 2 * PI * r
#+END_SRC
* Call the function on an integer
#+BEGIN_SRC python :noweb yes :exports both
  <<init_block>>
  return some_function(888)
#+END_SRC
#+RESULTS:
#+begin_example
5580.192
#+end_example

Сессия

Я также могу использовать сеанс для сохранения объектов данных в разных блоках кода.

* Session
#+begin_src python :session mysession
PI=3.14159
#+end_src
#+RESULTS:
#+begin_src python :results output :session mysession
print(PI)
#+end_src
#+RESULTS:
#+begin_example
3.14159
#+end_example

Диаграмма

Я также могу рисовать диаграммы, используя plantuml.

#+begin_src plantuml :file flow.png :exports results
title Authentication Sequence
Alice->Bob: Authentication Request
note right of Bob: Bob thinks about it
Bob->Alice: Authentication Response
#+end_src

Это конфигурация, которую я использовал.

(setq org-plantuml-jar-path
      (expand-file-name "~/workspace/software/plantuml/plantuml.jar"))
(setq plantuml-default-exec-mode 'jar)
;;  org-babel configuration
(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (shell . t)
   (plantuml . t)
   (python . t)))
(push '("plantuml" . plantuml) org-src-lang-modes)

Режим Python

Во время редактирования блока кода Python я могу перейти в режим Python, нажав C-c ‘

Резюме

И ниже окончательный сгенерированный вывод.

Файлы, которые я использовал, можно найти в этом репозитории.

использованная литература

Если вы еще не являетесь участником Medium и хотите им стать, нажмите здесь. (Часть вашей абонентской платы будет использована для поддержки alpha2phi.)