Подписка на блог

РСС — лучше всего

Ещё есть автоматические трансляции в Тумблере и Же-же. Если что-то не работает, напишите мне: ilyabirman@ilyabirman.ru.

Программирование

Как сделать окно браузера нужного размера?

Когда я написал про окно Бирмана, у меня спросили, как я делаю окно браузера ровно 1024 в ширину. Разумеется, встроенными средствами компьютера. Я просто захожу в меню скриптов и нажимаю там нужный пункт:

Как сделать окно браузера нужного размера?

Но откуда у меня взялось это меню вместе с пунктами? Я просто написал скрипты. Запускаете редактор скриптов:

Как сделать окно браузера нужного размера?

Пишете в нём что-нибудь в таком духе:

tell application "System Events"
	set frontMostApp to (name of first process where frontmost is true)
end tell

tell application frontMostApp
	set allWindows to (every window where visible is true)	
	set frontWindow to item 1 of allWindows
	tell frontWindow
		set bounds to {0, 21, 1024, 1557}
	end tell
end tell

И сохраняете. Теперь при запуске этого скрипта активное окно будет становиться нужного размера. Но это скорее всего будет Файндер, ведь вы из него запустили скрипт. Поэтому идёте в настройку редактора скриптов и включаете там меню скриптов снизу:

Как сделать окно браузера нужного размера?

Заходите в это меню, жмёте Open Scripts Folder → Open User Scripts Folder. Перемещаете свой файл скрипта в эту папку — и всё, этот скрипт показывается в меню.

Таким образом можно делать любые скрипты для любых приложений, например у меня несколько полезных для Айтюнса написано:

Как сделать окно браузера нужного размера?

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

11 июня   Айтюнс   браузеры   лайфхак   программирование   Сафари   Эпл

ПХПШторм и рефакторинг при переименовании файла

В заметке о ВС Коде я написал:

Однажды я видел, как разработчик переименовывал файл в «ПХПШторме». На экране несколько секунд заполнялся прогрессбар. Нет, спасибо.

Мне написал Александр Яскевич:

То, что ты видел — рефакторинг. Если на этот файл в проекте были ссылки, ПХПШторм их также менял в то время, пока ты наблюдал прогрессбар. Ну или просто искал. Даже если ничего не нашел, время на поиск тратится. В таких мелочах ИДЕ от редактора и отличается.

Я в курсе, что это рефакторинг. Тут есть две проблемы.

Во-первых, непонятно, зачем ему искать? Он же ИДЕ. Даже «просто редактор» умеет индексировать проекты в фоновом режиме. Он безо всякого поиска знает, где упоминается мой файл. И даже если действительно нужно изменить упоминания в нескольких файлах, на современном компьютере это не займёт заметного времени. Поэтому рефакторинг прогрессбару не оправдание.

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

8 мая   программирование

Как прикрутить поисковый движок «Роза»

Я уже рассказывал, что в новой Эгее 2.6 — новый поисковый движок «Роза» Романа Парпалака. На примере Эгеи расскажу немного о том, как вы можете использовать его в своих продуктах.

Что делает Роза

Роза — движок поиска по переданным ему данным.

У Розы нет «паука» для индексации. Это специально. В случае с движком блога, например, нет никакого смысла искать ссылки, ходить по страницам, разбирать их код. И ещё убеждаться, что не индексируешь одну и ту же заметку несколько раз, потому что она встретились на страницах разных тегов. Это лишняя работа: приложение-клиент знает, как устроены данные в нём, и может отдавать их поиску сразу «в чистом виде».

Роза понимает три команды: «проиндексируй вот это», «удали из индекса вот это» и «найди всё вот по этому запросу». Как устроен индекс и как она находит — клиенту знать не нужно, это чёрный ящик. Клиент должен только обеспечить Розе доступ к хранилищу, где она будет держать индекс, и своевременно сообщать об изменениях, чтобы этот индекс был актуален.

Таким образом, поиск — это взаимная работа клиента и Розы. Прикрутить её сложнее, чем использовать движок поиска общего назначения. Зато понимание структуры данных позволяет гибко форматировать результаты и учитывать их природу при ранжировании.

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

Как прикрутить поисковый движок «Роза»

Теперь к делу.

Хранилище

Хранилище — это объект, через который Роза взаимодействует с базой данных. Клиенту нужно передавать его Розе и для индексации, и для поиска. Поэтому удобно иметь функцию, которая его отдаёт, когда нужно:

function e2_rose_storage () {
  static $pdostorage = null;

  if ($pdostorage === null) {
    $pdo = new \PDO (
      'mysql:'.
      'host='. $_db_server .';'.
      'dbname='. $_db_name. ';'.
      'charset=utf8',
      $_db_user,
      $_db_password,
    );
    $pdo -> setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    $pdostorage = new PdoStorage ($pdo);
  }

  return $pdostorage;
}

Для простоты я убрал некоторые специфичные для Эгеи вещи. Я тут проверяю, нет ли уже и так созданного хранилища; если нет, то создаю; и в любом случае его возвращаю. На место переменных, начинающихся с подчёркивания, надо поставить настоящие реквизиты базы данных.

Индексация

Задача клиента — «рассказать» Розе о данных, чтобы она построила свой индекс. Для этого нужно добавить каждую сущность (в Эгее — заметку) в индекс:

$stemmer = new PorterStemmerRussian ();
$indexer = new Indexer (e2_rose_storage (), $stemmer);
$indexable = new Indexable (
  $_note_id,
  $_note_title,
  $_note_text
);
$indexer -> index ($indexable);

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

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

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

Можно отдавать и адрес страницы при индексациии, но для Розы это просто текстовое поле, она не пойдёт по этому адресу низачем, просто вернёт его потом вместе с результатами поиска. Я этим не пользуюсь, потому что мне сподручнее получить адрес заметки из неё идентификатора, а не от Розы.

Индексация одной заметки — быстрая операция, поэтому поддержание индекса в актуальном состоянии не составляет проблемы.

Но при обновлении Эгеи со старой версии, мне нужно аккуратно проиндексировать все написанные ранее заметки. В случае с моим блогом это около четырёх тысяч заметок. Поэтому просто запустить их индексацию в цикле нельзя: даже если операция уложится во временной лимит ПХП, всё это время пользователь будет думать, что сайт не отвечает. А если не уложится, то пользователь вообще ничего не увидит. Как обеспечить безболезненную фоновую индексацию — тема отдельной заметки, но важно, что это забота клиента, а не Розы.

Когда пользователь удаляет или отзывает заметку, я делаю примерно так:

$stemmer = new PorterStemmerRussian ();
$indexer = new Indexer (e2_rose_storage (), $stemmer);
return $indexer -> removeById ($_note_id);

Поиск

Чтобы искать, нам понадобится файндер (а ему понадобится стеммер):

$stemmer = new PorterStemmerRussian ();
$finder = new Finder (e2_rose_storage (), $stemmer);
$finder -> setHighlightTemplate (
  '<span class="'.CSS_CLASS_HIGHLIGHT.'">%s</span>'
);

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

Теперь можно сделать запрос и достать результаты поиска:

$rose_query = new Query ($query);
$rose_query -> setLimit (SEARCH_LIMIT); 
$resultSet = $finder -> find ($rose_query);

Тут я не могу продолжать как ни в чём не бывало и не сделать ремарку. Объекто-ориентированное программирование делает мне больно. Просто так написать нельзя:

$results = rose_find ($db_link, $query, SEARCH_LIMIT);

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

Итак, после того, как мы получили $resultSet, мы уже можем выводить результаты. Но это тот момент, когда можно попросить Розу подкрутить релевантность, что я и делаю:

foreach ($resultSet -> getFoundExternalIds () as $external_id) {
  $note_id = e2_note_id_from_rose_id ($external_id);
  $note_rec = e2_note_by_id ($note_id);
  if ($note_rec['IsFavourite']) {
    $resultSet->setRelevanceRatio ($external_id, 2);
  }
}

Так я поднимаю избранные заметки повыше.

Тут же Розу можно попросить сделать «сниппеты» — так называются фрагменты, выводящиеся в результатах поиска. Роза сама находит предложения с найденными словами, подсвечивает в них эти слова и собирает маленький кусок текста, достаточный для узнавания заметки в выдаче. Это делается так:

$snippetBuilder = new SnippetBuilder ($stemmer);
$snippetBuilder -> setSnippetLineSeparator(' · ');
$snippetBuilder -> attachSnippets ($resultSet, function (array $external_ids) {
  $result = array ();
  foreach ($external_ids as $external_id) {
    $note_id = e2_note_id_from_rose_id ($external_id);
    $note_rec = e2_note_by_id ($note_id);
    $note_pack = e2_package_note ($note_rec);
    $result[$external_id] = $note_pack['text'];
  }
  return $result;
});

Чтобы собрать сниппеты, Розе нужны полные тексты заметок — сама она их не хранит, а о структуре моей базы данных ничего не знает. Поэтому в метод attachSnippets мы тут передаём колбек, который Роза вызывает, чтобы их получить. Он, как видите, вытаскивает заметки из базы.

После этого можно собрать результаты:

foreach ($resultSet -> getItems () as $external_id => $item) {
  $note_id = e2_note_id_from_rose_id ($external_id);
  $note_rec = e2_note_by_id ($note_id);
  $note_pack = e2_package_note ($note_rec);
  $note_pack['title' ] = $item -> getHighlightedTitle ($stemmer);
  $note_pack['text' ] = '<p>'. $item -> getSnippet () .'</p>';
  $note_packs_found[] = $note_packs;
}

Я подсвечиваю найденные слова в заголовке и показываю сниппет вместо текста заметки.

Код выдачи результатов поиска неэлегантен — хотя бы потому, что я трижды прохожусь циклом по этим результатам, многократно вызываю одни и те же функции с одними и теми же параметрами. Никаких измеримых проблем эта неэлегантность не создаёт, а её исправление потребовало бы изменения АПИ Розы. Поэтому пока пусть будет так.

В этой заметке я упускаю часть слишком специфичных для Эгеи решений, фрагменты кода местами несколько упрощены. Из примеров полностью выпилен весь код, отвечающий за «смешение» результатов поиска Розы и стандартными средствами БД (я это делаю, потому что у Розы более высокие системные требования, чем у Эгеи, и на некоторых хостингах она может просто не завестись).

Если захотите использовать Розу в своих продуктах, своими мыслями делитесь с Романом, а не со мной.

30 апреля   веб-разработка   программирование   Эгея

ВС Код

Это сумбурный пост, потому что редактировать его мне некогда.

Я много лет использовал редактор кода «Сублайм-текст». Он не дотягивал по функциональности даже до «Эдитплюса», которым я пользовался на Винде больше десяти лет назад, но казался мне самым приятным и продвинутым из того, что есть на Маке. Всякие ИДЕ я не рассматривал — они уродские и тормозные. Однажды я видел, как разработчик переименовывал файл в «ПХПШторме». На экране несколько секунд заполнялся прогрессбар. Нет, спасибо.

Но месяц назад я нашёл «ВС Код». Кажется, это лучшее, что сделал Микрософт. Он устроен как идеальное ИДЕ: ИДЕ нет, а функция выполняется.

ВС Код

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

Зачем разная расцветка разным проектам? Например, мне нравится, что я просто узнаю по палитре, что передо мной: мой сайт, советы или Эгея.

Плагины — кайф, они умеют много чего. У меня установлена штука, которая на лету проверяет синтаксис ПХП, по одной кнопке находит определение функции в другом файле или все использования функции в проекте. Я понимаю, что это стандартная фича ИДЕ, но тут это идёт без фич «устанавливать и настраивать год», «тормозить» и «выглядеть как говно» в комплекте.

Управление плагинами в сто раз удобнее, чем в Сублайме. Там это всё спрятано, а тут — на виду. Легко искать, включать-выключать, обновлять.

Очень удобный встроенный гит. Прямо в редакторе подсвечивает изменения с прошлого коммита, даёт закоммитить новое, показывает диффы — никуда ходить не надо. Ну или вот, навёл на строку:

ВС Код

Она вытянула блейм из гита и документацию по функции ПХП. Самое крутое, что чтобы это было, я не ничего не делал — оно как-то само. Или, может, это плагин GitLens, который я тоже установил? В любом случае, я даже не заметил.

Можно считать это главной радостью ВС Кода: он просто врубается, как у тебя что устроено, что у тебя там есть, и заставляет это всё работать. Есть, например, ещё встроенная фича Tasks, которая сама находит твои package.json и gulpfile.js и тоже заставляет их работать без настройки. Тут, правда, сначала её надо один раз попросить включиться. Надеюсь, они додумаются в будущих версиях сделать это также прозрачно, как гит.

Кстати, лайфхак: я настроил пять боковых панелей (файлы, гит, поиск, отладка и расширения) на ⌘1...⌘5. Это стандартные для Мака сочетания для переключения между разными видами. Надо ведь постоянно переключаться между файлами и гитом.

Есть всякие мелкие недостатки, конечно, в том числе по сравнению с Сублаймом, но в целом — кайф.

Каждый месяц выходят обновления, в которых приносят миллион всего нового. Почитайте, например, описание апдейта за март.

2017   программирование   софт

Что почитать на выходных — 145

Вот:

  1. Developers’ side projects. Джоел Сполски рассказывает, как страшно в Америке программистам жить.
  2. The Case Against Progressive Enhancement’s Flimsy Moral Foundation.
  3. Why time management is ruining our lives. «The better you get at managing time, the less of it you feel that you have». Это да. «Part of the problem is simply that thinking about time encourages clockwatching, which has been repeatedly shown in studies to undermine the quality of work». И это да. Но вот это: «Work expands to fill the time available for its completion» — я не понял, почему проблема. Это подаётся так, будто настоящая цель тайм-менеджмента — максимизация времени безделья.
  4. Apple’s 2016 in review. Очередной разнос Эпла. Что-то последнее время их пишут все кому не лень; этот очень хороший. Про Мак Про (который не обновлялся четыре года): «what they built was a device based around their own ego needs of proving their critics wrong, not a device that served the purposes of their power users». И ещё: «They really miss Katie Cotton, because they seem to have gone tone deaf on how they explain the story of the product». Вообще, увольнение Кейти — самое удивительное решение Эпла за последнее время.
  5. Сначала конструкция, потом сетка. Игорь Штанг.
  6. Великая Отечественная Война. В разное время так назывались разные войны.

Однажды в Википедии: Moving sofa problem

Спасибо спонсору рубрики — рассылке «Дизайнерский дайджест». Каждую пятницу её читатели получают большое структурированное письмо с обзором статей и книг, обучающих материалов, инструментария и вдохновляющих проектов в сфере графического дизайна. Свежий выпуск приходит сразу после подписки, присоединяйтесь.

Склонировать структуру папок и файлов

Мне нужно было скопировать структуру папок и файлов с одного диска на другой. Чтобы всё лежало так же по папкам, под теми же именами, но каждый файл весил 0 байт.

Смысл этой операции вот в чём. Изредка мне нужно найти что-нибудь среди файлов десятилетней давности. У меня скопилось несколько жёстких дисков с разными архивами. И есть специальная коробочка, в которую можно вставить жёсткий диск и подключить по УСБ. Меня бесит, что я порой с третьего раза нахожу, на каком из них лежит то, что мне нужно.

Я придумал сделать папки, в которых будет лежать полная файловая структура каждого из моих жёстких дисков без самих данных. Тогда я смогу мгновенно находить любой файл по имени спотлайтом, а уже потом сразу втыкать жёсткий диск с настоящим файлом.

Пришлось попотеть, чтобы понять, как это сделать. У меня получилось так:

cd папка_которую_клонируем
find . -type d -print0 | xargs -0 -I {} mkdir -p папка_куда_клонируем/{}
find . -type f -print0 | xargs -0 -I {} touch папка_куда_клонируем/{}

Сложность была в том, что find возвращает список найденных файлов с пробелами в именах, и когда такие файлы передаёшь куда-то ещё, всё взрывается. Пришлось просить find в конце имени каждого найденного файла ставить символ 0 (-print0), а потом с помощью адской команды xargs это разбирать и скармливать в качестве аргументов другим командам. Учитывая, что я раньше ничего сложнее apachectl restart не писал, это была жесть.

Добавлено через полчаса: Читатели рассказали мне про -exec

2016   лайфхак   программирование

Слова weight и height

Часто веб-разработчиков ставит в лингвистический тупик такой ЦСС-код:

font-weight: normal;
line-height: 1.4em;

Запомните: слово height читается «хайт» несмотря на то, что слово weight читается «вейт».

2016   английский язык   программирование

Как работает мой сайт

Мой сайт работает на моём самописном движке на ПХП (единственное исключение — раздел «Блог», о нём в конце).

Файлы страниц сайта лежат в папках, соответствующих урлам разделов, например страница про Ангстрем лежит на сервере под именем .../www/projects/angstrom/angstrom.php. Задача этого файла — сгенерить ХТМЛ смысловой части этой страницы.

Метаданные

Рядом с файлом имя-папки.php должен лежать файл метаданных _имя-папки.php. Для Ангстрема он выглядит примерно так (выкинул часть полей для простоты):

<?php return array (

  'logo' => 'angstrom',
  'value' => '20140201',
  'title' => 'Ангстрем', 

  'x-showcase-title' => 'Ангстрем, конвертер всего',
  'x-copyright-years' => '2014...',

  'languages' => array (
    'english' => array (
      'title' => 'Ångström',
      'x-showcase-title' => 'Ångström, the converter',
    ),
  ),

) ?>

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

Там умная и гибкая система, которая позволяет делать отличия между сайтами на разных языках (ilyabirman.ru и ilyabirman.net) только там, где они нужны: домен, текст, правила типографики, твиттер-акаунт для шаринга; но всё остальное хранить в одном месте один раз.

Самое главное в файле метаданных — это поле logo. Это постоянный идентификатор страницы, который не поменяется, если я вдруг решу перенести её в другую папку. На нём завязаны многочисленные макросы. Например, на главной у меня есть этажик, где я показываю разные проекты в горизонтальной прокручиваемой полосе — «витрине».

Вот примерный код, который её рисует (подсветка синтаксиса глючит):

<?php $showcase_elements = array (
  'angstrom',
  'moscow-metro-multiplication',
  'therules-2-for-ios',
  'chelyabinsk-trams-2015',
  'emcee',
  'train-thirteen',
  'wireless-dj',
  'snooker-results-display',
  'moscow-metro-poster-vdnh',
  'forebruary',
  'moscow-metro-nanomap',
); ?>

<?php foreach ($showcase_elements as $showcase_element) { ?>
  <div class="b-showcase-element" style="width: 160px">
    <div class="b-showcase-element-image-wrapper">
      <div>
        <a href="<?= HREF ($showcase_element) ?>" class="nu">
          <img
            src="<?= FOLDER ($showcase_element) ?>i/icon-160@2x.png"
            alt="<?= strip_tags (TITLE ($showcase_element)) ?>"
            width="160" height="160"
          />
        </a>
      </div>
    </div>
    <div class="b-showcase-element-title">
      <a href="<?= HREF ($showcase_element) ?>">
        <?= EX ('showcase-title', $showcase_element)?>
      </a>
    </div>
  </div>
<?php } ?>

Макросы

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

  • HREF ($logo) возвращает полный урл страницы по её идентификатору;
  • FOLDER ($logo) возвращает путь к папке, в которой лежит страница;
  • TITLE ($logo) возвращает название страницы;
  • EX ($what, $logo) возвращает значение поля x-something из файла метаданных.

Я, как видите, использую EX и поле x-showcase-title для того, чтобы показывать особые заголовки в «витрине». Если я вдруг решу переименовать один из проектов и перенести в другую папку, и ещё сделать про него страницу на французском, чтобы она была доступна по адресу ilyabirman.net/french/обычный-путь-к-проекту — это займёт пару минут, не считая времени написания французского текста. При этому создавать папку /french/ на сервере и копировать туда все файлы не придётся — языковые элементы урла обрабатываются отдельно и на структуру папок на сервере не влияют.

Есть и другие макросы. CHILDREN вернёт массив всех дочерних для данной страниц. Например, в разделе проектов их список автоматически дополнится новым, если я создам подпапку со страницей нового проекта в ней.

А ещё у меня на страницах бывают переключалки между связанными страницами, вот, например, такой переключалкой провязаны несколько рассказов про Лондон. Это работает, потому что эти страницы связаны в одну группу через поле group в файле метаданных. Они при этом могут лежать вообще по любым урлам, их просто вернёт GROUPLINGS. Если одна из страниц группы окажется недоступна на одном из языков — не беда, значит не попадёт в список. Движок не станет генерить мёртвые ссылки.

Или вот есть ещё WITHIN, определяется так:

function WITHIN ($what, $id = false) {
  return AT ($what) or INSIDE ($what, $id);
}

Удобно использовать в меню, например, в котором плашку у текущего раздела надо поставить если мы в нём или любых его подразделах.

Есть макрос LANG, который возвращает текущий язык. Его удобно использовать, если страницы на разных языках отличаются двумя-тремя строками текста. Но чтобы не писать сто раз if (LANG == ’russian’) { ... }, можно просто положить в папке два файла — angstrom-english.php и angstrom-russian.php, тогда движок сразу возьмёт нужный из них.

Ещё есть TAIL, OFFSET, SIBLINGS, NEIGHBOURS и всякие другие, которые позволяют компактно и внятно выражаться в коде.

Я это называю макросами, а не функциями, потому что это точнее передаёт смысл, и ещё их можно вызывать без параметра $logo и без скобок (если других параметров нет), и тогда они сработают для текущей собираемой страницы:

<h1><?= TITLE ?></h1>

Шаблоны

У любой страницы в файле метаданных может быть поле apply-template — оно говорит движку, что надо пропустить страницу через определённый шаблон перед тем, как заворачивать в обёртку из меню и подвала.

Например, в подвале любого рассказа о поездке я даю ссылки на соседние. Их сколько нужно возвращает макрос SIBLINGS. Но я не копирую этот этаж из рассказа в рассказ — для этого у меня есть шаблон world-story, который применяется ко всем рассказам из поездок.

Шаблон может не просто завернуть страницу во что-то, но и как угодно её обработать перед использованием.

Вот начало файла .../www/world/london-2011-may/london-2011-may-russian.php:

Лондон — лучший город, где мне доводилось бывать.
IMG_0333.jpg Парламент и Биг-бен в Лондоне

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

Похоже на текст из редактора Эгеи, правда? Потому что я тут использую Нисден — форматтер Эгеи. Шаблон world-story автоматически пропускает текст через него. Поэтому тут автоматически работает всякая резиновость картинок, фоторамы и всё остальное, и в результате сам собой получается рассказ про Лондон.

Блог

Теперь про блог. Блог работает на Эгее и живёт своей жизнью, несмотря на внешнее сходство с остальным сайтом. Эгея, в отличие от остального сайта, используют базу данных для хранения заметок, комментариев и прочего. Сайту никак не мешает, что в папке /meanwhile/ у него живёт что-то «неродное». Он не находит там файла _meanwhile.php и поэтому считает, что эта папка для него не представляет ценности.

Мне надо, чтобы в блоге у меня использовался ЦСС с основного сайта, но всё же в нём есть несколько своих особенностей, поэтому напрямую я не могу залинковать тот же самый файл. Чтобы не носить общие для сайта изменения из одного файла в другой, я использую Галп, который автоматически собирает нужную версии ЦСС-файла для блога.

Ещё, как вы знаете, у меня есть русский и английский блоги. На самом деле их выдаёт одна и та же копия Эгеи, которая в зависимости от домена использует разные таблицы в базе данных.

Это недокументированная функция, но по секрету скажу что там, где у вас в Эгее лежит папка /user/, у меня лежит папка /users/ с двумя подпапками. Да, Эгея умеет быть многопользовательской уже много лет! Только никому не говорите. Если серьёзно, это работает на костылях. Заранее говорю, что не буду отвечать на письма с вопросом «как мне сделать так же».

2016   программирование   Эгея   этот сайт

Что посмотреть с ВВДЦ-2016

Кроме очевидных:

...я посмотрел ещё несколько сессий, которые меня заинтересовали:

  • 203. What’s New in Cocoa. Это просто всегда смотрю на всякий случай. Ура, дадут перетаскивать несистемные элементы правой стороны меню.
  • 205. What’s New in Cocoa Touch. Это тоже обязательно к просмотру, чтобы быть в курсе дела.
  • 208. What’s New in watchOS 3. Много интересного про дизайн и для дизайнеров. Порадовала идея вместо прогрессбара («делаем...») показывать галочку («задание принято!»), чтобы дать человеку спокойно опустить руку.
  • 217. Introducing SiriKit. Hey Siri, say hello to apps. Было интересно, как оно спроектировано. Плата за простоту подключения — негибкость. Ни к Ангстрему, ни к Правилам русского языка, например, не прикрутить.
  • 403. Swift API Design Guidelines. The Grand Renaming. Это прям самая клёвая сессия, про дизайн АПИ.
  • 501. Advances in iOS Photography.
  • 509. Speech Recognition API. Наконец-то, полезная штука.
  • 701. Introducing Apple File System. A snapshot of the next generation in storage. Давно жду новую файловую систему, поэтому было интересно. Снэпшоты кайф, должны сильно улучшить тайм-машину, а ещё, вероятно, сделают возможным лёгкую реализацию многопользовательскости на айпадах.
  • 705. How iOS Security Really Works. Интересно для общего развития. Чувак порадовал: «Злоумышленники устанавливают на ваши телефоны кейлоггеры, шпионские программы, неотключаемую рекламу. Откуда мы это знаем? Мы это видим на других платформах».
  • 712. Working with Wide Color. Посмотрел, чтобы быть лучше готовым к светлому будущему, когда основы перевернутся и в вебе тоже. Сколько же всего приходится взорвать в системе, чтобы поддержать другую цветовую модель!
  • 803. Typography and Fonts.
2016   ай-разработка   программирование   Эпл

Что почитать на выходных — 128

Вот:

  1. Кучка сложностей в простой обёртке. Шурик Бабаев рассказал подробности о внутренностях Ангстрема.
  2. Как создавался транспортный бренд Будапешта.
  3. What is the history behind the «breathing» sleeping LED on Apple laptops? «Apple carried out research into breathing rates during sleep and used that figure to derive a model for how the light should behave».
  4. Медитация и разумная внимательность. Рахим Давлеткалиев объяснил, зачем.
  5. Вальтер Скотт, Майн Рид и другие. Аль Капоне бы убил за такое.
2016   Ангстрем   дизайн   программирование   транспорт   чтиво   Эпл
Ранее Ctrl + ↓