Category: россия

Category was added automatically. Read all entries about "россия".

glider

емакс, часть 3: windows

емакс, часть 1: первый взгляд
емакс, часть 2: восторг
емакс, часть 3: windows
емакс, часть 4: ретроспектива

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

Сразу после запуска емакс встретил меня сообщением об ошибке в скриптах инициализации и антиалиаснутым курьером. "Окей, в принципе никто и не предполагал, что сразу все заработает" - подумал я и нажал Alt+F4, чтобы перезапустить емакс в режиме отладки. В ответ последовало: "<M-f4> is undefined", что в переводе на русский обозначает, что Alt+F4 по умолчанию ни на что не забинджен. Да, поездочка будет долгой...

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

upd. Также я столкнулся с проблемой тормозов. Часть из них была вызвана гитом (см. ниже по тексту), часть из них имела другие причины. Хорошая новость в том, что все удалось починить. Детали см. вот тут: http://xeno-by.livejournal.com/57626.html.

***

Первым делом я обдумал вопрос программного окружения. Так как емакс неслабо использует возможности стандартных юниксовых тулов (например, поиск по пачке файлов (читай, проекту) проще всего реализовать через find+grep), нужно было где-то достать эти самые тулы. Можно было просто вытащить греп и файнд из mingw, но отказываться от шелла тоже не хотелось, ибо писать дакт-тейп на елиспе - удовольствие ниже среднего. В итоге, остались два варианта: 1) запускать емакс из-под цигвина или чего-то подобного (к сожалению, я плохо разбираюсь в теме эмуляции юникса под виндой, поэтому не в курсе, как еще можно поступить в рамках этой опции), 2) юзать NT Emacs (т.е. емакс, скомпилированный в виде нативного виндового приложения), но при этом использовать bash и gnu utils от цигвина.

После чтения емакс-вики и статейки Стива Йегги я решил остановиться на второй возможности. Кроме общефилософского мнения о том, что предпочтительнее юзать нативную прилагу, немаловажным был тот фактор, что цигвин я видел первый раз в жизни, поэтому непонятно, какие косяки меня могли ожидать. В любом случае, и баш, и корные юниксовые утилиты доступны в обоих случаях, поэтому, выбрав NT Emacs, концептуально я ничего не терял. В итоге я поставил цигвин, добавил его bin в виндовый PATH, установил переменную окружения SHELL в c:\cygwin\bin\bash.exe (это все, что нужно для того, чтобы емакс проинтегрировался с цигвиновскими coreutils) и смело пошел навстречу граблям.

Самым первым делом я пофиксил шрифты. Если к сглаживанию как таковому я со временем привык, то сглаженный курьер меня продолжает удивлять и по сей день. Впрочем, оказалось, что установкой одной-единственной переменной можно сразу изменить шрифт для всего окна емакса. Для полноты картины отмечу два нюанса: 1) формат значений этой переменной нетривиален, 2) переменная локальна для фрейма, т.е. для новых окон нужно ее устанавливать заново. За деталями смотрим сюда.

Следующей на очереди была унификация формата сохраненной сессии емакса между виндой и линуксом. Винда успешно поддерживает симлинки, но никакими симлинками не превратить путь типа X:\ в путь типа /foo/bar. И это даже несмотря на то, что емакс прекрасно переваривает прямые слеши вместо обратных и наоборот. Проблема решилась при помощи цигвина. В папке c:\cygwin я воспроизвел структуру рабочего окружения линукса и забросил оттуда симлинки на папки с реальным контентом. А дальше всего лишь осталось заюзать библиотеку cygwin-mount, которая умеет маппить виртуальные юниксовые пути на реальные виндовые пути внутри папки цигвина.

Пришлось также неслабо поисследовать вопрос с хоткеями. В линуксе проблема гвоздями прибитых хоткеев отсутствует - и в метасити, и в компизе можно перебиндить что угодно, включая вещи вроде alt+tab. В винде все несколько грустнее. Во-первых, из коробки емакс не обрабатывал кнопки Win, отдавая их системе. Если в убунте я мог изображать любые сочетания клавиш с участием Win, то в винде эти штучки уже не работали. К счастью, нашлось простое решение. Для того, чтобы Win превратить в super (или во любой другой модификатор), нужно всего лишь установить парочку переменных.

Дальше - интереснее. Если проблемы с win+tab и win+цифры я ожидал, то увидеть занятыми ctrl+esc и даже win+= было удивительно. Вначале я пытался разрулить проблему, копаясь в реестре, но это были просто припарки - там заработало, тут отвалилось. Ситуацию переломил бесплатный тул AutoHotkey. С помощью несложного вида скриптов он позволяет перекрыть и обработать большой спектр хоткеев (я подозреваю, что все, что угодно, кроме ctrl+alt+del), а также даже скомпилировать свои скрипты в standalone икзешники. Кроме того, я перемаппил Caps Lock на Ctrl - это делается регедитом, без всяких тулов.

Конечно, мои изыскания не могли пройти мимо проблемы с разделителями строк. Вначале я подумал, что эту проблему удастся избежать, т.к. емакс достаточно смартовый редактор для того, чтобы автоматически понимать, где \n, а где \r\n. Но после того, как скрипт, отредактированный под виндой, отвалился в линуксе по причине лишнего символа \r, мне стало не до шуток. Была введена политика огораживания, по которой все новосозданные файлы, несмотря на текущую операционку, кодируются с разделителями в стиле юникса. Исключение - бат-файлы, которые без \r\n виндовый интерпретатор не съест. Интуитивно чувствую, что это решение слишком жестко, чтобы быть практичным, но будущее покажет.

Кстати, по концовке оказалось, что проблема была не в емаксе. Символы окончания строки испортил кое-кто другой. Некоторые из вас, вероятно, уже догадались. В честь этого все вместе передадим привет гиту и его core.autocrlf. Впрочем, тема гита на винде выходит за пределы и так уже большого поста.

Последняя грабля была связана снова с гитом. В интернетах много кто жалуется на неторопливость его виндового порта. Как я понял, это связано с тем, что гит юзает идиомы линукса, которые невозможно эффективно замаппить на виндовый апи, в честь чего и тормоза. На горьком опыте я выяснил, для дефолтного сетапа msysgit 1.7.2 операции вида git XXX выполняются минимум 0.3 секунды каждая (ssd, core i7, loads of ram). Все бы ничего, но при открытии каждого файла емаксовая инфраструктура сорс-контроля выполняет более 10 таких операций. Путем красноглазия удалось сократить время до 0.1 секунды на операцию, но это все равно баттхёрт! Пришлось отрубать, но, на счастье, получилось чисто - отключился только хук, но не остальной функционал вроде диффов.

***

tl;dr. Поставлено тулов: 1) Cygwin, 2) NT Emacs. Пришлось подпилить: 1) фонты, 2) имена файлов в сессиях, 3) системные хоткеи винды, 4) политику разделителей строк, 5) интеграцию с гитом. В результате под виндой: 1) gnu тулы из емакса работают, 2) шелл-скрипты из емакса (например, grep+find по проекту) работают, 3) сессии емакса, сохраненные в одной операционке, открываются в другой, 4) функциональность и хоткеи емакса в пределах моего воркфлова одинаковы - и в линухе, и в винде.
glider

емакс, часть 2: восторг

емакс, часть 1: первый взгляд
емакс, часть 2: восторг
емакс, часть 3: windows
емакс, часть 4: ретроспектива

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

Вначале я хотел все сделать правильно - пройти туториал, освоить emacs way (например, редактирование текста без стрелочек), но дело продвигалось крайне медленно в силу отсутствия привычки. Дело в том, что емакс появился задолго до того, как сформировались современные стандарты графического интерфейса, поэтому многие вещи для непосвященных вроде меня там кажутся... гм, экстравагантными. Поэтому, я решил сделать хитрее, а именно: адаптировать емакс под мои привычки после вижуал-студии. CUA-мод, undo-tree, tabbar, бессовестный ремап хоткеев сохранения, поиска и так далее - все пошло в дело.

После того, как лед тронулся, дела пошли все лучше и лучше. Когда я перестал спотыкаться на базовых вещах, играться стало гораздо интереснее. Через пару дней даже скобочки перестали казаться вырвиглазным абстракционизмом. По концовке удалось запилить:
1) Мейнстримный флейвор редактирования текста (виджет с деревом файлов, закладки, копипаста, традиционный undo/redo, привычные функции мышки),
2) Поддержку мультимониторности,
3) Простенький механизм проектов (в емаксе проектов нет, поэтому пришлось все делать самому - впрочем, 90% строительных блоков были уже реализованы в сторонних модулях),
4) Интеграцию с основными тулами (sbt для компиляции, git для сорс контроля).



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



Скажем, буквально вчера я заставил шифт-клик выделять текст (по умолчанию шифт-клик замаплен на нечто невразумительное). Все, что мне понадобилось - открыть файлик mouse.el, посмотреть как в этом файлике получают текущие координаты мышки и заюзать этот рецепт в своем обработчике шифт-клика. Написанный кодярник я сразу же проверил во встроенном REPL, нашел ошибку, поправил ее и скопипастил результат в файлик автозагрузки. Делов-то, правда?



Конечно, не обошлось без косяков. Например, мне никак не удалось заставить курсор оставаться на месте, даже если я выскролливаюсь мышкой за границы экрана. Понятно, что это можно побороть букмарками, да и не всегда это так уж необходимо, но осадок остается. Или, вот, полоска с табами рендерится сверху каждого текстового окна, и нет возможности ее показывать только сверху, а в других местах спрятать (это хорошо заметно на следующем скриншоте). Так получается потому, что в емаксе нет отдельной абстракции для табов - есть просто место для хедера, куда модуль tabbar рендерит гиперлинки, обернутые в специальный кнопкоподобный стиль. Но, лично в моем случае, это были мелочи на фоне того, что почти все удалось сконфигурировать себе по нраву.

Отдельного восторга заслуживает коллективный разум емаксеров, который нашел миллион способов выполнять самые разные задачи в text-only режиме. Вот, например, диред (dired). На первый взгляд, в текстовом буфере просто-напросто отображается вывод команды ls. Но, присмотревшись, понимаешь, что имена файлов и папок отрендерены гиперлинками и, кроме того, команды перемещения курсора сами прыгают к именам, даже если курсор был в другой части строки. Еще присмотревшись, понимаешь, что обычные кнопки вроде d или r перемаплены на выполнение операций с файловой системой. Дальше замечаешь вещи вроде dired-dwim-target. Скажем, если в двух окнах открыто по инстансу диреда, то диред уже не будет спрашивать куда копировать, а сам догадается, что надо использовать директорию, открытую в другом окне. Удобно - дает мне надежду на то, что со временем удастся-таки найти/написать замену тотал-коммандеру для линухи.



В завершение хочу пожелать каждому когда-нибудь поиграться с емаксом. За страшной маской допотопного гуи и скобочного программирования скрывается прекраснейший тул в моей практике. Даже несмотря на нулевое знание базовых вещей лиспа (например, мне так и не удалось написать лямбду, которая генерирует лямбду), мне удалось нафигачить крайне полезные вещи, которых так не хватало в других редакторах.

Самый большой страх у меня был связан с тем, что придется осваивать на каждом шагу непривычные хоткеи, но его удалось побороть тривиальным образом - просто методично перемаппить часто используемые фичи на удобные сочетания клавиш. Конечно, это неолдскульно и, наверняка, неэкономично с точки зрения движения рук - короче, полный постмодерн, но зато позволило мне сделать первый шаг в использовании емакса, отчего я сейчас невероятно счастлив! =)
glider

емакс, часть 1: первый взгляд

емакс, часть 1: первый взгляд
емакс, часть 2: восторг
емакс, часть 3: windows
емакс, часть 4: ретроспектива

Наконец, переборол свой страх перед емаксом и заставил себя слезть с gedit. За сегодня узнал много чего нового - ecb, dired, tabbar, ну и так, по мелочи настроил .emacs.d. Попутно сгенерилась куча вопросов, вот несколько из них.

1. В чем тайный смысл длинных хоткеев для частых действий? Вот, например, C-x C-_ для redo: требует нажатия пяти клавиш для выполнения весьма распространенной процедуры. Это ведь банально неудобно! Наверное, я что-то упускаю, но что? upd. Просто замаппил redo на C-y при помощи UndoTree. Надеюсь, тайный смысл многокнопочных шорткатов пойму позже.

2. С созданием хоткеев я в целом разобрался, но остался нерешенный момент. Как забиндить C-1? Когда я в init.el пишу (global-set-key (kbd "C-1") 'blah-blah), то хоткей тупо не применяется. Если в этой же строчке заменить С-1, например, на C-=, то все ок. upd. Выяснилось, что C-цифры замаплены на некий digit-argument, но я без понятия что это, поэтому просто заюзал другую комбинацию клавиш.

3. Что по концовке будет удобнее: CUA или стандартный подход емакса к копипасту? upd. Врубил CUA, ибо решил вначале добиться минимально необходимого/привычного набора фич, а потом уже играться с емаксом по ходу работы.

4. Как я понимаю, dired - выбор редакции для всех операций, которые касаются нескольких файлов одновременно? Например, поиск некоторого текста во всех файлах папки или замена чего-либо рекурсивно для всех файлов проекта. Или же есть какой-то более удобный тул для этой цели, про который, например, в силу юного возраста еще не написали в бложеках?

5. Как можно удобно сделать инкрементальный поиск по всем файлам проекта? Я нагуглил вариант с запуском диреда с флажком -R и инкрементальным поиском по окошку диреда. Есть ли альтернативные опции с автокомплитом, например, в минибуфере? Как я понял, и ido, и icicles поддерживают только поиск файла в текущей папке. Какие есть еще варианты? (задал вопрос на stackoverflow)

6. Под виндой я привык, что tortoise* регистрирует кастомные оверлеи на иконках файлов, лежащих под сорс-контролем. Файл не менялся после последнего коммита - зелененький, менялся - красненький, ну и в таком духе. Особенная прелесть такого подхода заключается в том, что иконки рекурсивно применяются к папкам, т.о. можно быстро увидеть что закоммитал, а что забыл. Есть ли что-то похожее в емаксе? Я видел, что ECB рисует иконки файлов с учетом их статуса в VCS. Но умеет ли он отображать статус папок? upd. Забил - вообще отключил иконки ECB. Во-первых, они часто глючат, а, во-вторых, магита хватает за глаза - одной кнопкой можно посмотреть статус репозитория, что, в общем-то, и нужно было от иконок.

7. Про какие мастхэв модули я должен знать? Я нашел интересный пост на SO: The single most useful emacs feature - но там больше про мелочи.
glider

онсайт собеседование с гуглом, часть вторая

Первая часть

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

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

Здесь меня постигло разочарование и удивление одновременно - моя собеседница сказала, что использует всего лишь какую-то несложную тулу для редактирования текста (нет, не vi), а больше ей ничего и не надо. Поиск и навигация по коду в ее воркфлове отделены от редактирования и осуществляются в некоем веб-туле аля Google Code Search. Здесь у меня три вопроса:
* Насколько близки возможности этого тула к публичному code search? Вот, я открыл случайный C#-проект в code search. Панелька навигации отображает структуру проекта и даже выделяет семантические элементы внутри файла. Это хорошо, но где гиперлинки в стиле "go to definition"?
* Можно ли поставить этот или аналогичный тул локально и индексировать свои личные проекты?
* Народ, ну как вы обходитесь без интегрированных в редактор кода рефакторингов?!

2. Я не смог удержаться и спросил одного из интервьюеров, а также и девушку за обедом про то, как народ использует 20% времени, которые политикой гугла отводятся на личные проекты. По рассказам (которые также коррелируют и с тем, что мне рассказала Дженни) получается, что можно замутить что-нибудь интересное, представить это что-то широкое публике и при успехе презентации ожидать приток свежих сил на мини-проектик. При особой пользе личного проекта для Мирового Разума, может предоставиться возможность заниматься им фулл-тайм (здесь мне рассказали историю некоего Кости, который сгенерил тул, умеющий в полуавтоматическом режиме искать data races; сейчас, при написании поста я нагуглил немного больше деталей). Звучит отлично, поэтому очень интересно было бы узнать детали.

3. Стала неожиданностью позиция народа относительно альтернативных языков программирования. Как я понял, в гугле есть четыре языка, на которых пишут большинство кода в продакшен - Java, C++, Python и Go. Мои вчерашние собеседники пишут исключительно на Java/C++ и иногда мелкие скрипты на питоне. Go считается мистической экзотикой, которую никто из них не пробовал, но, по слухам, это что-то классное. На провокационные вопросы типа: "а никогда не хотелось заюзать какой-нибудь другой ЯП?" или "согласись, приятно покодить в функциональном стиле?" никто не поддался. А самый первый мой интервьюер даже не слышал, что такое Scala. Отражает ли эта выборка мнений общую картину?

На пока что все. В следующем посте я попробую описать тематику вопросов (вчера было пять собеседований, по 1-3 задачки в каждом) и выскажу соображения по поводу подготовки на основе полученного опыта. К сожалению, тексты задачек я привести не смогу (NDA я не подписывал, но явно высказанной просьбе отказывать не хочу), но, надеюсь, будет интересно.
glider

Автоматическая синхронизация версии проекта с ревизией SVN

Я давно знал, что, указав для версии сборки атрибут [assembly: AssemblyVersion("1.0.*")] (или любую другую версию кроме 1.0), в 2008й студии мы получаем автогенерацию третьей и четвертой позиций версии - то есть номера билда (устанавливается в количество дней, прошедших на момент билда с 31.12.1999) и номера ревизии (устанавливается в количество секунд, прошедших на момент билда с начала суток, разделенное на 2 - если на два не делить, то получится overflow ибо у нас только 16 бит, а секунд в сутках 86400). Этот подход хорош тем, что при обычном процессе разработки практически невозможно выпустить две разных сборки с одной и той же версией (для этого придется успеть что-то поменять и после того еще и перекомпилировать проект в пределах двух секунд). Но на этом достоинства подхода заканчиваются, ибо из автогенерированной версии мы ничего полезного, кроме времени билда, узнать не можем.

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

К сожалению, непосредственно в студию такая функциональность не встроена и плагинов, ее обеспечивающих, не существует. Приходится выбирать из пачки не очень удобных вариантов - http://stackoverflow.com/questions/12176/svn-revision-version-in-net-assembly-w-out-cc-net. Написание кастомных тасков для MSBuild требует их последующей установки в систему, макросы SVN для автогенерации AssemblyInfo напрямую не подходят, руками делать тоже не хочется - везде есть какие-то недостатки.

На днях я наткнулся на наименее напряжный, с моей точки зрения, вариант и не поленился реализовать его во всех своих open-source проектах. Вот та самая статья: Using Subversion Revision as the AssemblyVersion - Revisited, а вот воркфлоу моими словами (он опускает некоторые детали, за которыми прошу обратиться к первоисточнику):
1) Используем тул SubWCRev.exe из TortoiseSVN, который умеет заменять макросы SVN на текущие значения,
2) Файлики AssemblyInfo.cs выкидываем из-под сорс контроля и для верности еще и игнорируем, чтобы не было постоянных промптов их добавить обратно,
3) Рядом с файлом AssemblyInfo.cs кладем файл AssemblyInfo.template, в котором заменяем номер билда в версии на макрос $WCREV$ (важно не забыть добавить этот файл в проект, чтобы помнить о его существовании, если надо будет что-нибудь поменять в AssemblyInfo, например, мажорную версию),
4) В пре-билд ивент проекта (конфигурация находится в свойствах проекта на закладке Build Events) записываем вызов тулзы из пункта 1, которая преобразует темплейт в AssemblyInfo.cs, после чего запускается билд,
5) Профит!

В итоге - исходная задача выполнена, и к тому же: 1) париться с настройкой надо всего лишь один раз, причем все необходимые настройки выполняются в файловом менеджере и GUI студии, 2) проект компилируется где угодно, 3) AssemblyInfo.cs заигнорен, поэтому каждый раз не будет мозолить глаза иконкой измененного контента и просьбой закоммитить.

P.S. Конечно же, если проект управляется системой continuous integration, то можно сделать все гораздо проще - плагином или кастомным билд-скриптом. Но, с другой стороны, для небольших проектов развертывание CI - это неоправданная затрата времени + требует надежного хостинга, поэтому такой подход целесообразен не всегда.

P.P.S. Насколько я знаю, ревизия в Git представляет собой непрозрачный длинный токен, который не поместится в 8 байт, отведенных на версию в PE формате. Это осложняет дело. Можно, например, вешать на сборку кастомный атрибут со значением этого токена, но кастомные атрибуты не показываются в меню винды File > Properties - неудобно. Можно также хранить токен в строковых метаданных PE-модуля при помощи атрибутов AssemblyTitle или AssemblyDescription - вроде бы неплохой вариант. Впрочем, сам не пробовал - не знаю, так что это просто догадки.