TGViewer
Channel Public Channel
annFlow

annFlow

@annsflow

Automation • LLM agents • second brain • integrations • pipelines • bots • chat funnels • lead generation • CRM • ops/operations • websites •SEO•VPS• VPN • time tracking/timing•logging•metrics @arsenynn

Portfolio: https://portfolio.arsenynn.quest/it-ai/
Subscribers
33
Photos
30
Videos
10
Links
89

Showing posts older than #102 · Back to latest

Older Posts 20 shown
Post #101 39
Инженерная реальность: плеер, фон и PWA

Сделать “плейлист в браузере” легко. Сделать радио-ощущение сложнее: нужно бесшовное звучание, устойчивый UI и поведение, которое не ломается при смене условий (сеть, устройство, фон).

1) Плеер как движок

Эффект “радио” держится на двух вещах: кроссфейд и состояния. Плеер работает как state machine (idle → buffering → playing), чтобы не было “двойного звука” и гонок при переключениях. Параллельно идёт префетч следующего трека, чтобы реакции на Next/Prev ощущались быстрыми.

2) Зачем нужна кнопка «Слушать в фоне»

На iOS/WebView “богатый” режим (WebAudio, видео-лупы, таймеры, префетч) часто агрессивно режется при сворачивании. Поэтому кнопка «Слушать в фоне» переводит радио в облегчённый профиль: отключает тяжёлые части, оставляет стабильное воспроизведение через простой <audio> и даёт быстрый возврат в основной режим без потери контекста.

3) PWA

PWA здесь не про “нативность”. Оно даёт более предсказуемый запуск интерфейса и повышает шанс, что сессия проживёт дольше. Но я не обещаю невозможного: фон в вебе нельзя гарантировать, поэтому и нужен отдельный “фон-режим”.

4) Gesture gate: Telegram Mini App / Safari WebView

Есть ещё один “взрослый” слой надёжности: когда платформа запрещает autoplay (особенно в WebView), проект не выглядит сломанным. Визуалы переводятся в режим ожидания до первого пользовательского жеста, а после тапа аккуратно стартуют заново. Это редкая, но важная деталь: большинство веб-плееров в такой ситуации просто молча “не играет” и выглядит как баг, а здесь это осмысленная деградация под реальные ограничения.

Telegram-контент превращается в медиа-объект, а не в ленту ссылок, и при этом система честно учитывает ограничения платформ.

Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#WithoutStreaming@annsFlow

💻 annFlow
Post #99 35
Как это работает внутри: индексатор → плейлист → стрим

Проект устроен как конвейер: Telegram-канал → каталог → эфир.

1) Индексатор пробегает канал, находит аудио и GIF/MP4, читает теги и формирует playlist.json.

2) /playlist?mix=&energy= отдаёт JSON с треками и визуалами уже в нужном порядке под текущие ручки.

3) /audio/{id} и /gif/{id} запрашивают медиа в Telegram и отдают его в браузер.

Ключевой принцип: аудио не сохраняется на диск. Сервер отдаёт данные потоково (chunked) по мере получения.

Визуалы кэшируются на диск, потому что они короткие и повторяются, а кэш заметно ускоряет переключения.

Самая важная часть (то, что превращает канал в эфир):


@app.get("/audio/{message_id}")
async def audio(message_id: int):
async def gen():
async for chunk in telethon_stream_bytes(message_id):
yield chunk

return StreamingResponse(
gen(),
media_type="audio/mpeg",
headers={"Cache-Control": "no-store", "Accept-Ranges": "none"},
)



— @app.get("/audio/{message_id}")
Маршрут: GET /audio/12345 попадает сюда, {message_id} это ID сообщения с треком в Telegram.

— async def audio(message_id: int):
Асинхронный обработчик, чтобы сервер не блокировался во время загрузки/отдачи. int фиксирует тип параметра.

— async def gen(): ... yield chunk
Асинхронный генератор: читает трек из Telegram порциями (async for) и сразу отдаёт каждый кусок (yield).

— StreamingResponse(gen(), ...)
Оборачивает поток в корректный HTTP-стрим: воспроизведение может начаться до полной загрузки файла.

— media_type="audio/mpeg"
Явно задаёт Content-Type, чтобы браузер правильно воспроизводил аудио.

— headers
no-store — не кэшировать аудио. Accept-Ranges: none — без Range-запросов (перемотка/дозагрузка “с середины” не предусмотрены).

Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#WithoutStreaming@annsFlow

💻 annFlow
  • ❤ 1
Post #98 41
Две ручки настроения: стиль и энергия

В Without Streaming я сделал управление как на пульте:
одна ручка смещает эфир Jazz ⇄ Hip-hop, вторая меняет энергию Drifting ⇄ Driving.

Основа намеренно простая и прозрачная: я помечаю треки тегами в Telegram (#J / #H / #JxH и #drift / #drive / #dd). Индексатор собирает это в playlist.json, а сервер по запросу /playlist?mix=&energy= пересобирает порядок треков. #JxH и #dd это треки, которые я сам считаю смешанными по стилю (Jazz×Hip-hop) и треки со смешанной энергией (между drift и drive).

Дальше код делает простую вещь: превращает положение ползунков в коэффициенты “сколько внимания дать каждой стороне”, и считает итоговую оценку трека score. Чем выше score, тем выше трек поднимается в выдаче /playlist.


jazz_bias = 1.0 - hiphop_bias

drive_bias = energy / 100.0
drift_bias = 1.0 - drive_bias

score = jazz_bias * w_jazz + hiphop_bias * w_hiphop \
+ drift_bias * w_drift + drive_bias * w_drive


• mix и energy превращаются в коэффициенты *_bias: это “сколько влияния” дать каждой стороне шкалы.
• w_jazz / w_hiphop / w_drift / w_drive это веса трека, которые получаются из тегов при индексации.
• score это итоговая оценка: чем она выше, тем раньше трек окажется в эфире при текущих настройках.

Дальше включается важная инженерная часть: чтобы эфир не зацикливался на узкой категории, сервер сначала отдаёт “профильные” треки (и мосты), а затем подмешивает остальные.

Почему пока не идеально: теги субъективны, две оси создают много комбинаций, и “музыкально правильно” не всегда совпадает с “самой высокой оценкой”.

Авто-режимы (Auto Flow / Auto Energy) двигают ручки плавно и не ломают текущий трек, а эффект проявляется на следующем.
Кстати, авто-режим можно включить прямо с ползунка: нажмите на “точку” (ползунок) и он начнёт двигаться автоматически.

В следующем посте разберу внутренний конвейер Without Streaming: как индексатор собирает playlist.json, как /playlist формирует эфир под ручки и как /audio стримит медиа из Telegram chunked без сохранения на диск.

Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#WithoutStreaming@annsFlow

💻 annFlow
Telegram Without Streaming Music with GIFs @arsenynn
Post #95 50
Радио из Telegram в один клик

У меня есть Telegram-канал Without Streaming, куда я фиксирую свою личную музыкальную медиатеку, а так же короткие видео-вырезки: из своих проектов @arsenynn и workflow@arsenynn. Для меня это не просто подборка, а слепок вкуса и времени.

Изначально все началось прагматично: прийти в компанию, на тусовку или сесть в машину и не подключаться к колонке или проигрывателю, а просто открыть свой канал на телефоне того, кто уже подключён, и включить музыку в один шаг.

Музыка и GIF здесь работают как компактная запись состояния: вместе они сохраняют настроение момента быстрее и точнее, чем любые пояснения.

Telegram как CMS. Новый пост в канале автоматически становится частью эфира, без отдельной админки и медиатеки.

Визуалы как «телеканал». Один визуал повторяется три раза, затем переключается на следующий; стартовый набор каждый раз перемешан.

Аудио стримится «на лету» из Telegram без сохранения на диск. Это осознанный выбор: минимум инфраструктуры и минимум «следов».

Техническая проекция простая: FastAPI + Telethon → JSON-плейлист → chunked-стрим

В следующем посте расскажу, как две ручки (Jazz ⇄ Hip-hop и Drifting ⇄ Driving) управляют настроением эфира через простые теги в Telegram.

Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#WithoutStreaming@annsFlow

💻 annFlow
Telegram Without Streaming Music with GIFs @arsenynn
  • ❤ 1
  • 🔥 1
Post #93 150
Post #91 55
Тема клавиатурных слоев на этом этапе закрыта.

Важно понимать: здесь описана лишь часть того, что можно построить на связке Karabiner + Hammerspoon. Я показал решения, которые придумал под себя и которые реально использую каждый день: слои, сигналы, логика и сценарии.

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

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

Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#macOSAutomation@annsFlow

💻 annFlow
Post #90 40
MIDI-клавиатура и OBS как аппаратный контроллер (Hammerspoon)

У меня несколько MIDI-клавиатур, в следствии появилась простая идея: использовать одну из них, как физическую панель управления, где клавиши запускают команды. Hammerspoon здесь работает как “прошивка”: принимает MIDI-события, переводит их в действия и управляет OBS по WebSocket.

Пример:

В конфиге есть карта действий smkActions[...], и для ноты 48 назначено:


smkActions[48].label = "OBS: Scene #01"
smkActions[48].fn = function() obsSetSceneByIndex(1) end


Что это значит:

- smkActions[48] — слот для конкретной MIDI-ноты (48).

- .label — человекочитаемое имя (для логов/понимания).

- .fn = function() ... end — функция, которая выполняется при нажатии этой MIDI-клавиши.

- obsSetSceneByIndex(1) — переключить OBS на сцену с индексом 1 (индекс берётся из списка сцен OBS).


Дальше в обработчике MIDI-событий есть логика: выполнять действия только в command mode (который включается sustain-педалью/CC64).


Ключевой фрагмент (суть):


if smkCommandMode and cmdType == "noteOn" then
local note = mdTable.note
local vel = mdTable.velocity or 0
if not note or vel <= 0 then return end

if note < SMK_NOTE_MIN or note > SMK_NOTE_MAX then return end

local act, layer = smkResolveAction(note)
if not act then return end
if not act.hotkey and not act.fn then return end

-- дальше debounce и выполнение act.fn / act.hotkey
end



- smkCommandMode — булевый флаг “режим команд включён”.

- cmdType == "noteOn" — реагируем на нажатие клавиши (Note On).

- mdTable.note — номер ноты (например, 48).

- mdTable.velocity — сила нажатия; vel <= 0 отсекается (чтобы не триггерить “пустые” события).

- SMK_NOTE_MIN/MAX — ограничение диапазона, чтобы обрабатывать только нужные 25 клавиш.

- smkResolveAction(note) — достаёт действие для конкретной ноты (с учётом возможных слоёв/оверрайдов).

- act.fn — если у ноты есть функция, она будет вызвана.



Дальше obsSetSceneByIndex(1) делает примерно такую цепочку:

1. Получает список сцен OBS (через кеш с маленьким TTL, чтобы не дергать OBS на каждый клик).

2. По индексу 1 берёт имя сцены.

3. Отправляет в OBS команду SetCurrentProgramScene через WebSocket.


Итоговая логика одной клавиши


MIDI note 48 → (command mode ON) → находим smkActions[48] → вызываем obsSetSceneByIndex(1) → OBS переключает сцену на #1.


Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#macOSAutomation@annsFlow

💻 annFlow
  • ❤ 1
  • 👀 1
Post #88 35
Мониторы и стабильность рабочего места (Hammerspoon)


Многомониторный сетап в macOS часто ведёт себя хаотично: после переподключения дисплеев окна “переезжают”, Dock может оказаться не на том экране, а раскладка мониторов меняется непредсказуемо. Чтобы это не ломало рабочее место, часть логики вынесена в Hammerspoon.


1) displayplacer + отслеживание подключений


Раскладка экранов применяется не вручную, а через displayplacer: Hammerspoon проверяет наличие конкретного дисплея по persistent ID и понимает, какая конфигурация сейчас активна (например, подключён ли iPad/Sidecar).


2) Авто-применение лэйаутов через скрипты


Под разные сценарии подготовлены скрипты в ~/.layouts/... (условно “с iPad” и “без iPad”). При изменении набора экранов Hammerspoon ждёт короткую паузу, даёт macOS “успокоиться”, и затем применяет нужный лэйаут автоматически.


3) Антихаос после отключения Sidecar/iPad


Одна из самых неприятных ситуаций: отключаешь iPad, и часть окон улетает на “крайний” экран. В этой конфигурации Hammerspoon отслеживает момент отключения и аккуратно возвращает такие окна на primary display, чтобы не искать их по всей комнате.

В следующем посте покажу, как в Hammerspoon я поднимаю WebSocket-связь с OBS.

Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#macOSAutomation@annsFlow

💻 annFlow
  • ❤‍🔥 1
  • ❤ 1
Post #87 36
Hammerspoon как локальный сервер и “пульт” управления

Одна из самых практичных вещей в моём сетапе Hammerspoon: он работает не только как хоткеи, но и как локальный HTTP-сервер. Это превращает Mac в “хаб”, который можно дергать командами с других устройств.


Как это устроено

- Поднимается HTTP server на фиксированном порту (в моём случае 9876).

- Авторизация сделана через header token (X-Auth-Token) вместо Basic Auth, потому что так удобнее и стабильнее интегрироваться с Shortcuts.

- Есть простой rate limit (минимальный интервал между вызовами), чтобы не спамить одинаковыми командами и не ловить гонки.

- Есть health-check / watchdog: сервер регулярно проверяет /ping и, если что-то пошло не так, перезапускается. То есть он не “умирает тихо”.


Что даёт на практике


Получается очень прямой “пульт управления”, где каждый endpoint это действие:

- медиа-команды по конкретным приложениям (например, Twitch/YouTube/Spotify/Music/Podcasts/Books)

- системные команды, включая pmset displaysleepnow (быстро погасить дисплеи)


Ключевой момент: это не “универсальная кнопка”, а точечные сценарии, завязанные на конкретные приложения и нужную последовательность шагов (активация, задержка, команда и т.д.).



Архитектура

- Mac Studio выступает как хаб: он выполняет действия локально и предсказуемо.

- Shortcuts на iPhone или другом Mac выступают как клиенты: нажал кнопку → ушёл HTTP-запрос → на Mac выполнилась команда.


Это даёт ощущение “домашнего пульта”: управление медиа и системными действиями не привязано к тому, где сейчас руки, какое окно активно и на каком устройстве ты находишься.

Дальше разберу связку Hammerspoon + displayplacer: авто-раскладка экранов без ручной правки.


Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#macOSAutomation@annsFlow

💻 annFlow
Post #86 43
Медиа-контроль как сценарии в Hammerspoon

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


Через Hammerspoon получилось приблизиться к нужному ощущению хотя бы на уровне практичного минимума: быстро и предсказуемо управлять воспроизведением в конкретных приложениях. Это не микшер в полном смысле, но уже радикально ускоряет работу с медиа.


Принцип

Не “универсальная кнопка паузы”, а сценарии под конкретные приложения:


активировать нужное приложение → дать фокусу “успокоиться” → отправить правильную команду → при необходимости иметь запасной путь.


1) Spotify: play/pause напрямую


Для Spotify используется AppleScript-команда playpause.

Плюс такого подхода: это не эмуляция клавиш, команда уходит прямо в Spotify и не зависит от того, какое окно активно.


2) YouTube / Twitch и похожие плееры: фокус → k


Для YouTube и Twitch сделан одинаковый паттерн:

- активируется приложение

- выход из Space-layer перед отправкой k, чтобы слой не перехватил клавишу

- короткая задержка

- отправляется k (стандартный play/pause в плеерах)


Важно: выход из слоя здесь не “косметика”, а инженерная деталь. Если оставить слой активным, k может интерпретироваться как команда слоя, а не как команда плеера.

Пример:


spaceLayer:bind({}, "t", function()
local app = hs.application.find("Twitch")
if not app then return hs.alert.show("Twitch не запущен") end
app:activate()
spaceLayer:exit()
hs.timer.doAfter(0.05, function() hs.eventtap.keyStroke({}, "k") end)
end)


Разбор:

- spaceLayer:bind({}, "t", ...) — внутри Space-layer клавиша T запускает сценарий.

- hs.application.find("Twitch") — найти запущенный Twitch (иначе показать alert).

- app:activate() — сфокусировать Twitch.

- spaceLayer:exit() — выйти из слоя, чтобы k не перехватился хоткеями слоя.

- hs.timer.doAfter(0.05, ...) — небольшая задержка для переключения фокуса.

- hs.eventtap.keyStroke({}, "k") — отправить k (play/pause).



3) Safari: тот же принцип “поймать нужный плеер”



Отдельно заведены сценарии под Safari, с тем же смыслом:

- сфокусировать браузер

- небольшая пауза

- отправить k в активную вкладку/плеер


Это удобно, когда медиа играет в разных местах: команда сначала приводит контекст в порядок, а потом уже нажимает “пауза”.


4) Apple Music и Podcasts: фокус → space + задержка



Для Music и Podcasts используется другой “язык управления”:

- активируется приложение

- небольшая задержка (чтобы фокус точно перешёл)

- отправляется space как play/pause



Задержка тут важна: без неё часть команд уходит “в никуда” или в неправильный элемент интерфейса.



5) Apple Books: UI scripting + fallback (самый надёжный вариант)



Books сделан максимально устойчиво, потому что интерфейс и состояния там бывают капризные:

- приложение активируется

- через System Events пробуется нажатие Play/Pause в меню (учтены разные названия меню и RU/EN)

- если меню не сработало, fallback: отправка space в приложение

Это по сути “двухконтурная система”: сначала самый надёжный путь (меню), затем резервный (клавиша).


В следующем посте покажу базовый код HTTP-сервера в Hammerspoon и структуру эндпоинтов.


Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#macOSAutomation@annsFlow

💻 annFlow
Post #85 39
Window Manager в Hammerspoon

Оконный менеджмент в macOS часто сбоит на уровне деталей: фокус, анимации и внутренние состояния приложений. В моем сетапе с Hammerspoon окна управляются напрямую через API Hammerspoon (работа с объектом окна и его геометрией, а не через UI-состояния), поэтому результат получается более стабильным и предсказуемым.


Базовый интерфейс управления окнами у меня построен на слое Ctrl + Option + клавиша. Это быстрые, мышечно-запоминаемые команды:

- Ctrl+Option+A прижимает окно к левому краю (левая половина)

- Ctrl+Option+D прижимает к правому краю (правая половина)

- Ctrl+Option+S ставит окно в центр (и т.д.)


Таких сочетаний много: под каждую “логичную” кнопку заведено своё действие для перемещения или изменения размеров окна. Для скорости работы на Mac это критично: окно перестаёт быть объектом, который “нужно руками расставлять”, и становится состоянием, которое вызывается одной командой.


1) Нулевая анимация

hs.window.animationDuration = 0


2) Два способа позиционирования

2.1) moveToUnit(...)

Надёжный тайлинг в долях экрана (0..1): левый/правый полукран, четверти и т.п. Устойчив к разным экранам и Dock/Menu Bar.

2.2) setFrame(...)

Когда нужна конкретная зона: колонка 25%, нижняя четверть, центрирование и т.д. Пример “правая колонка 25%” из конфига:


local win = hs.window.focusedWindow()
local screenFrame = win:screen():frame()
win:setFrame({
x = screenFrame.x + screenFrame.w * 0.75,
y = screenFrame.y,
w = screenFrame.w * 0.25,
h = screenFrame.h
})


Просто: берётся рабочая область экрана и окну задаётся прямоугольник, где ширина 25%, а x начинается с 75% (то есть край справа).

3) Toggle “разложить / вернуть”


Перед тайлингом сохраняется исходный frame в windowStates, затем можно одним действием вернуть окно “как было”. Это делает раскладки обратимыми.

4) Сетка окон приложения + возврат


Сценарий собирает окна текущего приложения, раскладывает сеткой по экрану, повторным запуском восстанавливает исходные позиции. Быстро наводит порядок и так же быстро возвращает обратно.


5) Перенос между мониторами


Перемещение на соседний экран по топологии: west/east/north/south. Это удобнее, чем “монитор №2”, потому что работает по реальному расположению экранов.

6) Микро-подстройка

Шаговые сдвиги (в конфиге шаг 100px) закрывают кейс “почти идеально, но нужно чуть подвинуть”.


Почему это надёжнее системных хоткеев и части готовых решений

Системные/некоторые сторонние команды часто завязаны на UI-состояние (фокус, анимации, “успел ли апп”). Здесь всё детерминированно: Hammerspoon получает окно, вычисляет целевую геометрию и применяет её напрямую (moveToUnit / setFrame / moveToScreen), при необходимости сохраняя состояние (windowStates). Плюс Hammerspoon в том, что я могу собирать собственные команды под себя и задавать в них любые параметры: точные размеры и координаты, привязку к экрану, шаги смещения, условия, сохранение/восстановление состояния и любые дополнительные характеристики, которые нужны именно моему workflow.

В следующем посте: мой подход к управлению медиа через Hammerspoon с задержками и fallback.

Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#macOSAutomation@annsFlow

💻 annFlow
  • 👍 1
Post #84 39
Hammerspoon это инструмент, который превращает macOS в настраиваемую среду под конкретный workflow. По сути, это лёгкая надстройка, которая слушает события клавиатуры и системы и выполняет действия, описанные кодом на Lua. Без лишнего UI и “мастеров настроек”: поведение задаётся напрямую, в виде правил и сценариев.


Главная ценность Hammerspoon в том, что он работает не как “ещё один ремаппер”, а как движок логики:

Запуск/фокус приложений, окна (позиции/раскладки/мониторы), навигация по окнам, медиа-контроль, системные действия, логика (проверки/задержки/фолбэки).

В моей практике это выглядит так:

- Caps Lock (мой “суперклавишный” слой): Caps Lock + любая цифра/клавиша у меня привязаны к запуску или фокусу конкретных приложений. Это основной способ перемещаться по системе без Dock и поиска.

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

- BackTick-layer: удержание backtick завязано на Leader Key: это вход в подслои, где, например, отдельные клавиши открывают нужные папки в Finder или конкретные проекты в ChatGPT. Я описывал об этом ранее тут.

Технически всё это описывается в конфигурации init.lua. Стандартный путь:

~/.hammerspoon/init.lua


Конфиг удобно хранить как код: версионировать, переносить на другие устройства, развивать поэтапно. В моём сетапе конфигурация синхронизируется через iCloud (через симлинк): система видит стандартный путь ~/.hammerspoon/, но фактически конфиг лежит в папке iCloud Drive, поэтому одинаковое поведение доступно на всех устройствах.

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

Как выглядит запуск приложения в Hammerspoon

Базовая конструкция в конфиге выглядит так:


hs.hotkey.bind(hyper, "i", function()
hs.application.open("путь к приложению")
end)


- hs.hotkey.bind(...) регистрирует сочетание клавиш

- hyper это набор модификаторов (Hyper-слой)

- "i" это клавиша-триггер внутри слоя

- function() ... end это действие, которое выполняется при нажатии

- hs.application.open(...) открывает приложение по точному пути

Альтернативный вариант для многих задач: hs.application.launchOrFocus("AppName").


В следующем посте расскажу про Window Manager в Hammerspoon.


Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#macOSAutomation@annsFlow

💻 annFlow
  • 🔥 2
  • ❤‍🔥 1
  • ❤ 1
Post #82 40
ru_option_punct.json1003 B
4) RU-раскладка: точечные правила только для русского набора

У русскоязычных пользователей macOS есть типовая проблема: в стандартной RU-раскладке запятая и точка находятся на Shift+6 и Shift+7. При активном письме это неудобно и замедляет набор.

Самый распространённый обходной путь, который я видел, это перейти в системных настройках на раскладку Russian PC. Там пунктуация размещена практичнее. Но цена такого решения для меня слишком высокая: меняется поведение части символов, и в том числе ломается привычная предсказуемость со знаком вопроса между EN и RU.

Поэтому я оставил стандартную RU-раскладку и сделал точечное исправление через Karabiner. Правило включается только в русском input source и не трогает английскую раскладку:

- Option + запятая печатает ,

- Option + точка печатает .


В результате , и . в RU оказываются в тех же позициях, что и в EN, но с удержанием Option. Для моего набора это удобнее, чем переход на Russian PC: пунктуация становится доступной, а остальная логика русской раскладки остаётся неизменной.

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

В следующем посте расскажу, как эти сигналы из Karabiner связаны с Hammerspoon и как я превращаю их в конкретные действия.

В следующем посте покажу мой базовый каркас конфига Hammerspoon.

Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#macOSAutomation@annsFlow

💻 annFlow
  • 🤝 3
  • 👍 1
  • 🤔 1
Post #81 38
grave_hold_f17.json485 B
3) backtick hold = F17

По той же логике у меня есть второй слой на backtick: тап печатает символ, а удержание отдаёт виртуальный F17. Этот слой я использую как “вход” в дополнительную иерархию команд через Leader Key.

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

Например, backtick (hold) + F у меня означает Finder. После этого ближайшие клавиши на клавиатуре становятся быстрыми шорткатами для открытия нужных мне папок в Finder. Это превращает навигацию по файловой структуре в пару нажатий, без поиска по боковой панели и без ручного кликанья.

Точно так же у меня сделан подслой для ChatGPT: backtick (hold) + G. В этом режиме ближайшие клавиши открывают нужный проект в ChatGPT. По сути, это “меню проектов под пальцами”, которое вызывается моментально и работает предсказуемо.

Такой второй слой удобен тем, что он не смешивает всё в одну плоскость: один слой у меня про повседневную навигацию, а backtick-слой становится входом в более глубокие, тематические подслои (папки, проекты, инструменты).

В следующем посте покажу, как я точечно правлю RU-пунктуацию в Karabiner, не ломая раскладку.

Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#macOSAutomation@annsFlow

💻 annFlow
  • ✍ 2
  • ❤ 1
  • 🤯 1
  • 👌 1
Post #80 41
space_hold_f18.json402 B
2) Слой на Space: tap = пробел, hold = F18

Это мой базовый слой и один из самых удачных с точки зрения эргономики.


Логика простая: пробел остаётся пробелом, а удержание пробела превращается в “служебную клавишу режима” (в моём случае это виртуальный F18). Дальше Hammerspoon слушает F18 и включает слой команд.

Почему именно Space: он находится в центре клавиатуры и всегда под большим пальцем. Это максимально естественная “кнопка режима”, потому что большой палец почти всегда свободен и его удобно держать в удержании, не мешая печати.


Ключевое преимущество такого подхода в том, что он не ломает текстовый ввод. Я печатаю как обычно: быстрый тап по пробелу всегда даёт пробел. А когда нужно управление, я просто зажимаю Space и получаю временный слой команд, который живёт ровно пока удержание активно.

Самый важный нюанс здесь это тайминг удержания. Я несколько раз перенастраивал этот слой и переписывал JSON, пока не нашёл комфортное значение to_if_held_down_threshold_milliseconds: чтобы режим не включался случайно при печати, но включался мгновенно, когда нужно.


JSON с этой модификацией прикрепляю.

Дальше разберу, как я строю иерархию команд через F17.

Оглавление темы 📌
Навигация по проектам канала 📍
Все проекты 🎶

#macOSAutomation@annsFlow

💻 annFlow
  • ✍ 3
  • ⚡ 3
  • ❤ 2
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →