brain_leakage_etc
119 subscribers
17 photos
2 videos
31 links
Не мысли, но мыслишки некоего @astynax. Можно сказать то, что не получилось дописать до средней длины публикаций в @brain_dump_etc
Download Telegram
Вчерашняя задачка (вторая часть дня 24) из Advent of Code была решена пристальным просмотром выхлопа GraphViz, для которого я сгенерил .dot-файлик.

На Reddit народ решал "с помощью Ctrl+F" то есть тоже глазами вычитывали почти все (правда, кто-то запарился и сделал симуляцию схемы в FPGA и прочих логических симуляторах).

А для меня сработал принцип "правильная визуализация — половина решения", сработал на 200% в данном случае :Р
🔥8👍3
TIL, что GitHub ещё и STL умеет рендерить нынче (у меня 3D-принтера нет, так что я как-то это новшество упустил). Узнал о такой функциональности, решив взглянуть, как выглядит результат генерации этих весёлых ёлочных игрушек: https://github.com/joe-warren/christmas-ornaments/blob/main/haskell-ornament.stl
🤯31
С Наступающим!
jshell> Stream.iterate("         1", x -> x.replaceFirst(" 1", "101")).takeWhile(x -> x.startsWith(" ")).forEach(System.out::println)
1
101
10101
1010101
101010101
10101010101
1010101010101
101010101010101
10101010101010101


BTW, jshell прям нормальный, выводит типы подвыражений и методы автодополняет :)
7👍1
Вот смотрю я на эти множественные доллары в Kotlin и хихикаю. Можно же просто экранировать ("\$") и всегда можно было. Или разрешили бы удваивать служебный символ, как много где давно сделано. А ещё можно было требовать всегда использовать {} — да, чуть более шумно, но не критично же! Зато встретить литерал с "${" сложнее и тут мы бы обошлись слэшем.

Удвоение как способ экранирования, например, в Python используется в обоих вариантах шаблонизации строк и в f-строках тоже. {, }, %, \ удваиваются для отмены действия. Можно (хоть и не нужно) делать всякие "отложенные подстановки":

>>> "%%%%s %%s %s" % 1 % 2 % 3
'3 2 1'
>>> "{{{{}}}} {{}} {}".format(1).format(2).format(3)
'3 2 1'
>>> f"%s {{}} {1}".format(2) % 3
'3 2 1'


Третий пример тут совсем шуточный, просто ради использования всех трёх способов форматировать строки в Python. Да-да, "There should be one-- and preferably only one --obvious way to do it." то самое 🌚
👍2😱1
Apple Script, конечно, в стиле COBOL дизайнили. Вот как я должен из головы написать такое?

set firstFolder to item 1 of input

tell application "Finder"
set fileList to every file of firstFolder whose name extension is "mp3"
end tell


Я ChatGPT попросил, естественно. В три итерации вида "— Падает так-то. — А, ну да, сделай так" получилось научить Apple Music играть папку как плейлист. Но только одну. И когда захочу все выделенные директории пройти, то Чада же буду просить, потому что не понимаю, как и куда сходу вписать что-то вроде "of every item in input".

Я ещё и ввожу этот код в Automator, который синтаксис подсвечивает только после нажатия кнопки с молотком (у неё нет тултипа, видимо "Build"). А если ты редактируешь код после подсвечивания, то новые кусочки будут без подсветки. Причём подсветка сделана в стиле WYSIWYG в Word, т.е. подсвеченные фрагменты перемежаются с новыми прямо внутри слова, например! А ещё иногда вводишь текст, курсор прыгает сам в следующую строчку и портит её 🙈 И при этом интерфейс автоматора тормозит как Word тормозил под Win'95 на первых Pentium.

И да, через shell scripting интероп между эппловыми программами не описать просто так. И в интерфейс программ описанные скрипты не встроить без Автоматора (или каких-то приседаний). Вот уже и папочка "Send to" в винде, куда достаточно было кинуть ярлыки на обычные скрипты, кажется верхом удобства.
👍4
Нашёл недавно один подкаст. Автор выкладывает его на PeerTube с заглушкой вместо видео. А я хочу именно слушать. Подкасты у меня играет PodcastAddict, ему можно скормить RSS из PeerTube и выпуски подтянутся. Вот только mp4 в этом конкретном случае какие-то битые: длительность неверная, индексирование не работает, так что ни дослушать потом нельзя, ни отмотать в другой раз до нужного места.

Решил скачать и сконвертировать, сначала даже обошёлся curl+sed+ffmpeg+bash. Но в итоге получил пачку mp3 с именами навроде UUID. Надо было переименовывать или тегать.

Пробовал таки потегать да так, чтобы PodcastAddict подхватил нормально даты и заголовки. Взял Python+mutagen, попробовал. Проиграл. Даты в ID3 вообще прокляты, потому что никто не знает, какие фреймы конкретная программа читает. А заголовки PodcastAddict просто игнорит, если подкаст берётся из локальной директории 🤮 Ну или ищет другой фрейм, про который я не знаю. Хоть файлы переименовывай, чего не хотелось бы, потому что автор подкаста поленился в едином стиле назвать выпуски и там полный треш, так что придётся ещё и вычищать от недопустимых символов и обрезать.
👍5
Ха-ха, всё ещё умею верстать на табличках с colspan/rowspan!

Забавно, что эволюция совершила виток и появился grid layout. Потому что не всегда хватает или просто неудобно использовать вложенные комбинации columns и rows.

А ведь когда-то деды закруглённые кнопки делали табличками 3x3! Но это от бедности делали, конечно (или нет).
🔥43
Задумался тут, а можно ли получить heatmap для файлов в репозитории Git. Конечно же, есть готовые решения, но я решил обойтись man и моими скромными навыками использования core utils.

git log --name-status --pretty=format: | \
awk "\$1 {print \$2}" | \
sort | uniq -c | sort -n


На большой репе стоит ограничить диапазон коммитов, но концепция в целом не поменяется.

Да, тут двойная сортировка, но так уж вышло, что uniq не умеет считать уникальные строки, только если повторы идут подряд. А вторая сортировка уже использует количества повторов и "арифметический" порядок.

awk тут просто печатает второй столбец, если первый не пуст. Так я отбрасываю пустые строчки, получающиеся при выводе "пустой" информации о коммите ("format:").

По хорошему, надо бы учитывать переименовывание и удаление, поскольку Git это даже отображает при выводе с флагом "--name-status". Но мне было лень такие тонкости учитывать. Вот когда надумаю сделать на Python скриптик, который бы дерево проекта выводил и подкрашивал оттенками красного "горячие" файлы — тут уже можно будет и заморочиться 😉
🔥4👍1
В кои-то веки пошёл ванильного JS под браузер написать немножко. Решил, раз всё равно WASM тащу, то почему бы async/await не заюзать и данные через fetch не поскачивать. И проиграл, конечно. Потому что fetch не только сам асинхронно работает, что понимаемно, но и body отдаёт как stream, что тоже понимаемо, но именно в браузере неудобно!

На Node можно сделать

for await (const chunk of response.body) {
// ...
}


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

const fetchAndRead = async (url) => {
const response = await fetch(url);
const reader = response.body.getReader();
const decoder = new TextDecoder();
let data = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
data += decoder.decode(value, { stream: true });
};
data += decoder.decode();
return data;
};


А я-то просто slurp хотел сделать 🙉. Кажется, что надо было забить и по-старинке взять XMLHttpRequest, хоть с ним тоже строчек на пять код потянет.
😱2
А ещё WASM можно только сервером раздать, поэтому "просто HTML cо статикой в соседней папке" не получится сходу сделать. Придётся как base64 инлайнить, а этому ещё предстоит научиться. И мегабайт на выходе будет больше, хоть и сжиматься оно будет неплохо.

И всё для чего? Просто чтобы сделать штуку, которую придумал за чаем — "jq, но в браузере и чтобы как самодостаточная страничка работало чисто на клиенте". Сам jq в WASM уже обернули до меня, я только стою на плечах гигантов.

Вот так выглядит MVP уже сейчас (вёрстка, как водится, инженерная; "WJQ" читать как "Вжик"):
9
Вот как давече упомянутый Вжик выглядит нынче:

http://astynax.me/wjq/?url=example.json&query=.message.words+%7C+map%28.word%29&flags=-c&pretty=true — жать [Fetch], потом жать [Execute]. Первый раз может грузиться чуть долговато, потому что WASM надо стянуть, но м.б. у GitHub и вполне быстрый CDN для статики 🌚

JSON можно накопипастить, не обязательно фетчить.

Кнопка [Remember] сохраняет параметры (но не JSON-данные!) в URL, чтобы можно было в закладки положить или поделиться, либо просто использовать кнопку "Назад" браузера как "Undo" 😎 History API используется максимально топорно, я специально всё в URL положил, а не в state, потому что так захотелось 🥴 Опять же, я в будущем могу захотеть трекать то, что вы там вжикаете👺

Пока писал это вот, подумал, что можно ещё сделать "скопировать как shell command" (curl + jq), элементарная фича же!

Ну и есть желание делать "fork", через открытые текущей конфигурации в новой вкладке. А ещё думал о том, чтобы можно было по кнопке добавлять следующий "шаг" — ещё одну query уже применительно к "Result" в виде нового fieldset — и так произвольное количество раз. Потом такие шаги можно было бы схлопывать в один, поскольку запросы jq композируются!

P.S. Чую, что в какой-то момент добавится поведение "выполнить отсюда и вниз" и получится кривенький вариант Jupyter Notebook или Org Mode, но зато прямо в браузере

P.P.S. Да, я в курсе, что Jupyter уже давно упаковали в WASM и можно его гонять локально. Но у меня тут Smol Software, а не этот ваш Bloatware!
👍3🤔2
Подумалось тут, что jq, это неплохо, конечно, но м.б. имеет смысл класть выхлоп jq в глобальную переменную — хоть в атрибут того же document. Чтобы из консоли DevTools можно было бы данные потыкать силами JavaScript.

Правда, инструментарий у JS не самый располагающий к удобному использованию в REPL. Может быть, стоит какой-нить lodash подтянуть, или что там носят ещё?

И да, это ещё один шажок в сторону Jupyter. Впрочем, я бы не отказался от того, чтобы можно было эдакий data playground иметь прямо в браузере. Только чтобы он был local first хотя бы в базовой комплектации — поэтому-то я и хочу свой wjq упаковать в самодостаточный HTML. Можно и что-то более развлекательное соорудить из p5, d3 и других визуальных штук. Но важно, чтобы оно было "no build" и максимально полноценно работало в offline. Есть, над чем подумать.
🔥3
Если кому-то показалось, что стало мало нытья, спешу сообщить, что могу ныть побольше, раз канальчик делал в том числе и для этого :) Лайкните и я буду ныть чаще, ибо есть, об чём 🙈
👍20
👺
🔥6
Ныть так ныть. Опять задел старую болячку, когда понадобилось на самсунговский Flip закинуть файлы из макоси. Как mass storage оно не подключается (к Маку), приходится пользовать OpenMTP. Но "в андроиде что-то сломали", как водится, так что теперь перед каждым синком надо идти в свойства сервиса "USB" на телефоне и грохать все application data. Тогда телефон забывает про мой Мак и заново спрашивает, подключаться ли к нему — и подключается. Без этих танцев телефон говорит "подключено", но с OpenMTP его не видит. И так каждый раз.
😢4😱2
Записал эту проблемку c OpenMTP и Samsung в свой gripe file. Об этой штуке я узнал из данного интервью:

https://lobste.rs/s/terwiu/lobsters_interview_with_technomancy — вообще рекомендую к прочтению, вдохновляющее. Technomancy, если что, это автор Leiningen для Clojure, а сейчас разрабатывает Fennel (Lisp поверх Lua). Очень крутой чел, достоин подражания.

Собсно, про gripe file в интервью было сказано следующее:
In my home directory, I have the gripe file. A friend in IRC gave me the idea. You just collect all the problems, complaints you have. How could the programs I use on a regular basis be better? Sometimes you see something can added or improved and you can delete this line from the gripe file. I love it. For example, SSH wouldn’t let you specify a directory for your config files. But a few years later, I went back and saw they had! So I deleted it from the gripe file, which is a really cool feeling. I recommend you keep a gripes file.

Мне идея понравилась, начал свой вести.
🔥7
Ох, уж этот Telegram. Режет длинные сообщения в произвольном месте, WYSIWYG отваливается в случайных местах, Markdown'ish разметка отгнила почти совсем. Копирую текст из Emacs, руками переразмечаю, шлю себе в Saved Messages, чтобы там отредактировать, если что сломается, и только потом публиковать.
👍7😢2💩1
Начал AoC делать на расте. Проиграл дважды — от того, сколько пердолинга, если нужно строками пожонглировать 🌚, и от того, насколько нерепрезентативный пример даден в первый же день 🙈 Первое терпимо — зато практика. Второе — просто особенность, моя и/или автора заданий 😉

BTW, в этом году 12 дней всего, автор подустал, понимаемо
😱3
Всё же абсолютно проклято. Хорошо, что я могу это делегировать. И даже ChatGPT советует просто цикл написать, а этот пример показал просто для полноты.

Это я решил сделать для uv обёртку, которая бы превращала
uv-try rich icecream

в
uv run --with 'rich' --with 'icecream' python

Посмотрел на этот однострочник на zsh и написал в пяток строк с помощью цикла :Р
🤯3🤔1😱1