alphred 1.2.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 10082ff7a1c31db5ad28cab456c3e7137548cf11
4
- data.tar.gz: ee77fca7bd2179bfa450d5008076939d6bbbd5d2
3
+ metadata.gz: 6e16e15e9c29efb59e1db59f3c521e7434a72792
4
+ data.tar.gz: e9e42358283d6f3b43f89c7a5e93e658de747bdf
5
5
  SHA512:
6
- metadata.gz: 25214cc2776cb407ca5a8d531045f66fbdbb7153e0a77240ab1fedc17432c4e92779498c744b0bc666dd3adad8761576fdfa87de8c95fa8bbf16926ebad97a8a
7
- data.tar.gz: 88bad2ca507218e07f7c4ef74cd2386b399ac49730373645ed38a8d5c6ecd38283164d5ea435659acd7b229d99d42c2d29f694aa288db77e591dd19af44790de
6
+ metadata.gz: 5fc789dedf8233a24917d2084f4c8340525b97df36932036acccd1a9223299dd0fad05ec258c85cd5ecaa394c75c6ed5746b6df2ce9728d15eef64f0c0df64a0
7
+ data.tar.gz: b9bac5f7129ebf6f67488c318c5b8a200ed0cb2a819ffd87afa71786440482fac4b0a157f7a3040becfdf69365f0e1ff8e5b578a7af2232fbdde1d56de261300
data/Gemfile CHANGED
@@ -1,12 +1,12 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- ruby "2.0.0"
3
+ ruby '2.0.0'
4
4
 
5
5
  # Specify your gem's dependencies in alphred.gemspec
6
6
  gemspec
7
7
 
8
8
  group :development do
9
- gem "guard"
10
- gem "guard-minitest"
11
- gem "pry"
9
+ gem 'guard'
10
+ gem 'guard-minitest'
11
+ gem 'pry'
12
12
  end
data/README.md CHANGED
@@ -86,34 +86,6 @@ This produces the following XML:
86
86
  </items>
87
87
  ```
88
88
 
89
- ### Workflow Configuration
90
-
91
- `Alphred::Config` provides some helpers for managing configuration that should
92
- persist when updating the workflow. This configuration is stored in an JSON
93
- file in the workflow data directory.
94
-
95
- ``` ruby
96
- # config.rb
97
-
98
- module Workflow
99
- defaults = { foo: "bar" }
100
- Config = Alphred::Config.new(**defaults)
101
- ```
102
-
103
- The corresponding Script Filter input and Run Action output then look like this:
104
-
105
- ``` shell
106
- # script filter
107
-
108
- ruby -r./config -e'puts Workflow::Config.filter_xml("{query}")'
109
- ```
110
-
111
- ``` shell
112
- # run action
113
-
114
- ruby -r./config -e'Forecast::Config.update!("{query}")'
115
- ```
116
-
117
89
  ### Releasing
118
90
 
119
91
  Including `alphred/tasks` in your `Rakefile` will allow access to Alphred's
@@ -1,26 +1,27 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
2
+ lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "alphred/version"
4
+ require 'alphred/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "alphred"
7
+ spec.name = 'alphred'
8
8
  spec.version = Alphred::VERSION
9
- spec.authors = ["Alpha Chen"]
10
- spec.email = ["alpha.chen@gmail.com"]
9
+ spec.authors = ['Alpha Chen']
10
+ spec.email = ['alpha.chen@gmail.com']
11
11
 
12
12
  spec.summary = %q{Helper utilities for making Alfred workflows.}
13
- spec.homepage = "https://github.com/kejadlen/alph"
14
- spec.license = "MIT"
13
+ spec.homepage = 'https://github.com/kejadlen/alphred'
14
+ spec.license = 'MIT'
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
- spec.bindir = "bin"
17
+ spec.bindir = 'bin'
18
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.require_paths = ["lib"]
19
+ spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency "builder", "~> 3.2"
21
+ spec.add_dependency 'builder', '~> 3.2'
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.10"
24
- spec.add_development_dependency "rake", "~> 10.0"
25
- spec.add_development_dependency "minitest"
23
+ spec.add_development_dependency 'bundler', '~> 1.10'
24
+ spec.add_development_dependency 'rake', '~> 10.0'
25
+ spec.add_development_dependency 'listen', '~> 3.0.0'
26
+ spec.add_development_dependency 'minitest'
26
27
  end
@@ -1,11 +1,5 @@
1
- require "builder"
1
+ require_relative 'alphred/version'
2
2
 
3
- require_relative "alphred/version"
4
-
5
- require_relative "alphred/config"
6
- require_relative "alphred/error"
7
- require_relative "alphred/icon"
8
- require_relative "alphred/item"
9
- require_relative "alphred/items"
10
- require_relative "alphred/mods"
11
- require_relative "alphred/text"
3
+ require_relative 'alphred/error'
4
+ require_relative 'alphred/item'
5
+ require_relative 'alphred/items'
@@ -1,14 +1,16 @@
1
- require_relative "item"
2
- require_relative "items"
1
+ require_relative 'item'
2
+ require_relative 'items'
3
+
4
+ require 'json'
3
5
 
4
6
  module Alphred
5
7
  class Error < StandardError
6
- ASSETS = File.expand_path("../../../assets", __FILE__)
8
+ ASSETS = File.expand_path('../../../assets', __FILE__)
7
9
 
8
10
  def self.try
9
11
  yield
10
12
  rescue Exception => e
11
- puts self.new(e).to_xml
13
+ print self.new(e).to_json
12
14
  end
13
15
 
14
16
  attr_reader :error
@@ -17,30 +19,32 @@ module Alphred
17
19
  @error = error
18
20
  end
19
21
 
22
+ def to_json(options=nil)
23
+ to_items.to_json(options)
24
+ end
25
+
20
26
  def to_items
21
- icon = File.join(ASSETS, "close.png")
27
+ icon = File.join(ASSETS, 'close.png')
22
28
  items = [ Alphred::Item.new(title: "#{self.error.class}: #{self.error}",
23
29
  icon: icon) ]
24
30
  items.concat(self.backtrace_items)
25
- Alphred::Items.new(*items)
26
- end
27
-
28
- def to_xml
29
- self.to_items.to_xml
31
+ Items[*items]
30
32
  end
31
33
 
32
34
  def backtrace_items
33
- icon = File.join(ASSETS, "more.png")
35
+ icon = File.join(ASSETS, 'more.png')
34
36
 
35
- base_dirs = $LOAD_PATH + [ENV["alfred_preferences"]]
37
+ base_dirs = $LOAD_PATH + [ENV['alfred_preferences']]
36
38
  to_delete = /^#{base_dirs.join(?|)}/
37
39
 
38
- self.error.backtrace.map {|line|
39
- title = line.sub(to_delete, "...")
40
- Alphred::Item.new(title: title,
41
- subtitle: line,
42
- arg: line,
43
- icon: icon)
40
+ self.error.backtrace.map { |line|
41
+ title = line.sub(to_delete, '...')
42
+ Item.new(
43
+ title: title,
44
+ subtitle: line,
45
+ arg: line,
46
+ icon: icon,
47
+ )
44
48
  }
45
49
  end
46
50
  end
@@ -1,59 +1,53 @@
1
- require "builder"
2
-
3
- require_relative "mods"
4
- require_relative "text"
1
+ require_relative 'struct'
5
2
 
6
3
  module Alphred
7
- class Item
8
- VALID_TYPES = %i[ default file file_skipcheck ]
9
-
10
- attr_accessor *%i[ uid arg valid autocomplete title subtitle mods icon text ]
11
-
12
- def initialize(**kwargs)
13
- raise ArgumentError.new("missing keyword: title") unless kwargs.has_key?(:title)
14
-
15
- @title = kwargs[:title]
16
-
17
- %i[ uid arg valid autocomplete subtitle ].each do |attr|
18
- self.instance_variable_set("@#{attr}", kwargs[attr]) if kwargs.has_key?(attr)
19
- end
20
-
21
- @icon = Icon(kwargs[:icon]) if kwargs.has_key?(:icon)
22
- @text = Text.new(kwargs[:text]) if kwargs.has_key?(:text)
23
- @mods = Mods.new(kwargs[:mods]) if kwargs.has_key?(:mods)
24
-
25
- self.type = kwargs[:type] if kwargs.has_key?(:type)
26
- end
4
+ class Item < Struct
5
+ attribute :valid, coerce: ->(x) { !!x }
6
+ attribute :uid
7
+ attribute :type,
8
+ coerce: ->(x) { x.to_s.gsub(?_, ?:) },
9
+ enum: %w[ default file file:skipcheck ]
10
+ attribute :title, required: true
11
+ attribute :subtitle
12
+ attribute :arg
13
+ attribute :autocomplete
14
+ attribute :icon, coerce: ->(x) { Icon(x) }
15
+ attribute :quicklookurl
16
+ attribute :mods, coerce: ->(x) { Mods.new(x) }
17
+ attribute :text, coerce: ->(x) { Text.new(x) }
18
+ end
27
19
 
28
- def type=(type)
29
- raise ArgumentError.new("`type` must be one of #{VALID_TYPES}") unless type.nil? || VALID_TYPES.include?(type)
20
+ class Icon < Struct
21
+ attribute :type, enum: %i[ fileicon filetype ]
22
+ attribute :path, required: true
23
+ end
30
24
 
31
- @type = type
32
- end
25
+ class Mod < Struct
26
+ attribute :valid, coerce: ->(x) { !!x }
27
+ attribute :arg
28
+ attribute :subtitle
29
+ end
33
30
 
34
- def type
35
- @type && @type.to_s.gsub(?_, ?:)
36
- end
31
+ class Mods < Struct
32
+ attribute :ctrl, coerce: ->(x) { Mod.new(x) }
33
+ attribute :alt, coerce: ->(x) { Mod.new(x) }
34
+ attribute :cmd, coerce: ->(x) { Mod.new(x) }
35
+ attribute :fn, coerce: ->(x) { Mod.new(x) }
36
+ attribute :shift, coerce: ->(x) { Mod.new(x) }
37
+ end
37
38
 
38
- def to_xml(xml=nil)
39
- xml ||= Builder::XmlMarkup.new(indent: 2)
40
- xml.item self.attrs do
41
- xml.title self.title
42
- xml.subtitle self.subtitle unless self.subtitle.nil?
43
- self.icon.to_xml(xml) unless self.icon.nil?
44
- self.mods.to_xml(xml) unless self.mods.nil?
45
- self.text.to_xml(xml) unless self.text.nil?
46
- end
47
- end
39
+ class Text < Struct
40
+ attribute :copy
41
+ attribute :largetype
42
+ end
43
+ end
48
44
 
49
- def attrs
50
- attrs = {}
51
- %i[ uid arg autocomplete type ].each do |attr|
52
- value = self.send(attr)
53
- attrs[attr] = value unless value.nil?
54
- end
55
- attrs[:valid] = (self.valid) ? "yes" : "no" unless self.valid.nil?
56
- attrs
45
+ module Kernel
46
+ def Icon(arg)
47
+ case arg
48
+ when Alphred::Icon then arg
49
+ when String then Alphred::Icon.new(path: arg)
50
+ when Hash then Alphred::Icon.new(**arg)
57
51
  end
58
52
  end
59
53
  end
@@ -1,8 +1,13 @@
1
- require "builder"
2
- require "delegate"
1
+ require 'delegate'
2
+
3
+ require 'json'
3
4
 
4
5
  module Alphred
5
6
  class Items < DelegateClass(Array)
7
+ def self.[](*args)
8
+ new(*args)
9
+ end
10
+
6
11
  attr_reader :items
7
12
 
8
13
  def initialize(*items)
@@ -10,14 +15,8 @@ module Alphred
10
15
  super(@items)
11
16
  end
12
17
 
13
- def to_xml
14
- xml = Builder::XmlMarkup.new(indent: 2)
15
- xml.instruct! :xml
16
- xml.items do
17
- self.items.each do |item|
18
- item.to_xml(xml)
19
- end
20
- end
18
+ def to_json(options=nil)
19
+ { items: items }.to_json(options)
21
20
  end
22
21
  end
23
22
  end
@@ -0,0 +1,71 @@
1
+ require 'json'
2
+
3
+ module Alphred
4
+ class Struct
5
+ class RequiredAttributeError < StandardError; end
6
+ class InvalidEnumError < StandardError; end
7
+ class InvalidAttributeError < StandardError; end
8
+
9
+ def self.attribute(name, **options)
10
+ attributes << Attribute.new(name, **options)
11
+
12
+ define_method(name) do
13
+ attributes[name]
14
+ end
15
+ end
16
+
17
+ def self.attributes
18
+ return @attributes if defined?(@attributes)
19
+ @attributes = []
20
+ end
21
+
22
+ attr_reader :attributes
23
+
24
+ def initialize(**input)
25
+ validate_input(input)
26
+
27
+ @attributes = self.class.attributes.select { |attr|
28
+ attr.required? || input.keys.include?(attr.name)
29
+ }.reduce({}) { |hash, attr|
30
+ hash.merge(attr.value_from(input))
31
+ }
32
+ end
33
+
34
+ def to_json(options=nil)
35
+ attributes.to_json(options)
36
+ end
37
+
38
+ private
39
+
40
+ def validate_input(input)
41
+ attribute_names = self.class.attributes.map(&:name)
42
+ invalid_keys = input.keys.reject {|key| attribute_names.include?(key) }
43
+ unless invalid_keys.empty?
44
+ msg = "Invalid attribute(s): #{invalid_keys.join(', ')}"
45
+ raise InvalidAttributeError.new(msg)
46
+ end
47
+ end
48
+
49
+ class Attribute
50
+ attr_reader :name, :coerce, :enum
51
+
52
+ def initialize(name, **options)
53
+ @name = name
54
+ @required = options.fetch(:required, false)
55
+ @coerce = options.fetch(:coerce, ->(x) { x })
56
+ @enum = options[:enum]
57
+ end
58
+
59
+ def required?
60
+ !!@required
61
+ end
62
+
63
+ def value_from(hash)
64
+ uncoerced = hash.fetch(name) { raise RequiredAttributeError.new(name) }
65
+ coerced = coerce.call(uncoerced)
66
+ raise InvalidEnumError.new(coerced) if enum && !enum.include?(coerced)
67
+ { name => coerced }
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,3 +1,3 @@
1
1
  module Alphred
2
- VERSION = '1.2.2'
2
+ VERSION = '2.0.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alphred
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alpha Chen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-18 00:00:00.000000000 Z
11
+ date: 2016-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: builder
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: listen
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 3.0.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 3.0.0
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: minitest
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -87,16 +101,13 @@ files:
87
101
  - assets/close.png
88
102
  - assets/more.png
89
103
  - lib/alphred.rb
90
- - lib/alphred/config.rb
91
104
  - lib/alphred/error.rb
92
- - lib/alphred/icon.rb
93
105
  - lib/alphred/item.rb
94
106
  - lib/alphred/items.rb
95
- - lib/alphred/mods.rb
107
+ - lib/alphred/struct.rb
96
108
  - lib/alphred/tasks.rb
97
- - lib/alphred/text.rb
98
109
  - lib/alphred/version.rb
99
- homepage: https://github.com/kejadlen/alph
110
+ homepage: https://github.com/kejadlen/alphred
100
111
  licenses:
101
112
  - MIT
102
113
  metadata: {}
@@ -1,59 +0,0 @@
1
- require 'fileutils'
2
- require 'json'
3
-
4
- module Alphred
5
- class Config
6
- def self.load(**defaults)
7
- config = new(**defaults)
8
- config.load!
9
- config
10
- end
11
-
12
- attr_reader :data
13
-
14
- def initialize(**defaults)
15
- @data = Hash[defaults.map {|k,v| [k.to_s, v.to_s] }]
16
- end
17
-
18
- def load!
19
- return unless File.exist?(path)
20
- data.merge!(JSON.load(File.open(path)))
21
- end
22
-
23
- def update!(json)
24
- data = self.data.merge(JSON.load(json))
25
- FileUtils.mkdir_p(File.dirname(path))
26
- File.write(path, JSON.dump(data), mode: ?w)
27
- end
28
-
29
- def [](key)
30
- data[key.to_s]
31
- end
32
-
33
- def filter_xml(filter=nil)
34
- filter ||= ''
35
-
36
- items = data.map do |key, value|
37
- title = if filter.empty?
38
- "Unset #{key}"
39
- else
40
- "Set #{key} to #{filter}"
41
- end
42
- Item.new(
43
- uid: key,
44
- arg: JSON.dump(key => filter),
45
- title: title,
46
- subtitle: self[key]
47
- )
48
- end
49
-
50
- Items.new(*items).to_xml
51
- end
52
-
53
- private
54
-
55
- def path
56
- File.join(ENV['alfred_workflow_data'], 'config.json')
57
- end
58
- end
59
- end
@@ -1,39 +0,0 @@
1
- require "builder"
2
-
3
- module Alphred
4
- class Icon
5
- VALID_TYPES = %i[ fileicon filetype ]
6
-
7
- attr_accessor *%i[ value type ]
8
-
9
- def initialize(**kwargs)
10
- raise ArgumentError.new("missing keyword: value") unless kwargs.has_key?(:value)
11
-
12
- @value = kwargs[:value]
13
- self.type = kwargs[:type] if kwargs.has_key?(:type)
14
- end
15
-
16
- def type=(type)
17
- raise ArgumentError.new("`type` must be one of #{VALID_TYPES}") unless type.nil? || VALID_TYPES.include?(type)
18
-
19
- @type = type
20
- end
21
-
22
- def to_xml(xml=nil)
23
- xml ||= Builder::XmlMarkup.new(indent: 2)
24
- attrs = {}
25
- attrs[:type] = self.type unless self.type.nil?
26
- xml.icon self.value, attrs
27
- end
28
- end
29
- end
30
-
31
- module Kernel
32
- def Icon(value)
33
- case value
34
- when Alphred::Icon then value
35
- when String then Alphred::Icon.new(value: value)
36
- when Hash then Alphred::Icon.new(**value)
37
- end
38
- end
39
- end
@@ -1,22 +0,0 @@
1
- require "builder"
2
-
3
- module Alphred
4
- class Mods
5
- MODS = %i[ shift fn ctrl alt cmd ]
6
-
7
- attr_accessor *MODS
8
-
9
- def initialize(**kwargs)
10
- MODS.each do |mod|
11
- self.instance_variable_set("@#{mod}", kwargs[mod]) if kwargs.has_key?(mod)
12
- end
13
- end
14
-
15
- def to_xml(xml)
16
- MODS.each do |mod|
17
- value = self.send(mod)
18
- xml.subtitle value, mod: mod unless value.nil?
19
- end
20
- end
21
- end
22
- end
@@ -1,17 +0,0 @@
1
- require "builder"
2
-
3
- module Alphred
4
- class Text
5
- attr_accessor *%i[ copy largetype ]
6
-
7
- def initialize(copy: nil, largetype: nil)
8
- @copy = copy
9
- @largetype = largetype
10
- end
11
-
12
- def to_xml(xml)
13
- xml.text copy, type: :copy unless self.copy.nil?
14
- xml.text largetype, type: :largetype unless self.largetype.nil?
15
- end
16
- end
17
- end