alfredlite 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](https://travis-ci.org/cjlucas/ruby-alfredlite)
|
|
2
|
+
[](https://travis-ci.org/cjlucas/ruby-alfredlite)
|
|
3
|
+
[](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
|