• User-Agent parser for Clojure

    Today, I detached another chunk of my codebase into a separate library. This time, it is for parsing User-Agent headers with Clojure. For a long time, I’ve been copying it from project to project, but now I decided to keep it aside from the code because it is not connected to the business logic. All the technical stuff that is not related to the very problem we are trying to solve should be kept as a separate library, I believe. The main code is all about the business problem.

    The library ships only one function, which is parse. It takes a string and returns a detailed map with information about the browser’s type, its version, manufacturer, operating system, etc. The library relies on good old Java UA Detector with the latest set of patterns. I know, there are already some solutions for that. But they either do not provide full information about a user or maintainers do not accept pull requests.

    Add it to your project:

    :dependencies [[user-agent "0.1.0-SNAPSHOT"]]
    

    Usage:

    (ns some.ns
      (:require [user-agent :as ua]))
    
    (def ua-sample
      "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36")
    
    (ua/parse ua-sample)
    
    {:producer "Google Inc."
     :family :CHROME
     :name "Chrome"
     :type :BROWSER
     :icon "chrome.png"
     :producer-url "http://www.google.com/"
     :url "http://www.google.com/chrome"
     :device {:category :PERSONAL_COMPUTER
              :name "Personal computer"}
     :os
     {:family :OS_X
      :family-name "OS X"
      :name "OS X"
      :producer "Apple Computer, Inc."
      :producer-url "http://www.apple.com/"
      :url "http://en.wikipedia.org/wiki/Mac_OS_X"
      :version
      {:bug-fix "6"
       :extension ""
       :groups ["10" "11" "6"]
       :major "10"
       :minor "11"
       :version "10.11.6"}}
     :type-name "Browser"
     :version
     {:bug-fix "3396"
      :extension ""
      :groups ["67" "0" "3396" "99"]
      :major "67"
      :minor "0"
      :version "67.0.3396.99"}}
    

    It supports plenty of desktop and mobile browsers as well as unusual ones like bots, crawlers or TVs. Hope you’ll enjoy it, your suggestions and PR’s are welcome.

  • Раньше было лучше

    Думаю, вы уже видели этот твит:

    I have a Python program I run every day, it takes 1.5 seconds. I spent six hours re-writing it in rust, now it takes 0.06 seconds. That efficiency improvement means I’ll make my time back in 41 years, 24 days :-)

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

    Поговорим об этом.

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

    Если ты хорошо знаешь Питон, то пусть программа на нем работает дольше, чем на Расте. Все дело в том, как человек воспринимает время. Если скрипт работает меньше какого-то порога, например, двух секунд, то для человека нет разницы, сколько это конкретно. В самом деле, кто может отличить 50 мс и 500 мс? Если это не система торможения в автомобиле, а обработка логов, то какая разница?

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

    На старой работе я с помощью Питона автоматизировл все что возможно. Сделал загрузку платежей из всех банков и платежных систем. Улучшил документооборот. Добавил прием заявок от населения. Запилил личный кабинет, сбор показаний счетчиков по смс и миллион других штук. Это был буквально информационный взрыв. Годами фирма делала вялые попытки как-то навести порядок, а тут такое. Было ли интересно пользователям, что Питон в 30 раз медленней Раста? Да наплевать.

    Кстати, никто их трех гигантов — Гугл, Эпл, МС — не использует С и С++ на мобилах как основной язык. У Гугла это доработанная напильником Джава. У Эпла был Obj-C, попытка нарастить старый Си до уровня Лиспа или Smalltalk. В итоге его заменили на Свифт, который по своей простоте напоминает скриптовый язык. У МС это .Net и Си-шарп, скучный ООП-язык, по сути продвинутая Джава. Во всех случаях к C/C++ прибегают только в крайнем случае, когда образуется горлышко.

    Это же справедливо и для десктопа. Виндовый софт пишут на Дотнете, для Мака на Свифте или Obj-C.

    Все нормально, жизнь идет своим чередом. Но все спорят про этот твит, натыкаешься и не понимаешь. Сижу в ступоре: о чем они спорят? Опровергни делом, а не словом! Портируй все, что хочешь на чистый Си под Винду 98, тогда и поговорим.

    На качественное ПО люди тратят треть жизни. Разработчик Total Commander пилит файловый менеджер уже 25 лет на Дельфи 2. Гвидо занимался Питоном 30 лет. Линус своей операционкой 20 лет. Емаксу Столлмана уже 40 лет. Тут каждый выбирает сам. Хочешь качественный софт – садись и пили. Может, после первого десятилетия получится что-то надежное.

    Разговоры о том, что теперь все плохо, а раньше было норм напоминают эту картинку:

    Конечно, с высоты опыта легко говорить, что раньше было лучше. Я читал воспоминания одного девелопера. Он пишет, что разрабатывал сайт в девяностых для крупной фирмы. Главное требование было читать прайс-лист из CSV-файла и показывать пользователю. По тем временам это было неслыханно. Все делалось на Си через CGI, шаблонизаторов не было, HTML собирался по кусочкам вперемешку с if-else. Делали несколько месяцев.

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

    Похоже, публика не умеет мысленно перемещаться во времени. Если сегодня я могу сделать что угодно на Маке и божественных языках, где все генерится мышкой, то и раньше так могли. Нет, не могли!

    Отдает Оруэллом, если честно. Центральная тема его произведений — память о прошлом. Никто не пытается сделать какой-то анализ, только и слышишь о том, что раньше было ништяк, а теперь плохо. Напоминает рыбку Дори с кратковременной памятью.

    Можно же поставить Винду XP, Фотошоп 9, Дельфи 7, Оперу 10. Вместо Андроида — кнопочная Нокия со Змейкой и Оперой-мини. Да, в Твиттер с Нокии уже не напишешь, в Инстаграм не запостишь. Технически возможно написать Джава-аплет под Нокию для постинга в Твиттер, но кто этим будет заниматься? Или можно взять последний 3D-Max и портировать его на Винду XP. А заодно все видео-драйверы и утилиты к нему. Но из-за разницы архитектур получится два 3D-Макса. Сколько пользователей будет у версии под XP? Зарплаты разработчиков будут неизмеримо больше продаж этой версии.

    Вот публика и потребляет новейший софт, Маки, Айфоны, беспроводные устройства, Что-Угодно-Script, и при этом раньше было лучше.

    У меня совершенно другая позиция. Все становится лучше. Не везде и сразу, где-то очень медленно, где-то излишне быстро с потерей нужных качеств. Но тем не менее. Я тоже раньше любил поворчать, что а вот раньше-то… Но в какой-то момент понял — хватит. И пересобрал себя. Жизнь всегда будет сложной и быстрой.

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

    А жизнь продолжается.

  • Интернет для юрлиц

    Особая жесть — это интернет для юрлиц. Вы когда-нибудь подключали интернет как ИП? Так послушайте.

    Он стоит примерно в двадцать раз дороже. Например, вы сидите на бизнес-этаже и платите 6000 рублей в месяц, а Вася из жилой квартиры выше — 350 рублей. Разница на порядок.

    Это тот же самый интернет. Юрлицо не требует особого железа или проводов. Это как одна и та же вода, которая по стояку заходит сначала в офис, а потом в квартиру. Вся разница в типе учетки на сервере.

    За колоссальную переплату я получаю ничего. Все те же внезапные обрывы, дрянная поддержка, наплевательское отношение.

    При разнице в цене в 20 раз скорость для юрлиц гораздо ниже. Вася из квартиры выше качает порево и игры терабайтами, а вам на обновление операционки нужен час. Аплоад крайне низкий: часовое видео на может заливаться на Ютуб и полтора часа, и два.

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

    Цены для юрлиц — банальный развод по принципу “есть деньги, значит, плати больше”.

  • Мракобесие в школах

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

    Но окончательно я офигел, когда зашел поп. Такой каноничный, пузо во, борода во, крест больше Афона. И погнал такую дичь, что аж затошнило. Что детей пытаются сделать врагами, запад высасывает мозги, что на Украине предали прошлое. Я немного терпел, а потом громко попросил его замолчать. Мамаши закудахтали, поп взбодрился и перешел к делу.

    Оказалось, вот зачем он пришел. По выбору родителей дети будут изучать или светский этикет, или историю с религиозным уклоном. Будет вести школьный учитель, а поп топит за то, чтобы выбрали религию. И тут же: это не религия, это просто история. А зачем же ты пришел, если это не религия?

    Мамаши выбрали религию, поп приободрился. Я объяснил, что сын на эту дичь ходить не будет, принципиально приеду с работы и заберу. Поп начал было опять про Украину, но я попросил его замолчать. Немного покусались, и он ушел.

    Мракобесие, деградация! Попы ходят по школам и топят за религиозные уроки. Дичь! До чего докатились. Учительница молчит, но по эмоциям вижу, что поддерживает меня. Учителей и так давят приказами и нормативами, а тут попы еще повылазили. После собрания говорит: этот урок не обязателен к посещению. Отпустить ребенка из школы не может, а посидеть в библиотеке норм. Так и решили.

    В Подмосковье, говорят, вообще попы ведут религиозные занятия вместо истории и биологии. Без комментариев.

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

  • Медицинская страховка

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

    В старой фирме дали страховку. Надо было сделать МРТ, решил воспользоваться. Не ожидал, что взаимодействие со страховой такое аналоговое. Звонишь, висишь в очереди. Потом объясняешь офисному сотруднику в мельчайших подробностях, что у тебя болит, куда пошел и что назначили. Он тебя придирчиво расспрашивает. Какая-то офисная крыса знает все до последней интимности.

    Страховые – жадные. Тебе пытаются отказать, нужно доказывать, что ты попадаешь под страховой случай. Это долго и унизительно.

    Моя жена стоматолог, вот что она рассказывает. Пациентов по страховым в клиниках не любит никто: ни врачи, ни дирекция, ни администраторы. Это вытекает в нелюбовь к пациенту. Страховых стараются перенаправить врачам более низкого ранга.

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

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

    Еще у врача есть такая штука как план. За невыполнение штраф. Выше я объяснил, что выручка по страховым не засчитывается в план текущего месяца, поэтому слишком много страховых пациентов увеличивает риск штрафа.

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

    У страховых фирм привычка тупо не платить клинике и тянуть до последнего для. Разрешено по договору полгода – не заплатят полгода. Авось бухгалтер пропустит или еще что. В клиниках с жесткими условиями администрация перекладывает выбивание долга из страховой на врачей.

    Будет ли врач после этого брать страховых? Только от безысходности.

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

  • Clojure extended: Java interop book

    Today, I published my first Clojure book about Java interop. It took 60 pages and seven chapters with five of them related to practice. I solve real cases borrowed from real projects I’ve have worked before in Clojure relying on Java a lot.

    I decided to write such a paper because I got tired of more and more Clojure books published. They all consider their reader as a newbie and do leave enough room for extended topics.

    The whole that book is a single extended topic. It consists of bits of knowledge I’ve been collecting for years. It is a tough and nerdy reading for those who bother with details. I’m really proud of I managed to complete it.

  • Remus: a new RSS/Atom feed parser for Clojure

    Recently, I found plenty of code that I usually borrow from project to project without hosting it on GitHub. I think I may share some of that since it might be useful to anybody.

    The first library I’d like to start with is a feed parser. There are already some Clojure wrappers for ROME and they even solve default cases. But mine wrapper is special since it supports lots of additional options and tweaks. So if you play with RSS a lot, try Remus, the library I’m introducing in this post.

    It’s also built on top of ROME but uses clj-http for HTTP communication with all its features, e.g. redirects settings, connection pooling, conditional requests by Etag.

    Remus fetches all the possible data from a feed including non-standard tags for further processing. Some feeds (YouTube, for example) distribute useful data with custom XML tags, e.g video statistics or geographical coordinates.

    Start with including the library into a project:

    :dependencies [[remus "0.1.0"]]
    

    Import it:

    (ns your.project
      (:require [remus :refer [parse-url parse-file parse-stream]]))
    
    ;;;;
    ;; or
    ;;;;
    
    (require '[remus :refer [parse-url parse-file parse-stream]])
    

    Now parse a URL:

    (def result (parse-url "http://planet.clojure.in/atom.xml"))
    

    The result will be a map with :response and :feed keys. The first one holds an HTTP response. You’ll need it to save some of the headers for further HTTP communication. The :feed key contains a huge map representing a parsed feed:

    (def feed (:feed result))
    
    (println feed)
    
    ;;;;
    ;; a small subset of the origin feed
    ;;;;
    
    {:description nil,
     :feed-type "atom_1.0",
     :entries
     [{:description nil,
       :updated-date #inst "2018-08-13T10:00:00.000-00:00",
       :published-date nil,
       :title
       "PurelyFunctional.tv Newsletter 287: DataScript, GraphQL, CRDTs",
       :author "Eric Normand",
       :link
       "https://purelyfunctional.tv/issues/purelyfunctional-tv-newsletter-287-datascript-graphql-crdts/",
       :contributors (),
       :uri "https://purelyfunctional.tv/?p=28660",
       :contents
       ({:type "html",
         :mode nil,
         :value "long HTML here....."
         }),
     :extra {:tag :extra, :attrs nil, :content ()},
     :published-date #inst "2018-08-13T11:59:11.000-00:00",
     :entry-links
     ({:rel "alternate",
       :type nil,
       :href "http://planet.clojure.in/",
       :title nil,
       :length 0}
      {:rel "self",
       :type nil,
       :href "http://planet.clojure.in/atom.xml",
       :title nil,
       :length 0}),
     :title "Planet Clojure",
     :link "http://planet.clojure.in/",
     :webmaster nil,
     :uri "http://planet.clojure.in/atom.xml",
     :authors ()}
    

    To parse a file:

    (def feed (parse-file "/path/to/some/atom.xml"))
    

    This function returns just a feed data structure.

    Remus supports options to specify how to communicate via HTTP; how to deal with broken or wrong encoded feeds; how to prevent receiving data you’ve already processed. I described all of this in the readme file and do not want to clone that text here. Instead, please look through that file and examples. I hope you’ll find the library helpful and will use it one day.

  • Что делать с залитым Маком

    Два дня назад я залил Мак. Он не работает, ждет ремонта в сервисном центре. Все из рук вон, не могу работать, не трекаю часы.

    Это уже второй раз, когда ноут ломается из-за воды. В сервисном центре я разговорился с мастером и вытянул из него полезные советы. Они показались мне особенно важными, поскольку я действовал наоборот и чуть не угробил технику.

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

    Забейте на несохраненные документы — вы их потом восстановите. На корректное завершение работы уйдет пара минут, что критично для системы.

    Бросайтесь в такси и езжайте в сервисный центр. Если вас не отпускают с работы (хотя какая работа без Мака) или вы сидите с грудным ребенком, передайте Мак таксисту и договоритесь с сотрудником центра, что он его примет.

    Сотрудники центра идут на такой способ приема техники, потому что знают: время критически важно. Даже если Мак был залит сурово, но доставлен через 20 минут, критических последствий можно избежать.

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

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

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

    Даже стыдно об этом вспоминать. Жаль, что не нашлось никого, кто бы спросил: Иван, зачем ты его разбираешь? Что хочешь там увидеть? Предположим, ты открыл его, а там вода. Значит, срочно ремонт. А теперь предположим, воды нет. Значит, все хорошо? Не факт. Если и правда обошлось, мастер его почистит от пыли и вернет через пару часов. Если нет, значит, вода вступила в реакцию, впиталась в батарею, и наступит жопа. Так что вариант один — в ремонт.

    Так и было в моем случае: открыл, а воды нет. Обрадовался. Пыль собрал, выправил полоски радиатора ножом. Собрал — не работает. Потерял 40 минут, пока ездил за специальными отвертками.

    В сервисном центре спрашиваю, а где вода? Мастер говорит — вот же, ушла в батарею. И действительно, правый блок вспух на два миллиметра. Сам этого не заметишь, только если обратят твое внимание.

    Теперь этот долбаный фен. Им нельзя пользоваться, потому что фен ускоряет процесс впитывания воды. Представьте эксперимент: на плотный картон поместили каплю. Если ее не трогать, то часть воды впитается, а другая высохнет. Если фигачить феном, она высохнет быстрее, но и впитывание будет происходить быстрее. Фен ускоряет оба процесса. Цель ремонта не высушить воду, а не допустить реакции деталей с водой. В данном случае фен делает вредную работу — ускоряет впитывание влаги.

    С осторожностью слушайте советы тех, кто “разбирается” в Маках. Не случайно взял это слово в кавычки. Если ваш знакомый просто снимал заднюю крышку и чистил пыль, это ни о чем не говорит. Специальный набор отверток дает +10 к уверенности, но ничего к знанию. Я и сам могу скручивать крышку по десять раз на дню и глазеть на потроха. Как это поможет реанимировать залитый Мак? Никак. “Разбирающийся” знакомый ничем не рискует, а вы — дорогой техникой.

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

    Короче, езжайте в ремонт асап. Теперь о том, как защитить Мак от воды.

    Вытирайте руки. В первый раз я залил мак каплями воды, которые стекали с влажных рук. Кажется, что ерунда, а в итоге смерть материнки и три недели ожидания новой из Москвы.

    Если капля попала на кнопки, не нужно на нее дуть. Так вы только загоните ее вглубь. Когда капля маленькая, она не может протечь в щель из-за сил поверхностного натяжения. Промокните ее ватной палочкой.

    Не держите кружку на одном столе с ноутбуком. Этому трудно следовать, потребуется усилие воли. На крайний случай пригодится хак. Кружка должна стоять на блюдце или подставке вдалеке от ноута. Взял кружку, поднес, глотнул, поставил обратно — туда, далеко, а не под самые руки.

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

    Купить подставку, которая держит Мак над поверхностью стола. Подойдет тем, у кого два внешний монитор и клавиатура.

    Надеюсь, что-то полезное я донес. Берегите технику Эпла. Иначе придется превозмогать на старенькой Ленове с Убунтой, но это тема отдельного рассказа.

  • Рост доллара

    У тех, кто живет в России, но работает за валюту, есть дурацкая черта — радоваться росту доллара. Прекратите это делать.

    Во-первых, это не доллар растет, а рубль падает.

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

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

    Не все работают за доллары. Если точнее, очень немногие. Врачи, учителя, госслужащие получают обычные рубли. От того, что ваш доход вырос на 10%, им не легче. Проседает вся страна.

    Если в стране начнется полная жопа, не помогут никакие доллары. Мудрое руководство может просто их национализировать, то есть изъять. Спасет только вывод их в другую страну. А в другой стране ваши сумасшедшие по меркам нищей России деньги будут равны среднему доходу. И придется пахать, чтобы просто обеспечить себя.

    Я согласен, что заработок в долларах лучше, и деньги в них хранить безопасней. Сам предпочитаю. Но ваша радость это пир во время чумы.

  • Проверка русской орфографии в Emacs

    Неделю назад добавил в Emacs проверку русской орфографии. Теперь проверяю заметки прямо в редакторе. Расскажу, как подружить Emacs с русским текстом и заодно об орфографии в принципе.

    Emacs умеет проверять текст без установки сторонних модулей. Для этого служат команды с префиксом ispell-. Например, ispell-buffer проверит весь буфер, ispell-region – выделенный фрагмент.

    Для проверки Emacs вызывает системную утилиту. Он передает ей слово, контекст и дополнительные параметры. Программа ищет слово по внутреннему словарю. Если оно найдено, то переходит к следующему слову. Если точного совпадения нет, программа предлагает похожие варианты для замены.

    По умолчанию Emacs использует одноименную программу ispell. Это старая консольная утилита, заменившая spell – еще более древнюю программу. Префикс i означает international, то есть проверку на любом языке при наличии словаря.

    Установить русский пакет в ispell долгое время не получалось. Его нет в репозиториях brew, поддерживается только Линукс. Сборка под Мак валилась ошибками в кодировках.

    Emacs работает не только с ispell, но и другими spell-совместимыми программами. К ним относится, например, aspell, утилита из проекта GNU. Она реализует тот же протокол обмена данными, что и ispell, но более мощная и современная.

    Поставим ее из brew:

    brew install aspell --with-lang-ru
    

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

    Полный список флагов можно посмотреть в формуле на Гитхабе.

    Чтобы Emacs понял, что теперь у нас aspell вместо ispell, скажем ему об этом командой:

    (setq ispell-program-name "aspell")
    

    Добавьте это выражение в свой .emacs файл. Необязательно перезагружать редактор. Чтобы изменения вступили в силу мгновенно, скопируйте этот же код в буфер *scratch*, поставьте курсор за последней скобкой и нажмите C-j.

    Начнем проверку на английском. Откройте любой файл с латиницей. Из списка команд, вызванного по M-x, выберите ispell-buffer. Редактор переключится в режим проверки:

    Когда spell-программа находит незнакомое слово, проверка останавливается в ожидании пользователя. Цифры от 0 до 9 служат для выбора подходящего слова. Клавиша i означает принять слово как исключение. Пробел означает пропустить слово.

    По окончанию проверки Emacs предложит сохранить правила в локальный словарь. Например, у вас было слово Postgres, о котором aspell не знал. Если в процессе проверки вы нажали i и сохранили локальные правила, то в следующий раз Emacs воспримет его как словарное слово.

    Чтобы проверить русский текст, переключите словарь командой ispell-change-dictionary. Выберите из списка пункт ru. Откройте файл на русском и запустите ispell-region.

    Проверка русского текста ничем не отличается от английского. Работают те же клавиши и команды. Вот как выглядит проверка этой заметки на этапе написания:

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

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

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

    Мой полный конфиг Емакса лежит на Гитхабе.

    А как дела с русским языком в вашем редакторе?

Страница 28 из 68