Пишу, по большей части, про историю, свою жизнь и немного про программирование.

Избранное

cmd.sh

Я тут случайно в спор ввязался — можно ли переписать бат-файл так, чтобы он запускался и выводил примерно одинаковый результат на трёх основных операционных системах — Виндоузе, Линуксе и МакОСи.

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

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

Что ж. Основная моя идея была в том, чтобы заменить команды батника на вызовы баш-функций, которые я спрячу в специальных конструкциях. В Виндоузе файл обработает обычный cmd.exe, на остальных операционках — bash.

То, что мне предстояло адаптировать начиналось вполне стандартно:

@ECHO off
CHCP 1251
CLS

Что тут происходит? Выключается вывод команд на экран (при адаптации это можно игнорировать), ставится однобайтовая кодировка CP1251 (это хорошо бы учесть) и очищается экран.

Поскольку «баш» этих команд не знает, надо определить три функции, спрятав их от cmd.exe. Сделать это несложно. Команду «двоеточие» cmd.exe трактует как начало метки и на дальнейшее не реагирует, а «баш» считает её пустой командой, которую можно точкой с запятой отделить от строки, которую мы хотим спрятать:

:; @ECHO() { :;}; CLS() { clear; }; CHCP() { ENC="$1"; }

Следующее, чему надо научиться — выводить текст в указанной в батнике кодировке. Это просто:

:; ECHO.() { echo $@ | iconv -f "CP$ENC"; }

Если теперь сделать файл запускаемым и добавить впереди #!/bin/bash (и пренебречь тем, что cmd.exe успевает ругнуться на эту строку до очистки экрана), у нас получится следующий файл, работающий во всех трёх операционках (кодировка должна быть Windows-1251):

#!/bin/bash
:; @ECHO() { :;}; CLS() { clear; }; CHCP() { ENC="$1"; }
@ECHO off
CHCP 1251
CLS
:; ECHO.() { echo $@ | iconv -f "CP$ENC"; }
ECHO. Всем привет

А вот дальше сложнее. Само меню организовано в оригинале так:

SET /p opt=Введите цифру:

IF %opt%==1 GOTO dns_auto
IF %opt%==2 GOTO dnschange
IF %opt%==3 GOTO exit

В «баше» goto (переход к метке) отсутствует и это проблема. Аналогов тоже нет. Единственное, что тут можно сделать — использовать вызов функций, но синтаксис в «бате» и «баше» сильно различается.

Как быть? Во-первых, сэмулировать функцией команду SET, во-вторвых, упростить это место, чтобы меньше было писать кода на «баше»:

:; SET() { shift; ECHO. -n "${@#*=}"; read -n1 "${1%%=*}"; echo; }
:; CALL() { eval "$(sed 's/%\(.*\)%/$\1/g' <<< "$1")" 2>&-; }

SET /p opt=Введите цифру:
CALL :menu_%opt%

Первая функция парсит команду SET выводит строку после равно, ждёт ввода и записывает значение в имя переменной, указанной слева от равно.

Вторая — заменяет CALL. В ней %variable% заменяется на $variable, выполняется подстановка переменной и получившееся имя выполняется как команда или функция «баша». Конструкция 2>&- нужна, чтобы избежать вывода ошибки в ситуации, если пользователь введёт что-нибудь не то.

Теперь надо как-то научиться определять функции так, чтобы их нормально «видел» и cmd.exe, и «баш». В батнике функции — просто любое место программы, начинающееся с метки и заканчивающееся вызовом GOTO :EOF:

:function_1
ECHO это якобы функция
GOTO :EOF

В «баше» то же самое могло бы выглядеть, например, так:

function_1() {
    echo это функция
}

Как это объединить? Я придумал следующий подход:

:; GOTO() { :; };

GOTO ;#start
:function_1 (){
ECHO. это [якобы] функция
GOTO :EOF
:; }

:;#start

В первой строке определяется пустая функция для «баша», потому что эта часть синтаксиса бат-файла нам не нужна.

Ниже идёт строка GOTO ;#start. С точки зрения «баша» тут две конструкции — GOTO, которая вызывает определённую выше пустую функцию и #start — строка комментария, так как в«баше» с «решётки» начинаются комментарии.

В «батнике» же эта же строка будет означать переход к метке с именем ;#start. Этот переход нужен нам, чтобы «обогнуть» строки, которые определены ниже, иначе cmd.exe начнёт сразу их выполнять, а нам этого не нужно. Их нельзя «спрятать» ниже основной программы, так как в «баше» функции должны определены раньше их вызова.

Что происходит дальше? С точки зрения cmd.exe ниже расположена метка :function_1 (как показывают мои эксперименты, часть после пробела просто отбрасывается), потом тело функции, команда её завершения GOTO :EOF и метка с именем :;}.

С точки зрения «баша» там определяется функция с именем :function_1, ниже идут вызовы уже определённых мною функций ECHO. и GOTO, а ещё ниже — уже знакомая нам пустая команда : и фигурная скобка, завершающая тело функции.

Соединяем всё вместе и получается следующая программа:

#!/bin/bash
:; @ECHO() { :;}; CLS() { clear; }; CHCP() { ENC="$1"; }
@ECHO off
CHCP 1251
CLS

:; GOTO() { :; };
:; ECHO.() { echo $@ | iconv -f "CP$ENC"; }; PAUSE() { read; }; 
:; SET() { shift; ECHO. -n "${@#*=}"; read "${1%%=*}"; }
:; CALL() { eval "$(sed 's/%\(.*\)%/$\1/g' <<< "$1")" 2>&-; }

GOTO ;#start

:menu_1 (){
ECHO. Пункт первый
GOTO :EOF
:; }

:menu_2 (){
ECHO. Пункт второй
GOTO :EOF
:; }

:;#start

SET /p opt=Введите цифру:
CALL :menu_%opt%

Мой оппонент признал, что в споре я победил.

Пишем на «Флиппере Зеро» по-русски

Вкратце: в русским текстом работать можно, но сложно, код лежит на «Гитхабе».

Не мог не обратить внимание, что несмотря на приличное количество русскоязычных авторов программ для «Флиппера Зеро» и российское происхождение устройства, в софте под него нигде не обнаружилось ни одной буквы по-русски.

Flipper Zero

Стало интересно — а есть ли вообще в устройстве поддержка русского языка? Сел вечерком за исходники прошивки и оказалось, что однозначного ответа на заданный вопрос нет. Частичная поддержка есть и её можно заставить работать, но она работает как будто по недосмотру — никто её не собирался делать, так случайно вышло.

Вывод русских букв (трансляция с экрана через оболочку qFlipper)

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

Внутри «Флиппера» довольно много всякого АПИ для вывода текста, от незатейливого, выводящего строку в заданные координаты, до довольно навороченного, умеющего переносить и выравнивать текст. К сожалению, с русскими буквами оно работать не умеет.

Под капотом у этого АПИ — очень известная в своей нише библиотека U∞g2, у которой по историческим, видимо, причинам есть два набора функций для работы со строками. Одни принимают только однобайтовую кодировку ASCII, другие работают в Юникоде.

АПИ «Флиппера», к сожалению, использует функции, которые с Юникодом работать не умеют. К счастью, по какой-то случайности, упомянутое АПИ содержит два вызова, которые помогают решить эту проблему, правда придётся помучаться.

Первый из них — canvas_set_custom_u8g2_font.

Чтобы что-то написать русскими буквами, нужен шрифт, который их содержит. Стандартный вывод canvas_set_font позволяет выбрать один из нескольких шрифтов, ни одни из которых кириллицу не поддерживает. Тут и приходит на помощь canvas_set_custom_u8g2_font. Он позволяет выбрать произвольный шрифт пакета U∞g2, — внутри их целая куча и некоторые в названии содержат слово «cyrillic».

Вот как я это делаю:

#include <u8g2/u8g2_fonts.c>
// …
canvas_set_custom_u8g2_font(canvas, u8g2_font_haxrcorp4089_t_cyrillic);

Файл u8g2/u8g2_fonts.c внутри себя содержит шрифты в особом формате, можно открыть его прямо в текстовом виде и посмотреть как всё устроено.

Шрифт мы выбрали, теперь надо что-нибудь вывести. Тут на помощь приходит canvas_draw_glyph. «Под капотом» у него лежит u8g2_DrawGlyph, которая понимает символы Юникода почти без танцев с бубном. Думаю, это чистое везение — наверняка эта функция появилась сильно позднее, поэтому у неё нет двух вариантов для работы с разными кодировками.

Плохая новость в том, что строки в коде мы обычно пишем в кодировке UTF-8, а canvas_draw_glyph ожидает их в UCS-2. Но есть и хорошая новость — в прошивке доступно АПИ для перекодирования, как обычно, великолепно документированное на языке Си.

Но canvas_draw_glyph, как можно понять из названия, выводит только один символ. Как же вывести строку? Достаточно просто — надо вывести её посимвольно, сдвигая координату на ширину символа. Звучит просто, но как это сделать?

Тут нас ждёт очередная засада. Дело в том, что canvas_glyph_width, которая должна бы это делать, принимает на вход только char, при том, что нижележащая u8g2_GetGlyphWidth преспокойно работает с Юникодом.

Поэтому я сделал просто — выдрал реализацию u8g2_GetGlyphWidth себе в исходники. В итоге мякотка моего решения выглядит вот так:

void unicode_draw_utf8_str(Canvas* canvas, uint8_t x, uint8_t y, char* str) {
    FuriStringUTF8State state = FuriStringUTF8StateStarting;
    FuriStringUnicodeValue value = 0;

    for(; *str; str++) {
        furi_string_utf8_decode(*str, &state, &value);
        if(state == FuriStringUTF8StateError) furi_crash(NULL);

        if(state == FuriStringUTF8StateStarting) {
            canvas_draw_glyph(canvas, x, y, value);
            x += unicode_GetGlyphWidth(&canvas->fb, value);
        }
    }
}

Тут unicode_GetGlyphWidth — скопированная реализация u8g2_GetGlyphWidth, а furi_string_utf8_decode используется для кодирования UTF-8-строки в последовательные символы UCS-2.

Надпись в «Гитхабе»

С тех пор как в первый раз увидел панель активности «Гитхаба», хочу на ней что-нибудь написать. Я даже всерьёз как-то порывался составить себе карту на год, чтобы по ней коммитить, пока не получится рисунок, но поленился. А позже сообразил, что можно сдвигать дату коммита в прошлое.

Моя панель активности за год на «Гитхабе»

И вот, годы спустя, я наконец сподобился сделать скрипт, чтобы автоматизировать процесс и написать себе там слово «ПРИВЕТ».

Скрипт переводит подготовленную картинку размером 52×7 пискелей в нужную интенсивность коммитов и распределяет их по датам. Для надписи я использовал шрифт silkscreen, русифицированный когда-то Димой Смирновым и чуть-чуть его размыл в графическом редакторе.

Если захотите себе такую же, вам понадобится так же bash, git и утилиты из набора ImageMagick. Создаёте пустой репозиторий на «Гитхабе», привязываете его к локальному, запускаете мою утилиту с картинкой и любуетесь изображением на панели активности.

GBox для Huwaei

Три года назад, пройдя от любви до ненависти к «Самсунгу» один шаг, я перешёл на «Хуавей», рискнув попытаться обойтись без гугловых сервисов. Честно сказать, продержался недолго — пришлось взламывать смартфон и почти сорокаминутным шаманством возвращаться в зону комфорта.

После этого ставить можно было что угодно, но работало не очень — уведомления не доходили, «Мир пэй» работать отказался, синтез и распознавание речи — тоже, а в смартфоне торчало какое-то увешанное иероглифами хакерское приложение.

Приложение GBox, установленное на моём телефоне; приложения не знают, что они внутри Huawei

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

Я уже давно хотел побаловать себя апгрейдом смартфона, и консультант в магазине, почуяв мои колебания рядом со стендом «Хуавея», мастерски разбил каждый пункт моих сомнений. В том числе показал мне способ как не страдать от отсутствия сервисов «Гугла».

Оказывается существует панацея — приложение GBox. Оно ставится прямо из собственного магазина «Хуавея» и запускает внутри себя любое гугловое приложение (включая «Гугл Плей»), притворяясь для него смартфоном, свободным от санкций. В моём случае это какой-то «Сяоми», но в интернетах пишут, что модель и производитель выбираются случайным образом.

Всё гугловое запускается в некой изолированной среде, а наружу создаются ярлыки, отдельные для каждого приложения. Удивительно, но работают даже пуш-уведомления.

Мне такой способ понравился значительно больше — не засоряется система, и приложения, типа «Мир пэя», не сходят с ума от противоестественного симбиоза сервисов «Гугла» и «Хуавея».

О хранении пластинок

У нас дома есть настоящий патефон в хорошем состоянии. Эта вещь когда-то принадлежала дедушке жены и мы регулярно ею пользуемся — ставим пластинки по велению души или по просьбе друзей.

Поэтому я постепенно расширяю коллекцию — докупаю пластинки на местном блошином рынке или в интернете. Коллекция пока не велика и стоит у меня на одной из полок. Пластинки именно стоят, так правильно — на каждом конверте любой пластинки это напечатано в виде инструкции.

Отпечаток одной пластинки на другой — видно отзеркаленную надпись «RUSSIA» и след вокруг «яблока»

У меня как-то руки не доходили выяснить почему пластинки надо ставить именно вертикально, но помог случай. Несколько дней назад я заглянул в кафе к своему приятелю, а там на одной из полок углядел патефонные пластинки, валявшиеся там для антуража, — стопкой и без конверта.

Некоторые из них меня заинтересовали (там была даже парочка дореволюционных), поэтому я взял их послушать и только дома обнаружил, что за годы хранения стопкой одна из односторонних пластинок испортила дорожки на рабочей стороне другой — там отпечатался рельеф вокруг «яблока» и часть надписи «REPRODUCED IN RUSSIA».

Вывод простой: хранение стопкой портит пластинки, так как под весом стопки одна пластинка может повредить дорожки на другой.

DOOGEE S98 Pro

В счёт годовой премии решил поменять себе смартфон — вместо служившего верой и правдой почти три года «Хуавея», купил себе тоже «Хуавей», но интереснее. Но об этом как-нибудь потом.

Прежний телефон выставил на продажу на «Авито». Продавался он что-то ни шатко, ни валко — похоже в Новый год всем не до новых приобретений. В основном попадались желающие получить его с хорошей скидкой или поменяться на что-нибудь для меня бесполезное.

Я меняльщикам обычно даже не отвечаю — сразу закрываю диалог без лишних слов. Но сегодня в одном из предложений поменяться мелькнула какая-то незнакомая модель — DOOGEE S98 Pro и я из любопытства решил одним глазком глянуть в интернете что это такое.

Только что распакованный смартфон DOOGEE S98 Pro

Оказалось, что это смартфон в «походной» комплектации — защищённый (IP68, IP69K, MIL-STD-810G), со стеклом Corning Gorilla Glass 5, с большим аккумулятором (утверждается, что заряд будет держаться до двух с половиной недель), с камерой ночного видения и тепловизором (!).

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

Сделал фотографию ёлки дома — сквозь неё видно батарею, а на полу — следы от труб системы отопления

Я решил, что это судьба — давно ищу себе телефон для суровых условий, учитывая, что я время от времени люблю залезть по́ уши в какое-нибудь болото, просто чудо, что я ещё ни разу не раскокал в таком режиме какой-нибудь нежный «офисный» смартфон.

Тепловизор зимой в новой квартире оказался занятной игрушкой, тем более сейчас в Казани стоят экстремальные морозы за −30°, много нового узнаёшь о своей квартире при помощи этой штуковины.

На диване след от недавно сидящего там меня, а температура кота — около 34,8 градусов

Дочке особенно понравилось смотреть на тепловые следы от собачьих лап и человеческих ног на полу, а я изучил стены. Возможно кое-где их надо будет утеплить, либо поставить плинтусные обогреватели.

Камера ночного видения — тоже интересная штука, используется инфракрасная камера с инфракрасной же подсветкой. Не знаю насколько будет полезно на природе, но по тёмной квартире походить интересно, чувствуешь себя как в каком-то боевике.

Ночной город из окна лестничного пролёта одной из многоэтажек

Вдаль камера то ли промахивается с фокусом, то ли просто «мылит» из-за недостаточного разрешения, что очень хорошо видно на снимке города, который я сделал из окна лестничного пролёта в гостях.

Надо будет попробовать поснимать днём — интересно какой будет эффект.

В общем, нарушил своё правило — не соглашаться на обмен в объявлениях, но не пожалел — интересный агрегат, теперь только надо куда-нибудь выбраться, чтобы протестировать его в более суровых условиях.

Получил нагрудный знак

Перед Новым годом Республика сделала прекрасный подарок: сегодня я из рук министра цифровизации Айрата Хайруллина получил нагрудный знак «За достижения в области информатизации и связи РТ».

Нагрудный знак «За достижения в области информатизации и связи РТ» и книжечка к нему

Предупреждая вопросы: никакого особого статуса этот нагрудный знак не даёт, просто приятное признание заслуг.

Грека и рак

В детстве меня много мучали буквой «р» — я её тогда не произносил и до сих пор этого не делаю, правда большинство этого не замечает, — со временем сам собой как-то научился её имитировать.

Походы к логопеду, в данном случае, дали мне только одно: я с пулемётной скоростью, быстрее всех, кто со мной пытался соревноваться, умею выдавать скороговорку про беспечного грека, который суёт руки в реки:

Ехал грека через реку,
Видит грека: в ре́ке рак,
Сунул грека руку в реку,
Рак за руку греку цап!

Сегодня веселил этим дочку и она, отсмеявшись, задала очень интересные вопросы: что за грека? через какую реку и куда он ехал? и зачем он засунул руку в реку?

Грека едет через реку в литературно-художественном и научно-публицистическом журнале «Красная Новь», №4, 1924 год

Судя по тому, что удалось нагуглить, ответы на эти вопросы неизвестны, однако проследив судьбу скороговорки от нашего времени до 20-х годов (в более ранних источниках грека не обнаруживается), кое-что узнать всё-таки удалось.

Первое, что меня сильно удивило, «грека», — по всей видимости, национальность, а не имя (как я думал ранее), — во всех ранних источниках это слово написано с маленькой буквы. Так что история не персонализированная и шансов когда-либо узнать, что грека забыл за рекою, исчезающе мало.

А во-вторых (и тут нас ждёт небольшое открытие), нашёлся ранний (1924 года) вариант скороговорки, в котором история несколько меняется! Он на скриншоте, в этом варианте грека «и рукою рака цап» и это совершенно другое дело.

Вообще в двадцатом веке вариантов концовки было множество: «грека за руку рак — цап!» (Георгий Никифоров, «Кимба», 1926), «рак у грека руку цап» (Бирюков, «Крылатые слова на Урале», 1960) или тот, что на скриншоте (Б. Д. Четвериков, «Атава», 1924 год).

Мне хочется верить, что самый ранний вариант, — опубликованный Борисом Дмитриевичем Четвериковым в «Красной Нови», является исходным, так как в нём больше логики. Если это так, то по меньшей мере один вопрос в истории про греку отпадает сам собой.

Интересная операция (18+)

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

Меня это сильно удивило — уж очень прогрессивно выглядит. Где 1914-й год и где тема гомосексуальности, а тем более — смены пола.

Операція образованія искусственаго влагалища изъ прямой кишки. С.-П., Типография В. Ѳ. Киршбаума, 1914

Уже забыл про эту историю, но на днях разбирая чем забит мой смартфон, опять наткнулся на эту фотку. Ну и стало интересно — что за врач такой жил в России, как он вообще пришёл к этой теме и какова была реакция в обществе на его изыскания?

Начал, как полагается с «Википедии» и знатно удивился, когда узнал из неё, что первая операция по смене пола была сделана в 1931 году. Тогда что за операции делал доктор, написавший эту книгу? Может я случайно наткнулся на сенсацию?

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

Оказывается операция, которая имеется в виду в книге, делалась женщинам с физическим отклонением — тем, у кого по разными причинам влагалище не развилось. Такая операция тоже, конечно, крутое достижение, но оскароносный фильм по этой истории уже не снимешь.

Голос Александра III? (вряд ли)


Александр III Александрович (1845—1894) — император Всероссийский, царь Польский и великий князь Финляндский. Отец последнего российского монарха Николая II

Оказывается в интернете есть аудиозапись, на которой, по одному из предположений, звучат голоса Александра Третьего и его супруги Марии Фёдоровны.

Запись была сделана на восковой цилиндр между между 1889 и 1893 годами в резиденции датского короля во Фреденсборге генеральным консулом Готфридом Рубеном, который в период 1889—1897 годов записывал известных певцов и актеров того времени, а также важных высокородных гостей членов монаршей семьи на недавно изобретенном фонографе.

В 2007-м году Университетская библиотека Дании начала оцифровку коллекции консула и выложила её в интернет на своём сайте, а в 2018 году датский журналист Йенс Корнелиус высказал предположение, что голоса на одной из записей могут принадлежать Александру III с супругой.

Прямых доказательств этому нет, но в пользу этой теории говорит тот факт, что замок Фреденсборг, где записывался голос, является резиденцией датских королей. И вряд ли там мог петь по-русски кто-то еще, кроме царя. Чья жена, к слову — урожденная датская принцесса Дагмара.

Из-за способа записи звук неважного качества, а часть записи вообще на датском, поэтому без расшифровки некоторые места не понять:

Женский голос:

— Я очень рада вас видеть сегодня. Потому, что хорошая погода, можно пойти гулять! (неразборчиво, на датском)

Мужской голос:

— Вы хотите я говорил что-нибудь вам. Это не всегда так легко, когда вы хотите… И еще вы прибавили, что хотите чтобы я спел что-нибудь. Ну что же, вот, как например, это…

Поёт:

Сам Бисмарк чуть от радости
Не вырвал трёх волос,
Как телеграф известие
Такое нам принес,
Что немцы храбро заняли
Пункт важный и большой
И утверждали в Африке
Права страны родной…
С тех пор в Берлине стар и млад
Одно лишь и твердят:
Nach Afrika, nach Kamerun!
Vivat, Nach Kamerun!
Nach Afrika, nach Kamerun!
Так немцы говорят!
Nach Afrika, nach Kamerun!
Vivat, Nach Kamerun!
Nach Afrika, nach Kamerun!
Так немцы говорят!

Мужской голос:

— Закончим на этом, не могу вам читать сегодня. Если б вы заранее меня предупредили, так это другое дело. Я бы взял с собой книгу или что-нибудь в этом роде, чтобы мне прочитать. А так прямо из головы, это нелегко. Вы меня застали врасплох. И конец. До свидания, господа.

Женской голос (на датском):

— Меня очень веселит слушать голос моего мужа.

Ранее Ctrl + ↓