AppleScript и Тетрис

Тетрис (20.11КиБ)
Непритязательный внешний вид получившегося Тетриса

Я тут книгу читаю про хакеров (в первоначальном смысле слова) — «Хакеры. Герои компьютерной революции». Книга довольно занудная, но тот дух, который она пытается передать, я ещё очень хорошо помню. Ассемблер, такты, хаки, придуманные трудности — всё это было как специи в программировании. Сейчас как-то чем дальше, тем преснее.

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

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

Для тех, кто не знает, надо наверное пояснить. ЭплСкрипт — это язык автоматизации пользовательских сценариев работы, он умеет управлять приложениями (с разной степенью успеха) и кое-какими вещами в «МакОСи».

Так как возможности что-то рисовать в нём нет, то стакан и фигуры сделаны из уменьшенных окошек приложения «TextEdit» — я их создаю по потребности и масштабирую к малому размеру. Получаются такие белые шарики, из которых всё и состоит.

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

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

Кажется это первая и единственная игра в реальном времени на ЭплСкрипте.
2 комментария
9 октября 2017 23:19

Передача по ссылке в AppleScript'е

ЭплСкрипт, конечно, очень странный язык. С одной стороны, ребята явно старались сделать программирование похожим на написание текста на естественном (английском) языке, с другой стороны, все кишочки спрятать не удалось. Любимые мои грабли — это передача значений по ссылке.

У этой штуки есть одна особенность, которую надо знать. Код ниже перебирает список и выводит в консоль всякую информацию об единственном элементе, который в списке содержится:
repeat with itm in {false}
	log itm -- Выведет «false»
	log class of itm -- Выведет «boolean»
	log itm is false -- Выведет… «false», хм
	log itm is true -- И снова «false»
end repeat
Непонятно, да? Элемент булевского типа, но не «истина» и не «ложь», как так? Дело в том, что этот элемент — ссылка. И прежде чем его с чем-то сравнивать, надо получить его значение. Вот так нормально:
repeat with itm in {false}
	log contents of itm is false -- Выведет «true»
end repeat
Контринтуитивно и неясно какую пользу это приносит, но вот так сделано.
2 комментария
9 октября 2017 20:59

Как мне AppleScript

Миша, мой коллега, под постом, где я написал про интерпретатор Brainfuck на AppleScript с беспокойством осведомился, не подсел ли я на AppleScript.

Краткий ответ: нет.

Длинный ответ таков.

Мне непонятно текущее состояние AppleScript. Очевидно, что концепция «пользователь пишет программы на английском» вполне себе ничего. Для непрограммистов это был бы выход. А для программистов такой язык жутко неудобен. По понятными причинам. Программисты привыкли писать много, а на велиречивом AppleScript писать не каждому понравится (не пишу «никому», потому что существует же Objective C). Все эти сокращения в языке — «собачки», доллары и разные скобочки, их нужно помнить, но они здорово экономят время при написании программы и при её чтении. Потому что они короткие и их больше помещается на экране.

Текущее состояние непонятно, потому что цели своей авторы языка не достигли. До сих пор нужно писать «set Var to Var + 1» и нельзя «set Var to Var plus one», какой же это английский? При этом язык уже полтора года не развивается.

То есть проблема «иногда быстро писать мелкие программы» явно пока не решена. Так как для этого «иногда» надо иметь память робота, чтобы вспомнить через несколько месяцев как в этом языке что-то проверить или присвоить. Сам язык ещё ничего, запоминающийся. Но если хочется чего-то чуть более серьёзного, то приходится обращаться к специальному API.

Например, чтобы вызвать текстовый редактор и написать там «Hello», нужно сделать следующее:
tell application "TextEdit"
	activate
	tell application "System Events" to keystroke "hello"
end tell
Я открываю приложение TextEdit (так встроенный в MacOS текстовый редактор называется) и прошу System Events понажимать в редактор несколько клавиш. Выделенное наклонным — это как раз пример такого API. Причём, если написать в кавычки «³˚¹⁄₃¹⁄₂», то программа либо не сделает ничего, либо напечатает в редактор ерунду. Всё устроено так, как будто System Events действительно жмёт клавиши на клавиатуре. А вот эти символы система не знает как ввести. То же будет с китайскими иероглифами, например.

Ещё, когда я только начал знакомиться с AppleScript, у меня было заблуждение, что AppleScript — язык общего назначения, вроде PowerShell или Bash. Ничего подобного, вместо bash в Mac OS есть bash. AppleScript толком не умеет даже получить данные от пользователя, скажем перехватить нажатие клавиши (и нет ничего встроенного, что может ему в этом помочь), а уж о том, как мало он умеет самостоятельно выводить и говорить нечего.

Так что симпатии к языку у меня не появится, думаю. Не для меня он. Но писать я на нём иногда буду, я и на CMD много странного писал в своё время.

Brainfuck на AppleScript

Для развлечения написал интерпретатор языка Brainfuck на AppleScript.

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

AppleScript медленный язык, следовательно и получившийся интерпретатор медленный (никаких оптимизаций я не делал), лучше всего на нём запускать небольшие программы. Например, «Hello, world»:
++++++++[>+++++++++<-]>.<+++++[>++++++<-]>-.+++++++..+++.< 
++++++++[>>++++<<-]>>.<<++++[>------<-]>.<++++[>++++++<-]> 
.+++.------.--------.>+.
Не уверен, что нигде не ошибся (всё-таки время четвёртый час ночи), но даже вложенные циклы на программах, которые я прогонял, работают нормально. Интерпретатор Brainfuck на AppleScript.

Запуск сайтов из Spotlight

Занялся потихоньку автоматизацией своих задач на «Маке».

Очень хотелось сделать так, чтобы по короткому имени, набираемому в Spotlight, открывались какие-то сайты. В интранете «Яндекса» очень много сайтов, которые я открываю десятки раз за день, вот я и подумал — было бы круто, если бы я набирал в Spotlight «wiki», нажимал Enter и мне открывался бы сайт wiki.yandex-team.ru.

Я знаю, что тут много ребят сидят на Windows, поэтому поясню. Spotlight (его аналог) есть на Windows 7 — это поисковая строка, куда можно вбить начальные буквы какого-то названия, а операционная система предложит к запуску список программ и/или файлов, имена или метаинформация которых наилучшим образом подходит под заданную пользователем строку.

В Mac OS X удобно, что это поисковое поле появляется по кнопке Ctrl+Пробел.

Написать плагин к Spotlight мне пока слабо́, а вот набросать на AppleScript программу, открывающую одноимённый сайт — пожалуйста.

Идея такова: кладу на диск одну и ту же программу в нескольких копиях, с разными именами — «wiki», «jira», «calendar» и так далее. Теперь их можно запускать откуда угодно, включая Spotlight. После запуска программа смотрит какое у неё имя, прибавляет к нему префикс/суффикс и проверяет существует ли получившийся домен, если да, то открывает его в браузере.

Программу надо сохранить при помощи редактора AppleScript (AppleScript Editor) с нужным именем (↑⌘S), формат файла должен быть «программа» («application»).

Вот сама программа (наверное маску «%.yandex-team.ru» нужно будет убрать, она вам будет мешать, если вы только не работаете в «Яндексе»):
-- Ищет по маскам хост, подставляя имя программы,
-- если найден, открывает его в браузере
-- bolknote.ru апрель 2011

tell application "System Events"
	set appname to the name of the current application
end tell

repeat with mask in {"%.yandex-team.ru", "www.%.ru", "www.%.com"}
	set AppleScript's text item delimiters to "%"
	set mask to text items of mask
	set AppleScript's text item delimiters to appname
	set hostname to "" & mask
	
	if resolve(hostname) then
		open location "http://" & hostname
		exit repeat
	end if
end repeat

on resolve(host)
	try
		do shell script "host '" & host & "'"
		return true
	on error
		return false
	end try
end resolve
Это пока мой первый опыт программирования в AppleScript, так что, возможно, какие-то вещи можно было сделать проще, напишите я поправлю.

Добавлено позднее: в комментариях один из читателей предложил более простой и изящный вариант. Ура!
41 комментарий
16 апреля 2011 20:15