[Перевод] Elsie: программируемые презентации
Как известно, существует целый ряд инструментов для создания информативных технических слайдов, и у этих инструментов есть свои недостатки. TLDR:
- При работе с WYSIWYG-решениями (напр., PowerPoint) требуется выполнять вручную массу монотонной работы, они не слишком хорошо поддерживают подсветку синтаксиса, не предоставляют качественных инструментов для точной отрисовки сложных фигур и анимации, а также их не так просто интегрировать с контролем исходников.
- Декларативные инструменты (напр., Beamer или reveal.js) гораздо лучше. В них серьёзно поддерживается подсветка синтаксиса, они позволяют рисовать сложные фигуры и анимацию (в особенности Beamer) и, кроме того, с лёгкостью версионируются. Правда, ни один из используемых с ними декларативных языков (ни LaTeX, ни HTML) не дают достаточной гибкости для создания по-настоящему сложных слайдов.
Здорово было бы иметь инструмент, позволяющий полностью контролировать всё, что изображено на слайде, но, в то же время, предоставляющий разумные умолчания при создании таких простых вещей, работа с которыми не требует тонкой детализации.
Ах, если бы только было можно приказать компьютеру сделать именно то, что я хочу, с возможностью вынести типичные сценарии в краткие команды (чтобы не писать слишком много при выполнении простых задач). Что ж, я программист, а всё это звучит очень по-нашему. Почему бы просто не написать программу, которая генерировала бы за меня слайды?
❯ Программируемые слайды
Можно возразить, что вышеупомянутые декларативные инструменты (Beamer и reveal.js) уже «по-своему» программируемые. Не хочу возвращаться к спору о том, являются ли LaTeX и HTML языками программирования, но всё равно вижу настоящую пропасть между декларативным языком, например, HTML и императивным языком, например, Python.
Вообразите на минутку, что больше не приходится щёлкать по текстовым рамкам в PowerPoint или писать разметку LaTeX/HTML –, а можно создать слайды, написав для этого программу на императивном языке, в идеале с применением слайдового API или библиотеки, которые бы упростили вам работу.
На первый взгляд такая идея может показаться глуповатой, но, если призадуматься — ведь программисты и так всё время пишут софт для представления данных пользователю (вспомните, что такое сайты, десктопные или мобильные приложения, т.д.). Так почему бы не создавать на языках программирования слайды для презентаций?
❯ Имеющиеся инструменты для программирования слайдов
Естественно, кому-то эта идея приходила на ум и ранее. Есть библиотека Python под названием python-pptx, в принципе, представляющая собой API для построения презентаций PowerPoint. Да, она отлично вам послужит, если вы любите PowerPoint (или если вынуждены им пользоваться), но многих проблем PowerPoint она не решает. Даже при использовании этой библиотеки вам всё равно будет сложно создавать сложные анимации и графику, красиво подсвечивать синтаксис в сниппетах с исходным кодом, а также отображать математические символы и уравнения в таком качестве, как в LaTeX. Но это шаг в верном направлении. Будь эта библиотека не так заточена под PowerPoint, а ещё содержала бы какой-либо высокоуровневый функционал (например, моделирование макетов или встроенная поддержка подсветки синтаксиса). Думаю, такой поддержки хватило бы для большинства практических случаев, с которыми мне приходится иметь дело.
Также существует API для создания слайдов Google. Для него характерны примерно такие же ограничения, как и в вышеприведенном примере с PowerPoint. Слайды приходится создавать с применением объекта JSON, который… мягко говоря, неидеален для чего-либо сложного.
Мне не удалось найти других инструментов, которые позволяли бы программировать слайды (если не считать ещё нескольких библиотек для создания слайдов PowerPoint).
❯ Elsie
Пару лет назад один мой коллега серьёзно приуныл, так как при помощи имеющихся решений ему пришлось создавать слайды с большим количеством технической информации (сниппеты кода, сложные схемы и анимация, математические символы, т.д). Чтобы решить эту проблему, он написал Elsie, библиотеку для Python, как раз позволяющую пользователю программно создавать слайды. В ней предоставляются базовые кирпичики (в частности, текстовые блоки, картинки, сниппеты кода, фигуры, списки, т.д.), которые можно комбинировать и так создавать слайды. На внутреннем уровне библиотека преобразует эти блоки в SVG, а затем отображает SVG-слайды в PDF.
Мы в нашей компании уже несколько лет пользуемся этой библиотекой, и Elsie кажется нам такой полезной, что мы даже решили написать по ней хорошую документацию и выложить в открытый доступ. В этом посте я не буду подробно рассказывать об Elsie, а просто помогу вам составить о ней впечатление. Вот простой пример на уровне hello world:
import elsie
# Создать новую презентацию
slides = elsie.SlideDeck()
# Создать новый слайд
slide = slides.new_slide()
# Отрисовать на слайде некоторый текст
slide.text("Hello world!")
# Отобразить слайды в PDF
slides.render("slides.pdf")
Вы импортируете библиотеку, создаёте несколько слайдов, а затем отображаете их в формате PDF. Не существует предметно-ориентированного языка (DSL) или другого подобного инструмента для таких целей, а здесь перед нами самый обычный Python. Вы вызываете функции, пользуетесь переменными, условными операторами, циклами, т.д. и выстраиваете ваши слайды.
В Elsie есть масса полезных возможностей, в частности, подсветка синтаксиса, макетирование или мощная система проявления. Также библиотека позволяет отображать LaTeX или разметку, а ещё с её помощью интерактивно создавать файлы в Jupyter. О том, как установить и использовать Elsie, рассказано в документации.
Но с моей точки зрения ключевое достоинство Elsie заключается в том простом факте, что она позволяет программировать создание слайдов. Это серьёзная смена парадигмы, изменившая весь подход к созданию слайдов и открывшая возможность делать такие вещи, которые ранее были попросту невозможны или очень сложны — если пользоваться WYSIWYG или декларативными инструментами.
Теперь постараюсь представить некоторые практические случаи и на этих примерах проиллюстрировать, почему бывает целесообразно программировать слайды. Я приведу фрагменты кода на Python, в которых используется Elsie, но в основном они послужат нам псевдокодом, просто, чтобы продемонстрировать полезность программирования слайдов. Следовательно, если вы знаете основы Python, но не знаете Elsie, то даже без подготовки должны нормально разобраться с API Elsie.
Честно говоря, я не утверждаю, что следующие практические задачи нельзя решить одними лишь декларативными инструментами или WYSIWYG. Просто постарайтесь задуматься, насколько сложно было бы это осуществить в вашем любимом пакете для подготовки слайдов.
❯ Избегаем монотонности в работе
Программирование исключительно помогает упростить повторяющиеся задачи, и это касается, в том числе, подготовки презентаций. Приведу несколько примеров, в которых программируемость позволяет избавиться от ручной работы, либо, например, не копипастить одни и те же вещи по всей презентации.
Быстрое изменение стилей
Допустим, вы хотите быстро поменять гарнитуру шрифта (или его размер, цвет, т.д.) во всех текстовых полях вашей презентации — чтобы взглянуть, какой вариант оформления смотрится лучше всего. Либо вы хотите изменить оформление для конкретной категории текстовых полей (например, для верхних или нижних колонтитулов). Хуже того, прямо перед выступлением вы можете осознать, что под презентацию не подходит соотношение сторон проектора (4:3
/16:9
) или освещённость в комнате (светло/темно) — и оформление нужно менять прямо сейчас.
При помощи декларативных инструментов справиться с такими изменениями также довольно легко. В некоторой степени это касается и WYSIWYG-редакторов, но при работе с ними от пользователя требуется немалая дисциплина — например, это касается применения разделяемых стилей (если инструмент их поддерживает). Без самодисциплины придётся прорабатывать слайды по очереди, один за другим, мучительно меняя интересующий вас стиль вручную.
При работе с программируемыми слайдами задаваемые по умолчанию кегль шрифта, цветовую тему, размеры слайда, т.п. можно выразить при помощи обычных переменных, которые будут заложены в код, создающий слайды. Здесь, если вам потребуется что-либо откорректировать — просто измените значение переменной (обычно такое изменение укладывается в одну строку) programmable slides, the default font size, color theme, slide dimensions, выполните программу — и вы сразу же получите новую версию слайдов.
# Разделяемый стиль – это просто переменная
color = "black"
...
slide1 = slides.new_slide(bg_color=color)
...
slideX = slides.new_slide(bg_color=color)
Что, если вы хотите изменить кегль шрифта только в избранных текстовых полях (категориях полей)? Просто создайте больше переменных! Например, вы хотите задать отдельный текстовый стиль для каждой категории текстового поля и иметь возможность с лёгкостью менять оформление всех текстов, относящихся к одной и той же категории.
default = elsie.TextStyle(size=30)
# При изменении этого стиля поменяется оформление всех сносок
footnote = elsie.TextStyle(size=20, italic=True)
...
slide.text("Foo bar[^1]", style=default)
slide.text("1: This is a footnote", style=footnote)
Короче говоря, при создании слайдов переменные могут очень пригодиться.
Как избегать ненужного копипаста
Часто я предпочитаю выводить краткое содержание моей презентации (особенно если она длинная). Но, если показать содержание только в самом начале, то читатель может забыть его уже через несколько слайдов. Поэтому обычно в ходе презентации я вывожу содержание неоднократно, а также подсвечиваю тот раздел, который пойдёт следующим. Примерно вот так:
Можно прикрутить специальные кнопки, позволяющие перелистывать отдельные слайды. Представьте, что мы хотим сначала показать какой-то контент, затем содержание, затем снова контент и т.д.
Таким образом, мне понадобится несколько раз выводить один и тот же слайд (с содержанием), но в слегка изменённом виде — там будет подсвечиваться другой раздел. Как хорош был бы способ многократно выполнять одну и ту же операцию, по-разному её параметризуя, но без копипаста. В языках программирования в таких случаях обычно говорят «вызывать функцию». Я могу просто создать функцию, получающую (пустой) слайд и имя актуального раздела –, а затем подсвечивать выбранный раздел. Просто покажу интерфейс функции и как она используется:
def draw_outline(slide, active_section):
# отобразить содержание на заданном слайде
# подсветить активный раздел
...
draw_outline(slides.new_slide(), "Section A")
draw_section_a(slides)
draw_outline(slides.new_slide(), "Section B")
draw_section_b(slides)
draw_outline(slides.new_slide(), "Section C")
...
Конечно же, это общая концепция, применимая не только к содержанию. Всякий раз, когда вам требуется многократно что-то отрисовать (может быть, с незначительными вариациями), можно записать это в функцию, параметризовать её и вызывать на множестве слайдов.
Также можно пользоваться циклами, чтобы выстраивать элементы сеткой или группировать их на слайде. Это делается всего в нескольких строках кода.
Словом, функции и циклы тоже очень полезны при создании слайдов.
❯ Автоматизируем создание слайдов
Если ваши слайды генерируются программно, то генерировать их можно не только автоматически, но и на основе всевозможных данных, поступающих из разных динамических источников (всё равно автоматически) — опять же, чтобы избежать изматывающей ручной работы.
Однажды я готовил слайды для тренинга и хотел показать слайд с несколькими IP-адресами виртуальных машин, к которым ученики могут подключаться. Эксплуатация (облачных) виртуальных машин — недешёвое удовольствие, поэтому я собирался загрузить машины прямо перед выступлением. Но IP-адреса этих машин назначались динамически, так что я не мог просто жёстко запрограммировать их на слайдах, скажем, за день до презентации.
Поскольку мои слайды программировались, я создал такую функцию, которая использовала API облачного провайдера, чтобы скачать IP-адреса тех машин, которые действуют в настоящий момент (1). Затем моя программа для показа слайдов могла при помощи этой функции получать актуальные IP-адреса и выводить их на экран при каждом выполнении программы. Поэтому я прогнал программу прямо перед началом тренинга — и так у меня сразу получились обновлённые слайды, копировать в них новые IP-адреса вручную не потребовалось.
В более общем виде, если при помощи вашей программы можно генерировать слайды, то она же позволяет автоматизировать и создание работ/представлений/публикаций/диаграмм, т.д. Например, можно создать целый конвейер, в котором можно экспериментировать, расставлять контрольные точки, собирать результаты, выполнять их постобработку, визуализируя и резюмируя –, а затем разворачивать прямо в красивую презентацию (2).
Думаю, что такие инструменты как python-pptx
создавались преимущественно для этой цели. Elsie предоставляет как автоматизацию, так и удобный строительный материал для создания технических презентаций (как раз в последнем аспекте PowerPoint слабоват).
❯ Параметризация слайдов
Автоматизируя подготовку слайдов, можно с лёгкостью создавать разные версии вашей презентации на разные прикладные случаи. Когда я готовил слайды к выступлению на Meeting C++, я немного опасался, что моя live-демонстрация (выводимая внутри IDE) по какой-нибудь причине не заработает. Чтобы перестраховаться, я решил создать две версии слайдов. В одной я предусмотрел дополнительные (заранее подготовленные) скриншоты с кодом — на случай, если с демкой возникнут проблемы, а другую сделал без скриншотов, если всё пойдёт нормально.
Поскольку мои слайды были запрограммированы, мне не составило труда сделать вышеописанное. Я просто создал (булеву) переменную, через которую контролировалось, какую именно версию выводить. Скриншоты вставлялись на мои слайды только при соответствующем значении переменной. Затем моя программа выводила две версии слайдов в два PDF-файла, соответственно, с установленным и со снятым флагом (3).
❯ Создание сложных визуализаций и анимации
На мой взгляд, это, пожалуй, самое большое достоинство императивного языка как средства для создания слайдов. Представьте, что хотите добавить на слайд какой-нибудь сложный рисунок, схему или анимацию. Не указывая контекста следующих анимаций (4) (в контексте данной статьи он не так важен), допустим, что мы хотим отрисовать нечто подобное:
Или подобное:
Именно такие вещи по-настоящему «делают разницу» при подготовке технических презентаций и зачастую позволяют объяснить концепцию гораздо лучше, чем при помощи единичного статического изображения. Даже представить себе не могу, как создавал бы подобные анимации в PowerPoint или reveal.js. Вероятно, они могли бы получиться в Beamer, но мне кажется, что их гораздо проще написать на Python, чем прибегать к TikZ.
Если вам кажется, что программировать такую анимацию слишком сложно, ведь можно взять и отрисовать их вручную — отмечу, что в Elsie такие анимации также можно делать из рисунков в форматах SVG или ORA, придерживаясь соответствующего соглашения об именованиях.
❯ Заключение
Надеюсь, на этих примерах у меня получилось показать, что есть такие сценарии, в которых целесообразно не рисовать, а программировать слайды. Разумеется, даже это решение несовершенно. Бывают случаи (например, при показе очень простых слайдов), когда быстрее и проще будет обойтись предметно-ориентированным, или декларативным языком, или WYSIWYG-редактором. А ещё приметим слона: чтобы у вас получились хорошие программируемые слайды, вы должны, как минимум, уметь писать код.
Что касается меня и тех практических случаев, с которыми мне сейчас приходится иметь дело — я первым делом попытаюсь запрограммировать презентацию, а только потом посмотрю в сторону WYSIWYG-редакторов или декларативных инструментов. А поскольку Elsie — единственный известный мне прикладной инструмент для программирования слайдов технической направленности, именно этой библиотекой я предпочитаю пользоваться. :)
Итак, если вы знаете Python, но всё ещё создаёте слайды вручную — попробуйте Elsie, чтобы прокачать это искусство.
- Если призадуматься, то прямо в этой функции можно было бы и запускать машины! ↩
- А затем можете отправить эти PDF по электронной почте ващему шефу — да, и этот шаг тоже автоматизируется. ↩
- Моя демка сработала отлично, но я был очень доволен, что на всякий случай предусмотрел и резервный выход! ↩
- Угадайте, а что показано на этих анимациях? :) ↩