Я все ще використовую emacs. Чому?
Я програмую з 1994 року. Крім того, я священник Православної Церкви України. Так буває 😀 За 30+ років я працював з купою IDE, редакторів текстів і середовищ розробки, але Emacs залишається незмінним інструментом вже більше 20 років і планую використовувати його і надалі. Якщо це не підігріло ваш апетит, то листайте далі 😀
Колись давно +точилися баталії+ йшло змагання між мовами C та Pascal. В процесі розвитку Pascal роздвоївся на Delphi та FreePascal. Це не допомогло йому втримати аудиторію, але мені довелося працювати з ними обома. Дещо краще було з Delphi, де був такий-сякий текстовий редактор, багато бібліотек, які там називались компонентами. Але було сумно з інтеграцією зовнішніх засобів, наприклад, систем контролю версій, кодуваннями чи вкрай невдала компонентна модель. FreePascal мав гарний кросплатформений компілятор, який можна було прив'язати до make - системи компіляції та управління задачами. Але не було сторонніх бібліотек та текстового редактора. Спробувавши доступні редактори і не задовольнившись жодним я, нарешті, спробував Emacs. Попри високий поріг входу, він чудово працював з купою кодувань та мов та мав інтегровану роботу з make. Мої перші конфіги були жахливою копіпастою, але вони закрили мої потреби, а я закохався у такий спосіб налаштування програм. В результаті розробка на FreePascal значно спростилася.
Зрештою, я відмовився від Delphi/Pascal на користь Python та Emacs. Хоча там і не було пристойного автодоповнення, як у Delphi, та й, по-хорошому, не може бути дотепер, мова дозволяла зробити складні речі дуже швидко, тому десь за 3 місяці написав ядро системи CRUD з декларативним визначенням звітів та GUI, яке генерувалось на основі SQL-запитів. На Delphi мені знадобився б десь рік. Писав я під Windows, але через її незручність я почав працювати на Linux.
Пройшли роки і Linux ставав тільки кращим, особливо у плані програмування. Python як не викликав у мене захвату, так не викликає і досі, а Java виявилась чудовою. Ці два інструменти стали основними засобами розробки на роки. За цей час з'являлись, сяяли і зникали редактори коду та IDE, я експериментував з купою мов та різними напрямками в розробці, але Emacs завжди був поруч, як той швейцарський ніж:
- потрібно зайти на віддалену машину та щось написати - а що краще за emacs це вміє?
- хайп навколо нової мови чи поправити якийсь конфігураційний файл — в Emacs вже є мінімальний робочий режим.
- потрібно написати статтю, документацію чи спланувати роботу - org-mode чудовий. Власне, в ньому і пишеться ця стаття.
- працюєш з різним освітленням на різних моніторах — emacs просто підлаштується і під це.
У 2021-му році моя робота змістилась в сторону Internet Of Things (IoT) і моїм основним, бо є GPIO[fn:1], та улюбленим, бо можна покласти в кишеню, інструментом, став Raspberry Pi. А у 2022 році росія розпочала широкомасштабне вторгнення і я поїхав у інше місце, подалі від стрілянини. Інтернет там був поганий, не найкращі умови для віддаленої роботи. І тут Emacs розкрив свій потенціал: він досить швидко працює як на слабенькому Raspberry Pi так і віддалено по ssh, отже можна мати засіб розробки прямо на пристрої, який ти розробляєш!
Досить скоро росіяни почали виносити енергетичну інфраструктуру і тут проявилися переваги Raspberry: він не тільки маленький, його, через перехідник, можна заживити і від автомобільного акумулятора. Ці нетипові, для сучасного програміста, умови прояснили для мене багато речей, про які я знав, використовував, але які були, все-таки філософією, а не практичним керівництвом[fn:2].
Але досить лірики, не за тим ви відкривали статтю. Поговорімо, краще про ⬇️
** Текстові редактори vs IDE
Колись давно, коли здавалось, що життя таке ж нескінченне, як Чумацький шлях, я приймав участь у навколокомп'ютерних срачах, холіварах. Срались про те, +яке пиво смачніше+ що краще: вінда, лінукс, чи фрібсд; яка мова крутіша і, обов'язково, яка IDE краща і чи, взагалі, потрібен в наш час текстовий редактор[fn:3]. В багатьох типових випадках IDE буде кращою за просто текстовий редактор, і я вписав Ідею в свій робочий процес та й в Emacs я намагаюся прикрутити функції IDE, якщо вони просто прикручуються або не тормозять. Але, на мою думку, **прорив у функціональності досягається вдалою комбінацією невеликої кількості простих рішень**, а не одним комбайном. І саме в цьому контексті текстовий редактор стає корисним, якщо ви слідуєте концепції ⬇️
** Unix Way
Напевне, всі програмісти чули про це. Це принцип організації роботи складних систем, побудований на комбінації простих рішень. Ці принципи були сформовані в часи, коли комп'ютери були ще великими, дорогими, повільними, а заводити інформацію в них було значно складніше, ніж зараз. Але тоді писався чудовий софт, який робив складні речі і який зараз би вимагав на порядки потужнішого обладнання та засобів розробки. Тоді це були саме принципи розробки, методичка, а не шанована, але безплідна філософія! IoT-ня та війна помістили мене в такі умови, коли я теж працював в умовах, наближених до тих, де було сформульовано Unix Way.
З однієї сторони, це фізична організація робочого процесу: у тебе може не бути зручної клавіатури, великого монітора чи швидкої мережі. Зрештою, я старий став, лінивий і на додачу до інструментів перти на об'єкт ще й ноутбук мені ліньки та й жалко, як десь гепнеш. От я і працюю з мобільника.
Коли тобі повільно і незручно, то ти дуже добре розумієш, що система повинна бути осяжною. Навіть в комфортному офісі, чим менше коду, тим краще. Тому думай, не про те, щоб додати фічі, а щоб побудувати мінімалістичне ядро, до якого, за потреби підключити потрібну функціональність. Якщо програма на C, то потрібно бути уважнішим, бо легко додати багів. Якщо функція більше 15 рядків, думай над дизайном. Тому і сказано: Do One Thing And Do It Well. Саме з цього принципа виходить текстовий вихлоп, який легко завернути в логи, просто перевірити та, базуючись на ньому, поєднати програми, які легко замінити, якщо що. І важливою частиною роботи стає ⬇️
** Текстовий редактор
Найбільшою відміною текстового редактора від IDE є його простота. Найперше, що він має вміти — це швидко запуститись, підсвітити код, зробити швидкий пошук-заміну тексту, з мінімумом рухів запустити програму, побачити результат і повернутись до коду. На невеликій програмі чи конфігові не потрібно складного автодоповнення, дебагера або рефакторига - лог прекрасен, а весь Unix Way будується навколо простоти і мінімалізму. Та і в контролер ти багато коду не запхнеш[fn:4]. Такі редактори, як nano, mcedit чи vi добре вписуються в цю концепцію. Через реактивність та простоту їх зручно зробити типовим редактором в системі. Але один редактор, здається, не відповідає вимогам і це ⬇️
** Emacs
Якщо бути чесним, в Emacs із коробки немає хорошого текстового редактора, навіть прийнятних налаштувань теж немає. Він поставляється з комбінаціями клавіш, які неактуальні ще з початку 80-х, бо тих клавіатур вже немає, але сам Emacs залишається корисним та актуальним. Бо Emacs - це не редактор, це система. Він був створений під сильним впливом Lisp-машин і є Lisp-середовищем з усіма плюшками і недоліками цього підходу: власне, мовою, що схожа на Common Lisp, інтерактивною розробкою, конфігурацією системи на цій мові, текстовим та графічним інтерфейсом на вибір, швидким стартом і щільною взаємодією із системою на якій він крутиться. Все це породило купу розширень, які дозволяють виконувати широкий спектр задач. Звісно, купа редакторів та всі IDE вміють взаємодіяти з операційною системою, але GUI не дає добратись до них по ssh.
Складні речі краще налаштовувати в текстовому файлі, а конфігурація IDE здійснюється через вікно налаштувань, де легко щось запороти. Мені стає погано коли потрібно лізти в налаштування Ідеї[fn:5]. Такі конфіги важко розповсюдити деінде, доводиться витягати його з архіва, заливати а github, на іншій машині його підкидати. Не факт, що пройде гладно через сумісність версій IDE і формату запису. API IDE, як правило, складніше, і застосувати розширення поза межами ком'пютера, де вони розроблялися довше. Тож мати однакові налаштування IDE скрізь, де ти працюєш значно складніше. Перевага Emacs - це текстовий конфіг, зроби git pull на новій машині — і отримаєш актуальний стан свого Emacs скрізь!
І є те, чого я не спостерігав ніде більше: це середовище, яким надихалися тайлові оболонки. Можна розділити вікно на кілька частин і бачити кілька файлів або різні частини одного файлу одночасно! Саме поєднання цих принципів робить Emacs актуальним сьогодні.
** Робочий процес
Щоб почати я зазвичай розпаковую архів з налаштуваннями Emacs. Там вже всі потрібні розширення, і основа у вигляді історії git. Далі git pull і все працює. Далі вступає в гру система зборки — make. За допомогою цієї утиліти дуже просто автоматизувати весь процес розробки більшості проектів починаючи від ініціалізації, продовжуючи керуванням залежностями, зборкою, тестуванням і деплоєм проекта. І по ходу діла описувати та відслідковувати роботу в Readme.org. Навіть для Java, хоча я і розробляю все в IDE, є корисним завернути maven в make, щоб щось віддалено швиденько поправити та зробити make deploy. Єдине, де такий підход не спрацював, це розробка під Android.
Останнім часом я часто став працювати з телефону, прийоми роботи з яким відмінні від роботи за комп'ютером. При роботі з комп'ютером у мене відкрито кілька терміналів між якими легко перемикатись. Там зручно лазити по каталогам та переглядати файли. На телефоні незручне перемикання між вікнами. На щастя, в Emacs є свій файловий менеджер - dired. Але з коробки він незручний все незручно відсортовано та перемішано, то я написав розширення для сортування та попереднього перегляду. Тепер не потрібно тримати окремі консолі для зручного перегляду та редагування файлів.

Варто сказати, що потреби допилювати dired дуже довго не було, тому, що в Emacs дуже зручно відкривати файли, особливо якщо налаштовано ⬇️
** Completion
В Emacs може не бути просунутого доповнення для певної мови, але є два режими, які часто використовуються: company-mode провадить стандартне віконечко з варіантами та документацією. Але є і більш вдале рішення на базі окремого буферу — completion. Ось як у мене працюють обидва варіанти:

#+BEGIN_SRC elisp
(setq completions-format 'one-column)
(setq completions-header-format nil)
(setq completions-max-height 20)
(setq completion-auto-select nil)
(define-key minibuffer-mode-map (kbd "C-n") 'minibuffer-next-completion)
(define-key minibuffer-mode-map (kbd "C-p") 'minibuffer-previous-completion)
(define-key completion-in-region-mode-map (kbd "C-n") 'minibuffer-next-completion)
(define-key completion-in-region-mode-map (kbd "C-p") 'minibuffer-previous-completion)
(defun my/minibuffer-choose-completion (&optional no-exit no-quit)
(interactive "P")
(with-minibuffer-completions-window
(let ((completion-use-base-affixes nil))
(choose-completion nil no-exit no-quit))))
(define-key completion-in-region-mode-map (kbd "M-RET") 'my/minibuffer-choose-completion)
;; marginalia-mode
(marginalia-mode t)
(setq marginalia-field-width 50)
;; company-mode
(add-hook 'after-init-hook 'global-company-mode)
(global-set-key (kbd "\e\em") 'company-complete)
(company-quickhelp-mode)
(setq company-quickhelp-delay 3)
(setq company-idle-delay nil)
#+END_SRC
** Compilation
Буфер компіляції. Можна запустити компіляцію використовуючи make compile і, якщо є помилки цей буфер перенаправить вас в потрібне місце в коді. А можна перетворити його в монітор роботи програми, виконавши make run чи python mycode.py. Одним з налаштувань цього режиму є розумне розширення під вміст буфера. В звичайному стані цей буфер знаходиться в якби звернутому стані займаючи мінімум місця, а при перемиканні в нього адаптується під розмір тексту. такої поведінки я ще не бачив в IDE. Для мене це важливо, бо розумно розподіляє увагу між кодом і вихлопом, який мене цікавить і мінімізує кількість моїх рухів. Ось мій хак, щоб це запрацювало:
#+BEGIN_SRC elisp
(require 'popwin)
(popwin-mode 1)
(setq popwin:special-display-config
'(("*Help*" :position right :width 40 :stick t)
("*Messages*" :position bottom :height 10 :stick t)
("*compilation*" :position bottom :height 15 :stick t :regexp t)
("*eshell*" :position bottom :height 15 :stick t)
("^\\*helpful.*" :position right :width 0.4 :stick t :regexp t)
))
(defvar my-window-max-height 25
"Height of the window when it is active.")
(defvar my-window-min-height 10
"Minimum height of the window when it is not active.")
(defun my-adjust-popwin-windows ()
"Minimum height of the window when it is not active."
(dolist (win (window-list))
(let ((buf (window-buffer win)))
(when (and buf
(assoc (buffer-name buf) popwin:special-display-config))
(let ((config (cdr (assoc (buffer-name buf) popwin:special-display-config))))
(when (eq (plist-get config :position) 'bottom)
(if (eq (selected-window) win)
(with-selected-window win
(enlarge-window (- my-window-max-height (window-height))))
(with-selected-window win
(shrink-window (- (window-height) my-window-min-height))))))))))
(add-hook 'window-selection-change-functions
(lambda (_) (my-adjust-popwin-windows)))
#+END_SRC
** А як же без...
- дебагера? Режим compilation + системи логування чудові. Єдине, де я користуюсь дебагером, це Android. І то, тільки тому, що logcat став незручним.
- автодоповнення та навігації по коду? По-перше, таке-сяке автодоповнення для більшості мов є. Для Java все сумно, є тільки базове автодоповнення, але і з цим можна жити. Як не дивно, але без автодоповнення можна працювати, а от швидкість відгуку системи для мене важливіше. Навігація по коду теж багато для чого є, хоч на рівні language-mode, хоч на рівні тегів (у мене налаштовано автоматичне оновлення тегів при зберіганні).
- рефакторинг? Це той момент, коли потрібна IDE :)
- управління проектом? Emacs має кілька систем управління проектом, наприклад, projectile. Я не люблю ставити лишні розширення, тому використовую базовий .dir-locals.el
- системи контролю версій? Рідний vsc непоганий, magit чудовий.
** Що ще?
Потенціал Emacs Lisp, мови розширень Emacs, недооцінений. Це потужна та зріла мова, а Emacs надає купу зручностей для неї: REPL, автодоповнення, гарну документацію, можливість взаємодії з системою і, навіть, оболонку eshell, яка дозволяє змішати lisp з командами операційної системи. І купу бібліотек, які доступні у вигляді готових пакетів. Ви можете використовувати її не тільки для розширень, а і для купи разових задач, не вартих навіть окремого файла для зберігання, як то скачати дані, розпарсити їх і т.і. В принципі там є все, щоб крутити якісь сервіси з можливістю оновлення коду без перезапуска.
*** Приклад разової задачі
Стандартна задача аналізу лога. У мене є регулятор, який читає значення температури та вологості. В процесі розробки я пишу лог який я і хочу проаналізувати. Я запускаю make run і в буфері Compilation мені виводиться щось на кшталт:
#+BEGIN_SRC
t 10
t 12
t 18
h 80
t 25
t 30
t 33
h 77
t 31
t 28
#+END_SRC
В Emacs є буфер *scratch* для виконання lisp-кода. От його я і використовую для разових задач. Я фільтрую значення >= 30, щоб подивитись, як відпрацьовує регулятор. Тут функція my/with-compilation-buffer передає вміст буфера *compilation* в my/filter-compilation-temp.
#+BEGIN_SRC elisp
(defun my/with-compilation-buffer (handler)
"Call HANDLER with the lines of the *compilation* buffer as a list."
(with-current-buffer "*compilation*"
(funcall handler (split-string (buffer-string) "\n"))))
(defun my/filter-compilation-temp (lines)
"Filter LINES starting with 't' where value >= 30 and print to stdout."
(interactive)
(let ((results nil))
(dolist (line lines)
(when (and (stringp line)
(string-match "^t \\([0-9]+\\)$" line)
(>= (string-to-number (match-string 1 line)) 30))
(push line results)))
(if results
(with-temp-buffer
(dolist (result results)
(insert (format "%s\n" result)))
(princ (buffer-string) t)))))
#+END_SRC
Залишилось лише викликати (my/with-compilation-buffer 'my/filter-compilation-temp). Це можна зробити в чомусь, що підтримує виклик функції: консолі ielm, прямо тут, в *scratch* або в інтерактивному виклику натиснувши M-:
Але саме цікавіше, що в Emacs вбудовано команну оболонку, eshell. Вона дозволяє вивести результат у змінну чи передати конвеєром
#+BEGIN_SRC
eshell> (my/with-compilation-buffer 'my/filter-compilation-temp)
t 30
t 33
t 31
eshell> (my/with-compilation-buffer 'my/filter-compilation-temp) | wc -l
3
#+END_SRC
Нажаль, eshell ще не навчився приймати вхідний текст через пайп, але можна вивести у змінну echo "Hello eshell" | wc -c > #'myvar.
** Закінчення
Коли ти слідкуєш за простотою системи, складні інструменти і великі ресурси вже не критичні[fn:6]. Звісно, в мене є значно потужніше залізо, ніж телефон чи Raspberry Pi, але саме поєднання Linux, make та Emacs дозволяє ефективно писати код та організовувати процеси навколо нього. Звісно, є те, що не буває простим, в моєму випадку це були розробка під mobile або бухгалтерія, тут Unix Way не буде працювати.

Варто сказати, що я находжу Emacs оптимальним, але є ще два популярні інструменти, які роблять приблизто теж саме. Це Vim та VSCode. Обидва мають приблизно ті ж можливості: складніші за тупий редактор, але недотягують до IDE, всі троє налаштовуються, мають мову розширень. Головним недоліком Vim є те, що він псує текст ;) і мова конфігурації гірша за Lisp. А до VSCode не доберешся по ssh і він все-таки повільніший, а швидкість відгуку редактора для мене залишається вагомим аргументом. Заради цього я готовий пожертвувати просунутим автокомплітом. Всі три редактори підтримують сучасні мови через lsp-mode, що забезпечує автодоповнення та навігацію по коду для Python чи JavaScript, наближаючи його до можливостей IDE, але втрачається простота і швидкість, які я так ціню.
Тут я згадав лише основні моменти, чому Emacs актуальний для мене, а по багатьом з них можна було б написати по статті. Для когось цей підхід не відкриє нічого нового, а хтось, можливо, відкриє для себе чудові пласти програмістської культури. Зрештою, вагомою частиною програмування є фан. UNIX, Lisp, Emacs і все довколо них розробляли дуже талановиті і, напевно, геніальні люди. Атмосфера вільних, творчих, сміливих та рок-н-рольних 70-х досі присутня в цих інструментах, а винаходи того часу досі не втрачають актуальності. Якщо ви ще не торкнулись цього, спробуйте, виконайте
#+BEGIN_SRC
sudo apt install emacs
#+END_SRC
* Footnotes
[fn:1] [[https://en.wikipedia.org/wiki/General-purpose_input/output][GPIO]] - інтерфейс для підключення датчиків
[fn:2] Як же це схоже на ситуацію в християнстві!
[fn:3] Звісно, отримати відповідь чи варто вкладатись в ту чи іншу технологію такі срачі не можуть, дешевше і швидше попробувати зробити щось на кожній з них і вирішити для себе що, де і за яких умов краще.
[fn:4] Ладно, тепер це вже неактуально, python туди запхали ;)
[fn:5] Якщо налаштовувати Emacs через вікно налаштувань, стає ще гірше
[fn:6] Це перегукується з практикою християнства, де одним з побічних ефектів є перемикання з володіння на буття. В цей час якби самі-по-собі відпадають купа речей, звичок, намірів і людей. І от таке простіше життя приносить радість. Але це вже інша історія.
Я програмую з 1994 року. Крім того, я священник Православної Церкви України. Так буває 😀 За 30+ років я працював з купою IDE, редакторів текстів і середовищ розробки, але Emacs залишається незмінним інструментом вже більше 20 років і планую використовувати його і надалі. Якщо це не підігріло ваш апетит, то листайте далі 😀
Колись давно +точилися баталії+ йшло змагання між мовами C та Pascal. В процесі розвитку Pascal роздвоївся на Delphi та FreePascal. Це не допомогло йому втримати аудиторію, але мені довелося працювати з ними обома. Дещо краще було з Delphi, де був такий-сякий текстовий редактор, багато бібліотек, які там називались компонентами. Але було сумно з інтеграцією зовнішніх засобів, наприклад, систем контролю версій, кодуваннями чи вкрай невдала компонентна модель. FreePascal мав гарний кросплатформений компілятор, який можна було прив'язати до make - системи компіляції та управління задачами. Але не було сторонніх бібліотек та текстового редактора. Спробувавши доступні редактори і не задовольнившись жодним я, нарешті, спробував Emacs. Попри високий поріг входу, він чудово працював з купою кодувань та мов та мав інтегровану роботу з make. Мої перші конфіги були жахливою копіпастою, але вони закрили мої потреби, а я закохався у такий спосіб налаштування програм. В результаті розробка на FreePascal значно спростилася.
Зрештою, я відмовився від Delphi/Pascal на користь Python та Emacs. Хоча там і не було пристойного автодоповнення, як у Delphi, та й, по-хорошому, не може бути дотепер, мова дозволяла зробити складні речі дуже швидко, тому десь за 3 місяці написав ядро системи CRUD з декларативним визначенням звітів та GUI, яке генерувалось на основі SQL-запитів. На Delphi мені знадобився б десь рік. Писав я під Windows, але через її незручність я почав працювати на Linux.
Пройшли роки і Linux ставав тільки кращим, особливо у плані програмування. Python як не викликав у мене захвату, так не викликає і досі, а Java виявилась чудовою. Ці два інструменти стали основними засобами розробки на роки. За цей час з'являлись, сяяли і зникали редактори коду та IDE, я експериментував з купою мов та різними напрямками в розробці, але Emacs завжди був поруч, як той швейцарський ніж:
- потрібно зайти на віддалену машину та щось написати - а що краще за emacs це вміє?
- хайп навколо нової мови чи поправити якийсь конфігураційний файл — в Emacs вже є мінімальний робочий режим.
- потрібно написати статтю, документацію чи спланувати роботу - org-mode чудовий. Власне, в ньому і пишеться ця стаття.
- працюєш з різним освітленням на різних моніторах — emacs просто підлаштується і під це.
У 2021-му році моя робота змістилась в сторону Internet Of Things (IoT) і моїм основним, бо є GPIO[fn:1], та улюбленим, бо можна покласти в кишеню, інструментом, став Raspberry Pi. А у 2022 році росія розпочала широкомасштабне вторгнення і я поїхав у інше місце, подалі від стрілянини. Інтернет там був поганий, не найкращі умови для віддаленої роботи. І тут Emacs розкрив свій потенціал: він досить швидко працює як на слабенькому Raspberry Pi так і віддалено по ssh, отже можна мати засіб розробки прямо на пристрої, який ти розробляєш!
Досить скоро росіяни почали виносити енергетичну інфраструктуру і тут проявилися переваги Raspberry: він не тільки маленький, його, через перехідник, можна заживити і від автомобільного акумулятора. Ці нетипові, для сучасного програміста, умови прояснили для мене багато речей, про які я знав, використовував, але які були, все-таки філософією, а не практичним керівництвом[fn:2].
Але досить лірики, не за тим ви відкривали статтю. Поговорімо, краще про ⬇️
** Текстові редактори vs IDE
Колись давно, коли здавалось, що життя таке ж нескінченне, як Чумацький шлях, я приймав участь у навколокомп'ютерних срачах, холіварах. Срались про те, +яке пиво смачніше+ що краще: вінда, лінукс, чи фрібсд; яка мова крутіша і, обов'язково, яка IDE краща і чи, взагалі, потрібен в наш час текстовий редактор[fn:3]. В багатьох типових випадках IDE буде кращою за просто текстовий редактор, і я вписав Ідею в свій робочий процес та й в Emacs я намагаюся прикрутити функції IDE, якщо вони просто прикручуються або не тормозять. Але, на мою думку, **прорив у функціональності досягається вдалою комбінацією невеликої кількості простих рішень**, а не одним комбайном. І саме в цьому контексті текстовий редактор стає корисним, якщо ви слідуєте концепції ⬇️
** Unix Way
Напевне, всі програмісти чули про це. Це принцип організації роботи складних систем, побудований на комбінації простих рішень. Ці принципи були сформовані в часи, коли комп'ютери були ще великими, дорогими, повільними, а заводити інформацію в них було значно складніше, ніж зараз. Але тоді писався чудовий софт, який робив складні речі і який зараз би вимагав на порядки потужнішого обладнання та засобів розробки. Тоді це були саме принципи розробки, методичка, а не шанована, але безплідна філософія! IoT-ня та війна помістили мене в такі умови, коли я теж працював в умовах, наближених до тих, де було сформульовано Unix Way.
З однієї сторони, це фізична організація робочого процесу: у тебе може не бути зручної клавіатури, великого монітора чи швидкої мережі. Зрештою, я старий став, лінивий і на додачу до інструментів перти на об'єкт ще й ноутбук мені ліньки та й жалко, як десь гепнеш. От я і працюю з мобільника.
Коли тобі повільно і незручно, то ти дуже добре розумієш, що система повинна бути осяжною. Навіть в комфортному офісі, чим менше коду, тим краще. Тому думай, не про те, щоб додати фічі, а щоб побудувати мінімалістичне ядро, до якого, за потреби підключити потрібну функціональність. Якщо програма на C, то потрібно бути уважнішим, бо легко додати багів. Якщо функція більше 15 рядків, думай над дизайном. Тому і сказано: Do One Thing And Do It Well. Саме з цього принципа виходить текстовий вихлоп, який легко завернути в логи, просто перевірити та, базуючись на ньому, поєднати програми, які легко замінити, якщо що. І важливою частиною роботи стає ⬇️
** Текстовий редактор
Найбільшою відміною текстового редактора від IDE є його простота. Найперше, що він має вміти — це швидко запуститись, підсвітити код, зробити швидкий пошук-заміну тексту, з мінімумом рухів запустити програму, побачити результат і повернутись до коду. На невеликій програмі чи конфігові не потрібно складного автодоповнення, дебагера або рефакторига - лог прекрасен, а весь Unix Way будується навколо простоти і мінімалізму. Та і в контролер ти багато коду не запхнеш[fn:4]. Такі редактори, як nano, mcedit чи vi добре вписуються в цю концепцію. Через реактивність та простоту їх зручно зробити типовим редактором в системі. Але один редактор, здається, не відповідає вимогам і це ⬇️
** Emacs
Якщо бути чесним, в Emacs із коробки немає хорошого текстового редактора, навіть прийнятних налаштувань теж немає. Він поставляється з комбінаціями клавіш, які неактуальні ще з початку 80-х, бо тих клавіатур вже немає, але сам Emacs залишається корисним та актуальним. Бо Emacs - це не редактор, це система. Він був створений під сильним впливом Lisp-машин і є Lisp-середовищем з усіма плюшками і недоліками цього підходу: власне, мовою, що схожа на Common Lisp, інтерактивною розробкою, конфігурацією системи на цій мові, текстовим та графічним інтерфейсом на вибір, швидким стартом і щільною взаємодією із системою на якій він крутиться. Все це породило купу розширень, які дозволяють виконувати широкий спектр задач. Звісно, купа редакторів та всі IDE вміють взаємодіяти з операційною системою, але GUI не дає добратись до них по ssh.
Складні речі краще налаштовувати в текстовому файлі, а конфігурація IDE здійснюється через вікно налаштувань, де легко щось запороти. Мені стає погано коли потрібно лізти в налаштування Ідеї[fn:5]. Такі конфіги важко розповсюдити деінде, доводиться витягати його з архіва, заливати а github, на іншій машині його підкидати. Не факт, що пройде гладно через сумісність версій IDE і формату запису. API IDE, як правило, складніше, і застосувати розширення поза межами ком'пютера, де вони розроблялися довше. Тож мати однакові налаштування IDE скрізь, де ти працюєш значно складніше. Перевага Emacs - це текстовий конфіг, зроби git pull на новій машині — і отримаєш актуальний стан свого Emacs скрізь!
І є те, чого я не спостерігав ніде більше: це середовище, яким надихалися тайлові оболонки. Можна розділити вікно на кілька частин і бачити кілька файлів або різні частини одного файлу одночасно! Саме поєднання цих принципів робить Emacs актуальним сьогодні.
** Робочий процес
Щоб почати я зазвичай розпаковую архів з налаштуваннями Emacs. Там вже всі потрібні розширення, і основа у вигляді історії git. Далі git pull і все працює. Далі вступає в гру система зборки — make. За допомогою цієї утиліти дуже просто автоматизувати весь процес розробки більшості проектів починаючи від ініціалізації, продовжуючи керуванням залежностями, зборкою, тестуванням і деплоєм проекта. І по ходу діла описувати та відслідковувати роботу в Readme.org. Навіть для Java, хоча я і розробляю все в IDE, є корисним завернути maven в make, щоб щось віддалено швиденько поправити та зробити make deploy. Єдине, де такий підход не спрацював, це розробка під Android.
Останнім часом я часто став працювати з телефону, прийоми роботи з яким відмінні від роботи за комп'ютером. При роботі з комп'ютером у мене відкрито кілька терміналів між якими легко перемикатись. Там зручно лазити по каталогам та переглядати файли. На телефоні незручне перемикання між вікнами. На щастя, в Emacs є свій файловий менеджер - dired. Але з коробки він незручний все незручно відсортовано та перемішано, то я написав розширення для сортування та попереднього перегляду. Тепер не потрібно тримати окремі консолі для зручного перегляду та редагування файлів.

Варто сказати, що потреби допилювати dired дуже довго не було, тому, що в Emacs дуже зручно відкривати файли, особливо якщо налаштовано ⬇️
** Completion
В Emacs може не бути просунутого доповнення для певної мови, але є два режими, які часто використовуються: company-mode провадить стандартне віконечко з варіантами та документацією. Але є і більш вдале рішення на базі окремого буферу — completion. Ось як у мене працюють обидва варіанти:

#+BEGIN_SRC elisp
(setq completions-format 'one-column)
(setq completions-header-format nil)
(setq completions-max-height 20)
(setq completion-auto-select nil)
(define-key minibuffer-mode-map (kbd "C-n") 'minibuffer-next-completion)
(define-key minibuffer-mode-map (kbd "C-p") 'minibuffer-previous-completion)
(define-key completion-in-region-mode-map (kbd "C-n") 'minibuffer-next-completion)
(define-key completion-in-region-mode-map (kbd "C-p") 'minibuffer-previous-completion)
(defun my/minibuffer-choose-completion (&optional no-exit no-quit)
(interactive "P")
(with-minibuffer-completions-window
(let ((completion-use-base-affixes nil))
(choose-completion nil no-exit no-quit))))
(define-key completion-in-region-mode-map (kbd "M-RET") 'my/minibuffer-choose-completion)
;; marginalia-mode
(marginalia-mode t)
(setq marginalia-field-width 50)
;; company-mode
(add-hook 'after-init-hook 'global-company-mode)
(global-set-key (kbd "\e\em") 'company-complete)
(company-quickhelp-mode)
(setq company-quickhelp-delay 3)
(setq company-idle-delay nil)
#+END_SRC
** Compilation
Буфер компіляції. Можна запустити компіляцію використовуючи make compile і, якщо є помилки цей буфер перенаправить вас в потрібне місце в коді. А можна перетворити його в монітор роботи програми, виконавши make run чи python mycode.py. Одним з налаштувань цього режиму є розумне розширення під вміст буфера. В звичайному стані цей буфер знаходиться в якби звернутому стані займаючи мінімум місця, а при перемиканні в нього адаптується під розмір тексту. такої поведінки я ще не бачив в IDE. Для мене це важливо, бо розумно розподіляє увагу між кодом і вихлопом, який мене цікавить і мінімізує кількість моїх рухів. Ось мій хак, щоб це запрацювало:
#+BEGIN_SRC elisp
(require 'popwin)
(popwin-mode 1)
(setq popwin:special-display-config
'(("*Help*" :position right :width 40 :stick t)
("*Messages*" :position bottom :height 10 :stick t)
("*compilation*" :position bottom :height 15 :stick t :regexp t)
("*eshell*" :position bottom :height 15 :stick t)
("^\\*helpful.*" :position right :width 0.4 :stick t :regexp t)
))
(defvar my-window-max-height 25
"Height of the window when it is active.")
(defvar my-window-min-height 10
"Minimum height of the window when it is not active.")
(defun my-adjust-popwin-windows ()
"Minimum height of the window when it is not active."
(dolist (win (window-list))
(let ((buf (window-buffer win)))
(when (and buf
(assoc (buffer-name buf) popwin:special-display-config))
(let ((config (cdr (assoc (buffer-name buf) popwin:special-display-config))))
(when (eq (plist-get config :position) 'bottom)
(if (eq (selected-window) win)
(with-selected-window win
(enlarge-window (- my-window-max-height (window-height))))
(with-selected-window win
(shrink-window (- (window-height) my-window-min-height))))))))))
(add-hook 'window-selection-change-functions
(lambda (_) (my-adjust-popwin-windows)))
#+END_SRC
** А як же без...
- дебагера? Режим compilation + системи логування чудові. Єдине, де я користуюсь дебагером, це Android. І то, тільки тому, що logcat став незручним.
- автодоповнення та навігації по коду? По-перше, таке-сяке автодоповнення для більшості мов є. Для Java все сумно, є тільки базове автодоповнення, але і з цим можна жити. Як не дивно, але без автодоповнення можна працювати, а от швидкість відгуку системи для мене важливіше. Навігація по коду теж багато для чого є, хоч на рівні language-mode, хоч на рівні тегів (у мене налаштовано автоматичне оновлення тегів при зберіганні).
- рефакторинг? Це той момент, коли потрібна IDE :)
- управління проектом? Emacs має кілька систем управління проектом, наприклад, projectile. Я не люблю ставити лишні розширення, тому використовую базовий .dir-locals.el
- системи контролю версій? Рідний vsc непоганий, magit чудовий.
** Що ще?
Потенціал Emacs Lisp, мови розширень Emacs, недооцінений. Це потужна та зріла мова, а Emacs надає купу зручностей для неї: REPL, автодоповнення, гарну документацію, можливість взаємодії з системою і, навіть, оболонку eshell, яка дозволяє змішати lisp з командами операційної системи. І купу бібліотек, які доступні у вигляді готових пакетів. Ви можете використовувати її не тільки для розширень, а і для купи разових задач, не вартих навіть окремого файла для зберігання, як то скачати дані, розпарсити їх і т.і. В принципі там є все, щоб крутити якісь сервіси з можливістю оновлення коду без перезапуска.
*** Приклад разової задачі
Стандартна задача аналізу лога. У мене є регулятор, який читає значення температури та вологості. В процесі розробки я пишу лог який я і хочу проаналізувати. Я запускаю make run і в буфері Compilation мені виводиться щось на кшталт:
#+BEGIN_SRC
t 10
t 12
t 18
h 80
t 25
t 30
t 33
h 77
t 31
t 28
#+END_SRC
В Emacs є буфер *scratch* для виконання lisp-кода. От його я і використовую для разових задач. Я фільтрую значення >= 30, щоб подивитись, як відпрацьовує регулятор. Тут функція my/with-compilation-buffer передає вміст буфера *compilation* в my/filter-compilation-temp.
#+BEGIN_SRC elisp
(defun my/with-compilation-buffer (handler)
"Call HANDLER with the lines of the *compilation* buffer as a list."
(with-current-buffer "*compilation*"
(funcall handler (split-string (buffer-string) "\n"))))
(defun my/filter-compilation-temp (lines)
"Filter LINES starting with 't' where value >= 30 and print to stdout."
(interactive)
(let ((results nil))
(dolist (line lines)
(when (and (stringp line)
(string-match "^t \\([0-9]+\\)$" line)
(>= (string-to-number (match-string 1 line)) 30))
(push line results)))
(if results
(with-temp-buffer
(dolist (result results)
(insert (format "%s\n" result)))
(princ (buffer-string) t)))))
#+END_SRC
Залишилось лише викликати (my/with-compilation-buffer 'my/filter-compilation-temp). Це можна зробити в чомусь, що підтримує виклик функції: консолі ielm, прямо тут, в *scratch* або в інтерактивному виклику натиснувши M-:
Але саме цікавіше, що в Emacs вбудовано команну оболонку, eshell. Вона дозволяє вивести результат у змінну чи передати конвеєром
#+BEGIN_SRC
eshell> (my/with-compilation-buffer 'my/filter-compilation-temp)
t 30
t 33
t 31
eshell> (my/with-compilation-buffer 'my/filter-compilation-temp) | wc -l
3
#+END_SRC
Нажаль, eshell ще не навчився приймати вхідний текст через пайп, але можна вивести у змінну echo "Hello eshell" | wc -c > #'myvar.
** Закінчення
Коли ти слідкуєш за простотою системи, складні інструменти і великі ресурси вже не критичні[fn:6]. Звісно, в мене є значно потужніше залізо, ніж телефон чи Raspberry Pi, але саме поєднання Linux, make та Emacs дозволяє ефективно писати код та організовувати процеси навколо нього. Звісно, є те, що не буває простим, в моєму випадку це були розробка під mobile або бухгалтерія, тут Unix Way не буде працювати.

Варто сказати, що я находжу Emacs оптимальним, але є ще два популярні інструменти, які роблять приблизто теж саме. Це Vim та VSCode. Обидва мають приблизно ті ж можливості: складніші за тупий редактор, але недотягують до IDE, всі троє налаштовуються, мають мову розширень. Головним недоліком Vim є те, що він псує текст ;) і мова конфігурації гірша за Lisp. А до VSCode не доберешся по ssh і він все-таки повільніший, а швидкість відгуку редактора для мене залишається вагомим аргументом. Заради цього я готовий пожертвувати просунутим автокомплітом. Всі три редактори підтримують сучасні мови через lsp-mode, що забезпечує автодоповнення та навігацію по коду для Python чи JavaScript, наближаючи його до можливостей IDE, але втрачається простота і швидкість, які я так ціню.
Тут я згадав лише основні моменти, чому Emacs актуальний для мене, а по багатьом з них можна було б написати по статті. Для когось цей підхід не відкриє нічого нового, а хтось, можливо, відкриє для себе чудові пласти програмістської культури. Зрештою, вагомою частиною програмування є фан. UNIX, Lisp, Emacs і все довколо них розробляли дуже талановиті і, напевно, геніальні люди. Атмосфера вільних, творчих, сміливих та рок-н-рольних 70-х досі присутня в цих інструментах, а винаходи того часу досі не втрачають актуальності. Якщо ви ще не торкнулись цього, спробуйте, виконайте
#+BEGIN_SRC
sudo apt install emacs
#+END_SRC
* Footnotes
[fn:1] [[https://en.wikipedia.org/wiki/General-purpose_input/output][GPIO]] - інтерфейс для підключення датчиків
[fn:2] Як же це схоже на ситуацію в християнстві!
[fn:3] Звісно, отримати відповідь чи варто вкладатись в ту чи іншу технологію такі срачі не можуть, дешевше і швидше попробувати зробити щось на кожній з них і вирішити для себе що, де і за яких умов краще.
[fn:4] Ладно, тепер це вже неактуально, python туди запхали ;)
[fn:5] Якщо налаштовувати Emacs через вікно налаштувань, стає ще гірше
[fn:6] Це перегукується з практикою християнства, де одним з побічних ефектів є перемикання з володіння на буття. В цей час якби самі-по-собі відпадають купа речей, звичок, намірів і людей. І от таке простіше життя приносить радість. Але це вже інша історія.
no subject
Date: 2025-08-21 10:34 pm (UTC)eglot є вбудований та вміє рудиментальне типу 'перейменувати змінну'
> Приклад разової задачі
для такого звичайний 'юнікс-вей' набагато є простіший і ним можна поділитися з бовдуром-колегою, який сидить ув vim
хоча приклад інтеграції з eshell є гарний
no subject
Date: 2025-08-22 05:21 am (UTC)Я намагаюсь уникати мовних серверів, бо це ускладнює тримати однакову конфігурацію на різних машинах та ОС. Крім того, мої експерименти з Java виявились глючними, простіше було використати netbeans.
Приклад з
awkпростіше, але тут не той обсяг статті, щоб качати відкись данні, парсити їх та пхати в БД. Якщо просто вивестиt >= 30в окремий буфер буде менше коду, але я демонстрував конвеєр вeshell. Крім того, кожен раз, як я хочу виконати аналіз, мені потрібно зберегтиcompilationу файл і натравити на ньогоawk...~, а так я просто викликаю потрібну функцію, навіть можу прописати її в.dir-locals.el`, projectile і т.і.no subject
Date: 2025-08-22 07:36 am (UTC)я просто виділяю блок щоб потім M-x shell-command-on-region
no subject
Date: 2025-08-22 07:47 am (UTC)Лог, як правило, великий. Особисто мені зручніше просто скормити весь буфер. Але то таке.
no subject
Date: 2025-08-22 06:07 pm (UTC)У eshell є недолік, вона може скормити вихлоп lisp-коду через пайп, а от прийняти на вхід функції — ні. отакої.
no subject
Date: 2025-08-22 09:35 pm (UTC)Але щодо автодоповнення - .... в наші дні копілот виконує велику частину роботи. За деякими замірами більше 50% нового коду написано не руками. (Хоча при цьому продуктивність підросла лише на 10% чи щось таке)
no subject
Date: 2025-08-23 03:29 am (UTC)У мене не так багато шорткатів, бо я їх не пам'ятаю, тому М-х. А далі комплетіон прєкрасєн.
Давно вже, особливо як з'явились stackoverflow та github.
І це не дивно, бо потрібно спочатку детально пояснити, потім вичитати, потім побачити баги, знову детально пояснити і так по колу.
А якщо код генерується в темі, де ти плаваєш, то то доводиться потім розбиратися в темі і забагованому коді.
no subject
Date: 2025-08-23 05:37 am (UTC)> 10%
Ну, це може також означати, що продуктивність - це не лише про написання коду.
> А якщо код генерується в темі...
Це працює не так.
От, позавчора. Дивлюсь - багато повторів. Пишу: "#define SET_IF_OK(" - а воно мені - хрясь - і дописує, що я хочу; буквально читає думки. Тоді по коду підійшов до одного шматка повтору - а воно мені - хрясь - пропонує замінити це і купу інших повторів на макрос, який "я" щойно ввів.
Відправляю коміт, тисну кнопку "autoreview" - а воно мені - хрясь - пояснило, що у двох місцях нюанси: було: static_cast у float, а тепер нема; а в іншому місці була додаткова умова, а тепер без.
Це не копіпаста зі стак оверфлоу, це зовсім інша взаємодія.
no subject
Date: 2025-08-23 05:57 am (UTC)М-х комплешн доволі розумний, підкаже якщо ти приблизно знаєш, що хочеш.
https://github.com/copilot-emacs/copilot.el є й таке, потрібно буде прикрутити.
no subject
Date: 2025-08-23 06:30 am (UTC)Відкриваєш віконечко діалогу, пишеш: "я чомусь отримую отаку-то відповідь від цього INNER JOIN (навіть без копіпасти; воно само здогадується, про який саме джойн йдеться). Який нюанс я пропустив?" І воно тобі пояснює.
no subject
Date: 2025-08-23 08:01 am (UTC)Я зрозумів аро що ви 😀, це і грок чудово вміє. Я трохи про інше, emacs має гарний prediction для М-х.
no subject
Date: 2025-08-23 06:13 am (UTC)Я трохи не про те. Вже давно купа коду не нами писана. Але продуктивність від того зростає не так сильно, як того хотілося б.
З усього, що я використовував, stackoverflow мені найбільше подобався: там був досвід живих людей і було повно ідей. Навіть замінусовані відповіді нерідко ставали в нагоді, бо давали їжу для роздумів.
no subject
Date: 2025-08-23 06:25 am (UTC)no subject
Date: 2025-08-23 08:02 am (UTC)😀