python

Автоматическая визуализация python-кода. Часть четвертая: поддержка документирования

  • пятница, 1 ноября 2019 г. в 00:25:31
https://habr.com/ru/post/471836/
  • Python


Ссылки на предыдущие части:

  • Часть первая — введение, графические примитивы, необходимые для создания графического представления кода
  • Часть вторая — реализация генератора графического представления кода (выполнена, в основном, на Питоне), микро язык разметки
  • Часть третья — новые возможности графики

Пример среды, поддерживающей такое графическое представление показан на картинке ниже.

image

Среда, поддерживающая графическое представление кода

В четвертой части статьи речь пойдет о поддержке процесса документирования.

Вокруг да около


Посмотрим, что доступно разработчику в плане работы с документацией.

Питон поддерживает строки документации для модулей, классов и функций. Это хорошо. Комментарии также иногда используются для документирования.

Существуют генераторы документации, вроде doxygen и sphinx. Это тоже хорошо.

Однако иногда хочется немного большего. Бывают случаи, когда описание функции или класса становится слишком большим и строки документации (или комментарии) излишне «разбухают». Количество не исполняемых строк начинает подавлять количество исполняемых, что может затруднить чтение из-за размытости кода. Еще одна проблема — это различные диаграммы. В текст готовую картинку не вставишь. Можно вставить только описание диаграммы, например Plant UML диаграмму, но даже в этом случае нужно обеспечить рендеринг, что сделать непосредственно в тексте программы затруднительно.

Решение проблемы простое — сохранить пространное описание в отдельном файле, а в коде оставить пометку, о том, что документация находится там-то. Отдельный файл можно рендерить подходящим образом в нужный момент. А пометка в коде желательно должна быть интерактивной, то есть обеспечивать переход к документации по одному щелчку мыши. В принципе, пометку в тексте программы можно рассматривать шире: это может быть и URL, и какое-то место в другом файле исходного текста, и картинка, и внешний файл с документацией.

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

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

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

Реализация в Codimension IDE


Наряду с текстовым, Codimension IDE поддерживает графическое представление кода. Также IDE поддерживает язык разметки. Поэтому задача добавления нового графического элемента для отображения ссылок на документацию является достаточно простой.

Для начала сформулируем требования к новой функциональности в компактном виде:

  • Поддержать формат markdown с рендерингом «на лету» (просмотр и редактирование)
  • На графическом представлении кода поддержать новый элемент для документации, используя язык разметки CML
  • Графический элемент для документации должен работать в трех вариантах: только ссылка на другое место; только якорь для ссылок из других мест; и ссылка и якорь
  • Ссылка может быть URL или указывать на файл (возможно, с указанием номера строки или якоря), который IDE в состоянии показать
  • В markdown поддержать диаграммы Plant UML
  • Поддержать быстрое создание новых файлов документации и ссылок на них для графического представления кода
  • Поддержать идиому стартовой точки документации для проекта, аналогично тому, как это делает github

Markdown и рендеринг


Codimension IDE использует qutepart в качестве компонента редактора текста, а qutepart, в свою очередь, поддерживает markdown из коробки: подсветка синтаксиса уже сделана. Для автоматического рендеринга можно воспользоваться тем же подходом, что и для питон файлов. Основное поле разбивается на две части. Слева — текст markdown, а справа — рендеринг:


Редактирование markdown с автоматическим рендерингом

Рендеринг, конечно, осуществляется автоматически. IDE определяет паузу в редактировании текста и обновляет рендеринг, если необходимо. Для режима просмотра markdown левая часть с текстовым редактором подавляется.

Для рендеренга удобным оказалось использовать библиотеку mistune, которая позволяет быстро преобразовать текст в HTML. Готовый HTML отправляется QT компоненту для отображения. Библиотека mistune также оказалась достаточно гибкой для того, чтобы добавить распознование описаний диаграмм plantUML. Диаграмма добавляется как блок кода с соответствующим языком, например:


Распознавание диаграмм plantUML

plantUML поддерживает разные типы диаграмм. Для Codimension описание диаграммы прозрачно, то есть оно не анализируется, а как есть передается plantUML. Соответственно, все поддерживаемые типы будут отображаться в окне просмотра. На момент написания статьи plantUML поддерживал следующие тэги начала/конца разных типов диаграмм:

  • @startuml / @enduml
  • @startgantt / @endgantt
  • @startsalt / @endsalt
  • @startmindmap / @endmindmap
  • @startwbs / @endwbs
  • @startditaa / @endditaa
  • @startjcckit / @endjcckit

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

Из библиотеки QT используется компонент QTextBrowser, который поддерживает HTML. К сожалению, поддерживаемый диалект HTML ограничен, поэтому конечный результат почти невозможно сделать идеальным. Возможно, этот недостаток удастся исправить в будущем.

Вмешательства потребовала и обработка щелчков мыши на ссылках. В ссылке может оказаться что-то из следующего:

  • внешний ресурс (начинается с http:// или с https://)
  • файл c относительным путем от корня проекта или от текущего файла (удобно, когда каталог проекта перемещается по файловой системе)
  • файл c абсолютным путем

А если это файл, то можно указать (необязательный элемент) или идентификатор якоря в этом файле, или номер строки. В обоих случаях дополнительная информация используется для прокрутки файла до нужного места.

Графический элемент


Графический элемент имеет смысл вводить с помощью нового CML комментария, аналогично тому, как это уже сделано, например, для групп. CML поддерживает атрибуты, что также потребуется для нового графического элемента.

# cml 1 doc ....

Ссылка на документацию в некотором смысле подобна комментарию — она не является выполняемой строчкой программы, но сообщает дополнительную информацию о каком-то контексте. Codimension IDE распознает несколько типов комментариев: независимые, лидирующие и боковые. Для документации кажется разумным поддержать независимые и лидирующие графические элементы так же, как это сделано для комментариев. С боковым элементом для документации возникает неясность. Дело в том, как боковые комментарии отрисовываются для многострочного блока кода. Справа от блока рисуется прямоугольник, покрывающий все строчки бокового комментария с поддержкой соответствия номеров строк. А что делать, если CML doc встретился в середине бокового комментария, не совсем ясно. С другой стороны, ссылка все равно ведет к какому-то другому месту, поэтому поддержка боковых CML doc выглядит излишней — контекст конкретной строки в блоке кода очень узок. Поддержка боковых CML doc для функций и классов так же кажется излишней. Поэтому на данном этапе будут реализованы только независимые и лидирующие CML doc. Стоит заметить, что если в будущем появится обоснованная необходимость поддержки боковых CML doc и хорошая идея как их отображать, то такую функциональность можно будет добавить.

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

Теперь ясен и список атрибутов для CML doc комментария:

  • link — ссылка на другое место
  • anchor — идентификатор якоря для ссылок из других мест
  • title — текст для отображения в графическом элементе
  • bg, fg, border — индивидуальные цвета элемента, если его требуется выделить особенным образом

Хотя бы один из двух атрибутов link и anchor должны присутствовать. Без них такой CML doc комментарий не имеет особого смысла. Остальные атрибуты не обязательны. Текста может не быть совсем, а цвета могут быть и стандартными.

Вот пример кода, использующего CML doc, и его графическое представление:


Независимый и лидирующий CML doc комментарии

Разница между лидирующим и независимым элементами только в том, куда ведет соединитель: либо к конкретному блоку, либо к соединителю между блоками.

Когда курсор мыши оказывается над иконкой, а у элемента присутствует атрибут link, то форма курсора меняется, подсказывая, что по щелчку будет выполнен переход.

Графический элемент также поддерживает контекстное меню. Доступна опция для просмотра или редактирования атрибутов элемента, включая цвета, и опция удаления элемента.

Другие графические элементы


Почти все остальные элементы на графическом представлении кода могут иметь документацию (исключения, например, составляют комментарии и docstrings). Поэтому для них предусмотрен способ создания элемента документации через контекстное меню.


Контекстное меню для работы с документацией

Вариантов всего два. Первый «Add/edit doc link/anchor...» приводит к модальному диалогу для ручного ввода атрибутов link, anchor и title. Здесь у разработчика полная свобода куда направить ссылку, где разместить файл и т.п.

Второй вариант интереснее. Название пункта длинное, обусловленное выполняемыми действиями: «Create doc file, add link and open for editing». Все действия выполняются автоматически без всякого ввода, что позволяет решить организационный вопрос быстро:

  • Принимается решение о файле, в котором будет находиться документация (рассмотрим ниже)
  • В исходном тексте добавляем # cml 1 doc ..., который указывает на файл с документацией и имеет сгенерированные якорь и текст. Якорь генерируется как doc<случайное число>. Текст фиксированный: See documentation
  • Если файл документации уже существует, то он открывается на редактирование в новой вкладке
  • Если файл документации не существует, то он создается, открывается на редактирование в новой вкладке, а в буфер редактирования добавляется краткая справка, включая как сослаться на только что вставленный # cml 1 doc ... комментарий.

Решение о файле зависит от того, загружен ли проект. Если загружен, то в корне проекта создается подкаталог doc и далее относительный путь от корня проекта до файла исходного текста. Имя файла формируется путем подмены расширения на .md. Например, если проект расположен в

/home/me/myProject

а добавление документации осуществляется для файла проекта

/home/me/myProject/src/utils.py

то будет создан файл документации

/home/me/myProject/doc/src/utils.md

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

Если проект не загружен, то рядом с файлом создается подкаталог doc, а в нем файл с подмененным расширением на .md. Такой сценарий, однако, кажется маловероятным. Уж коли речь зашла о документации, то почти наверняка это работа над проектом, а не над отдельным файлом.

Разумеется, в любой момент можно поменять автоматически сгенерированные элементы либо путем редактирования # cml 1 doc ... в текстовом редакторе, либо в диалоге на графическом представлении.

Стартовая точка документации проекта


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

Здесь можно немного расширить подход github так, чтобы работал и вариант по умолчанию, и вариант специфической организации документации. Если ничего не сказано, то будем искать файл README.md в корне проекта. А свойства проекта можно расширить еще одним полем, в котором указывается конкретный файл стартовой точки документации.

Для открытия документации проекта предусмотрено два варианта. На панели инструментов главного окна IDE добавлена кнопка с иконкой markdown. При нажатии будет открыт файл документации в режиме просмотра, если он имеется. Если же файла нет, то будет предложено расположение файла документации и будет открыта новая вкладка в режиме редактирования с текстом — заглушкой. Второй вариант — это ссылка на welcome страничке Codimension, которая показывется когда нет ни одной другой открытой вкладки. Сопроводительный текст будет включать слова о документации проекта и ссылку, если документация найдена. Именно эту welcome страничку увидет пользователь, открывший проект впервые.

Проверка на практике


Описанная выше функциональность опробована на кошках, то есть на проекте самой Codimension IDE. Теперь установочный пакет включает документацию, подготовленную в формате markdown. Это тестирование функциональности нельзя считать совсем полным, так как готовилась документация для конечного пользователя, а не по коду. Однако общее впечатление, что получилось вполне приемлимо.

Открытые вопросы


Нужна ли поддержка боковых CML doc элементов? Если да, то как их отрисовывать, например, для такого случая:

a = 10  # Comment line 1
b = 20  # cml 1 doc title="my side doc"
c = 30  # cml+      link="http://codimension.org"
d = 40  # Comment line 4
        # Comment line 5

Можно было бы распознавать описания plantUML диаграмм прямо в строках документации. Если такая поддержка сделана, то как на графическом представлении кода показывать эти диаграммы?

Для облегчения построения plantUML диаграмм можно было бы добавить функциональность с таким сценарием:

  • Пользователь щелкает правой кнопкой мыши на классе на графическом представлении кода или в любом другом окне (список классов проекта, структурированное содержимое файла)
  • В контекстном меню выбирает пункт для генерации описания класса в формате plantUML
  • Сгенерированное описание сохраняется в текстовом буфере
  • Пользователь вставляет текст в markdown документ и модифицирует его, если необходимо

Жизненность такого сценария под вопросом, хотя реализовать его достаточно тривиально.

Если у вас возникли идеи, пожалуйста, поделитесь ими в комментариях.