← На главную

SPEEM написал 1000 строк Lisp, чтобы заменить Xcode на Doom Emacs

03.06.2026 19:30 · hackernews

Автор iOS-приложения SPEEM полностью отказался от Xcode и выстроил весь рабочий процесс в Doom Emacs. Он не просто редактировал файлы в редакторе — он добился того, чтобы сборка, запуск симуляторов, установка приложения, стриминг логов и создание новых проектов делались из Emacs с помощью собственных хоткеев.

В основе лежат консольные утилиты Apple: xcodebuild для компиляции, xcrun simctl для управления симуляторами, sourcekit-lsp для автодополнения и swift-format для форматирования. Xcode, по сути, просто графическая обёртка над ними. Автор написал около 1000 строк Emacs Lisp (файл modules/ios.el), где связал всё это воедино.

Он настроил sourcekit-lsp так, чтобы тот брал исполняемый файл из активной Xcode, а не из CommandLineTools — иначе ломалась диагностика. Для этого пришлось вручную генерировать buildServer.json через xcode-build-server. Автор сделал так, чтобы этот файл создавался автоматически при первом открытии Swift-файла в проекте. Он также научил Emacs находить корень Xcode-проекта, даже если файл лежит глубоко в папках или внутри .xcodeproj.

Сборка выполняется командой SPC i b: сначала резолвятся зависимости Swift Package Manager, потом идёт xcodebuild с флагом COMPILER_INDEX_STORE_ENABLE=YES, чтобы заработал поиск перекрёстных ссылок через встроенный в sourcekit-lsp clangd. После успешной сборки LSP перезапускается, и диагностика обновляется мгновенно.

Запуск (SPC i s) устроен так: автор выбирает один или несколько симуляторов из своего списка (у него их восемь — для арабской и английской локалей, на iPad и iPhone). Каждый симулятор параллельно загружается, а его статус-бар автоматически приводится к «скриншотному» виду (9:41, полные полоски, без оператора). Затем приложение собирается, находится в DerivedData по дате модификации, извлекается Bundle ID, убивается старый процесс, устанавливается новый и запускается. Весь процесс идёт цепочкой через &&, и любая ошибка останавливает его и выводится в буфер *compilation*.

Для быстрой итерации по UI есть SPC i r — утилита entr пересобирает и переустанавливает приложение при каждом сохранении Swift-файла. Это замена hot-reload.

Логи идут из двух источников: stdout через simctl launch --console-pty и системный лог-стрим по имени процесса. Автор реализовал строгую фильтрацию: пропускаются только строки с его эмодзи-маркерами (, , ☁️), ошибками, варнингами и критическими сбоями. Весь шум от nw_connection, BackBoardServices и RunningBoard отбрасывается. Каждый симулятор получает отдельный буфер, их можно открывать рядом.

Создание нового проекта (SPC i n) генерирует YAML-файл для XcodeGen, запускает xcodegen generate, создаёт buildServer.json и открывает свежий ContentView.swift — LSP уже работает.

Автор честно признаёт, что Xcode всё ещё нужен для подписывания и Provisioning, редактирования Asset Catalog и Storyboards, профилирования в Instruments и загрузки в App Store Connect. Но это редкие операции, не входящие в ежедневный цикл.

Он предупреждает: если вы уже пользуетесь Emacs — эта схема даст вам полный контроль. Если нет — Xcode вполне адекватен, и переходить ради этого не стоит.

Читать оригинал →