Статьи

Забавные и практичные рабочие процессы Alfred в Ruby

взгляд

Альфред — инструмент производительности OS X, который может превратить определенные пользователем команды в действия. Они известны как рабочие процессы, и они могут быть написаны на разных языках, включая Ruby.

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

  1. Отображение того, что на веб-сайте, используя скребок экрана
  2. Использование JSON API и символьного ключевого слова для быстрой конвертации валюты
  3. Создание событий календаря OS X на естественном языке

Если вы новичок в Альфреде, не забудьте прочитать предыдущую статью, чтобы освоиться.

Примечание: вам нужно будет купить Alfred Powerpack для использования и создания рабочих процессов .

Alfredo

Ранее мы отправляли информацию Альфреду, преобразовав хэш Ruby в XML (используя гем gyoku ), а затем распечатав его в стандартный stdout . В этом уроке мы будем использовать гем, который немного упрощает это: Alfredo .

Сначала установите самоцвет alfredo . Как и для любого гема рабочего процесса, обязательно установите его для любого Ruby, который вы используете внутри bash-скрипта рабочего процесса , обычно /usr/bin/ruby :

 $ gem install alfredo 

Затем используйте его, создав объект рабочего процесса, добавив в него элементы и распечатав XML:

 require 'alfredo' workflow = Alfredo::Workflow.new workflow << Alfredo::Item.new({ title: "Example", arg: "example" }) workflow.output! 

Одна из приятных особенностей alfredo заключается в том, что он будет заполнять отсутствующие атрибуты элементов рабочего процесса, такие как uid (используется для отслеживания вашего поведения для прогнозирования), и автоматически заполняться интеллектуальными значениями по умолчанию. Если вам не нужны эти атрибуты, обязательно укажите их в конструкторе Alfredo::Item .

Соскоб экрана

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

К счастью, с сайтами процесс обычно работает так:

  1. Отправить запрос GET на конечную точку HTML (URL)
  2. Разобрать строку ответа HTML в проходимый хеш
  3. Используйте хэш

Если JavaScript много, то на шаге 1 может потребоваться безголовый браузер с движком JS.

Давайте создадим рабочий процесс Альфреда, который будет отображать заголовки на первой странице rubyflow, а затем откроет выбранную страницу. Все, что нам нужно, это пустой рабочий процесс с Inputs->Script Filter подключенным к Actions->Open URL .

Внутри фильтра сценариев установите bash в качестве типа сценария, добавьте сценарий Ruby в папку рабочего процесса, а затем запустите его с /usr/bin/ruby :

 require 'net/http' require 'nokogiri' require 'alfredo' url = "http://www.rubyflow.com" uri = URI.parse(url) body = Net::HTTP.get(uri) html = Nokogiri::HTML(body) workflow = Alfredo::Workflow.new html.css(".body h1 a").each do |el| if el.text != "" workflow << Alfredo::Item.new({ title: el.text, subtitle: "Open this page in your browser", arg: url + el["href"] }) end end workflow.output! 

rubyflow_result

Насколько это было легко?

Конвертация валюты с помощью JSON API

Ключевые слова рабочего процесса не обязательно должны быть словами . Если вам нужен быстрый конвертер валют, создайте рабочий процесс фильтра сценариев с символом валюты в качестве ключевого слова, а затем с суммой в качестве аргумента. Обязательно снимите флажок «с пробелом» в узле фильтра сценариев, чтобы вы могли использовать суммы, такие как «$ 100» вместо «$ 100».

Мы можем использовать бесплатный API конвертации валют, предоставляемый Fixer.io .

 require "json" require "net/http" require "alfredo" amount = ARGV[0] || 1.0 base = "USD" amount = amount.to_f amount = 1.0 if amount == 0.0 url = "http://api.fixer.io/latest?base=#{base}" uri = URI.parse(url) body = Net::HTTP.get(uri) json = JSON.parse(body, symbolize_names: true) workflow = Alfredo::Workflow.new json[:rates].each do |rate| # rate is in the format [:CUR, float] total = rate[1].round(4) * amount workflow << Alfredo::Item.new({ title: total.to_s + " " + rate[0].to_s, subtitle: "Copy this value to the clipboard", arg: total }) end workflow.output! 

Поскольку здесь мы используем ключевое слово аргумент, мы получаем к нему доступ через ARGV[0] , передавая его в скрипт

 $ /usr/bin/ruby your_script.rb {query} 

Чтобы скопировать выбранное значение в буфер обмена, обязательно добавьте Outputs->Copy to Clipboard с текстом {query} в качестве текста и подключите его к выходу фильтра сценариев.

currency_converter_result

Рабочий процесс напоминания

Давайте создадим рабочий процесс, который позволит нам устанавливать уведомления календаря OS X на основе естественного языка. Например, мы могли бы сказать rem "pay the light bill on tuesday" . Вот как это будет работать:

  1. Получить напоминание и время от аргумента ключевого слова
  2. Передайте их AppleScript в одной строке (кажется, Альфред поддерживает только одну
    аргумент на этот раз)
  3. Разбейте строку и создайте событие в Calendar .

Мы будем использовать nickel самоцвет (https://github.com/iainbeeston/nickel) для анализа времени, так как он может анализировать сообщения и время вместе:

 $ gem install nickel 

Откройте irb чтобы увидеть, в какие времена nickel будет анализироваться.

 > require 'nickel' > event = Nickel.parse "pay the light bill on tuesday" => message: "pay the light bill", occurrences: [#<Occurrence type: single, start_date: 20151103>] > event.occurrences.first.start_date.day => 3 

Обратите внимание, что nickel настоящее время не очень хорош в выводе вещей. Вам нужно будет указать AM / PM, если вы используете этот формат — он работает нормально с 24-часовым временем:

 > Nickel.parse "Go to the gym at 5:00 pm" => message: "Go to the gym", occurrences: [] > Nickel.parse "Go to the gym today at 5:00 pm" => message: "Go to the gym", occurrences: [#<Occurrence type: single, start_date: 20151101, start_time: 170000>] 

Хорошо, теперь давайте напишем рабочий процесс:

 require 'nickel' require 'alfredo' query = ARGV[0] parsed = Nickel.parse(query) workflow = Alfredo::Workflow.new if parsed != nil && parsed.occurrences.size > 0 event = parsed.occurrences.first reminder = parsed.message date = event.start_date || DateTime.new time = event.start_time || DateTime.new date_string = date.to_date.strftime "%m/%d/%Y" time_string = time.to_time.strftime "%I:%M %p" time_string[0] = '' if time_string[0] == '0' workflow << Alfredo::Item.new({ title: "Remember \"#{reminder}\" on #{date_string} at #{time_string}", arg: "#{reminder};#{date_string} #{time_string}" }) end workflow.output! 

AppleScript

Далее нам нужен AppleScript, который создаст событие Calendar на основе времени, обработанного nickel . AppleScript дает нам возможность автоматизировать приложения OS X с возможностью создания сценариев, отправляя им события Apple.

Чтобы узнать, какое поведение сценариев поддерживает приложение, нам нужно изучить его словарь AppleScript. Это можно отобразить, открыв редактор AppleScript (находится в папке «Служебные программы» и называется « Редактор сценариев» ), затем перейдите в « File->Open Dictionary и выберите нужное приложение.

Глядя на словарь для календаря, мы можем увидеть, какие свойства необходимы для создания нового события:

calendar_applescript_event

В представлении узла рабочего процесса добавьте узел Actions->Run NSAppleScript и подключите его к узлу фильтра сценариев. Затем добавьте следующий код:

 -- Found at http://erikslab.com/2007/08/31/applescript-how-to-split-a-string/ on split(theString, theDelimiter) -- save delimiters to restore old settings set oldDelimiters to AppleScript's text item delimiters -- set delimiters to delimiter to be used set AppleScript's text item delimiters to theDelimiter -- create the array set theArray to every text item of theString -- restore the old setting set AppleScript's text item delimiters to oldDelimiters -- return the result return theArray end split on alfred_script(query) tell application "Calendar" tell calendar "Home" set inputString to query set inputArray to my split(inputString, ";") set reminder to item 1 of inputArray set dateString to item 2 of inputArray set newDate to my date (dateString) make new event at end with properties {description:reminder, summary:reminder, location:"Event Location", start date:newDate, end date:newDate} end tell end tell end alfred_script 

Обратите внимание, что мы получаем аргумент, переданный из узла фильтра сценариев с аргументом on alfred_script вместо {query} как в узле уведомлений.

Кроме того, ключевое слово AppleScript, которое может быть неочевидным, является my . Это сообщает AppleScript, что контекст является сценарием верхнего уровня, а не целью блока Tell. Нам это нужно, потому что AppleScript не будет продолжать искать, если что-то не определено конкретно в текущем контексте.

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

reminder_result

Чтобы получать уведомления о событиях календаря, нам нужно включить их в настройках ( CMD-, ) приложения «Календарь». Вы можете указать, хотите ли вы, чтобы оповещение появлялось в начале события или раньше.

calendar_alerts

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

Вывод

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

Да, и если вы хотите, чтобы рабочий процесс отображался в верхней части статьи, его можно найти на GitHub .

Есть отличные идеи для рабочих процессов? Дайте нам знать об этом в комментариях.