![](https://habrastorage.org/getpro/habr/post_images/614/c7a/da8/614c7ada8fa9c432327c7c1c938c7efa.png)
Большинство людей — визуалы. Они используют изображения, чтобы вникнуть в суть проблемы. А вот мэйнстримные языки программирования, напротив, основаны на текстовом представлении. Возникающую пропасть между текстом и графикой заполняют ASCII-изображения, нарисованные с помощью текстовых символов и вставленные в исходный код программы. Я их обожаю! Как-то раз я кинул клич в Twitter и мне прислали гораздо больше примеров, чем я ожидал. Спасибо всем участвовавшим. В этой теме попалось несколько прекрасных примеров, которые я собрал и разложил на категории. Для каждого изображения дается ссылка на соответствующий репозиторий.
Структуры данных
Одно из самых распространенных применений ASCII-арта в коде — наглядно показать структуру данных.
Первый пример из исходного кода LLVM:
![](https://habrastorage.org/getpro/habr/post_images/ff5/7cb/208/ff57cb208f11f9b31188822a08f4a90c.png)
Исходник
Расположение полей в структуре данных в Jikes RVM:
![](https://habrastorage.org/getpro/habr/post_images/bb3/e0c/dab/bb3e0cdabb582517d8c23946eabec191.png)
Исходник
Поворот дерева в Musl:
![](https://habrastorage.org/getpro/habr/post_images/c12/2e1/4b9/c122e14b9beb666c4e36495be3c7ff81.png)
Исходник
Двусторонняя очередь в Rust:
![](https://habrastorage.org/getpro/habr/post_images/c72/c4f/0ce/c72c4f0cea0281700e587dd43ed4031a.png)
Исходник
Внутренности компилятора Swift:
![](https://habrastorage.org/getpro/habr/post_images/633/2bb/f95/6332bbf95a2bc5d1490b8818a406d3f4.png)
Исходник
Расположение элементов в заголовке Malloc:
![](https://habrastorage.org/getpro/habr/post_images/dd0/b2c/862/dd0b2c86246df9d16bda8e51ac280249.png)
Исходник
Конечные автоматы
Профилирование Javascript:
![](https://habrastorage.org/getpro/habr/post_images/317/e78/afa/317e78afa9d6b7d26d3ae64ecd9485f4.png)
Исходник
RPC в Cloud Spanner:
![](https://habrastorage.org/getpro/habr/post_images/3ec/524/5ff/3ec5245ff6dc5eb47ac7771a1eaaf28a.png)
Исходник
Состояния потока ввода-вывода:
![](https://habrastorage.org/getpro/habr/post_images/3e1/1f1/211/3e11f121175100ec0325edb1107f38a4.png)
Исходник
Логика предметной области
Поток управления в декомпилируемой программе NWScript:
![](https://habrastorage.org/getpro/habr/post_images/7db/af2/a88/7dbaf2a8826aaea457899e18197cb055.png)
Исходник
Внутренности ECC:
![](https://habrastorage.org/getpro/habr/post_images/d20/189/1bc/d201891bc063b794ec7959e4e08dd4c9.png)
Исходник
Форматирование чисел:
![](https://habrastorage.org/getpro/habr/post_images/0aa/d4a/ba5/0aad4aba5e907c7bbad6d2110402f27e.jpg)
Исходник
Квантовый контур:
![](https://habrastorage.org/getpro/habr/post_images/129/fc9/747/129fc9747fc4ea6c6e043e47a924cc04.png)
Исходник
Балансировка задач управления памятью в ядре операционной системы:
![](https://habrastorage.org/getpro/habr/post_images/0d8/734/7b0/0d87347b04abf48ec8597ee582f81ea8.png)
Исходник
Совместимость типов (это особенно впечатляющий случай, потому что здесь ASCII-арт является кодом!)
![](https://habrastorage.org/getpro/habr/post_images/db5/ebb/24f/db5ebb24f9fa331ff7318e07b572d447.png)
Исходник
Формат файла DBF:
![](https://habrastorage.org/getpro/habr/post_images/31f/500/249/31f500249dcc973e7f1bcae9e409aba5.png)
Исходник
Lookup-таблица для обработки изображений:
![](https://habrastorage.org/getpro/habr/post_images/594/be1/705/594be17056cc3fe6d71389e24dea98a2.png)
Исходник
Форма цветовой функции:
![](https://habrastorage.org/getpro/habr/post_images/b28/bcf/9c2/b28bcf9c2adf188df33e74a18410ae64.png)
Исходник
Структура URL:
![](https://habrastorage.org/getpro/habr/post_images/e9c/393/667/e9c3936671ccbfed7d6738e0eee513d9.png)
Исходник
«Краткая» справка по отмене операций в emacs:
![](https://habrastorage.org/getpro/habr/post_images/54b/0b8/44f/54b0b844f9d246c035dfad33a68702df.png)
Исходник
Примечание переводчика: по ссылке еще очень много подобных графиков
Геометрия
Контроль высоты в бортовом компьютере Apollo (!!!):
![](https://habrastorage.org/getpro/habr/post_images/2c5/d56/f29/2c5d56f2926246c9ad833e9bacb3766b.png)
Исходник
Разбитие изображения на сегменты:
![](https://habrastorage.org/getpro/habr/post_images/5f5/121/1f6/5f51211f663ee97b3c40e1b6b90708e4.png)
Исходник
Траектории бумеранга в Nethack:
![](https://habrastorage.org/getpro/habr/post_images/45b/482/d7b/45b482d7b5634e1d0e6e68d0abe61b41.png)
Исходник
Отрисовка границ элемента в CSS:
![](https://habrastorage.org/getpro/habr/post_images/0cf/55e/964/0cf55e9644f5d91bee34be75dbd36a29.png)
Исходник
Дерево квадрантов:
![](https://habrastorage.org/getpro/habr/post_images/a8b/a2c/715/a8ba2c7157885843a1a9647b84e160c9.png)
Исходник
Управление скоростью работы станка:
![](https://habrastorage.org/getpro/habr/post_images/7e9/990/d45/7e9990d45b135907b0af18088f60ea3b.jpg)
Исходник
Скроллинг веб-страниц:
![](https://habrastorage.org/getpro/habr/post_images/894/c42/fd7/894c42fd7d0619db9e21b0af356b290b.png)
Исходник
Надеюсь, вам понравилось!
Дополнительный пример от переводчика:
График интерполяции значения:
![](https://habrastorage.org/getpro/habr/post_images/1d2/6af/485/1d26af485dae4b491e7f0bb6a3edd141.png)
Исходник
Комментарии (23)
reticular
19.02.2019 12:19+1` /)/)
=(';')=
(").(")…catsmile
19.02.2019 20:48+1Персонально я в своих комментариях использовал
(_*_)
и
?\_(?)_/?
Как правило это было связано с форматом респонса API.
Keyten
20.02.2019 15:29--MEOW--/>? ?
?????| ?_? _|
? ???/`? _x ?
?? ? /??? ? |
??? /? ??? ?
?/?|?? |?|?|
?| (??__?_)_)
?\??
tuxi
19.02.2019 14:13Аж слезу пустил. Моя первая (не первая по счету, но первая сделанная на персоналке) программа была предназначена для создания из ASCII символов заставок для использования их в других программах. ДВК-2М и Pascal. Называлась S.M.I.T. Управление клавиатурой, сохранение в готовый код на Паскале.
surly
20.02.2019 13:52Аналогично, но для Robotron-1715. Преобразования в исходники не было, только рисование, сохранение, загрузка.
Lpndn
19.02.2019 19:26Давно думал, как элегантно внедрять схемы в текстовую документацию, а про ASCII совсем позабыл. Спасибо!
mechatroner
19.02.2019 19:35Спасибо за популяризацию интересной идеи!
Но вот только зачем было в качестве КДПВ ставить первое изображение? И в оригинальной статье его нет.
vyo
19.02.2019 21:36Порой и сам код тянет на ASCII-арт. Чего хоть стоит паттерн для захвата двух последовательно идущих символов в lua:
"(.)(.)"
(пример настоящий).
mafia8
19.02.2019 22:09Файл сжать и перевести в uue. Поместить в исходный код с некоторым текстом, плагин редактора заметит этот текст, достанет файл, развернёт и покажет.
DROS
19.02.2019 23:20О, сам пользуюсь такой методикой для описания формата хранения например или какого хитровыкрученного алгоритма. Очень удобно. Правда «рисую» ручками, а не софтом.
KvanTTT
20.02.2019 00:07+1Возникла идея. Графы можно описывать с помощью graphviz, а блок-схемы — с помощью mermaid. Ведь можно сделать поддержку рендера этих объектов прям внутри IDE! Описывать графы и блок-схемы нужно будет в комментах с помощью привычных для Markdown маркеров ```dot, ```mermaid. Да и вообще можно сделать рендер и маркдауна тоже.
Исходники останутся "диффабельным", но при этом в IDE будут рендериться наглядные картинки.
Danik-ik
20.02.2019 08:41Ну, добрая четверть примеров похожа на текстовый вариант выхлопа plantuml (поверх graphviz работает). Кмк, лучший uml формат для хранения в git. И плагин к Идее есть. И локально запускается, не только онлайн.
И если бы мне захотелось вставлять в код uml диаграммы в комментариях, я бы делал это автогенерацией из исходника на plantuml
MacIn
20.02.2019 00:21А то как же.
Вот иллюстрация работы класса с «устаревающим» набором данных:
{ TSlinky } // mW0__ <-data items // _0_|3 ^ // ___|2 | // ___|1 | // __|0 | //t <------------------+
Вспоминается документация к СМ ЭВМ и программам для ОСРВ, которая была отпечатана, судя по всему, на «барабанных» АЦПУ и там было полно таких схем, как в статье, объясняющих структуры данных, программных и аппаратных комплексов, интерфейсов…
sergey-gornostaev
20.02.2019 06:58+1В коде Netty (javadoc'ах если быть точным) это активно используется:
The following diagram describes how I/O events are processed by ChannelHandlers in a ChannelPipeline typically. An I/O event is handled by either a ChannelInboundHandler or a ChannelOutboundHandler and be forwarded to its closest handler by calling the event propagation methods defined in ChannelHandlerContext, such as ChannelHandlerContext.fireChannelRead(Object) and ChannelOutboundInvoker.write(Object). I/O Request via Channel or ChannelHandlerContext | +---------------------------------------------------+---------------+ | ChannelPipeline | | | \|/ | | +---------------------+ +-----------+----------+ | | | Inbound Handler N | | Outbound Handler 1 | | | +----------+----------+ +-----------+----------+ | | /|\ | | | | \|/ | | +----------+----------+ +-----------+----------+ | | | Inbound Handler N-1 | | Outbound Handler 2 | | | +----------+----------+ +-----------+----------+ | | /|\ . | | . . | | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()| | [ method call] [method call] | | . . | | . \|/ | | +----------+----------+ +-----------+----------+ | | | Inbound Handler 2 | | Outbound Handler M-1 | | | +----------+----------+ +-----------+----------+ | | /|\ | | | | \|/ | | +----------+----------+ +-----------+----------+ | | | Inbound Handler 1 | | Outbound Handler M | | | +----------+----------+ +-----------+----------+ | | /|\ | | +---------------+-----------------------------------+---------------+ | \|/ +---------------+-----------------------------------+---------------+ | | | | | [ Socket.read() ] [ Socket.write() ] | | | | Netty Internal I/O Threads (Transport Implementation) | +-------------------------------------------------------------------+
Magn
21.02.2019 00:41Да, было дело.
Хотя лично мне кажется, что некоторые из представленных в посте «комментариев» тянут на страницу в нормальной документации. ASCII-арт комментарий должен помочь быстро понять суть, если её можно передать простой картинкой, но не более. Имхо, конечно.
KhodeN
21.02.2019 11:32В тестах RxJS используются не только для документирования, но и для входных и ожидаемых данных (событий в потоках).
DSolodukhin
А чем можно рисовать такие диаграммы, как в примере с компилятором swift?
impwx Автор
Похоже на AsciiFlow.
dlinyj
sudo apt install asciio && asciio
n00ker
можно накидать схему в plantUml и сгенерировать ascii код по ней.