программирование
PCRE и UTF-16
Прочитал в документации по библиотеке PCRE, что с версии 8.30 она поддерживает кодировку
Написал два примера на Си: один для
# это я на своём «Маке» скомпилировал
~$ gcc-4.7 -I/usr/local/Cellar/pcre/8.32/include/ -L/usr/local/Cellar/pcre/8.32/lib/ -lpcre -std=c99 -o utf8 utf8.c
~$ gcc-4.7 -I/usr/local/Cellar/pcre/8.32/include/ -L/usr/local/Cellar/pcre/8.32/lib/ -lpcre16 -std=c99 -o utf16 utf16.c
# два файла в разных кодировках, почти 1,5 млн. строк, правда используется далеко не это количество
~$ wc -l utf8.txt
1424462 utf8.txt
~$ wc -l utf16.txt
1424462 utf16.txt
~$ time ./utf8
PCRE version: 8.32 2012-11-30
Yes!
…
Yes!
real 0m1.372s
user 0m1.286s
sys 0m0.039s
~$ time ./utf16
PCRE version: 8.32 2012-11-30
Yes!
…
Yes!
real 0m0.048s
user 0m0.004s
sys 0m0.035sЛибо я
Лично мне кажется, что API толком не работает и ошибка в том, что в pcre16_compile не указывается длина шаблона.
Уходим с телефоном, «МакБук» выключается
Причина, по которой я засел за Пайтон и стал изучать как из него работать с Bluetooth в том, что мне очень хотелось сделать следующую вещь: как только я покидаю рабочее место, мой ноутбук блокируется.
Идея выглядела просто: надо посмотреть присутствует ли в эфире мой смартфон, если нету, значит я
В общем, всё получилось у меня. Если хотите, чтобы у вас работало так же, то двигайтесь по шагам.
Шаг №1.
Нужно узнать так называемый «адрес» вашего устройства и привязать его к компьютеру. Тут ничего сложного нет, заходим в настройки «Блютуз» на «Маке» (они находятся в «Системных настройках»), привязываем его как обычно и переписываем себе 12 букв, разделённых минусами, это и есть адрес:

Шаг №2.
С этого шага потребуется уметь пользоваться терминалом. Создаём запускаемый файл
#!/usr/bin/python
import objc
import sys
from subprocess import call
objc.loadBundle('IOBluetooth', globals(), bundle_path=u'/System/Library/Frameworks/IOBluetooth.framework')
def CheckDevice(address):
dev = IOBluetoothDevice.withAddressString_(address)
if dev.isConnected():
return True
conn = dev.openConnection()
if conn == -536870185: # Bluetooth is off
return True
if conn == 0:
dev.closeConnection()
return True
return False
cmdtorun=(r'/System/Library/CoreServices/Menu Extras/User.menu/Contents/Resources/CGSession', r'-suspend')
try:
if not CheckDevice(sys.argv[1]):
call(cmdtorun)
except IndexError:
print("Usage: bt-lock <device address>")В скобках замечу, чтобы сделать файл запускаемым нужно в терминале выполнить следующую команду: chmod a+x
Шаг 3.
Создаём файл ~/Library/LaunchAgents/ru.bolknote.Bluetooth-lock.crontab.plist с таким вот содержимым:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>ru.bolknote.Bluetooth-lock.crontab</string>
<key>Program</key>
<string>/usr/local/bin/bt-lock</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/bt-lock</string>
<string>а̲д̲р̲е̲с̲ ̲в̲а̲ш̲е̲г̲о̲ ̲у̲с̲т̲р̲о̲й̲с̲т̲в̲а̲</string>
</array>
<key>Nice</key>
<integer>20</integer>
<key>StartInterval</key>
<integer>30</integer>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>И выполняем в терминале команду «launchctl load ru.bolknote.Bluetooth-lock.crontab.plist». Это всё.
Чтобы отключить всю эту марахайку, достаточно выполнить в терминале команду «launchctl unload ru.bolknote.Bluetooth-lock.crontab.plist» или выключить Bluetooth на ноуте.
Решение только для «Мака», как работать из Пайтона с Блютузом под другие операционные системы, я не знаю.
Bluetooth в Mac OS из Python
Я тут учусь работать с Блютузом из Пайтона на «Маке», пока сделал сканирование всех видимых в эфире устройств:
import objc
import time
from Foundation import NSDate, NSDefaultRunLoopMode
from AppKit import NSApplication, NSAnyEventMask
objc.loadBundle('IOBluetooth', globals(), bundle_path=u'/System/Library/Frameworks/IOBluetooth.framework')
class DeviceInquiry(NSObject):
def init(self):
self = super(DeviceInquiry, self).init()
self._inquiry = IOBluetoothDeviceInquiry.inquiryWithDelegate_(self)
self._stop = False
return self
def getfounddevices(self):
self._inquiry.start()
app = NSApplication.sharedApplication()
app.setActivationPolicy_(2)
while not self._stop:
time.sleep(.01)
app.nextEventMatchingMask_untilDate_inMode_dequeue_(NSAnyEventMask,\
NSDate.dateWithTimeIntervalSinceNow_(1), NSDefaultRunLoopMode, True)
return tuple((dev.getName(), dev.getAddressString()) for dev in self._inquiry.foundDevices())
@objc.typedSelector("v@:@@")
def deviceInquiryDeviceFound_device_(self, inquiry, device):
self._stop = True
@objc.typedSelector("v@:@iB")
def deviceInquiryComplete_error_aborted_(self, inquiry, err, aborted):
self._stop = True
print DeviceInquiry.new().getfounddevices()Модуль pyobjc (в маковском Пайтоне он уже есть) — это мост между Пайтоном
Последняя строчка — пример использования, выдаётся список списков, состоящих из двух элементов — имени устройства и его «адреса» (это шесть шестнадцатеричных чисел, разделённые минусом).
Юникодные часы
В Юникоде есть несколько символов часов (не знаю, отобразятся ли они у вас, вот они): «🕐🕜🕑🕝🕒🕞🕓🕟🕔🕠🕕🕡🕖🕢🕗🕣🕘🕤🕙🕥🕚🕦🕛🕧.»
Тут, как видите, шаг полчаса. Я вчера за завтраком сделал Юникодные часы, которые «ходят» поворотом символа (через

Рассказать я хотел не об этом. Я и раньше встречался с тем, что часть Юникода не воспринимается многими программами нормально, особенно что касается раздела «Эмодзи, например „Яндекс.Фотки“ не так давно порадовали меня следующим (стоило переименовать картинку, всё стало в порядке):

Редактор „Сублиме Текст 2“ часто падает, если в тексте программы встречаются эти символы, а вот „Сафари“ удивил больше всех. Он их, вроде бы, понимает,
"🕐".length; // 2
'🕐'[0]; // строка со «сломанным» символом
escape('🕐'); // "%uD83D%uDD50"То есть, он считает символы Эмодзи не одним символом, а двумя. Такой вот баг. Мне пришлось в коде на ДжаваСкрипте это учитывать.
Дополнение: в комментариях подсказывают, что вроде так и задумано. Так как этим символы представлены четырьмя байтами (суррогатной парой), ДжаваСкрипт, который не умеет работать с такой парой как с одним символом, разделяет его на два.
О стоимости доступа к объектам в PHP
Удивительное — рядом: недавно искали с нашими админами место в коде где больше всего тормозит вывод одной страницы одного из сайтов, сделанных в недрах нашей компании в незапамятные времена.
Код был довольно запутанный, попросили меня помочь. Место я вычислил. Если его закоментировать, страница начинала выдаваться не за десятки секунд, а за единицы.
Никогда такого не видел. Как вы думаете, что тормозило? Запросы к базе?
Вовсе нет.
После выборки из базы, данные выкладывались в массив сложных объектов, в данном месте это было массив из почти что 500 объектов, внутри объектов лежали другие объекты, а них — ещё. Заполнение этой структуры занимало немало времени, но тормозило другое — цикл перебора массива объектов с выводом свойств объектов третьей вложенности.
В цикле не было вызвано ни одной функции (кроме htmlspecialchars), а вывод всего этого хозяйства занимал порядка десятков секунд.
Тег шаблона (NOEMBED?)
Традиционно в HTML4 для этого используют тег SCRIPT у указанием
<script type="text/x-template" id="template-ok">
<div><div class="button">OK</div></div>
</script>Либо используют комментарии (у Сергея Чикуёнка был рассказ
Был раньше такой нестандартный тег COMMENT, но его сейчас никто не понимает, даже Эксплорер прекратил его поддержку, в данном случае он бы пригодился.
Мне вчера ночью подумалось, что можно использовать и более лаконичные теги — NOFRAMES или NOSCRIPT. Первый показывает своё содержимое, если браузер не поддерживает фреймы, второй, если выключены скрипты. Если выключенные скрипты ещё встречаются у сетевых параноиков, то браузера без поддержки фреймов сейчас и не встретишь, а если таковые и есть, то
Особенность же тегов в том, что они в нормальных условиях являются аналогом комментария, то есть не добавляют своё содержимое в DOM, поэтому они вполне пригоды на роль шаблонного тега.
<noframes id="template-ok">
<div><div class="button">OK</div></div>
</noframes>
<script>
alert(document.getElementById('template-ok').innerText); // содержимое шаблона
</script>Не сказать, что это
Когда я уже дописал эту заметку, мне пришла в голову мысль, что а) тег NOEMBED был бы, наверное, более семантичем, чем NOFRAMES, он имеет отношение к встраиванию контента, а я совсем про него забыл, б) тег EMBED был бы, наверное, ещё более семантичен, но, к сожалению, он слишком тяжёл для браузера, надо испытывать, но я предполагаю, что даже если контент явно незнакомый, браузер всё равно попытается угадать что это. Но надо провести испытания, конечно же.
Так что, я бы остановился бы на NOEMBED.
Вычисление без единой инструкции процессора
Это очень круто, цитирую почти полностью:
Авторы продемонстрировали, что механизм трансляции адресов на архитектуре x86 обладает полнотой Тьюринга, т. е. с его помощью можно реализовать любой алгоритм. С помощью хитрой настройки различных контрольных таблиц, которыми пользуется процессор, они вводят процессор в состояние, в котором он не может выполнить ни одной инструкции, т. к. непрерывно происходят исключения, но разные исключения в зависимости от приготовленных данных — и таким образом процессор вычисляет!
Известно, что одной инструкции условного перехода по вычитанию (вычисли
a=a-b, и если это меньше или равно нуля, перейди в c) достаточнодля Тьюринг-полноты. В этом хаке такая инструкция симулируется с помощью последовательности page faults (от невозможности загрузить данные), которая заканчивается double fault (когда указатель на стек уменьшается ниже нуля).Любопытно, что ни один существующий эмулятор x86 не мог правильно запустить этот хак, потому что он опирается на слишком извращенную конфигурацию контрольных таблиц, и на тонкие нюансы поведения процессора в этой извращенной конфигурации.
У всего этого даже есть практические применения, правда, в области, которая ничего хорошего и полезного миру не приносит — обнаружение того, что программа бежит под отладчиком или в виртуальной машине.
Таким образом вычисление происходит без единой инструкции процессора! Речь идёт о проекте trapcc, на Ютьюбе есть видео, где запущена известная игра «Жизнь», запрограммированная таким способом (код специально адаптирован под эмулятор Bochs).
Протокол «jar» в FireFox
К сожалению, не удаётся сейчас найти эту статью, но я
Я тогда ещё подумал, что ведь уже есть один браузер, который уже это умеет — это «Файерфокс». У него есть протокол «jar», который ровно это и делает: позволяет адресоваться внутрь
Я уже четыре года назад пробовал воспользоваться этим протоколом,
Итак, адрес с протоколом jar выглядит следующим образом:
jar:/files/jartest.jar!/foto.jpg
Первая часть урла представляет любой адрес, по которому можно скачать архив (тут могут быть использованы протоколы http, https, file, ftp,

Как видите, я поместил внутрь архива часть ЦСС и две картинки, одну из которых поставил задним фоном. Причём, как и в случае обычного урла, протокол по которому загружается ресурс можно опустить (часть «http», в данном случае), будет использован текущий протокол.
Но есть и бочка дёгтя. С пустым кешем или после обновления страницы архив грузится один раз, но если сделать полную перезагрузку страницы (⇧+⌘+R или шифт+контрол+R в Виндоуз), то загружается он столько раз, сколько раз ресурсов грузится на странице. Видимо,

О̷п̷е̷р̷а̷
«Опера» устала бороться, похоже:
Все наши новые продукты будут использовать движок WebKit для рендеринга и V8 для обработки JavaScript. Они будут основаны на опенсорсном браузере Chromium и его компонентах. Конечно же, браузер — это гораздо больше, чем просто движок, поэтому все эти перемены для обычных пользователей произойдут
где-то далеко под капотом. Такие пользователи заметят только улучшившуюся совместимость с сайтами, особенно мобильными, большинство из которых были как следует протестированы только в браузерах на WebKit.
Я бывший фанат «Оперы», собственно, я испытал к этому продукту всю гамму чувств: от ненависти до фанатизма. И хотя сейчас я придерживаюсь очень спокойного к нему отношения, мне всегда нравилась эта норвежская компания, которая несмотря на трудности,
Но бо́льшую часть времени я был яростным фанатом их браузера и сохранил к нему доброе отношение. Очень жаль, что «Опера» покидает нас как самостоятельный браузер, но, надеюсь, что с использованием чужого движка, она не растеряет свою энергию и креативность.
В новости есть упоминание, что «Опера» будет теперь участвовать в разработке движка «Вебкит», хочу пожелать им удачи!
Полезная «кошка»
Про антипаттерн «Useless cat» я рассказал, отдельной заметкой хочу описать чем может быть полезна команда cat, кроме вывода файла на экран. Немногие знают, что у этой команды есть ключи командной строки. В некоторых случаях очень полезно их знать, правда, в разных операционках они могут различаться.
Я приведу те, которые одинаковы у меня в «Маке» и на Линуксе, в моём смартбуке:
# вывести и пронумеровать все непустые строки
cat -b /etc/passwd
# вывести, включая непечатаемые символы (в нотации «^» и «М-»), в конце строки вывести «$»
# (зачем нужен в конце доллар я не знаю, видимо какой-то очень специальный случай)
cat -e /etc/passwd
# вывести, нумеруя все строки
cat -n /etc/passwd
# вывести, заменяя идущие подряд пустые строки на одну
cat -s /etc/passwd
# вывести с непечатаемыми символами, преобразуя табуляцию в «<i>^I</i>»
cat -t /etc/passwd
# вывести, включая непечатаемые символы (в нотации «^» и «М-»)
cat -v /etc/passwdКлючи, конечно же, можно комбинировать. Кстати, первый ключ я использовал в последнем варианте «ругающегося однострочника», очень удобно там было пронумеровать им строки, только я там не учёл, что строки нумеруются с единицы, а не с нуля.
Антипаттерн: useless cat
Есть такой антипаттерн программирования в командной строке как useless cat. Переводится не «бесполезная кошка» (хотя для смеха можно переводить и так), а как «бесполезная [команда] cat».
Несмотря на то, что многие команды — awk, sed, cut и прочие умеют самостоятельно читать из файла, программисты
# неправильно:
cat /etc/passwd | cut -d: -f1
# правильно:
cut -d: -f1 /etc/passwdЕсли команда не умеет принимать имя файла в качестве параметра, то и в этом случае cat не нужен, достаточно воспользоваться перенаправлением. Тут могут быть детали, так как синтаксис перенаправления гораздо богаче, чем используемое в 90% случаев простое перенаправление из файла и в файл и размер этого богатства разный в разных шеллах, я приведу пример для bash:
# плохо (пример для bash):
cat /etc/passwd | read firstline && echo $firstline
# можно так (такой синтаксис bash поддерживает не в полном объёме):
</etc/passwd read firstline && echo $firstline
# лучше так:
read firstline </etc/passwd && echo $firstlineВообще, стоит изучить внимательно синтаксис перенаправлений, потому что он позволяет делать такие вот вещи без лишних команд (опять bash):
# читаем файл /etc/passwd в массив, разделители элементов в файле — двоеточие
IFS=: passwd=($(</etc/passwd))
# читаем первые десять байт из последних десяти строк файла /etc/passwd
dd bs=1 count=10 if=<(tail -10 /etc/passwd) 2>&-/dev/random
В комментариях мне вопрос задали — откуда в компьютере взяться случайным числам. Казалось бы — там же всё детерминированно. С одной стороны — да, с другой стороны…
Помню, в «Спектруме» (это компьютер, на котором я работал больше всего в детстве), в Бейсике, был оператор RANDOMIZE — инициализация генератора случайных чисел. Если вызвать его
bolk@Bolk /$ php -r 'mt_srand(1); echo mt_rand();'
1244335972
bolk@Bolk /$ php -r 'mt_srand(1); echo mt_rand();'
1244335972Если же вызывать RANDOMIZE без параметров, то его значение инициализируется текущим временем. Это уже лучше, потому что в данном случае элемент случайности вносит сам пользователь — как просчитать когда он запустит программу? Какое будет время на часах? На «Спектруме» отследить запуск программы не получится, а без этого нельзя ответить на вопрос какое значение выдаст генератор случайных чисел.
Но на компьютерах посложнее, например, на том, с которого вы сейчас это читаете, отследить запуск проще простого, посмотреть в этот момент на часы — ещё проще. Что делать? Значит надо собирать больше «шумов» окружающего мира.
Какие «шумы» может собирать компьютер вокруг себя?
Как уже было сказано, сильную сумятицу в стройность машинной логики вносит пользователь, грех не пользоваться: нажатия клавиш, движения мышкой, запуск программ, управление ими. Ещё можно, например, снимать значения с загрузки процессора, со списка процессов, занимаемой процессами память и расходуемого время (при условии, что на машине работает сейчас пользователь), вполне источник случайных данных. Ведь эти значения зависят от действий пользователя.
Что делать, когда пользователь пошёл налить себе кофе? Вполне можно использовать шумы внешнего мира. Шумы в прямом смысле, с микрофона послушать что там снаружи происходит — окружающие звуки или просто шумы аудиотракта в отсутствие микрофона. Можно глянуть, что там бегает по сети — широковещательную активность других пользователей. Что ещё? Мало ли у компьютера датчиков? Например, можно смотреть что у нас там на с температурой на процессоре, которая зависит и от температуры в комнате, и от собственных шумов схемотехники датчиков.
Вот как выглядят показания температурных датчиков на моём ноуте, снимаемые каждую секунду:

Если присмотреться внимательно, можно увидеть колебания в градус, не очень много, но температурных датчиков у меня 13 штук.
Если время от времени снимать этот цифровой хаос, скапливать
Под занавес, наверное нужно прояснить — для чего нужны такие «суперслучайные» числа. Ну, казалось бы, инициализируем временем и все дела, для чего использовать
Ведь сертификаты для защиты генерируются вполне определённым образом на основании случайных чисел. Стоит ввести в тот же алгоритм те же числа и получим тот же сертификат.
A new hop
У Дмитрия Радищева (DiBR) в ЖЖ увидел. Попробуйте набрать в консоли
traceroute -m 100 216.81.59.173Подождите, пока сигнал выйдет за пределы вашей сети и наслаждайтесь! Для Виндоуз команда будет выглядеть так: «
Если хочется прочитать без лишнего мусора, то я вот такой вариант сделал (это под Виндоуз уже работать не будет):
traceroute -m100 -q1 216.81.59.173 2>&- | awk '/pisode/{_=1}{if(_)print$2}' | tr . ' 'ROT13 и ROT47 в Bash
Неожиданно сообразил, что функции ROT13 и ROT47 очень просто делаются в командной строке:
# Это ROT13, «крыша» превращается в «отливы»:
$ echo roof | tr n-za-mN-ZA-M a-zA-Z
ebbs
# А это ROT47, «привет» превращается в чёрт знает что:
$ echo Hello | tr '!-~' 'P-~!-O'
w6==@Непонятный баг с AJAX в IE8
В процессе переезда одного из наших проектов на новый сервер, Интернет Эксплорер восьмой версии стал выдавать

В этом месте в коде не было ничего криминального, создание объекта для «аякса», асинхронная посылка запроса и проверка свойств того что пришло. Методом проб и ошибок удалось выяснить, что ошибка возникает при попытке обращения к свойствам «status» и «responseText» (а так же «responseXML», в коде он не использовался, но я просто попробовал).
Промучавшись с полчаса, я догадался переключить IE на работу с объектом ActiveX Microsoft.XMLHTTP, вместо XMLHttpRequest, у первого диагностика получше — ему
На этот раз я получил нумерную ошибку (скриншота не сохранилось), по номеру которой я нашёл сообщение на сайте Микрософт, что ошибка связана с неверной кодировкой, пришедшей со стороны сервера. В «Хроме» посмотрел кодировку — оказалось, что кодировка с сервера приходит как «cp1251»:

Интернет Эксплорер такую кодировку не понял, один из админов вписал её руками, поскольку при смене версии ПХП заменили сервер FastCGI на
Видимо, встретив странную кодировку, IE не смог понять как ему читать то, что пришло, он вообще не заполнил некоторые свойства, а объект, попытавшись получить к ним доступ, не понимал в чём дело и выдавал пустую ошибку, которая и символизировала это «я не понял что произошло».
JS-string decode by Bash
Столкнулся я тут с необходимостью раскодировать строку в том формате, который используется в JSON, т. е. когда символы, кроме латиницы и ещё некоторых знаков кодируются как \uXXXX.
Можно было, конечно, вызвать
Сделал на «Баше» и утилитах командной строки (кстати, легко переделать, при желании, и на «sh»):
:|sed -E '' 2>&- && SED='sed -E' || SED='sed -r'
uNNNNhelper() {
printf $(echo -n "$@") | iconv -f utf-16be
}
uNNNN() {
eval $(
echo -n "$@" |
$SED '
s/([^[:alnum:]])/\\\1/g
s/^/echo /
s/((\\\\[Uu]....)+)/$(uNNNNhelper \1)/g
s/\\\\[Uu](..)(..)/\\\\x\1\\\\x\2/g
'
)
}
uNNNN 'Hello, \U043C\U0438\U0440!' # выведет «Hello, мир!»Бу: ООП в bash, дополнение
Дописал немного «Бу», библиотеку ООП для «Баша», о которой я рассказывал недавно. Прошлая версия не умела работать напрямую (не из методов, снаружи) со свойствами. Новая умеет.
# … пример из предыдущего поста, дополненный
Dog.New dog # создаём экземпляр «собаки»
$dog.cnt =100 # записываем в свойство «cnt» значение «100», обратите внимание на пробел перед «равно»
cnt="$($dog.cnt)" # чтение значения из свойстваПомимо этого, появилась возможность уничтожить объект (все ссылки на него становятся недействительными, их надо очистить вручную, а так же автоматический сборщик мусора, который лучше не включать (довольно заметно тормозит), но зато он уничтожает объекты сам, когда все переменные и свойства других объектов, указывающие на него, исчезают:
@Destroy $dog # yничтожаем объект, в $dog теперь мусор
Dog.New dog # опять создаём «собаку»
unset dog # удаляем ссылку
@Class.gc # вызов сборщика вручную
@Class.gc.on # включаем тормоза и автоматический сборщик мусора
Dog.New dog # и снова создаём «собаку»
dog2="$dog" # ссылка на тот же экземпляр «собаки»
unset dog
echo Объект ещё существует, осталась одна ссылка
unset dog2
echo Объекта уже нетКстати, при уничтожении объекта любым из этих способов вызывается деструктор (метод «__destruct»), если он есть, конечно.
«Магический экран» на CSS
У всех в детстве была игрушка «магический экран»? Такая прямоугольная штуковина, обычно из красного пластика с двумя крутилками, которые надо было поворачивать, чтобы
А все знают, что браузеры на основе «вебкита» («Хром», «Сафари» и им подобные) некорректно отрабатывают некоторые комбинации CSS3-селекторов? Они «забывают» их перерисовывать, если меняется состояние, зависящее
Меня раздрадает этот баг, ему много лет, его не правят

Вчера ночью я про него думал и меня осенило каким образом баг можно использовать, чтобы создать
На основе этого бага я наколдовал «магический экран» без использования Джаваскрипта (не забудьте, работает в «Сафари» или «Хроме»). Если вести справа налево кружки́ рисуются, если слева направо — стираются. «Крутилки» только для декора, они не работают.
Шаманство и контакт с космосом происходит вот в этом участке CSS:
.outer>i:hover+i+i {
width: 10px;
height: 10px;
background: gray;
border-radius: 50%;
z-index: 2;
margin: -2px 0 0 -2px;
}Поле для рисования состоит из кучи элементов размером 3×3, когда я наезжаю курсором на один из них, срабатывает «:hover» и меняет стиль кружка́, который находится сильно после того, на который я наехал курсором. Это нужно, чтобы «вебкит» не увидел момента, когда курсор уходит с элемента. «Вебкит» хоть и неправильно работает с селекторами, тем не менее содержит кучу «хаков», чтобы в распространённых случаях всё выглядело как надо.
Таким образом, браузер не получает события, что курсор с элемента ушёл и оставляет стиль как есть — я увеличиваю размер элемента до 10×10 и меняю цвет на серый, на экране за курсором остаётся шлейф из таких элементов справа от курсора. Если же двигаться слева направо, наезжая на кружки, то браузер видит нужные события и очищает стиль, кружки пропадают.
В самых свежих «Сафари» 5.1 и «Хроме» 24 мой «магический экран» работает.
InnoDB full-text search
Хорошие новости, оказывается, с версии 5.6.4 MySQL поддерживает полнотекстовые поиск в InnoDB (12 лет прошло с момента появления этого движка в Майэскюэле) и, кстати, в версии 5.5 и выше
POSTQUEL
POSTQUEL — это язык запросов, который
POSTQUEL расшифровывается как «POSTgres QUEry Language», «язык запросов Постгреса», он был разработам в 1985 году в Калифорнийском университете в Беркли под руководством Майкла Стоунбрейкера, POSTQUEL основан на языке запросов QUEL, который использовался на тот момент в БД «Ингрес».
Примеры того на что был похож POSTQUEL есть в польской Википедии:
Получить размер заработной платы сотрудника Ковальски (pracownicy — сотрудники, płace — зарплата):
retrieve (PRACOWNICY.placa) from PRACOWNICY where PRACOWNICY.nazwisko = "Kowalski"Все сотрудники старше 40 лет (wiek — возраст, nazwisko — имя):
retrieve (P.nazwisko) from P in PRACOWNICY where P.wiek > 40Найти все департаменты, целиком занимающие один этаж (pietro — этаж, dnazwa — сокращение от «название департамента»):
retrieve (DEPART.dnazwa)
where DEPART.pietro NOT-IN {D.pietro from D in DEPART where D.dnazwa != DEPART.dnazwa}«Постквел» был более формализованным языком, чем Эскюэль, все команды строились по одному образцу и не допускали вариаций. Других подробностей я не нашёл, к сожалению, детального описания языка мне обнаружить пока не удалось, было бы любопытно посмотреть на него и проанализировать сильные стороны.
Добавлено позднее. Я обнаружил документацию 1992 года на «Постгрес», где довольно подробно упоминается и «Постквел» (ссылка есть в комментариях). Интересный
Например, оперировал он объектами, поддерживал наследование (все примеры из упомянутой документации):
create STUD_EMP (location = point) inherits (EMP)Поддерживал массивы (индексы начинаются с единицы):
create SAL_EMP (name = char[], pay_by_quarter = int4[4])
append SAL_EMP (name = "bill", pay_by_quarter="{10000, 10000, 10000, 10000}")
retrieve (SAL_EMP.name) where SAL_EMP.pay_by_quarter[1] !=SAL_EMP.pay_by_quarter[2]Поддерживал историю, вот, например, срез данных с первого января 1970 по наши дни:
retrieve (E.salary)
from E in EMP["Jan 1 00:00:00 1970 GMT", "now"]
where E.name = "Sam"Была возможность создавать пользовательские типы (тут создаётся новый тип массива):
define type int_array
(element = int4, internallength = variable,
input = array_in, output = array_out)Так же как и пользовательские функции:
define function eq_area_circle
(language = "c", returntype = bool)
arg is (circle, circle)
as "/usr/postgres/tutorial/circle.o"
define function manager
(language = "postquel", returntype = EMP)
arg is (EMP)
as "retrieve (E.all) from E in EMP
where E.name = DEPT.manager
and DEPT.name = $1.dept"
retrieve (EMP.name)
where name(manager(EMP)) = "Joe"Была даже перегрузка операторов!
define operator =
(arg1 = circle, arg2 = circle,
procedure = eq_area_circle)И так далее.