воскресенье, 10 марта 2013 г.

Почему Emacs?

   На сегодняшний день основным инструментом программистов являются супер-технологичные IDE, помогающие выполнять процентов 80 ежедневной работы. Они умеют очень многое: автоматически дополнять код, отлаживать приложение, проводить сложный рефакторинг. Поэтому люди, пользующиеся такими старыми, с виду, инструментами, как Emacs, кажутся совсем уж чудаками. Но чудачество ли это в самом деле? И почему этот текстовый редактор до сих пор жив и все еще пользуется уважением?

  На моей предыдущей работе я программировал в основном J2EE-приложения. Мне очень нравились Eclipse и Jetbrains Idea, с их помощью мне удавалось за очень короткое время разрабатывать формочки, веб-сервисы и даже архитектуру приложения. Да я, в общем, не особо и задумывался о том, на чем писать. Все пишут в Eclipse -- ну и я тоже.

  А потом все резко изменилось. Мне предложили написать для платформы Android виртуальное казино. В приложении была всего одна формочка, зато масса логики, которую нужно было алгоритмизировать. Самым неприятным занятием было объявить в xml-файле 130 полей разметки на столе для ставок, затем их же проинициализировать в коде на java. Ни Eclipse, ни Idea уже ничем не могли мне в этом помочь, а выполнять эту работу вручную совсем не хотелось. Мои коллеги относились к этому проще. Они полагали, что раз платят, то нужно выполнять задание, даже если оно такое бездумное и скучное. Также полагал и мой менеджер. А как считаете вы?

  Еще во время учебы в школе я решил, что стану программистом. Я обажал каверзные задачки, участвовал в олимпиадах, мне очень нравилось составлять алгоритмы. Профессия программиста меня привлекала своей загадочностью. В то время мне казалось, что программисты занимаются невероятно сложной и очень интеллектуальной работой. Сейчас уже прошло примерно пятнадцать лет с тех пор, и я уже думаю несколько иначе.

  Чем же сегодня занимаются программисты на крупных фирмах, особенно на тех, которые практикуют "промышленное программирование"? Разве программированием? Большая часть времени уходит на всякую конфигурацию Spring или других фреймворков, генерацию заготовок кода при помощи IDE, добавление всяческих аннотаций для связи различных частей кода, написание и прогон тестов и т.д. Изредка код писать все-таки приходится. Но это, как правило, очень простой код: взять что-то из базы, привести объект к другому типу, в цикле пройтись по коллекции. Давайте спросим себя: неужели именно такое программирование нам нравится?

  Когда я взялся писать виртуальное казино для Android, было ощущение, что меня разбудили после долгого сна. Я почуствовал, что передо мной задача очень отличающаяся от тех, что мне приходилось делать раньше. Мне не нужно было писать никаких конфигураций, да и IDE ничем не могло мне помочь. Мне нужно было писать алгоритмы и думать, много думать и много писать.

  Первое, что я обнаружил, так это то, что текстовый редактор в Eclipse никуда не годится. Я набираю код всеми десятью пальцами сразу, и мне не надо смотреть на клавиатуру, когда мои пальцы находятся над клавишами алфавита. А для перемещения по тексту необходимо сдвигать правую руку на клавиши со стрелочками или даже еще дальше -- к PgDown/PgUp. Но даже это не идет ни в какое сравнение с тем, как отвлекает необходимость хвататься за мышку! Это здорово выбивает из состояния потока!

  Во-вторых, конечно же, я не стал писать эти 130 полей вручную. Нужно было разработать какой-то генератор кода, и здесь Eclipse опять ничем не смог мне помочь. Писать плагины для Eclipse невероятно затратное дело. Следовало выбрать один из скриптовых языков вроде Perl, Python или Ruby. Но я все равно не понимал, почему не сделать возможность в Eclipse для написания простых плагинов как раз для таких случаев. В редакторе Eclipse есть курсор, и им можно было бы выделять фрагменты текста для обработки. А когда пишешь скрипт для обработки текста, например, на Perl, курсора нет, и необходимо как-то парсить структуру текста регулярными выражениями или помечать места для упрощения анализа текста.

  В-третьих, когда огромный xml-файл был уже готов, время от времени приходилось подправлять сгенерированные координаты ячеек. Например, поднять весь ряд немного вверх, или сдвинуть часть ячеек чуть-чуть правее. Теоретически, можно было переделать генератор, сгенерировать новый код, вставить его на замену старому и решить задачу. Но в моем случае первоначально сгенерированный код уже был обработан вручную, и повторная генерация кода потребовала бы повторной его ручной обработки. Мне дико не хватало возможности написать макрос, чтобы текстовый редактор выполнял всю обработку за меня.

  Мне не понравилось программировать казино на Android в Eclipse. Оказалось, что Eclipse прекрасно подходит для задач code monkeys, ежедневно клепающих формочки для очередной CRM на Java. Но этот же Eclipse совсем плохо показывает себя в задачах, для которых у него нет заготовок вроде генераторов кода.

  Давайте спросим себя, что же это за задачи, для которых IDE подходят не очень хорошо?

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

  Вернемся к самому первому тезису статьи. В самом ли деле, те, кто используют Emacs, безнадежно устаревшие чудаки? Или все-таки действительно есть причины для применения этого древнего текстового редактора?

  А вы знаете, что, например, в Emacs можно настроить сочетания клавиш таким образом, чтобы всю работу с текстом, в том числе и перемещение, можно было выполнять, не убирая пальцы с алфавитно-цифровой клавиатуры? И тем более не хватаясь за мышку? Когда концентрация на коде максимальна, очень важно не отвлекаться на посторонние вещи!

  Редактору Emacs легко придать абсолютно аскетичный вид. Казалось бы, зачем убирать панели инструментов, строку меню, боковые навигаторы кода и прочие элементы управления, если у нас итак достаточно вместительные экраны мониторов? Ответ очень простой: пространства на экране никогда не бывает достаточно! Когда-нибудь в будущем, когда картинка будет проецироваться пользователю напрямую в мозг и не будет ограничена размерами монитора, все равно будут те, кому и такое изображение покажется недостаточно вместительным. Эти будущие гики, также, как и сегодняшние, будут стараться убрать с изображения все отвлекающие детали и максимально освободить себе рабочее пространство, чтобы заполнить его действительно полезной информацией.

  Таким образом, Emacs идеально подходит для тех, кому требуется полная концентрация внимания на редактируемом тексте.

  Текстовый редактор Emacs -- это, по сути, небольшое ядро, включающее в себя интерпретатор языка Emacs Lisp, и громадное количество скриптов, написанных на этом Lisp-е. Весь интерфейс, все функции, вообще всё-всё-всё в Emacs -- это программы на Emacs Lisp. Все эти скрипты хорошо документируемы и доступны в исходных кодах. Поэтому, если вас что-то не устраивает в Emacs, то вы вольны изменить это так, как вам нравится. Писать плагины для Emacs невероятно просто.


  Я специально хочу остановиться на этой мысли: писать плагины для Emacs так просто, что я, не задумываясь, пишу их чуть ли не для каждой сложной задачи. Посмотрите, как выглядит "Hello World" в стиле Emacs Lisp:
 
  (defun my-test-message ()
     (interactive)
     (message "Hello, World!"))
 
  Обратите внимание, сколько xml-конфигураций мы здесь не правим, сколько интерфейсов не реализовываем, сколько классов не наследуем! Всего одна простая функция, и если её скомпилировать (C-x C-e за последней скобкой функции), она тут же становится частью редактора Emacs!

  Именно эта простота написания плагинов так сильно подкупает в Emacs. Когда я программирую на Java, я пишу расширения Emacs для генерации всего того boilerplate-кода, который не умеет генерировать Eclipse. Emacs автоматизирует мне много по-настоящему скучной рутинной работы!

  Есть и еще одна проблема, с которой плохо справляются IDE -- это нестандартные и предметно-ориентированные языки программирования. Для них нет и никогда не будет поддержки в Eclipse, Idea, Netbeans и т.д. Но зато вы с лёгкостью можете добавить поддержку любого нужного вам языка в Emacs!
 
  У Emacs есть еще один существенный плюс: превосходная интеграция с Clojure. Исторически сложилось так, что программисты на Lisp-подобных языках предпочитают разрабатывать программы в Emacs, потому что в этом редакторе есть все, что нужно лисперу. Это и правильная подсветка кода и скобочек, и автодополнение кода, и REPL для интерактивной разработки, и просмотр документации, и многое другое. Если вы планируете посвятить много времени Lisp-подобным языкам, то вам однозначно стоит попробовать Emacs. Тем более, что освоив Clojure вам будет уже довольно просто разобраться с Emacs Lisp и разрабатывать плагины для этого текстового редактора. Если у вас действительно возникнет желание изучить также и Emacs Lisp, могу порекомендовать вам пособие.
 
  Откровенно говоря, нужно признать, что у Emacs есть одна проблема: довольно высокий порог вхождения. Далеко не с первого раза можно понять, как там что устроено и почему именно так, а еще как переделать, чтобы было удобнее. В Emacs множество комбинаций клавиш начинаются с Ctrl, от чего сильно устает левый мизинец; комбинации для перемещения курсора придумали как будто специально, чтобы ими было неудобно пользоваться: Ctrl-f, Ctrl-b, Ctrl-n, Ctrl-p. Это связано с тем, что Emacs создали очень давно, когда у клавиатур не только не было клавиши "Win", но даже и само расположение клавиш было другим. Например, Клавиша Ctrl находилась на том месте, где сейчас традиционно расположена Alt, и Ctrl в то время нажимали большим пальцем левой руки, а вовсе не мизинцем.


  Но, как уже было сказано, ничто не мешает вам изменить управляющие клавиши. Например, известный Emacs-ер Xah Lee создал проект ergoemacs, в котором он предлагает совершенно иную раскладку, намного более эргономичную.
 
  Для слушателей Clojure Course, которые хотели бы попробовать Emacs, я создал немного модифицированную версию Ergo Emacs. Этот конфиг, конечно, не заменит начального ознакомления с документацией, но зато поможет сделать работу с Emacs несколько удобнее.
 
  Ниже несколько основных клавиатурных сочетаний, которые я использую в своем конфиге. Здесь используются следующие традиционные для Emacs обозначения клавиш: C -- Ctrl, M -- Alt, S -- Shift.
 
  Перемещение курсора:
 
  M-i -- up
  M-k -- down
  M-j -- left
  M-l -- right
  M-u -- word left
  M-o -- word right
  M-S-i -- page up
  M-S-k -- page down
  M-S-j -- beginning of document
  M-S-l -- end of document
  M-h -- end of line
  M-S-h -- beginning of line
  C-l -- go to line
 
  Редактирование текста:
 
  M-m -- new line
  M-d -- backspace
  M-f -- delete
  M-Space -- start/end selection
  M-c -- copy
  M-x -- cut
  M-v -- paste
  M-s -- save document
  C-o -- open file

  Работа с окнами:

  C-x 2 -- split window horizontally
  C-x 3 -- split window vertically
  C-x 0 -- close current window
  C-x 1 -- leave only current window
  M-q -- next window
  M-S-9 -- shrink horizontal window
  M-S-0 -- enlarge horizontal window
  M-9 -- shrink vertical window
  M-0 -- enlarge vertical window
 
  Закладки:
 
  C-b -- set bookmark
  M-b -- jump to bookmark
 
  Системные операции:
 
  F5 -- run Emacs command
  C-x C-c -- close Emacs
  C-x b -- select buffer
  C-x k -- kill buffer
  C-c l -- truncate long lines on/off
  C-g -- сancel
  F11 -- show help for my keybindings

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

 А вообще, конечно, очень рекомендую прочесть учебник по Emacs в переводе Алекса Отта.

27 комментариев:

  1. На мой взгляд эргономичностость можно улучшить установив плагин Evil. :)

    ОтветитьУдалить
    Ответы
    1. Да. емакс без эвил мода не продуктивен и нуждается в педальках. Хотя сам заядлый виомюзер и емакс не смог полюбить. Уж очень все плохо прикручивается к эвил моду. Зато вим прекрасно кастомизируется.

      Удалить
    2. У меня опыт использования Emacs меньше года, пока не сталкивался со сложностями связанными с Evil. По ощущениям полный Vim в Emacs.

      Удалить
    3. Да нафига вам Vim в Emacs? Если нравится Vim, так и пишите в нем, зачем эти компромиссы?

      Удалить
    4. Это не компромисс это максимизация добра. Когда я начал осваивать Emacs я честно около 2х месяцев пользовался всеми емаксовыми шорткатами. В результате я понял, что в шутке, что в емакс есть все кроме хорошего текстового редактора, доля шутки не большая. Теперь когда я редактирую код я пользуюсь vi а для всего остального (открыть файл или перейти в другой буфер) я использую емаксовыми шорткатами. На мой взгляд получилось очень удобно. Ну а вам Дмитрий могу посоветовать освоить вим на уровне редактирования кода и тогда сможете "почувствовать разницу" :)

      Удалить
    5. Емаксовые шорткаты вообще не предназначены для того, чтобы ими пользоваться, об этом я и писал в статье. Ну а Vim я знаю, пользовался им с 2003-го по 2011-й годы очень активно. Единственное, что заставило меня соскочить на Emacs -- это VimScript, который я считаю одним из самых уродливых языков программирования. Писать на Emacs Lisp гораздо приятнее.

      Удалить
    6. Так ведь давно уже можно плагины для вима на python и ruby писать.

      Удалить
    7. И это все равно жуткий pain-in-the-ass. Кроме того, там большая часть написания плагина -- это конкатенация строк, чтобы получить vim-команду.

      Удалить
    8. Я пробывал эргономемакс тоже. Не пошло. Скажите Дмитрий а чем вас не устраивает emacs с Evil или другим Vim-эмулятором? Я совершенно не могу обходиться без многих комманд Vim-a при редактировании. Как вы живете без возможности нажать на o и начать писать код с новой строки с правильным отступом в не зависимости где стоял курсор на данный момент? :)

      Удалить
    9. Очень просто: я нажимаю для этого M-n :-)

      Удалить
    10. у тебя M-n это 'reindent-then-newline-and-indent
      а надо что-то типа
      (lambda () (interactive) (progn (move-end-of-line 1) (newline-and-indent))))

      Удалить
    11. Действительно хороший совет, спасибо! Исправлю.

      Удалить
    12. А не, не совсем. Если мне нужно текующую строку разбит на две, то эта функция не подходит, т.к. она идет в конец строки и только тогда создает новую.

      Удалить
  2. Вимеры набежали :-) Нравится Vim -- пишите в Vim-е, нечего вимовские настройки в Emacs тянуть. У нас и свои есть!

    ОтветитьУдалить
  3. Таки я не понял. Куда дели C-w?

    ОтветитьУдалить
  4. Одному мне интересно, что заставило вас набивать 130 одинаковых полей? Может архитектуру плохо продумали?

    ОтветитьУдалить
  5. Кабы вы подучились программированию (вместо того, чтобы "писать алгоритмы"), может, и ничего бы вышло. На каком-нибудь приличном языке, а не на скале с адом ХМЛ.

    А впрочем, валяйте.

    ОтветитьУдалить
  6. Ну что бы я делал без ваших советов... :-)

    ОтветитьУдалить
  7. Подскажите знатоки emacs.
    как сделать чтобы при перемещении курсора вверх-вниз он не прыгал к концам коротких строк?
    режим picture-mode не годится, так как он вставляет ненужные пробелы

    ОтветитьУдалить
  8. Дмитрий, у меня вопрос про Ctrl. Мне кажется, что то, что Ctrl находился на месте Alt на клавиатурах Lisp-машин -- большое такое лукавство. Вроде как раз Ctrl находился там же где и сейчас (слева и снизу от Z), а вот Alt, относительно Ctrl, действительно, располагался иначе. Я не прав?

    ОтветитьУдалить
  9. вот сколько не читаю про ctrl в emacs, везде почему-то не обращают внимания на то, что ctrl прекрасно жмется ладонью левой руки. Выходит куда эргономичней маппинга на капс. У того-же xah-lee подробнее.:
    http://ergoemacs.org/emacs/swap_CapsLock_Ctrl.html

    ОтветитьУдалить
    Ответы
    1. Xah Lee имел в виду, что дополнительно можно нажимать и ладонью. А если этот способ кажется удобным для всех комбинайций -- рекомендую попробовать зажать ладонью левой руки Ctrl и набрать комбинацию C-x C-e.

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

      Удалить
  10. Этот комментарий был удален автором.

    ОтветитьУдалить
  11. А есть ли возможность писать плагины для Emacs на чем-то кроме lisp?
    (Конкретно интересует Python)

    ОтветитьУдалить
    Ответы
    1. Нет, только Lisp. Если интересует Python -- возьмите Sublime Text.

      Удалить
  12. Никакой емакс никогда не сравнится с eclimом

    ОтветитьУдалить