alfredlite 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +2 -0
- data/Gemfile +7 -0
- data/README.md +76 -0
- data/Rakefile +30 -0
- data/alfredlite.gemspec +16 -0
- data/lib/alfredlite.rb +1 -0
- data/lib/alfredlite/feedback.rb +115 -0
- data/lib/alfredlite/version.rb +10 -0
- data/lib/alfredlite/workflow.rb +34 -0
- data/spec/feedback_spec.rb +36 -0
- data/spec/spec_helper.rb +11 -0
- metadata +74 -0
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/cjlucas/ruby-alfredlite.png?branch=master)](https://travis-ci.org/cjlucas/ruby-alfredlite)
|
2
|
+
[![Build Status](https://travis-ci.org/cjlucas/ruby-alfredlite.png?branch=develop)](https://travis-ci.org/cjlucas/ruby-alfredlite)
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/alfredlite.png)](http://badge.fury.io/rb/alfredlite)
|
4
|
+
|
5
|
+
AlfredLite is a lightweight modular framework for creating
|
6
|
+
[Alfred](http://www.alfredapp.com/) workflows.
|
7
|
+
|
8
|
+
## Features ##
|
9
|
+
- Modular design
|
10
|
+
- Only load the modules your workflow uses
|
11
|
+
- Faster load times (execution speed is an underappreciated feature of any workflow)
|
12
|
+
- Less bundeled dependencies
|
13
|
+
- Subclassable workflows
|
14
|
+
- `Alfred::Workflow` is designed to be subclassed, the possibilities are endless!
|
15
|
+
|
16
|
+
## Synopsis ##
|
17
|
+
Here's a trivial example of a workflow that utilizes Alfred's feedback system:
|
18
|
+
```ruby
|
19
|
+
require 'alfredlite' # this loads the workflow module
|
20
|
+
require 'alfredlite/feedback' # all submodules have to be loaded explicitly
|
21
|
+
|
22
|
+
class ExampleWorkflow < Alfred::Workflow
|
23
|
+
BUNDLE_ID = 'net.cjlucas.alfred.example'
|
24
|
+
|
25
|
+
def intitialize
|
26
|
+
super(BUNDLE_ID)
|
27
|
+
end
|
28
|
+
|
29
|
+
def query(input)
|
30
|
+
# parse the user's input
|
31
|
+
data_array = get_imaginary_data(input)
|
32
|
+
|
33
|
+
# add new feedback items to array
|
34
|
+
data_array.each do |data|
|
35
|
+
# Alfred::Workflow#feedback_items and Alfred::Feedback::Item
|
36
|
+
# become available when the feedback module is loaded
|
37
|
+
feedback_items << Alfred::Feedback::Item.new.tap do |item|
|
38
|
+
item.title = data.info
|
39
|
+
item.subtitle = data.more_info
|
40
|
+
item.icon = '/path/to/icon.png'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# send our feedback_items to Alfred to be processed and displayed
|
45
|
+
puts feedback_items.to_xml
|
46
|
+
end
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
Then we add a simple script for our Alfred workflow action
|
51
|
+
```ruby
|
52
|
+
require 'example_workflow'
|
53
|
+
|
54
|
+
ExampleWorkflow.new.query("{query}")
|
55
|
+
```
|
56
|
+
|
57
|
+
|
58
|
+
## Requirements ##
|
59
|
+
AlfredLite is tested against the following verions of Ruby:
|
60
|
+
- 1.8.7 (preinstalled on OS X Mountain Lion)
|
61
|
+
- 1.9.3
|
62
|
+
- 2.0.0 (preinstalled on OS X Mavericks)
|
63
|
+
|
64
|
+
### Module-level dependencies ###
|
65
|
+
- Workflow module
|
66
|
+
- None
|
67
|
+
- Feedback module
|
68
|
+
- [REXML](http://www.germane-software.com/software/rexml/) (included with all versions of Ruby)
|
69
|
+
|
70
|
+
## Contributing ##
|
71
|
+
- Bug Fixes
|
72
|
+
- Reporting bugs is encouraged and greatly appreciated, send them [here](https://github.com/cjlucas/ruby-alfredlite/issues).
|
73
|
+
- If you're contributing a bug fix, please make sure you're committing your fixes on the `develop` branch
|
74
|
+
(bonus points for creating a dedicated bug fix branch).
|
75
|
+
- Feature Requests
|
76
|
+
- Have an idea that will help make writing your workflows easier? Then submit it [here](https://github.com/cjlucas/ruby-alfredlite/issues).
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
2
|
+
|
3
|
+
#require 'rubygems'
|
4
|
+
#require 'bundler/setup'
|
5
|
+
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
|
8
|
+
require 'alfredlite/version'
|
9
|
+
|
10
|
+
task :default => [:spec]
|
11
|
+
|
12
|
+
task :spec do
|
13
|
+
RSpec::Core::RakeTask.new do |task|
|
14
|
+
task.verbose = false
|
15
|
+
task.rspec_opts = '--color'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
task :build do
|
21
|
+
system 'gem build alfredlite.gemspec'
|
22
|
+
end
|
23
|
+
|
24
|
+
task :release => :build do
|
25
|
+
system "gem push alfredlite-#{Alfred::VERSION}.gem"
|
26
|
+
end
|
27
|
+
|
28
|
+
task :clean do
|
29
|
+
system 'rm -f *.gem'
|
30
|
+
end
|
data/alfredlite.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
2
|
+
|
3
|
+
require 'alfredlite/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'alfredlite'
|
7
|
+
s.version = Alfred::VERSION
|
8
|
+
s.summary = 'AlfredLite is a lightweight modular framework for creating Alfred workflows.'
|
9
|
+
s.authors = ['Chris Lucas']
|
10
|
+
s.email = ['chris@chrisjlucas.com']
|
11
|
+
s.homepage = 'https://github.com/cjlucas/ruby-alfredlite'
|
12
|
+
s.license = 'MIT'
|
13
|
+
s.files = `git ls-files | egrep '^[^\.]'`.split(/\r?\n/)
|
14
|
+
s.test_files = s.files.select { |f| f.match(/^spec\/.*\.rb$/) }
|
15
|
+
s.platform = Gem::Platform::RUBY
|
16
|
+
end
|
data/lib/alfredlite.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'alfredlite/workflow'
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
module Alfred
|
4
|
+
class Workflow
|
5
|
+
def feedback_items
|
6
|
+
@feedback_items ||= []
|
7
|
+
end
|
8
|
+
|
9
|
+
def feedback_xml
|
10
|
+
doc = REXML::Document.new
|
11
|
+
doc << REXML::Element.new('items')
|
12
|
+
feedback_items.each { |item| doc.root << item.to_xml }
|
13
|
+
|
14
|
+
doc
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Alfred
|
20
|
+
module Feedback
|
21
|
+
class Item
|
22
|
+
# Compatibility Note:
|
23
|
+
# In Ruby 1.8, Object#type is defined, to workaround this the type
|
24
|
+
# attribute can be accessed via #item_type
|
25
|
+
ATTRIBUTES = [:uid, :arg, :valid, :autocomplete, :item_type]
|
26
|
+
ATTRIBUTES_XML_MAP = {
|
27
|
+
:item_type => :type,
|
28
|
+
}
|
29
|
+
CHILD_NODES = {
|
30
|
+
:title => [],
|
31
|
+
:subtitle => [],
|
32
|
+
:icon => [:type],
|
33
|
+
}
|
34
|
+
|
35
|
+
def initialize
|
36
|
+
@item_type = 'file'
|
37
|
+
end
|
38
|
+
|
39
|
+
def valid=(valid)
|
40
|
+
@valid = valid ? 'true' : 'false'
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_xml
|
44
|
+
item_node = REXML::Element.new('item')
|
45
|
+
ATTRIBUTES.each do |attrib|
|
46
|
+
value = method(attrib).call
|
47
|
+
xml_attrib = ATTRIBUTES_XML_MAP.fetch(attrib, attrib)
|
48
|
+
#item_node[xml_attrib.to_s] = value unless value.nil?
|
49
|
+
item_node.add_attribute(xml_attrib.to_s, value) unless value.nil?
|
50
|
+
end
|
51
|
+
|
52
|
+
CHILD_NODES.each do |node_name, node_attribs|
|
53
|
+
value = method(node_name).call
|
54
|
+
unless value.nil?
|
55
|
+
item_node << REXML::Element.new(node_name.to_s).tap do |child|
|
56
|
+
child.text = value
|
57
|
+
|
58
|
+
node_attribs.each do |attrib|
|
59
|
+
attr = self.class.child_attribute_name(node_name, attrib)
|
60
|
+
value = method(attr).call
|
61
|
+
child.add_attribute(attr, value) unless value.nil?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
item_node
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# generate getters and setters
|
73
|
+
|
74
|
+
def self.instance_method_exists?(method)
|
75
|
+
# In Ruby 1.8, Object.instance_methods returns and array of strings
|
76
|
+
# In Ruby 1.9+, it returns an array of symbols
|
77
|
+
method = RUBY_VERSION < '1.9' ? method.to_s : method.to_sym
|
78
|
+
|
79
|
+
instance_methods.include?(method)
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.child_attribute_name(child_node, attribute)
|
83
|
+
"#{child_node}_#{attribute}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.getter_unless_exists(attr)
|
87
|
+
getter = attr.to_sym
|
88
|
+
attr_reader attr unless instance_method_exists?(getter)
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.setter_unless_exists(attr)
|
92
|
+
setter = "#{attr}=".to_sym
|
93
|
+
attr_writer attr unless instance_method_exists?(setter)
|
94
|
+
end
|
95
|
+
|
96
|
+
ATTRIBUTES.each do |attrib|
|
97
|
+
getter_unless_exists(attrib)
|
98
|
+
setter_unless_exists(attrib)
|
99
|
+
end
|
100
|
+
|
101
|
+
CHILD_NODES.each do |name, attribs|
|
102
|
+
getter_unless_exists(name)
|
103
|
+
setter_unless_exists(name)
|
104
|
+
|
105
|
+
attribs.each do |attrib|
|
106
|
+
child_attribute_name(name, attrib).tap do |attr|
|
107
|
+
getter_unless_exists(attr)
|
108
|
+
setter_unless_exists(attr)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Alfred
|
4
|
+
class Workflow
|
5
|
+
CACHE_DIR = '/Library/Caches/com.runningwithcrayons.Alfred-2/Workflow Data'
|
6
|
+
DATA_DIR = '/Library/Application Support/Alfred 2/Workflow Data'
|
7
|
+
attr_reader :bundle_id
|
8
|
+
|
9
|
+
def initialize(bundle_id)
|
10
|
+
@bundle_id = bundle_id
|
11
|
+
end
|
12
|
+
|
13
|
+
def storage_path
|
14
|
+
@storage_path ||= File.join(ENV['HOME'], DATA_DIR, bundle_id)
|
15
|
+
self.class.mkdir(@storage_path)
|
16
|
+
@storage_path
|
17
|
+
end
|
18
|
+
|
19
|
+
def volatile_storage_path
|
20
|
+
@volatile_storage_path ||= File.join(ENV['HOME'], CACHE_DIR, bundle_id)
|
21
|
+
self.class.mkdir(@volatile_storage_path)
|
22
|
+
@volatile_storage_path
|
23
|
+
end
|
24
|
+
|
25
|
+
def query(input)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def self.mkdir(path)
|
31
|
+
FileUtils.mkdir_p(path) unless File.exists?(path)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path('../spec_helper.rb', __FILE__)
|
2
|
+
|
3
|
+
Item = Alfred::Feedback::Item
|
4
|
+
|
5
|
+
describe Item do
|
6
|
+
it 'adds attributes and child nodes properly' do
|
7
|
+
item = Item.new.tap do |item|
|
8
|
+
item.title = 'this is the title'
|
9
|
+
item.subtitle = 'this is the subtitle'
|
10
|
+
item.arg = 'this is the arg'
|
11
|
+
item.valid = false
|
12
|
+
item.uid = 'alfredlite-43223'
|
13
|
+
item.autocomplete = 'autocompleter'
|
14
|
+
item.icon = '/path/to/icon.png'
|
15
|
+
item.icon_type = 'fileicon'
|
16
|
+
end
|
17
|
+
xml = item.to_xml
|
18
|
+
|
19
|
+
# check attributes
|
20
|
+
Item::ATTRIBUTES.each do |attrib|
|
21
|
+
xml_attrib = Item::ATTRIBUTES_XML_MAP.fetch(attrib, attrib)
|
22
|
+
xml.attributes[xml_attrib.to_s].should eq(item.method(attrib).call)
|
23
|
+
end
|
24
|
+
|
25
|
+
# child nodes
|
26
|
+
Item::CHILD_NODES.keys do |node_name|
|
27
|
+
nodes = xml.children.select {|child| child.name.eql?(node_name.to_s)}
|
28
|
+
nodes.count.should eq(1)
|
29
|
+
nodes.first.name.should eq(node_name)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
#it "Doesn't add attributes and nodes that are nil" do
|
34
|
+
#item = Item.new
|
35
|
+
#end
|
36
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: alfredlite
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Chris Lucas
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2013-07-02 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description:
|
22
|
+
email:
|
23
|
+
- chris@chrisjlucas.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- CHANGELOG.md
|
32
|
+
- Gemfile
|
33
|
+
- README.md
|
34
|
+
- Rakefile
|
35
|
+
- alfredlite.gemspec
|
36
|
+
- lib/alfredlite.rb
|
37
|
+
- lib/alfredlite/feedback.rb
|
38
|
+
- lib/alfredlite/version.rb
|
39
|
+
- lib/alfredlite/workflow.rb
|
40
|
+
- spec/feedback_spec.rb
|
41
|
+
- spec/spec_helper.rb
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: https://github.com/cjlucas/ruby-alfredlite
|
44
|
+
licenses:
|
45
|
+
- MIT
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
version: "0"
|
65
|
+
requirements: []
|
66
|
+
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.3.6
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: AlfredLite is a lightweight modular framework for creating Alfred workflows.
|
72
|
+
test_files:
|
73
|
+
- spec/feedback_spec.rb
|
74
|
+
- spec/spec_helper.rb
|