Приветствую, читатель. Меня зовут Алексей Самойлов. Недавно сделал для себя утилиту для восприятия таблиц на слух, которая сильно упростила мне жизнь. Надеюсь, она пригодится и вам. Утилита в том числе поддерживает вывод в JSON, а значит, круг её использования шире, чем пользователи скринридеров.


Так как я незрячий, пользуюсь программами экранного доступа. В Linux это, например, Gnome-Orca.

У меня всегда возникали сложности с чтением форматированных пробелами или чёрточками и плюсиками таблиц.

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

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

Представьте python код, где есть обычная вложенность вроде: класс, функция, цикл. И внутри цикла синтезатор говорит 12 раз слово “пробел”, а затем читает строку кода. Удобно? Не очень. Но для кода решение в скринридерах есть, это звуковые сигналы, либо проговаривание отступов только при смене вложенности вроде:

class Foo:
4 пробел def bar():

8 пробел min_val = 3
        max_val = 9
        # вложенность читается только при её смене
        for i in range(min_val, max_val + 1):
12 пробел print(i)
8 пробел return True
4 пробел some_property: str = "some value" 

Озвучивание знаков пунктуации тоже можно настроить и при необходимости они тоже будут проговариваться

Для кода удобное средство уже есть, а для таблиц в терминале нет.

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

А что у нас есть в консоле? AWK, как пример. И каждый раз вручную писать AWK выражения, чтобы просто читать табличный вывод? Очень медленно, дополнительная отвлекающая нагрузка на мозг.

При этом в браузере я спокойно могу взаимодействовать с таблицами максимально комфортно.

Вот мы и подобрались к идее создания небольшой утилиты на bash для исправления этой ситуации.

tablefmt делает из такого

PID USER      %CPU COMMAND
123 root       0.0 bash
456 john      12.5 vim -u NONE

такое

PID: 123, USER: root, %CPU: 0.0, COMMAND: bash
PID: 456, USER: john, %CPU: 12.5, COMMAND: vim -u NONE

Каждое значение указывается вместе с его названием. Просто, предсказуемо, доступно для восприятия.

Особенности

  • Оптимизирован для скринридеров — вывод в форме key: value на строку

  • Три режима вывода — inline (по умолчанию), вертикальный, и JSON Lines

  • Сортировка и выбор определенных колонок — параметры --columns, --sort, --first, --last

  • Нумерация записей--number добавит номер перед каждой строкой

  • Обрабатывает ps, top, df, free, separator tables, и многое другое

  • Никаких зависимостей — только bash и awk

И сразу пример:

Команда:

printf 'NAME|AGE|CITY\n----|----|----\nIvan|30|Moscow\n' | tablefmt --separator '|' --jsonl

И ответ:

{"NAME":"Ivan","AGE":"30","CITY":"Moscow"}

А это уже намного интересней.

Как это может быть полезно не только незрячим разработчикам?

Некоторые программы, например, speedtest-cli или yt-dlp поддерживают вывод в JSON-формате.

А что, если нужная вам консольная утилита JSON формат не поддерживает?

Вы вполне можете использовать tablefmt, чтобы получить JSON-строки, объединить их в массив и спокойно разбирать дальше.

Например, запускаем top -b -n 1 | tablefmt, направляем stdout поток в json файл, а дальше открываем этот json файл, к примеру, в python и либо построчно каждой строке делаем json.loads, либо переводы строк “\n” заменяем на запятую, оборачиваем в квадратные скобки и уже это парсим и получаем список словарей, с которыми можно работать как обычно.

Больше примеров и инструкция по установке находится в репозитории: https://github.com/alekssamos/tablefmt

Всем спасибо, что дочитали статью до конца. Желаю удачи.

P.S. Это моя первая статья на Хабре.

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