brain_dump_etc
637 subscribers
99 photos
4 videos
3 files
383 links
Дампы мыслей, свалка ссылок, программизмы, вот это всё (ВНИМАНИЕ: много вкусовщины!)

Автор надампленых мыслей: @astynax

Чат к каналу: https://t.me/brain_dump_chat
Плейлист трансляций: https://youtube.com/playlist?list=PLUFoWyWge7mrg4GqHLMZV62gGC912PCGq
Download Telegram
​​Продолжение истории про движок для историй.

Предметы "в ранних версиях" про дублировались в момент поднятия и при показе описания локации не показывались при наличии копий в инвентаре. Это позволило имитировать "подбирание" без добавления какого-либо состояния самим локациям. Зато при наличии предметов стало возможно добавить оные в виде зависимостей к нужным переходам. Так появились переходы у предусловием. Вообще, подобные связи вида "предмет—страница" или "предмет—инвентарь" очень легко оформлять в виде соотношений "многие ко многим" и особенно быстро это делается силами Django ORM!

При наличии хоть каких-то условных переходов можно реализовывать изрядную такую нелинейность. Пример: проход к боссу закрытый с помощью трёх ключей, каждый из которых получаешь в отдельном квесте, но порядок выполнения квестов не влияет на результат. Или можно метроидванию смоделировать, описав приобретаемые навыки персонажа как предметы, и требовать "умения летать" в отдельных регионах мира!

А потом мы решили (я видео пишу с напарником, он мой код комментирует, всем весело) сделать механизм сохранений. И вот тут стало сложновато ;) Прогресс прохождения конкретной игры конкретным пользователем было решено не дублировать, вместо этого я придумал создавать завязанные на прогресс сохранения, которые бы хранили снимки прогресса на момент сохранения. Это вылилось в жонглирование связями в стиле "привязать все предметы, привязанные к прогрессу, к сохранению, а от прогресса отвязать". Хорошо хоть, что транзакции есть! В какой-то момент получился пресловутый CRUD: список сохранений, сортировка по времени последнего изменения, типичные Django-задачи :)

Подбор предметов намекает на выбрасывание оных, а это уже отслеживание того, где и что было выброшено. Но сделали! И, разумеется, учли в подсистеме сохранений. А ещё добавили ведение заметок, сквозное для всех сохранений (не изменяется при загрузке старых). Заметки можно прикреплять к локациям или просто "пришпиливать" чтобы всегда были на виду — всё это влияет на то, что и когда отображается.

Пока это всё, что уже реализовано. Но есть и планы на будущее.

Пока выброшенные предметы нельзя использовать в переходах, но если такое сделать, то это уже будет заготовка для "применения", а потом можно уже будет продумать "трату" предмета в процессе "применения к месту": "потратил доски, сделал мост" и тому подобное.

Есть ещё мысль помимо "требования наличия" предметов добавить переходам возможность давать игроку предметы и/или отбирать их. Во-первых, это позволит выкинуть отдельные механизмы подбора и выбрасывания. А во-вторых открывает целое море возможностей!

Вы только представьте локацию-магазин, описанную в виде набора переходов обратно в этот же магазин, но с тратой денег и получением покупок? Можно даже реализовать "продажи не для всех", просто требуя наличия предмета-разрешения или предмета-билета (с отбиранием оного на выходе). Целая система экономики, не поддерживаемая отдельным кодом, а просто "сделанная в редакторе"!
​​Рубрика "позабавило в интернете".

Тут для Nintendo Switch выпустили карандаш для рисования с соответствующим ПО. Но в Switch стоит обычный емкостной сенсор, никакого специального слоя от Wacom нет. Можно лишь "эмулировать палец", чем карандаш упомянутый и занимается: не зря у карандаша на конце "присоска" площадью с пол-пальца.

Вот только как передать силу нажатия (для рисования это важно)? И зачем карандашу провод, второй конец которого подключается к консоли через разъём для гарнитуры? Пока это тайна! Но я уже пофантазировал на эту тему :)

Моя версия такая: программа для рисования выдаёт некий звук на выход для наушников, а карандаш измеряет силу нажатия пьезоэлементом или чем-то подобным и возвращает в виде того же звука переменной громкости (амплитудная модуляция!) в микрофонный вход консоли!

Косвенно моя догадка подтверждается тем, что карандаш заявлен под названием "sonarpen" и работает "with no batteries or bluetooth required"! То самое "дешёвое и сердитое" решение, какие я люблю!

И пусть карандаш подключается проводом, что выглядит не очень современно, да и точности особой не даст из-за технологии touch-сенсора, но японцы любят всякое эдакое. Вспомните хоть радар для рыболовов и швейно-вышивальную машинку, в роли аксессуаров для GameBoy %)
Ха, "так и вышло"!

> "It is a half-meter cable that plugs into the audio jack, and technically it pretends to be a headset. So, in Colors, it actually plays a tone through the audio. A tone of about 8000 hertz goes through the cable to the tip of the pen. There is a resistor in there as well that dampens the tone depending on the amount of pressure that is applied to the tip of the pen. This vibration goes back to the Switch through the internal microphone of the pen, which measures the volume of the sound. That calculates the pressure used on the screen. So the touch is recorded by the screen as normal, but the pressure goes through that thing. It is an ingenious idea." (источник)

Ох уж эти рекламные словечки вроде "ingenious"
​​Рубрика "проект выходного дня"

Я имею определённый опыт рисования процедурной графики на комбинаторах. Даже стримил это дело, и сюда тоже писал. Как-то раз я сидел в Haskell REPL и писал комбинаторы, чтобы ASCII-Art композить в таком же стиле: отражения, масштабирование, стыковка "в ряд" и "в столбик". Результат получился небезынтересный, отложил в ящик, чтобы когда-нибудь сделать маленький DSL, который можно было бы вводить и сразу видеть результат в реальном времени. Предполагалось что-то вроде правил для L-систем, если вдруг кто знаком. Вот только то, что попадает в мой ящик, очень редко из него достаётся :(

На днях копался в закромах и нашёл ту самую заготовку. Решил, что хочу доделать, но копаться с TUI в Haskell что-то не очень хочется, поэтому волевым усилием переписал всё на Elm. Вот результат: <https://github.com/astynax/elm-charart>

Буквально сегодня добавил процедурное раскрашивание. Которое можно использовать напрямую для рисования, если не хочется из кусочков композить: вы просто описываете функцию "координаты -> символ+цвет". Получается что-то вроде tixy.land за вычетом анимации (её, при желании, тоже можно добавить!).

Визуализация есть, теперь остаётся сделать уже язык, которым можно было бы вводить правила построения картинок. Пока делал демки, подумал, что тут будет хорошо смотреться конкатенативный язык (ага, Forth!) с примесью ФВП.

А потом можно будет организовать выгрузку правил в виде большой строки, которую можно будет скормить голому движку (через flags) и получить встраиваемый элемент для сайтиков в стиле старой школы. Я такое уже делал в меньших масштабах, когда захотелось "ASCII-дождик" воткнуть на одну страничку.
👍1
​​Что-то заработался, едва хватило сил успеть для Hacktoberfest накоммитить в опенсорсы. Но вы меня не теряйте, что-то да выдам в ближайшее время: пул тем есть, нужно слегка разгрести.

Сейчас по работе пишу на Kotlin, так уж вышло. И всё какие-то eDSL. А в такое если погрузишься, начинаешь везде видеть всё те же DSL :)

На днях увидел примерчик BASIC-подобного языка прямо внутри кода на Scala. Подумал, "а ведь на Kotlin оно делается просто"! Вот и получилось такое:

https://gist.github.com/astynax/76b09a79f2cf31f4ee55d384f3bc8f7a

Не идеально и не похоже на настоящий BASIC на 100%, но тут уже накладываются ограничения буковки "e" в "eDSL". Впрочем, у меня получилось более близко, чем в скаловском оригинале.

Интерпретатор сам по себе "тривиален", так что я только "рыбу" накидал, чтобы код на DSL проходил проверку типов, если вдруг кто захочет доделать - милости прошу! Заодно сможете проверить, работает ли мой пример (на настоящем BASIC я проверял – с точностью до синтаксиса, код рабочий!).
Интересно получается, что я только-только начал на 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, в котором посылка сообщений сделана с передачей не только получателя, но и автора. И пользуются этой возможностей примерно так же — делают контекстно-зависимые расширения для языка. Почитать об этом можно в "Семь языков за семь недель" — крайне советую!
👍2
Дополнение: нет, multiple receiveres, это не "тайпклассы для бедных" и не "как типажи в Rust" (ох уж эти кулики и их желание похвалить своё болото через насмешки над чужими!).

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

Расширяйте кругозор, мыслите шире, будьте открыты к новому или просто иному!
Ух, опять большая пауза вышла. Буду писать про то, что сделал буквально вот прямо сейчас, а то так и не соберусь…

Время от времени приходится смотреть перевод на русский или расшифровку того или иного английского слова. Проще говоря, мне нужен словарь.

В xfce есть программка-словарь в виде диалогового окна. Вот только сценарий "скопировал слово, переключился на окно словаря, вставил, пролистал выдачу в поисках нужного, переключился обратно к тексту" слишком уж длинноват. Мне же хочется по сочетанию клавиш видеть перевод во всплывающем окне. Решил это желание запрограммировать.

Словарь из xfce использует протокол DICT — отдельный сетевой протокол для запроса словарных карточек. Я с этим протоколом раньше сталкивался, когда использовал в консоли программу dict(1). Вот только переключаться в консоль и запрашивать перевод там столь же непозволительно долго :( Но зато утилиту командной строки уже можно взять за основу моей поделки!

Помимо dict(1) взял

- Rofi для показа экранного меню
- Zenity для запроса ввода
- notify-send для показа всплывающих сообщений

Получился скрипт vortaro.py ("vortaro" — это "словарь" на Эсперанто). Да-да, ужас-ужас, питонолапша. Я знаю. Зато я решил задачу быстро! Ибо plumbum сильно упрощает написание сценариев, склеивающих воедино пачку внешних программ. Хотя бы на bash писать не пришлось. Может быть потом перепишу на Haskell и turtle.

Сейчас скрипт смотрит в primary selection слово, пробует поискать его в первом словаре из списка, затем во втором и так далее. Если карточка найдена, то текст показывается во всплывающем сообщении. В том случае, когда конкретного слова в словаре не оказывается, но есть похожие на него слова, то сначала показывается меню, позволяющее выбрать одно из таких слов. Довольно таки специфическое поведение, готовую программу я бы скорее всего не нашёл. А тут полчаса и готово!
👍11🔥4
​​Ранее писал я про то, что в #kotlin неплохо бы иметь возможность иметь несколько receivers, когда строишь сложные #DSL. И в каком-то виде это уже завезли в Kotlin 1.6.20! И даже синтаксически получилось не слишком ужасно :D

Основное преимущество подхода в том, что можно "насыщать" расширениями тип T1 строго в контексте T2, не имея возможности модифицировать T2. А возможность указать несколько контекстов позволяет эти контексты (де)композировать.

Поживём и увидим, будет ли от нововведения больше пользы или вреда

В примере Int получает свойство mm, доступное в контексте DSL при наличии контекста "измеримости". По месту вызова измеримость означает масштабирование. Да, пример синтетический, но какой уж смог сходу придумать.
🤔6👍4
Для разнообразия напишу о том "с чем я сейчас играюсь". Это опять #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 тоже кое-какая функциональность для подобных задач есть, но тут целый параллельный мир для меня открылся! В дополнение к наработанным "открывалкам" есть богатый инструментарий по созданию своих, это всё тоже очень по-имаксовски.
👍5🤔4😱1
Помимо ссылок ещё есть "сессии", когда вы записываете блок команд для пошагового исполнения. Блок начинается с парочки s-exps, открывающих в соседней панели сеанс диалога с интерпретатором, скажем, Python. Затем в блоке идут уже команды для этого интерпретатора. Блок нарочно исполняется не целиком, как это было бы сделано в Babel, а именно построчно — и нарочно же выполняется с демонстрацией результата выполнения каждой команды в соседней панели. Это тоже своего рода исполняемые заметки, но не "сниппеты", а "демо", они же test blocks. Вы, наверняка, встречались с проектом tldr, так вот тут то же самое, но примеры можно выполнять прямо тут же, не копируя в shell. Опять же, очень интересно и очень не мейнстримово :)

Я пока пробую смешивать Org с eev в заметках для себя. Тут я всё же скорее согласен со Столлманом — негоже неподготовленного читателя бросать в яму с острыми с непривычки скобками. К тому же eev привязывает заметки к Emacs в большей степени, чем Org, который за пределами Babel хотя бы просто "рендерить" умеют многие инструменты (pandoc, GitHub/Gist). И тем не менее сама идея исполняемых ссылок мне очень понравилась, буду продолжать исследовать эту тему.
👍13
Забыл ссылку дать на вот это видео: https://www.youtube.com/watch?v=86yiRG8YJD0
Там и про драму со Столлманом есть, и про иторию повяления проекта, и вообще видение автора можно прочувствовать. Занятное.
🔥6
Не могу не поделиться ссылкой на прекрасное:

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 в стиле "это мой последний язык" (в смысле, что больше ничего не понадобится, настолько хорош). Ходил, читал — забавное!
👍18🤔1
Я давно интересуюсь хранением знаний, пусть и не выработал пока привычки сохранять всё, что хотел бы хранить. Но способы разные я периодически изучаю.

Когда-то давно, в середине 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.
🔥5👍3
(опять Телеграм не опубликовал одним сообщением)

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

В прошлый раз я упоминал кнопки, как способ насыщения базы знаний функциональностью. Кнопки позволяют выполнить некоторое действие, связанное с тем кусочком знаний, который вы в данный момент изучаете и таким образом дополнить общую картину. Скажем, вызвать почтовую программу с шаблоном письма к заданному адресату (полезно для GTD) или запустить воспроизведение музыки заданного исполнителя (моя личная хотелка — аннотированный каталог музыки, в котором я наконец-то смогу ориентироваться).

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

Emacs ушёл на шаг вперёд: в Org Mode можно добавлять свои типы ссылок, да и встроенных типов предостаточно. Вы можете ссылаться на файлы, статьи встроенной документации, emails (такие ссылки работают как mailto-ссылки в браузере). Можно даже выполнять при клике на ссылку elisp-код или shell-command. Так что в рамках org-файлов ссылки можно смело считать кнопками!

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

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

> Но ведь есть же docstrings, скажете вы. И будете правы — есть! Но, увы, не для каждого языка. И Literate Programming тоже не всегда получается применять.

Применительно к Emacs я знаю две реализации кнопок: eev (который я уже упоминал) и GNU Hyperbole. Оба проекта — реальные долгожители. И оба ну очень персональные!
👍2
evv

Этот проект опирается на то, что раз уж у нас не редактор, а среда исполнения Emacs Lisp, то почему бы не писать короткие s-expressions в любом месте и не позволять таковые "кликать". С одной стороны человеку, отторгающему скобочки из принципа, такой вариант точно не подойдёт, с другой стороны каждую ссылку видно. То есть вы видите имя функции, которая будет вызвана при выполнении кода. В Org Mode код elisp-ссылок не виден по умолчанию, что может кого-то очень даже насторожить.

Очевидно, что добавить свои виды ссылок/кнопок легко: вы просто пишете больше функций! Автор eev тут не чурается макросов и генерирует функции для открытия PDF в ваших любимых читалках на нужной странице или в позиции первого вхождения такой-то подстроки. В итоге при должной консистентности именования (генераторы её вполне успешно обеспечивают) ссылки ещё и самодокументируются, да и вызвать describe-function можно в любой момент.

Недостаток такого подхода тоже очевиден: вы прямо в файлах, не являющихся кодом на elisp, оставляете кусочки оного. Но для себя так делать можно! Зато кнопки хранятся всегда рядом с тем, к чему относятся и при желании могут быть "выполнены в уме", если Emacs с eev не окажется под рукой (тут тоже важна самодокументируемость).
GNU Hyperbole

Этот проект существует дольше, чем Org Mode, ещё с середины 90х, и успел за это время стать вещью в себе и целой экосистемой. Автор положил в одну коробку всё, что хотел иметь в Emacs: тут и свой outliner, и средство для управления окнами редактора, и система гиперссылок. К счастью, можно использовать не всё и сразу, а только сами гиперссылки (на остальное можно посмотреть, как образчик "проекта на всю жизнь").

Hyperbole предоставляет возможность оставлять в любом тексте ссылки (называемые implicit buttons) либо вообще без какой либо разметки, либо с минимальной вида {google this}. Вы нажимаете сочетание клавиш или кликаете мышью на текст кнопки, а Hyperbole по расширяемому набору эвристик пытается понять, как кнопка должна сработать. Плюс всегда есть способ не выполнить действие, а получить описание того, что будет выполнено при "нажатии" кнопки.

Во многом кнопки Hyperbole похожи на автоссылки в разных системах. Например, вы можете сделать так, чтобы текст вида "foo#12234" работал как ссылка на ticket под номером 12234 в bug tracker к проекту foo — и текст останется просто текстом, дополнительная разметка не потребуется! Строго говоря, {} нужны только для кнопок, которые нельзя описать одним "словом" и это минимальная цена, которую можно заплатить за поддержку "кнопок с параметрами".

Ещё у Hyperbole есть механизм explicit buttons. Эти кнопки называются явными, потому что требуют явного создания. В отдельном файле, связанном с текущим текстом, сохраняется метаинформация о том, что такой-то участок текста является кнопкой такого-то типа и с такими-то параметрами. В результате в тексте вы видите emacs button — это "нажимаемые" (ага, то же имя при другом смысле) объекты в документе, не связанные с содержимым документа напрямую, а создаваемые в интерфейсе редактора при открытии документа. Org Mode, встроенная справочная система, просмотрщик man pages — все они использую emacs buttons для показа ссылок/кнопок в интерфейсе, так что Hyperbole тут выступает вполне последовательно.

Минус explicit buttons понятен сразу: вне Emacs не получится даже увидеть, что какой-то фрагмент текста, это кнопка. И нужно не забывать поставлять файл кнопок вместе с файлом, в который кнопки вставлены. Зато никаких s-expressions на виду! Опять же, очень персонально!

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

Мне лично, как человеку, который не боится скобок и при этом сторонник "явного в противовес неявному" (питонисты порадуются), ближе подход eev: я хочу видеть, что за кнопки я жму.

Но подход Hyperbole интересен поддержкой ссылок без разметки — можно попробовать реализовать такое в миниатюре, без подключения сверху целой развесистой системы. А ещё можно попробовать размечать eev-кнопки как emacs buttons, потому что это выделит их визуально и даст возможность привязать контекстно-зависимые сочетания клавиш.

Ещё eev мне нравится тем, что это по сути обёртка над встроенными действиями "перейти в конец текущей строки"+"выполнить elisp s-expression перед курсором"! Всё остальное — функции для оживления ссылок. Но таковых и у самого Emacs в избытке, пусть иногда и не настолько самодокументируемых.

Я только прошёлся по верхам, оба проекта слишком велики, чтобы в пару абзацев описать каждый. Про GNU Hyperbole автор буквально недавно написал на Reddit и рассказал, что же это такое и для чего он делает уже третий десяток лет :) Если вдруг читатель тяготеет к Emacs, как к средству управления знаниями, рекомендую приобщиться к тому или другому проекту пусть даже кругозора расширения ради!

Есть ещё один проект, не связанный с Emacs, который тоже про вот это вот всё и который мне очень нравится как явление. Но про него я расскажу как-нибудь в другой раз.
👍7
The Stubborn Computing Manifesto

Прочитал недавно статейку с таким названием. Процитирую вступление:

> Stubborn computing is about using computers the way you want to.
>
> Stubborn computing is about being able to pick — and stick to — what you think is the best tool for the job. It's an investment in software over time: As with the carpenter's hammer, the chef's knife or the weaver's loom, it's about subconscious and intrinsic mastery of the tools of one's craft - a deep-seated skill growing along with a never-ending creative process. Ars longa, vita brevis.

Закончил читать с мыслью "так это же про меня!". И более того, манифест хорошо описывает то, чем я занимался всю мою около-компьютерную жизнь!

Сидел на DOS, писал на Pascal, хотя слышал уже, что надо на Си писать. И мне было хорошо. Потом под Windows использовал Delphi. И тоже было отлично.

Слез с Windows на Ubuntu/Debian Linux и мне хорошо, а до этого было хорошо на Windows XP. Причём мне было хорошо на XP, когда все уже сидели на Win7. Сейчас мне на дебианах хорошо, хотя окружающие постоянно пытаются меня куда-то перетащить — то в "дивный мир Эппла", то на "настоящий Linux" (arch).

Несколько лет пользовал Sublime Text, пропуская мимо ушей то, насколько лучше жить на PyCharm. Потом сам решил пересесть на Emacs. И с тех пор только и слышу, насколько он старый, насколько уродлива цветовая схема, насколько больше плюшек у VSCode. А мне норм. Вот эта цитата хорошо соотносится моим выбором Emacs:

 Stubborn computing is about working — sometimes hard — towards maximizing personal computational enjoyment.

Да, я использую то, в изучение чего я вложил силы. И то, чего мне сейчас достаточно. Почувствую, что перестало хватать — пересяду на MacOS, IntelliJ IDEA. Сейчас же ThinkPad мой меня радует больше, чем оставшийся от работы MacBook. Привык, настроил, пользуюсь успешно и с удовольствием.

И это не ностальгия, не ретроградство, не недовольство засильем bloatware, не фанатичное стремление к использованию suckless software, не гонка за мифическим Unix Way. Такие явления формируют вокруг себя субкультурки, причисляя себя к которым нужно всё время соответствовать — обычно соответствовать ожиданиям других. Кому-то может и нравится подобное. А я слишком упрям :)
👍29🔥5💩1