fa
Feedback
brain_dump_etc

brain_dump_etc

رفتن به کانال در Telegram

Дампы мыслей, свалка ссылок, программизмы, вот это всё (ВНИМАНИЕ: много вкусовщины!) Автор надампленых мыслей: @astynax

نمایش بیشتر
592
مشترکین
اطلاعاتی وجود ندارد24 ساعت
+17 روز
+430 روز
آرشیو پست ها
evv Этот проект опирается на то, что раз уж у нас не редактор, а среда исполнения Emacs Lisp, то почему бы не писать короткие s-expressions в любом месте и не позволять таковые "кликать". С одной стороны человеку, отторгающему скобочки из принципа, такой вариант точно не подойдёт, с другой стороны каждую ссылку видно. То есть вы видите имя функции, которая будет вызвана при выполнении кода. В Org Mode код elisp-ссылок не виден по умолчанию, что может кого-то очень даже насторожить. Очевидно, что добавить свои виды ссылок/кнопок легко: вы просто пишете больше функций! Автор eev тут не чурается макросов и генерирует функции для открытия PDF в ваших любимых читалках на нужной странице или в позиции первого вхождения такой-то подстроки. В итоге при должной консистентности именования (генераторы её вполне успешно обеспечивают) ссылки ещё и самодокументируются, да и вызвать describe-function можно в любой момент. Недостаток такого подхода тоже очевиден: вы прямо в файлах, не являющихся кодом на elisp, оставляете кусочки оного. Но для себя так делать можно! Зато кнопки хранятся всегда рядом с тем, к чему относятся и при желании могут быть "выполнены в уме", если Emacs с eev не окажется под рукой (тут тоже важна самодокументируемость).

Buttons В прошлый раз я упоминал кнопки, как способ насыщения базы знаний функциональностью. Кнопки позволяют выполнить некоторое действие, связанное с тем кусочком знаний, который вы в данный момент изучаете и таким образом дополнить общую картину. Скажем, вызвать почтовую программу с шаблоном письма к заданному адресату (полезно для GTD) или запустить воспроизведение музыки заданного исполнителя (моя личная хотелка — аннотированный каталог музыки, в котором я наконец-то смогу ориентироваться). Гиперссылки в принципе тоже являются кнопками, но действие оказывают всегда одно и то же — позволяют перейти к другому кусочку информации. Кроме того, гиперссылки обычно встроены в систему и позволяют расширить разве что номенклатуру поддерживаемых направлений для перехода. По крайней мере в большинстве виденных мною систем ссылки — это просто ссылки. Emacs ушёл на шаг вперёд: в Org Mode можно добавлять свои типы ссылок, да и встроенных типов предостаточно. Вы можете ссылаться на файлы, статьи встроенной документации, emails (такие ссылки работают как mailto-ссылки в браузере). Можно даже выполнять при клике на ссылку elisp-код или shell-command. Так что в рамках org-файлов ссылки можно смело считать кнопками! Вот только всю ли информацию можно хранить в .org? Представим, что вы хотите фиксировать процесс изучения языка программирования или хотите сохранить для будущего себя заметки к проекту. Да, всегда можно приложить сбоку .org-файл и располагать в нём ссылки на места в коде, но такой путь привнесёт неявности: вы не видите в коде ссылок на заметки. Частично решить проблему со ссылками в коде можно решить с помощью комментариев, в тексте которых могут быть написаны ссылки, но это потребует наличия поддержки таких ссылок в редакторе. И это всё ещё будут ссылки для перехода, а не кнопки. А ведь иногда хочется не перейти к заметке, а, скажем, выполнить код примера. > Но ведь есть же docstrings, скажете вы. И будете правы — есть! Но, увы, не для каждого языка. И Literate Programming тоже не всегда получается применять. Применительно к Emacs я знаю две реализации кнопок: eev (который я уже упоминал) и GNU Hyperbole. Оба проекта — реальные долгожители. И оба ну очень персональные!

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

Конечно, всё это может показаться сложным для человека, который не хочет ничего "программировать", а хочет создавать интерактивные шаблоны в Notion (есть мнение, что это вполне себе программирование). Люди делают в Notion очень сложные и мощные штуки. И я рад раз них! А мне, вот, не хочется завязываться на сервис. И я строю мою персональную базу знаний :)

Я давно интересуюсь хранением знаний, пусть и не выработал пока привычки сохранять всё, что хотел бы хранить. Но способы разные я периодически изучаю. Когда-то давно, в середине 00х, ещё сидя на Windows, пробовал вести заметки в отдельном ПО, но дело не пошло. Зато написал свою реализацию липких листочков на Delphi, с красивой иконкой, с окном, не использующим стандартные декораций! Но сами заметки так и не приучился оставлять Уже в 10х были попытки начать вести ZimWiki, заметок десять я туда сохранил, но, опять же, процесс не пошёл. Не прижились и личные блоги. Более-менее что-то начало копиться, когда пересел на #Emacs и Org mode. Но записывал я всё равно мало и как правило волнами — после знакомства с очередным явлением вроде цифровых садов (писал об этом) вдохновения хватало на некоторое время. Личная Wiki какое-то время пополнялась довольно активно, но и её я слегка подзабросил: всё же пока я не готов именно к "садоводству", мне бы сейчас знания просто фиксировать, а не то что взращивать. Прямо сейчас мне нравится использовать Org-Roam. Потому что когда я пользуюсь основным компьютером, мне максимально удобно что-то записать именно туда. Заметок пока мало, так что какой-то особой пользы от их связывания друг с другом я пока не вижу, но я таки возвращаюсь к информации время от времени, а это уже польза! Я даже уже начал обустраивать эту итерацию exobrain по своему вкусу. Сделал себе hotkey, который открывает заметку с именем текущего режима (или создаёт, если таковой нет). Иметь такие заметки очень удобно, когда нужно вспомнить ссылку на документацию к языку или, скажем, функцию Emacs, которая для данного контекста полезна, но нужна редко. Например, внутри заметки к lisp-mode есть Org-Babel-скрипт, который скачивает документацию к ASDF (это инструмент для работы с проектами в Common Lisp) и несколько исполняемых ссылок, открывающих локальную копию документации во внешнем браузере и в eww встроенном в Emacs. И вот тут хочется отметить саму возможность расширения функциональности ПО, которое хранит ваши знания. Emacs для меня очень ценен тем, что я могу его расширять написанием действительно небольшого количества кода. Да, те же расширения Org Roam невелики и нужны только мне, но на то это и Personal Information Manager! * * * Не так давно читал интересную статью: Programmable Notes. Если сократить её до минимума, то автор видит пользу от - агентов, эдаких пользовательских мини-программ, которые в диалоговом режиме запрашивают у вас данные и уже по ним генерируют заметки; - программируемых кнопок (в тексте заметок или просто где-то), нажатие которых инициирует запуск агентов или другие действия по автоматизации рутины; - скриптов, которые перерабатывают данные и находят в них паттерны, связывают заметки вместе, словом, "думают" за вас; - AI, которые вёл бы с вами разговор хотя бы в виде echo chamber). А ещё автор несколько раз упоминает агентность) пользователя, вот даже цитата про это: > Enabling users to design and share their own (tools) is the only way to give people agency over their knowledge bases. Фантазии автора статьи по поводу AI меня пока лишь позабавили, а вот всё остальное, наоборот, срезонировало! Я могу иметь у себя в Emacs — и имею(!) — и агентов, и кнопки, и скрипты: - агенты, это org capture — автоматизируемая система создания заметок по шаблонам; - про кнопки я планирую написать позже, но по сути это могут быть просто функции на Emacs Lisp; - скрипты тоже пишутся на Emacs Lisp, а для Org Mode есть пакеты вроде org-ql для написания запросов, да и тот же Org Roam хранит метаданные в SQLite.

Не могу не поделиться ссылкой на прекрасное: https://ianthehenry.com/posts/janet-game/ Автор хотел рассказать, как у него получилось пописать игру на языке Janet — это такой маленький диалект Lisp — в связке с Raylib — а это уже библиотечка для кросс-платформенного игростроя. Причем изначально предполагалось, что это будет игра в технологии, а не использование технологий для построения игры (всё, как я люблю!) :) Начал автор с изучения экосистемы языка. Мне, например, такое нравится читать. И сравнивать с экосистемами, знакомыми мне. В процессе использовался Nix, чтобы тот же Raylib нормально собрался под MacOS (начинаем записывать, про что же ещё эта серия заметок, кроме геймдева!). Буквально после написания пары функций у автора возникла необходимость тестировать код. Нормальными assertions. А это уже пахнет макросами! В процессе изучения макросоводства в лиспах в целом и в Janet в частности автор и шишек набил, и посравнивал Lisp-1 с Lisp-2 (ссылки на пейперы, цитаты, красота!). Исследовал он всё это в разрезе борьбы с проблемами, которые возникают при разворачивании макроса в окружении, где функции, использованные в теле макроса, были переопределены. Не каждый с такими проблемами вообще сталкивается и уж точно далеко не каждый думает о надёжности макросов наперёд! В итоге автор наделал себе макросов для генерации макросов и сваял тестовый фреймворк — да, для тестирования логики игры, если вернуться по стеку. Тесты автор решил понаделать и для рендеринга — чтобы глазами видеть косяки. Тут ему пригодился Emacs, который умеет вставлять картинки прямо в код (ага, как DrRacket). Вот только хранить картинки высокого разрешения рядом с кодом автору не хотелось, тем более что игра предполагалась пиксельная и машинерию рисования стоило тестировать на картинках низкого разрешения. Но Emacs-то картинки сглаживает при растягивании так, что пиксели за мылом не видно! А значит нужно… запатчить Emacs. Под MacOS, напомню. С помощью Nix, конечно же! :D Спойлер: игра в итоге так и не была доделана, хоть и был в итоге написан код, отвечающий за построение области видимости (FOV) — игра предполагала stealth-механики. Про это тоже было довольно интересно почитать! P.S. В статье есть ссылки на оды любви в языку Janet в стиле "это мой последний язык" (в смысле, что больше ничего не понадобится, настолько хорош). Ходил, читал — забавное!

Забыл ссылку дать на вот это видео: https://www.youtube.com/watch?v=86yiRG8YJD0 Там и про драму со Столлманом есть, и про иторию повяления проекта, и вообще видение автора можно прочувствовать. Занятное.

Помимо ссылок ещё есть "сессии", когда вы записываете блок команд для пошагового исполнения. Блок начинается с парочки s-exps, открывающих в соседней панели сеанс диалога с интерпретатором, скажем, Python. Затем в блоке идут уже команды для этого интерпретатора. Блок нарочно исполняется не целиком, как это было бы сделано в Babel, а именно построчно — и нарочно же выполняется с демонстрацией результата выполнения каждой команды в соседней панели. Это тоже своего рода исполняемые заметки, но не "сниппеты", а "демо", они же test blocks. Вы, наверняка, встречались с проектом tldr, так вот тут то же самое, но примеры можно выполнять прямо тут же, не копируя в shell. Опять же, очень интересно и очень не мейнстримово :) Я пока пробую смешивать Org с eev в заметках для себя. Тут я всё же скорее согласен со Столлманом — негоже неподготовленного читателя бросать в яму с острыми с непривычки скобками. К тому же eev привязывает заметки к Emacs в большей степени, чем Org, который за пределами Babel хотя бы просто "рендерить" умеют многие инструменты (pandoc, GitHub/Gist). И тем не менее сама идея исполняемых ссылок мне очень понравилась, буду продолжать исследовать эту тему.

Для разнообразия напишу о том "с чем я сейчас играюсь". Это опять #emacs, но в необычном даже для имаксоводов ключе. В мире Emacs принято структурировать знания в Org Mode — это наш Notion, Roam (org-roam я тоже начал осваивать наконец-то). А если структурируемые знания связаны с программированием, то многие присовокупляют и Babel. Это такой способ добавить в заметку фрагмент кода, который можно "запустить", получить результат выполнения в желаемом виде тут же в документе и подать на вход другому фрагменту, потенциально написанному на другом языке — потому название и отсылает к Вавилонской башне. Ещё Babel позволяет писать код с использованием подхода Literate Programming (у меня даже демо использования babel есть). Я этот подход когда-то пытался в массы продвигать, правда, без видимого успеха . Среди имаксоводов LP тоже не то чтобы слишком широко распространился, но многие в таком виде описывают свою конфигурацию, так что умеренный успех всё же имеется! Это всё очень интересно, но, как я в начале обмолвился, вполне привычно для пользователей Emacs. А рассказать я хотел об eev. Описать вкратце, что же из себя eev представляет, довольно сложно. Это одновременно и способ закреплять знания о собственном исследовании Emacs и не только, так и, в каком-то смысле, стиль жизни — последнее как раз очень по-имаксовски! eev как подход родился в 90х в результате неудовлетворённости тем, как было принято изучать Emacs как платформу. Изначально это были расставляемые прямо в прозе s-expressions вида (find-file "…/foo.el"), выполнение (evaluation) которых командовало Emacs'у открыть нужный файл с исходниками. Потом в дополнение к искоробочным функциям добавились более выразительные варианты, могущие прыгнуть к нужному месту файла через поиск подстрок. Названы такие фрагменты были исполняемыми ссылками. Причём сделано было всё максимально агностично к формату самой прозы: все ссылки всегда являются однострочниками на Emacs Lisp, выполняются по принципу "прыгнуть в конец текущей строки и выполнить s-exp, чья закрывающая скобка стоит в конце строки" — да, в середину текста ссылку просто так не вставить, но зато можно ссылки иметь коде на любом языке, в котором есть построчные комментарии. При этом отсутствие сокрытия "адреса" ссылки за описанием преподносится как плюс: вы всегда видите код, который собираетесь выполнить, а значит можете его исследовать — уже благодаря интроспекции самого Emacs. Это с одной стороны перекладывает на вас заботы о безопасности выполняемого кода, с другой же стороны побуждает исследовать саму систему, хакать её в изначальном смысле этого слова. Получаются эдакие hackable notes. В какой-то момент eev заметил и даже одобрил Столлман. Но он же в итоге и посетовал на то, что пользователь видит код на Lisp, чего в норме быть не должно — это прямо таки маленькая драма в истории eev, упоминаемая в каждом докладе о проекте :Р За годы были наработаны "find functions" буквально для всего. Можно сослаться на страницу или подзаголовок PDF-файла, на видео в YouTube с указанием временной метки — "переход" по ссылке откроет адрес во внешней программе или, наоборот, отобразит результат в виде тестовой выжимки во временном буфере Emacs. Да, в org-mode тоже кое-какая функциональность для подобных задач есть, но тут целый параллельный мир для меня открылся! В дополнение к наработанным "открывалкам" есть богатый инструментарий по созданию своих, это всё тоже очень по-имаксовски.

​​Ранее писал я про то, что в #kotlin неплохо бы иметь возможность иметь несколько receivers, когда строишь сложные #DSL. И в каком-то виде это уже завезли в Kotlin 1.6.20! И даже синтаксически получилось не слишком ужасно :D Основное преимущество подхода в том, что можно "насыщать" расширениями тип T1 строго в контексте T2, не имея возможности модифицировать T2. А возможность указать несколько контекстов позволяет эти контексты (де)композировать. Поживём и увидим, будет ли от нововведения больше пользы или вреда В примере Int получает свойство mm, доступное в контексте DSL при наличии контекста "измеримости". По месту вызова измеримость означает масштабирование. Да, пример синтетический, но какой уж смог сходу придумать.

Ух, опять большая пауза вышла. Буду писать про то, что сделал буквально вот прямо сейчас, а то так и не соберусь… Время от времени приходится смотреть перевод на русский или расшифровку того или иного английского слова. Проще говоря, мне нужен словарь. В xfce есть программка-словарь в виде диалогового окна. Вот только сценарий "скопировал слово, переключился на окно словаря, вставил, пролистал выдачу в поисках нужного, переключился обратно к тексту" слишком уж длинноват. Мне же хочется по сочетанию клавиш видеть перевод во всплывающем окне. Решил это желание запрограммировать. Словарь из xfce использует протокол DICT — отдельный сетевой протокол для запроса словарных карточек. Я с этим протоколом раньше сталкивался, когда использовал в консоли программу dict(1). Вот только переключаться в консоль и запрашивать перевод там столь же непозволительно долго :( Но зато утилиту командной строки уже можно взять за основу моей поделки! Помимо dict(1) взял - Rofi для показа экранного меню - Zenity для запроса ввода - notify-send для показа всплывающих сообщений Получился скрипт vortaro.py ("vortaro" — это "словарь" на Эсперанто). Да-да, ужас-ужас, питонолапша. Я знаю. Зато я решил задачу быстро! Ибо plumbum сильно упрощает написание сценариев, склеивающих воедино пачку внешних программ. Хотя бы на bash писать не пришлось. Может быть потом перепишу на Haskell и turtle. Сейчас скрипт смотрит в primary selection слово, пробует поискать его в первом словаре из списка, затем во втором и так далее. Если карточка найдена, то текст показывается во всплывающем сообщении. В том случае, когда конкретного слова в словаре не оказывается, но есть похожие на него слова, то сначала показывается меню, позволяющее выбрать одно из таких слов. Довольно таки специфическое поведение, готовую программу я бы скорее всего не нашёл. А тут полчаса и готово!

Дополнение: нет, multiple receiveres, это не "тайпклассы для бедных" и не "как типажи в Rust" (ох уж эти кулики и их желание похвалить своё болото через насмешки над чужими!). Языки бывают разные, с разными свойствами и подходами к решению задач. Одного универсального решения для каждого класса задач нет и не предвидится. И тем более не будет языка, который бы любую задачу решал строго наиболее подходящим для всех и каждого способом. Расширяйте кругозор, мыслите шире, будьте открыты к новому или просто иному!

Интересно получается, что я только-только начал на Kotlin писать как на основном языке и уже упёрся в нехватку "множественных receivers" в языке. К счастью, этот же вопрос уже давно заботит многих и подвижки в нужную сторону есть, так что я не теряю надежду. Вот уж тогда я развернусь! В чём же суть? В возможности при объявлении extension method указать не только объект, к которому вызов метода будет адресован, но и объект, определяющий контекст — своего рода "область видимости", в которой метод будет доступен. Для людей со стороны расшифрую. Kotlin позволяет добавить метод к имеющемуся типу (это и есть тот самый receiver, упомянутый выше) постфактум: fun String.repeatTimes(n: Int) = ... "foo" repeatTimes 5 // здесь скобки и точку можно опустить Если объявить такую функцию-расширение внутри тела класса, то использовать это расширение можно будет только в методах этого же класса: class Context { operator fun String.invoke() { // перегружаем вызов в роли функции ... } fun buzz() { "a"() // тут это можно! "b"() } } Сама по себе такая локализация интересна постольку-поскольку. Но в Kotlin есть ещё "лямбды последним аргументом", которые позволяют функцию вида fun loop(n: Int, body: () -> Unit) {...} вызывать с выносом последнего аргумента за скобки: loop(5) { ... } // вместо loop(5, {...}) Так вот, такую лямбду можно описать с привязкой к контексту. Тогда в области видимости функции будет присутствовать неявный this, ссылающийся на объект контекста. Это позволяет использовать те самые локальные расширения в теле этой лямбды! fun inContext(body: Context.() -> Unit) { ... } inContext { "a"() "b"() } Применив капельку фантазии и упомянутые приёмы, легко сделать, скажем, роутер для вашего micro-framework: routes { "/" { // строка вызывается с лямбдой в роли аргумента GET { +"Hello, " // перегрузка унарного плюса для строк, +"World!" // который для них обычно не реализован } } "login" { GET { ... } POST { ... } } } У данного подхода есть недостаток: нужно владеть кодом класса контекста, чтобы мочь добавить ограниченные по видимости расширения для других типов. В какой-нибудь stringBuilder добавить своих "глаголов" не получится — это final класс, его не расширить и не унаследовать. А вот те самые multiple receivers разрешат добавить расширение для одного типа в контексте другого — также постфактум, не владея кодом ни того класса, ни другого! Это чем-то похоже на инстенциирование класса типов в Haskell — вы добавляете поведение к типу, не изменяя ни объявление поведения, ни объявление типа. Не то чтобы эта языковая возможность нужна всем и каждому, но на концепцию языка она ложится хорошо и пользу авторам библиотек она точно принесёт. Так что ждём'c :) P.S. в той части Fleet (новая IDE, которую я пилю в JetBrains — да, теперь мне можно про это говорить) у меня как раз такие DSL имеются, и они ощутимо выиграют от multiple receivers :Р P.P.S. Кому-то вся эта история может напомнить язык Io, в котором посылка сообщений сделана с передачей не только получателя, но и автора. И пользуются этой возможностей примерно так же — делают контекстно-зависимые расширения для языка. Почитать об этом можно в "Семь языков за семь недель" — крайне советую!

​​Что-то заработался, едва хватило сил успеть для Hacktoberfest накоммитить в опенсорсы. Но вы меня не теряйте, что-то да выдам в ближайшее время: пул тем есть, нужно слегка разгрести. Сейчас по работе пишу на Kotlin, так уж вышло. И всё какие-то eDSL. А в такое если погрузишься, начинаешь везде видеть всё те же DSL :) На днях увидел примерчик BASIC-подобного языка прямо внутри кода на Scala. Подумал, "а ведь на Kotlin оно делается просто"! Вот и получилось такое: https://gist.github.com/astynax/76b09a79f2cf31f4ee55d384f3bc8f7a Не идеально и не похоже на настоящий BASIC на 100%, но тут уже накладываются ограничения буковки "e" в "eDSL". Впрочем, у меня получилось более близко, чем в скаловском оригинале. Интерпретатор сам по себе "тривиален", так что я только "рыбу" накидал, чтобы код на DSL проходил проверку типов, если вдруг кто захочет доделать - милости прошу! Заодно сможете проверить, работает ли мой пример (на настоящем BASIC я проверял – с точностью до синтаксиса, код рабочий!).

Сил оформлять полноценные статьи пока нет, выдам выжимку того, чем я сейчас занимаюсь. Может быть что-то из этого и разовьётся в статью-другую! Продолжаю приобщаться к #Gemini, почитываю чужие gemlogs, подумываю поднять зеркало этого канала в рамках своей капсулы (в Gemini так называют серверы, участвующие в сети). Выгрузил данные канала в виде JSON, накидал транскодер в Org mode. Но тут оказало, что Telegram не выгружает изображения, добавляемые к сообщениям ботом — не "фото + заметка", а именно "сопровождающее изображение". Я таких написал достаточно, чтобы жалеть о потере. Поэтому поднятие зеркала пока подвисло, может пройдусь вручную по публикациям и утяну картинки, а может и так оставлю — посмотрим. Членствую в чате RuGemini, "нас мало, но мы в тельняшках". Кто-то хочет "вернуть себе Web", кто-то хочет уйти из Web совсем и делает proxy для поиска по StackOverflow, чтобы читать из Acme) под Plan9 — развлекаются, проще говоря. В Gemini контента, как ни странно, чатовцы мало генерят. А в самой Geminispace есть, что почитать перед сном. Вот только находить контент мне удобно на ПК, а читать удобно с телефона! Вот и подумываю о том, чтобы сделать свой сервис закладок или даже аналог Pocket. Может даже с проксированием HTML, чтобы читать в text-only виде и околотекстовый Web. Коль скоро в Gemini нет cookies, а аутентификация делается с помощью SSL-ключей, приватный proxy не выглядит таким уж небезопасным решением. Помимо Gemini, закопался ещё и в IndieWeb — тоже занятный островок для недовольных современным Web. Эти недовольны его хрупкостью и зависимостью от больших корпораций (коих пренебрежительно называют silos) и призывают владеть своими данными, а так же развивать свою identity в сети. Микроформаты вроде h-card, публикация через MicroPub — есть, про что почитать и что себе на сайт утащить. Можно послушать подкаст — неплохая вводная в IndieWeb! Вот как-то так. Может ещё и про железки напишу (пополнил коллекцию интересными штучкам от M5Stack) — в такой же манере, а может и более структурировано.

Я вам скажу, с вводом данных в #Gemini работать не скучно: аналога POST в Gemini нет, как нет и URL encoded параметров! И cookies тоже отсутствуют, как класс, как вы помните. Да, вы можете привязаться к пользовательскому сертификату и таким образом реализовать сессионность, но это уже будет сквозное состояние, чего хотелось бы избежать. Зато Gemini сервер может запросить строку специальным ответом. После чего клиент покажет пользователю диалог с заданным приглашением, а результат ввода отправит обратно на сервер в виде query string. Соответственно, если вы хотите получить несколько значений, то вам нужно будет каждое запросить отдельно и сохранить в URL (кроме последнего, которое будет в query string). При этом размер запроса ограничен килобайтом на всё про всё — много не попостишь. Но тем интереснее! Лелею идею написать FSM, которая взяла бы на себя весь этот сбор параметров, чтобы в обработчике запроса уже иметь все данные введёнными. Для Jetforce описание параметров можно будет оформить как "eDSL #Python-style" — на декораторах. Также было бы интересно попробовать воплотить в Gemini интерактивность, подобную той, что использует #Racket в своих Stateful Servlets. Там вы тоже пишете код так, что данные вводятся "запросами к пользователю": вы отравляете пользователю форму, и получаете результат тут же в коде. Внутри всё реализовано на сохранении состояния в URL и рэкетовых continuations, снаружи же выглядит как магия — люблю такое ;) А уж насколько магически выглядят Web Cells: вы имеете переменную, которая помнит состояние между вызовами обработчика запроса, и таких переменных даже может быть несколько!

​​Повозился тут со штуками вокруг Gemini (см выше). Серверы Именно статический "сайт" поднимать не особо хотелось, но таки поднял: gemini://recursive.one (он же через проксю). Раздаётся с помощью Agate, минималистичного Gemini-сервера, написанного на #Rust. Agate кроме раздачи статики ничего не умеет, так что пока статическая страница и повисит %) Потыкал пакеты из набора haskell-gemini: пока сыровато. Так что #Haskell с Gemini я подружу позже. Зато приятно оказалось пользоваться Jetforce. Это фреймворк для #Python такой. Построен на Twisted, внутри типы проаннотированы, async тут и там, при этом код выглядит "как Flask", то есть как набор декорированных функций — современненько! Мне интересно было именно "Gemini приложение" написать, то есть что-то, создающее контент на лету. Получилось вполне прилично: основная функциональность в Jetforce уже есть. Нужно только будет написать eDSL для более удобного (чем захват регулярками) описания параметров в путях. Клиенты На десктопе попробовал пожить с Castor, графическим клиентом, написанным на #Rust, опять же. Но клиент пока слишком юн, и им не слишком удобно пользоваться. В итоге пересел на Lagrange. Вот этот — красавец! Написан на C11 и SDL, аппаратно ускоряет отрисовку, красиво показывает текст, может и графику показать inline, управляется хоткеями. Даже "лого" генерирует для ресурсов на основе их имени — как умолчательные аватары на GitHub, вы такие точно видели. Пока я крайне доволен пользованием, рекомендую! На Android пока остановился на deedum. Он не слишком красив, но крайне шустр и нетребователен к ресурсам. Контент В Gemlogs — это такие дневники в Geminiverse — народ пишет, есть что почитать. А ещё есть зеркала Lobste.rs и HackerNews, даже с комментариями. Ту же Wikipedia можно почитать через такой прокси. Словом, уютненько :^)

Рубрика "дичь, которую творил я когда-то": всё те же часы, только в железной версии (ATMega8). Корпус из монтажной коробки, п
+3
Рубрика "дичь, которую творил я когда-то": всё те же часы, только в железной версии (ATMega8). Корпус из монтажной коробки, пена от коврика, светофильтр из ткани 3M, трубочки для коктейля в роли световодов, вот это вот всё. Макетка и сдвиговый регистр старше меня (макетка — сильно старше). Забавно, что "часики-то тикают", хотя цать лет назад я даже не очень свежую батарейку ставил :)

В этом году опять не нашёл времени добить AdventOfCode, однако 46 звёздочек из 50 считаю неплохим результатом. Если что, AoC, это такой марафон по решению задачек с помощью кода. Я про него уже писал. Решал я задачки на #Haskell, как водится. Довольствовался "просто нормальными решениями", которые было приятно реализовывать без необходимости погружаться в оптимизации. Итоги: удовольствие получено, нервов затрачено немного, руки размяты. А вот общее впечатление от задачек в этого года, увы, смешанное. Возможно, дело в том, что это AoC'2019 был очень хорош, а нынешний просто получился "как раньше": с задачками на вида "пишите уже процедурщину, иначе не дождётесь окончания вычисления" (это могу терпеть) и "вспомнил известный алгоритм — решил, не вспомнил — не решил" (вот такое не люблю!). А ещё в этом году были самоповторы: три вариации конвеевской "Жизни" с незначительными отличиями, это не то, чего ждёшь от авторов. Возможно, год выдался тяжёлым и для них… Так или иначе, advent calendars — это здорово! Подкину таковых на разные темы: - "Advent of Haskell 2020" — познавательно-развлекательные статейки о #Haskell - "Kotlin Christmas" — то же самое, но про #Kotlin - "QEMU Advent Calendar 2020" — традиционный уже календарь всякого забавного, что можно запустить в QEMU (про этот календарь я тоже писал); день №12, например, это всё та же "Жизнь", но в виде самозагружаемой (без ОС!) программы на #Rust Из прошлогодних могу упомянуть "‘A Language a Day’ — Advent Calendar 2019": 25 разных языков программирования по одному на день со ссылками на документацию и примерами кода. Наконец, возвращаясь к AoC, отмечу, что в этих наших интернетах множество людей делится своими решениями в виде статей и прочих стримов. Вот, например, репозиторий со ссылками на решения AoC на куче языков (ЯП и не очень вроде jq) — вдруг кому захочется свои решения посравнивать с чужими. И да, всех с Новым Годом!

​​Промежуточный отчёт о прогрессе работы над PixCell/Elm. Сейчас: - Реализованы все инструменты, которые я обычно делал в других версиях - Имеется выгрузка в PNG, - Перерисованы все пиктограммы для кнопок с использованием самого редактора (выгрузил в PNG, закодировал в Base64, положил в константы, подставляю в SVG в процессе рисования GUI) - GUI мастшабируется под размер экрана (ага, PNG мылятся, oldschool!), опробован на iPad — работает пристойно Хотелки: - Сохранение текущего состояния в URL, чтобы можно было "в закладку положить" - Выпадающие меню для инструментов на манер docks у NeXTSTEP - Сохранение результатов работы в Local Storage Варианты путей для эволюции: - Анимации на базе сохранённых в Local Storage "кадров" (уж больно не хочется делать управление задержкой между кадрами...) - Большой коллаж из "тайлов" в Local Storage. Тут вам и некое подобие "знакомест" с фиксированными палитрами на тайл, и, опять же потенциально, редактор карт из тайлов. Можно даже PETSCII Art замутить, предварительно нарисовав все нужные символы, даже палитра для Commodore 64 уже есть (вторая из трёх, помимо EGA (первой) и Apple II (третьей)). Вчера максимально быстро и лениво накидал галереею примеров того, что можно в редакторе нарисовать. Буду пополнять.