суббота, 1 октября 2016 г.

В поисках редактора Github-flavored Markdown

Обоснование

Я занимаюсь преподаванием в техническом ВУЗе. И для меня это не основная работа — прежде всего я инженер-программист. Как инженер, я стараюсь всё автоматизировать. Чтобы не повторяться на лекциях и практиках раз за разом, я пишу примеры и статьи для своих курсов.

Есть ряд требований к формату моих примеров:
  • Примеры кода должны иметь читаемый, прокомментированный в нужных местах код, понятный даже новичку в предметной области курса
  • Но даже читаемого кода недостаточно: на каждый пример нужна статья-путеводитель
  • В этой статье будет отполированный текст, схемы, иллюстрации и примеры кода.
  • Стиль должен накладываться на уже готовый контент.
На один курс требуется порядка 10-30 объёмных статей. Верстать такие статьи в MS Word или LibreOffice Writer — удовольствие так себе, потому что станет трудно отделять контент от стилей, вставлять куски кода или обеспечивать удобную навигацию по серии статей.

В конце концов я пришёл к Github-flavored Markdown. Работа с онлайн-редакторами Markdown быстро обескураживает, и встаёт вопрос выбора Offline-редактора.

ReText на Ubuntu

На Ubuntu после прочтения ряда отзывов я выбрал редактор ReText — открытое ПО, которое разрабатывается в репозитории на github.

Об этом редакторе есть хорошая статья на хабре: habrahabr.ru/post/161669
Несомненные плюсы редактора:
  • Парсер редактора хорошо умеет работать в Github-совместимом режиме, и это большая редкость среди редакторов Markdown
  • Есть live preview, который включается в меню редактора
  • Есть публикация в ODT и PDF
  • Есть поддержка расширений, которая позволяет включить подсветку кусков исходного кода в Preview документа, включить Table of Contents и другие подобные вещи. В сочетании с публикацией в PDF/ODT это часто работает неправильно.
  • На заметку: я для себя перечислял через запятую расширения "codehilite" и "toc", которые после перезапуска редактора начинали работать.
Минусы:
  • В сочетании с публикацией в PDF/ODT расширения часто работают неправильно.
  • Live preview пока что посредственно работает с автоскроллингом: если вы редактируете текст, автоскроллинг preview может уйти куда-либо в сторону на сложных документах.
  • Публикация в ODT реализована простым созданием объекта класса QTextDocument и записью его с помощью QTextDocumentWriter. В результате корректно генерируются только простые документы, а в сложных стили, подсветка кода или Table of Contents могут слететь, и даже простые маркеры списков экспортируются неправильно.
Пользователям Linux я бы посоветовал поставить версию из репозитория Github, а не из системных репозиториев. В этом случае вы встретите меньшее число недоработок.
 
   

Github Atom на любой платформе

Другой удобный вариант — это Github Atom, который обладает всеми плюсами предыдущего редактора (кроме разве что экспорта в ODT). Кроме того, Github Atom легко устанавливается на любой платформе, и имеет средства, например, для просмотра файловой структуры.

Несколько советов:
  • Если вы набираете русский текст, то отключите в настройках встроенный плагин Spell Check. На момент написания этого поста плагин ищет ошибки только по английскому словарю, и безнадёжно подчёркивает красным цветом весь русскоязычный текст.
  • В основной поставке атома уже есть поддержка Preview: хоткей "Ctrl+Shift+M"
  • Есть сторонний пакет "markdown-scroll-sync", который качественно синхронизирует курсор в тексте и прокрутку preview документа
  • Встроенный парсер Markdown может запросто сломаться на вставках исходного кода. Пакет "language-markdown" перегружает и улучшает встроенный парсер, исправляя его от поломок и добавляя подсветку вставок исходного кода.

Публикация на Github Pages

Сервис Github предоставляет хостинг статических сайтов, известный как Github Pages. Никакого бекенда — всё должно быть на Javascript (без XHR, т.е. без запросов на другие доменты), CSS и HTML. Правда, есть интеграция с генератором Jekyll, который превращает Markdown в HTML, а SCSS в CSS.


Если вы хотите развернуть свой сайт со статьями на Markdown, дам несколько советов:
  • Jekyll написан на Ruby, и его проще развернуть на Linux или MacOSX, а не на Windows. Однако, знание Ruby вам едва ли потребуется.
  • Будьте готовы испортить свой Markdown из-за заголовка, который вам придётся добавлять в каждую статью. В примере ниже свойство title можно и не ставить, а вот разделители "---" поставить придётся в любом случае, иначе Jekyll просто не будет обрабатывать весь файл:
  • ---
    title: 'UV-параметризация сферы'
    ---
  • Чтобы запустить локальную версию сайта на http://localhost:4000/, запустите Jekyll в режиме веб-сервера командой "jekyll serve". Jekyll будет автоматически отслеживать изменения в каталоге проекта и перегенерировать файлы.
  • Если вы хотите, чтобы ваши статьи имели обозначенный вами же preview в соцсетях, вы можете настроить интеграцию OpenGraph с Jekyll.
Исходники моего собственного сайта лежат в репозитории ps-group/ps-group.github.io. Вы можете изучить его как неидеальный, но вполне практичный пример настройки Jekyll.

На сегодня у меня всё.

среда, 13 апреля 2016 г.

Маленькие заметки о Chroot

Я хочу получить свой маленький билд-сервер под Ubuntu. Билд-сервер должен быть локальным, вложенным в основную систему, и при этом должен полностью изолировать исходники от живущих снаружи компиляторов, библиотек и прочего барахла (своего рода SDK своими руками).

Здесь будут полезные заметки, которые появились в ходе попыток это сделать.

На билдсервере должна быть минимальная система для динамической линковки:
  • GLibc, а лучше LSB libc (минимальная POSIX-совместимая библиотека C, предоставленная проектом Linux Standards Base)
  • Библиотеки криптографии (т.к. они иногда обновляются с целью закрытия уязвимостей).
  • Библиотеки мультимедиа: OpenGL, OpenAL, SDL2, SDL1.2 (т.к. они соединяют с драйверами)
  • Возможно, ещё какие-то библиотеки, которые имеют стабильные API и ABI
Всё остальное должно быть доступно лишь для статической линковки:
  • C++ STL (варианты: libstdc++, libc++)
  • C++ Boost
  • C++ Cocos2dx
  • C++ Cinder
  • C++ SFML
  • C GLFW
  • И так далее

Chroot и Debootstrap

ОС Linux позволяет создать виртуальную корневую директорию, и войти в неё из-под оболочки терминала. Получается система в системе, причём вложенная система изолирована (не от вредоносного ПО, а от случайного обращения наружу).

Скрипт debootstrap есть в репозиториях Ubuntu, он позволяет скачать и установить в виртуальный корень целый дистрибутив Debian или Ubuntu произвольной версии. После установки можно будет сделать chroot во вложенную систему, и уже там установить необходимое окружение разработки и так далее.

Вот две типичных команды скачивания/установки вложенной системы
# Скачает и установит 32-битной Trusty (Trusty - это Ubunty 14.04) в папку ./trusty32
sudo debootstrap --arch i386 trusty ./trusty32/
# Скачает и установит Trusty родной архитектуры (x64 на моей машине) в папку ./trusty64
sudo debootstrap trusty ./trusty64/

Ещё debootstap позволяет
  • Поставить систему неродной архитектуры, пусть даже ARM (тогда будет запускаться через QEMU)
  • Поставить любую доступную версию Debian или Ubuntu
  • Указать зеркало, с которого скачивать пакеты (например, зеркала Yandex или локальный сервер в Вашей организации)

Настройка chroot после установки вложенной ОС

  1. Чтобы войти в chroot-папку, введите "sudo chroot ./trusty32" (trusty32 - путь к вложенной системе в моём случае)
  2. После установки локаль ещё не настроена, что делает систему не совсем работоспособной. Нагугленная настройка в две строчки выручила меня:
    # Английский язык (Американский диалект), кодировка UTF-8.
    echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
    locale-gen
  3. Войти в chroot-папку может только рут, поэтому для сброса привелегий рута внутри вложенной системы надо настроить пользователя:
    # Выполнить 1 раз и пройти консольный мастер настройки пользователя "bb"
    adduser bb
    # Выполнять каждый раз для логина под пользователем bb
    su - bb
  4. ...
Пост будет обновляться.

четверг, 10 декабря 2015 г.

Семантика владения в C++

C++ 11

Язык C++ сильно изменился с выходом нового стандарта, C++ 2011. Сменилась генеральная линия партии: теперь разработчикам не рекомендуется вообще использовать new и delete, потому что всё можно сделать проще без них. Вот сразу пример:

Кратко о выделении памяти

В C++ есть два места, где можно размещать переменные — это стек (stack) и динамическая куча (heap).
  • Стек выделяется для каждого потока каждой программы операционной системой. При вызове функции стек растёт, потому что через вершину стека передаются параметры функции и адрес возврата. В начале работы функции стек растёт ещё раз, потому что в нём располагаются локальные переменные. При выходе из функции размер стека уменьшается.
  • Куча не размечена, операционная система даёт программисту возможность выделять или освобождать отдельные куски этой кучи. При этом куча подвержена фрагментации, и нет гарантий, что при общей нехватке памяти в системе запрошенный программой кусок памяти удастся выделить.

Кратко о семантике владения

Пожалуй, самая популярная в наше время парадигма программирования - объектная. В рамках парадигмы любая программа представляется как набор объектов, например:
  • Объект Application, который хранит основной цикл интерактивного приложения
  • Абстрактный объект Shape (т.е. фигура без каких-либо уточнений) и конкретные классы RectangleShape, CircleShape и так далее.
  • Объекты Enemy и EnemyBehavior, хранящие соответственно визуальное представление и поведение врага в игре
Обычно любым объектом (кроме самого главного) кто-то владеет. Иначе говоря, кто-то
  • создаёт объект сразу или по мере необходимости
  • управляет поведением объекта или даёт управлять им кому-то ещё
  • удаляет объект
Отношение владения формирует иерархию объектов. Иерархия хорошо представляется в виде дерева — в дереве легко понять, кто кем владеет:
  • корень дерева прямо или косвенно владеет всем, корнем не владеет никто
  • листья дерева никем не владеют 
Кстати говоря, дерево является графом без циклов.

Сильные указатели

Типы std::unique_ptr<T> и std::shared_ptr<T> являются умными указателем, подходящим для древовидной иерархии владения. Советы:
  • Используйте shared_ptr, если объектом владеют несколько родителей. Например, если одна и та же картинка используется в качестве фона нескольких кнопок.
  • Используйте функцию std::make_shared для создания shared_ptr, это лучше в плане читаемости и скорости выполнения кода.
  • Используйте функцию std::make_unique для создания unique_ptr, это лучше в плане читаемости кода.

Слабые указатели

Допустим, что в нашем дереве мы захотим иметь ссылку из дочернего узла на родительский, или даже на соседнюю ветку. Например, хотим в объекте-враге хранить указатель на цель, котоую он сейчас атакует.
Если мы создадим shared_ptr, в графе владения возникнет цикл. 
Циклы удаляются только в средах выполнения со сборкой мусора (именно в этом причина снижения производительности из-за сборки мусора в «современных» языках, таких как Java и C#).
Во избежание создания циклов используйте weak_ptr для ссылания на родителя или другую ветвь. Суть weak_ptr очень проста:
  • он никак не владеет тем, на что указывает, и не меняет время жизни
  • значение указателя внутри weak_ptr обратится в ноль в тот момент, когда объект, на который указывает weak_ptr, уничтожится.
  • weak_ptr тесно связан с shared_ptr, и они взаимно приводятся друг в друга
Подробнее и с примерами про weak_ptr и shared_ptr можно прочитать здесь: http://archive.kalnitsky.org/2011/11/02/smart-pointers-in-cpp11/  

Применения семантики владения

Семантика владения, основанная на unique_ptr, shared_ptr, weak_ptr и полном отсутствии new/delete, позволяет проще и надёжнее писать различные программы:
  • Игры, применяющие паттерн SceneGraph и обрабатывающие физические коллизии между объектами
  • Компиляторы, использующие Abstract Syntax Tree для промежуточного хранения модели кода
  • WYSIWYG-редакторы, загружающие модель документа в память программы и отображающие документ на экране

понедельник, 15 июня 2015 г.

Двойная буферизация GDI+ с WTL

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

понедельник, 8 июня 2015 г.

Ubuntu Make в действии

В Ubuntu Trusty (это LTS-выпуск 14.04) есть отличный способ установки инструментов для разработчика — Ubuntu Make. Он способен по заранее подготовленным рецептам установить и настроить нужный вам SDK, попутно «подтянув» все необходимые для него пакеты.

понедельник, 1 июня 2015 г.

Так ли нужны пакетам в Ubuntu права root?

В этом посте я расскажу о том, как, теоретически, может работать установка приложений для Linux прямо в HOME, без прав root и в обход системного пакетного менеджера.

среда, 21 августа 2013 г.

Дополнительная проверка типов в OpenGL

В ноябре прошлого года Дмитрий Грибенко, разработчик компилятора clang из Киева, представил новое расширение clang: проверка типов в функциях, интерпретирующих тип аргумента A, переданного по указателю на void*, различными способами в зависимости от значения аргумента B.