Примечание от переводчика: типично пятничная статья во вторник утром… почему бы и нет?



Большинство людей — визуалы. Они используют изображения, чтобы вникнуть в суть проблемы. А вот мэйнстримные языки программирования, напротив, основаны на текстовом представлении. Возникающую пропасть между текстом и графикой заполняют ASCII-изображения, нарисованные с помощью текстовых символов и вставленные в исходный код программы. Я их обожаю! Как-то раз я кинул клич в Twitter и мне прислали гораздо больше примеров, чем я ожидал. Спасибо всем участвовавшим. В этой теме попалось несколько прекрасных примеров, которые я собрал и разложил на категории. Для каждого изображения дается ссылка на соответствующий репозиторий.

Структуры данных


Одно из самых распространенных применений ASCII-арта в коде — наглядно показать структуру данных.

Первый пример из исходного кода LLVM:


Исходник

Расположение полей в структуре данных в Jikes RVM:


Исходник

Поворот дерева в Musl:


Исходник

Двусторонняя очередь в Rust:


Исходник

Внутренности компилятора Swift:


Исходник

Расположение элементов в заголовке Malloc:


Исходник

Конечные автоматы


Профилирование Javascript:


Исходник

RPC в Cloud Spanner:


Исходник

Состояния потока ввода-вывода:


Исходник

Логика предметной области


Поток управления в декомпилируемой программе NWScript:


Исходник

Внутренности ECC:


Исходник

Форматирование чисел:


Исходник

Квантовый контур:


Исходник

Балансировка задач управления памятью в ядре операционной системы:


Исходник

Совместимость типов (это особенно впечатляющий случай, потому что здесь ASCII-арт является кодом!)


Исходник

Формат файла DBF:


Исходник

Lookup-таблица для обработки изображений:


Исходник

Форма цветовой функции:


Исходник

Структура URL:


Исходник

«Краткая» справка по отмене операций в emacs:


Исходник
Примечание переводчика: по ссылке еще очень много подобных графиков

Геометрия


Контроль высоты в бортовом компьютере Apollo (!!!):


Исходник

Разбитие изображения на сегменты:


Исходник

Траектории бумеранга в Nethack:


Исходник

Отрисовка границ элемента в CSS:


Исходник

Дерево квадрантов:


Исходник

Управление скоростью работы станка:


Исходник

Скроллинг веб-страниц:


Исходник

Надеюсь, вам понравилось!

Дополнительный пример от переводчика:

График интерполяции значения:


Исходник

Комментарии (23)


  1. DSolodukhin
    19.02.2019 12:05
    +1

    А чем можно рисовать такие диаграммы, как в примере с компилятором swift?


    1. impwx Автор
      19.02.2019 12:11
      +4

      Похоже на AsciiFlow.


      1. dlinyj
        19.02.2019 12:45

        sudo apt install asciio && asciio


    1. n00ker
      19.02.2019 13:04

      можно накидать схему в plantUml и сгенерировать ascii код по ней.


  1. reticular
    19.02.2019 12:19
    +1

    ` /)/)
    =(';')=
    (").(")…


    1. catsmile
      19.02.2019 20:48
      +1

      Персонально я в своих комментариях использовал
      (_*_)
      и
      ?\_(?)_/?
      Как правило это было связано с форматом респонса API.


    1. Keyten
      20.02.2019 15:29

      --MEOW--/>? ?
      ?????| ?_? _|
      ? ???/`? _x ?
      ?? ? /??? ? |
      ??? /? ??? ?
      ?/?|?? |?|?|
      ?| (??__?_)_)
      ?\??


    1. hogans
      22.02.2019 10:17
      +1

      обычно другого зайца применяют:
      (\__/)
      (='.'=)
      е[:]|||||[:]3
      (")_(")


  1. tuxi
    19.02.2019 14:13

    Аж слезу пустил. Моя первая (не первая по счету, но первая сделанная на персоналке) программа была предназначена для создания из ASCII символов заставок для использования их в других программах. ДВК-2М и Pascal. Называлась S.M.I.T. Управление клавиатурой, сохранение в готовый код на Паскале.


    1. surly
      20.02.2019 13:52

      Аналогично, но для Robotron-1715. Преобразования в исходники не было, только рисование, сохранение, загрузка.


  1. Lpndn
    19.02.2019 19:26

    Давно думал, как элегантно внедрять схемы в текстовую документацию, а про ASCII совсем позабыл. Спасибо!


  1. mechatroner
    19.02.2019 19:35

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


    1. impwx Автор
      19.02.2019 19:53
      +1

      Это отсылка к старому мему.


  1. vyo
    19.02.2019 21:36

    Порой и сам код тянет на ASCII-арт. Чего хоть стоит паттерн для захвата двух последовательно идущих символов в lua: "(.)(.)" (пример настоящий).


  1. mafia8
    19.02.2019 22:09

    Файл сжать и перевести в uue. Поместить в исходный код с некоторым текстом, плагин редактора заметит этот текст, достанет файл, развернёт и покажет.


  1. DROS
    19.02.2019 23:20

    О, сам пользуюсь такой методикой для описания формата хранения например или какого хитровыкрученного алгоритма. Очень удобно. Правда «рисую» ручками, а не софтом.


  1. KvanTTT
    20.02.2019 00:07
    +1

    Возникла идея. Графы можно описывать с помощью graphviz, а блок-схемы — с помощью mermaid. Ведь можно сделать поддержку рендера этих объектов прям внутри IDE! Описывать графы и блок-схемы нужно будет в комментах с помощью привычных для Markdown маркеров ```dot, ```mermaid. Да и вообще можно сделать рендер и маркдауна тоже.


    Исходники останутся "диффабельным", но при этом в IDE будут рендериться наглядные картинки.


    1. Danik-ik
      20.02.2019 08:41

      Ну, добрая четверть примеров похожа на текстовый вариант выхлопа plantuml (поверх graphviz работает). Кмк, лучший uml формат для хранения в git. И плагин к Идее есть. И локально запускается, не только онлайн.


      И если бы мне захотелось вставлять в код uml диаграммы в комментариях, я бы делал это автогенерацией из исходника на plantuml


  1. MacIn
    20.02.2019 00:21

    А то как же.
    Вот иллюстрация работы класса с «устаревающим» набором данных:

    { TSlinky }
    
    //           mW0__ <-data items
    //          _0_|3      ^
    //       ___|2         |
    //    ___|1            |
    //  __|0               |
    //t <------------------+
    
    

    Вспоминается документация к СМ ЭВМ и программам для ОСРВ, которая была отпечатана, судя по всему, на «барабанных» АЦПУ и там было полно таких схем, как в статье, объясняющих структуры данных, программных и аппаратных комплексов, интерфейсов…


  1. 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)            |
      +-------------------------------------------------------------------+
    


  1. MonkAlex
    20.02.2019 10:04
    +1

    У нас есть такая штуковина для определения видимости контролов =)
    image


  1. Magn
    21.02.2019 00:41

    Да, было дело.
    image

    Хотя лично мне кажется, что некоторые из представленных в посте «комментариев» тянут на страницу в нормальной документации. ASCII-арт комментарий должен помочь быстро понять суть, если её можно передать простой картинкой, но не более. Имхо, конечно.


  1. KhodeN
    21.02.2019 11:32

    В тестах RxJS используются не только для документирования, но и для входных и ожидаемых данных (событий в потоках).