ppl 1.5.2 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,6 +3,15 @@ require "vpim/vcard"
3
3
 
4
4
  class Ppl::Adapter::Vcard::Vpim
5
5
 
6
+ @@postal_address_property_map = {
7
+ :street => :street,
8
+ :postalcode => :postal_code,
9
+ :pobox => :po_box,
10
+ :country => :country,
11
+ :region => :region,
12
+ :locality => :locality,
13
+ }
14
+
6
15
  def encode(contact)
7
16
  vcard = Vpim::Vcard::Maker.make2 do |maker|
8
17
  encode_birthday(contact, maker)
@@ -65,23 +74,11 @@ class Ppl::Adapter::Vcard::Vpim
65
74
  def encode_postal_address(contact, vcard_maker)
66
75
  if !contact.postal_address.nil?
67
76
  vcard_maker.add_addr do |address|
68
- if !contact.postal_address.street.nil?
69
- address.street = contact.postal_address.street
70
- end
71
- if !contact.postal_address.postal_code.nil?
72
- address.postalcode = contact.postal_address.postal_code
73
- end
74
- if !contact.postal_address.po_box.nil?
75
- address.pobox = contact.postal_address.po_box
76
- end
77
- if !contact.postal_address.country.nil?
78
- address.country = contact.postal_address.country
79
- end
80
- if !contact.postal_address.region.nil?
81
- address.region = contact.postal_address.region
82
- end
83
- if !contact.postal_address.locality.nil?
84
- address.locality = contact.postal_address.locality
77
+ @@postal_address_property_map.each_pair do |vpim_name, ppl_name|
78
+ value = contact.postal_address.send(ppl_name)
79
+ if !value.nil?
80
+ address.send("#{vpim_name.to_s}=", value)
81
+ end
85
82
  end
86
83
  end
87
84
  end
@@ -112,12 +109,11 @@ class Ppl::Adapter::Vcard::Vpim
112
109
  def decode_postal_address(vcard, contact)
113
110
  if !vcard.address.nil?
114
111
  contact.postal_address = Ppl::Entity::PostalAddress.new
115
- contact.postal_address.street = vcard.address.street
116
- contact.postal_address.postal_code = vcard.address.postalcode
117
- contact.postal_address.po_box = vcard.address.pobox
118
- contact.postal_address.locality = vcard.address.locality
119
- contact.postal_address.region = vcard.address.region
120
- contact.postal_address.country = vcard.address.country
112
+ @@postal_address_property_map.each_pair do |vpim_name, ppl_name|
113
+ value = vcard.address.send(vpim_name)
114
+ method = "#{ppl_name.to_s}="
115
+ contact.postal_address.send(method, value)
116
+ end
121
117
  end
122
118
  end
123
119
 
@@ -1,8 +1,8 @@
1
1
 
2
2
  class Ppl::Application::Command
3
3
 
4
- attr_accessor :name
5
- attr_accessor :description
4
+ @@property_values = {}
5
+
6
6
  attr_accessor :storage
7
7
 
8
8
  def execute(input, output)
@@ -12,5 +12,47 @@ class Ppl::Application::Command
12
12
  def options(parser, options)
13
13
  end
14
14
 
15
+ def self.add_property(name)
16
+ @@property_values[name] = {}
17
+ self.add_static_property_setter(name)
18
+ self.add_instance_property_getter(name)
19
+ self.add_instance_property_setter(name)
20
+ end
21
+
22
+
23
+ private
24
+
25
+ def self.add_static_property_setter(property_name)
26
+ define_singleton_method(property_name) do |value = nil|
27
+ if value.nil?
28
+ @@property_values[property_name][self]
29
+ else
30
+ @@property_values[property_name][self] = value
31
+ end
32
+ end
33
+ end
34
+
35
+ def self.add_instance_property_getter(property_name)
36
+ define_method(property_name) do
37
+ instance_variable = instance_variable_get("@#{property_name}")
38
+ class_variable = @@property_values[property_name][self.class]
39
+ if !instance_variable.nil?
40
+ instance_variable
41
+ elsif !class_variable.nil?
42
+ class_variable
43
+ end
44
+ end
45
+ end
46
+
47
+ def self.add_instance_property_setter(property_name)
48
+ define_method("#{property_name}=") do |value|
49
+ instance_variable_set("@#{property_name}", value)
50
+ end
51
+ end
52
+
53
+ add_property :name
54
+ add_property :description
55
+
56
+
15
57
  end
16
58
 
@@ -11,13 +11,9 @@ class Ppl::Application::Shell
11
11
  command = select_command(input)
12
12
  prepare_command(command, input)
13
13
  outcome = execute_command(command, input, output)
14
- rescue OptionParser::InvalidOption
15
- output.error($!)
16
- output.error(@optparse.to_s)
17
- rescue OptionParser::MissingArgument
18
- output.error($!)
19
- output.error(@optparse.to_s)
20
- rescue Ppl::Error::IncorrectUsage
14
+ rescue Ppl::Error::ContactNotFound
15
+ output.error("ppl: Contact '#{$!}' not found")
16
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument, Ppl::Error::IncorrectUsage
21
17
  output.error($!)
22
18
  output.error(@optparse.to_s)
23
19
  rescue
@@ -1,10 +1,8 @@
1
1
 
2
2
  class Ppl::Command::Add < Ppl::Application::Command
3
3
 
4
- def initialize
5
- @name = "add"
6
- @description = "Add a new contact"
7
- end
4
+ name "add"
5
+ description "Add a new contact"
8
6
 
9
7
  def options(parser, options)
10
8
  parser.banner = "usage: ppl add <contact> <name>"
@@ -1,12 +1,13 @@
1
1
 
2
2
  class Ppl::Command::Bday < Ppl::Application::Command
3
3
 
4
+ name "bday"
5
+ description "List, show or change birthdays"
6
+
4
7
  attr_writer :list_format
5
8
  attr_writer :show_format
6
9
 
7
10
  def initialize
8
- @name = "bday"
9
- @description = "List, show or change birthdays"
10
11
  @list_format = Ppl::Format::AddressBook::Birthdays.new
11
12
  @show_format = Ppl::Format::Contact::Birthday.new
12
13
  end
@@ -1,12 +1,13 @@
1
1
 
2
2
  class Ppl::Command::Email < Ppl::Application::Command
3
3
 
4
+ name "email"
5
+ description "Show or change a contact's email address"
6
+
4
7
  attr_writer :show_format
5
8
  attr_writer :list_format
6
9
 
7
10
  def initialize
8
- @name = "email"
9
- @description = "Show or change a contact's email address"
10
11
  @show_format = Ppl::Format::Contact::EmailAddresses.new
11
12
  @list_format = Ppl::Format::AddressBook::EmailAddresses.new
12
13
  end
@@ -1,12 +1,10 @@
1
1
 
2
2
  class Ppl::Command::Help < Ppl::Application::Command
3
3
 
4
- attr_accessor :command_suite
4
+ name "help"
5
+ description "Show a list of commands"
5
6
 
6
- def initialize
7
- @name = "help"
8
- @description = "Show a list of commands"
9
- end
7
+ attr_accessor :command_suite
10
8
 
11
9
  def execute(input, output)
12
10
  @command_suite.sort_by_name
@@ -26,7 +24,7 @@ class Ppl::Command::Help < Ppl::Application::Command
26
24
  name = command.name
27
25
  description = command.description
28
26
 
29
- if @name == name
27
+ if self.name == name
30
28
  next
31
29
  end
32
30
 
@@ -1,10 +1,8 @@
1
1
 
2
2
  class Ppl::Command::Init < Ppl::Application::Command
3
3
 
4
- def initialize
5
- @name = "init"
6
- @description = "Create an empty address book"
7
- end
4
+ name "init"
5
+ description "Create an empty address book"
8
6
 
9
7
  def options(parser, options)
10
8
  parser.banner = "usage: ppl init [directory]"
@@ -1,12 +1,12 @@
1
1
 
2
2
  class Ppl::Command::Ls < Ppl::Application::Command
3
3
 
4
+ name "ls"
5
+ description "List all contacts"
6
+
4
7
  attr_writer :format
5
8
 
6
9
  def initialize
7
- @name = "ls"
8
- @description = "List all contacts"
9
-
10
10
  @format = Ppl::Format::AddressBook::OneLine.new
11
11
  end
12
12
 
@@ -1,12 +1,12 @@
1
1
 
2
2
  class Ppl::Command::Mutt < Ppl::Application::Command
3
3
 
4
+ name "mutt"
5
+ description "Integration with mutt's query_command"
6
+
4
7
  attr_writer :format
5
8
 
6
9
  def initialize
7
- @name = "mutt"
8
- @description = "Integration with mutt's query_command"
9
-
10
10
  @format = Ppl::Format::AddressBook::MuttQuery.new
11
11
  end
12
12
 
@@ -15,43 +15,27 @@ class Ppl::Command::Mutt < Ppl::Application::Command
15
15
  end
16
16
 
17
17
  def execute(input, output)
18
- query = input.arguments.shift
19
- if query.nil?
20
- raise Ppl::Error::IncorrectUsage, "You must provide a query"
21
- end
22
-
23
- address_book = @storage.load_address_book
24
-
25
- matches = mutt_search(address_book, query)
26
-
27
- if matches.count > 0
28
-
29
- line = sprintf(
30
- "Searching database... %d entries... %d matching:",
31
- address_book.count,
32
- matches.count
33
- )
18
+ query = require_query(input)
19
+ matches = mutt_search(query)
20
+ output.line(describe_result(matches))
21
+ matches.count > 0
22
+ end
34
23
 
35
- results = @format.process(matches)
36
24
 
37
- output.line(line)
38
- output.line(results) unless results == ""
39
- true
25
+ private
40
26
 
41
- else
42
- output.line("No matches")
43
- false
27
+ def require_query(input)
28
+ if input.arguments.first.nil?
29
+ raise Ppl::Error::IncorrectUsage, "You must provide a query"
44
30
  end
45
-
31
+ input.arguments.first
46
32
  end
47
33
 
48
-
49
- private
50
-
51
- def mutt_search(address_book, query)
34
+ def mutt_search(query)
35
+ @address_book = @storage.load_address_book
52
36
  matches = Ppl::Entity::AddressBook.new
53
37
 
54
- address_book.each do |contact|
38
+ @address_book.each do |contact|
55
39
  next if contact.email_addresses.empty?
56
40
 
57
41
  matching_emails = contact.email_addresses.select do |email_address|
@@ -68,5 +52,23 @@ class Ppl::Command::Mutt < Ppl::Application::Command
68
52
  matches
69
53
  end
70
54
 
55
+ def describe_result(matches)
56
+ if matches.count > 0
57
+ describe_matches(matches)
58
+ else
59
+ "No matches"
60
+ end
61
+ end
62
+
63
+ def describe_matches(matches)
64
+ summary = sprintf(
65
+ "Searching address book... %d entries... %d matching:",
66
+ @address_book.count,
67
+ matches.count
68
+ )
69
+ results = @format.process(matches)
70
+ [summary, results].join("\n").strip
71
+ end
72
+
71
73
  end
72
74
 
@@ -1,10 +1,8 @@
1
1
 
2
2
  class Ppl::Command::Mv < Ppl::Application::Command
3
3
 
4
- def initialize
5
- @name = "mv"
6
- @description = "Rename a contact"
7
- end
4
+ name "mv"
5
+ description "Rename a contact"
8
6
 
9
7
  def options(parser, options)
10
8
  parser.banner = "usage: ppl mv <contact> <new ID>"
@@ -1,12 +1,13 @@
1
1
 
2
2
  class Ppl::Command::Name < Ppl::Application::Command
3
3
 
4
+ name "name"
5
+ description "List, show or change names"
6
+
4
7
  attr_writer :show_format
5
8
  attr_writer :list_format
6
9
 
7
10
  def initialize
8
- @name = "name"
9
- @description = "List, show or change names"
10
11
  @show_format = Ppl::Format::Contact::Name.new
11
12
  @list_format = Ppl::Format::AddressBook::Names.new
12
13
  end
@@ -1,12 +1,13 @@
1
1
 
2
2
  class Ppl::Command::Org < Ppl::Application::Command
3
3
 
4
+ name "org"
5
+ description "List, show or change organizations"
6
+
4
7
  attr_writer :show_format
5
8
  attr_writer :list_format
6
9
 
7
10
  def initialize
8
- @name = "org"
9
- @description = "List, show or change organizations"
10
11
  @show_format = Ppl::Format::Contact::Organization.new
11
12
  @list_format = Ppl::Format::AddressBook::Organizations.new
12
13
  end
@@ -1,12 +1,13 @@
1
1
 
2
2
  class Ppl::Command::Phone < Ppl::Application::Command
3
3
 
4
+ name "phone"
5
+ description "List, show or change phone numbers"
6
+
4
7
  attr_writer :show_format
5
8
  attr_writer :list_format
6
9
 
7
10
  def initialize
8
- @name = "phone"
9
- @description = "List, show or change phone numbers"
10
11
  @show_format = Ppl::Format::Contact::PhoneNumber.new
11
12
  @list_format = Ppl::Format::AddressBook::PhoneNumbers.new
12
13
  end
@@ -1,12 +1,13 @@
1
1
 
2
2
  class Ppl::Command::Post < Ppl::Application::Command
3
3
 
4
+ name "post"
5
+ description "List, show or change postal addresses"
6
+
4
7
  attr_writer :show_format
5
8
  attr_writer :list_format
6
9
 
7
10
  def initialize
8
- @name = "post"
9
- @description = "List, show or change postal addresses"
10
11
  @show_format = Ppl::Format::Contact::PostalAddress.new
11
12
  @list_format = Ppl::Format::AddressBook::PostalAddresses.new
12
13
  end
@@ -1,10 +1,8 @@
1
1
 
2
2
  class Ppl::Command::Rm < Ppl::Application::Command
3
3
 
4
- def initialize
5
- @name = "rm"
6
- @description = "Delete a contact"
7
- end
4
+ name "rm"
5
+ description "Delete a contact"
8
6
 
9
7
  def options(parser, options)
10
8
  parser.banner = "usage: ppl rm <contact>"
@@ -3,12 +3,10 @@ require "readline"
3
3
 
4
4
  class Ppl::Command::Shell < Ppl::Application::Command
5
5
 
6
- attr_writer :format
6
+ name "shell"
7
+ description "Interactive mode"
7
8
 
8
- def initialize
9
- @name = "shell"
10
- @description = "Interactive mode"
11
- end
9
+ attr_writer :format
12
10
 
13
11
  def options(parser, options)
14
12
  parser.banner = "usage: ppl shell"
@@ -1,12 +1,12 @@
1
1
 
2
2
  class Ppl::Command::Show < Ppl::Application::Command
3
3
 
4
+ name "show"
5
+ description "Display the full details of a contact"
6
+
4
7
  attr_writer :format
5
8
 
6
9
  def initialize
7
- @name = "show"
8
- @description = "Display the full details of a contact"
9
-
10
10
  @format = Ppl::Format::Contact::Full.new
11
11
  end
12
12
 
data/lib/ppl.rb CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  module Ppl
3
3
 
4
- Version = "1.5.2"
4
+ Version = "1.5.3"
5
5
 
6
6
  module Adapter
7
7
  end
data/ppl.gemspec CHANGED
@@ -2,8 +2,8 @@
2
2
  Gem::Specification.new do |spec|
3
3
 
4
4
  spec.name = "ppl"
5
- spec.version = "1.5.2"
6
- spec.date = "2012-12-23"
5
+ spec.version = "1.5.3"
6
+ spec.date = "2012-12-26"
7
7
 
8
8
  spec.required_ruby_version = ">= 1.9.3"
9
9
 
@@ -1,18 +1,91 @@
1
1
 
2
- describe Ppl::Application::Command, "#execute" do
2
+ describe Ppl::Application::Command do
3
3
 
4
4
  before(:each) do
5
5
  @command = Ppl::Application::Command.new
6
6
  end
7
7
 
8
- it "should raise not implemented error" do
9
- expect{@command.execute(nil, nil)}.to raise_error(NotImplementedError)
8
+ describe "#execute" do
9
+ it "should raise not implemented error" do
10
+ expect{@command.execute(nil, nil)}.to raise_error(NotImplementedError)
11
+ end
10
12
  end
11
13
 
12
- it "should accept a storage adapter" do
13
- storage = double(Ppl::Adapter::Storage)
14
- @command.storage = storage
15
- @command.storage.should be storage
14
+ describe "#storage=" do
15
+ it "should accept a storage adapter" do
16
+ storage = double(Ppl::Adapter::Storage)
17
+ @command.storage = storage
18
+ @command.storage.should be storage
19
+ end
20
+ end
21
+
22
+ describe "#add_property" do
23
+ it "should allow new properties to be defined" do
24
+ class TestCommand123 < Ppl::Application::Command
25
+ add_property :some_property
26
+ end
27
+ end
28
+
29
+ it "should allow properties to have values assigned to them" do
30
+ class TestCommand456 < Ppl::Application::Command
31
+ add_property :some_property
32
+ some_property "a value"
33
+ end
34
+ TestCommand456.some_property.should eq "a value"
35
+ end
36
+
37
+ it "should expose properties as instance variables too" do
38
+ class TestCommand789 < Ppl::Application::Command
39
+ add_property :some_property
40
+ some_property "a value"
41
+ end
42
+ instance = TestCommand789.new
43
+ instance.some_property.should eq "a value"
44
+ end
45
+
46
+ it "should allow properties to be overwritten by instance variables" do
47
+ class TestCommand901 < Ppl::Application::Command
48
+ add_property :some_property
49
+ some_property "a value"
50
+ end
51
+ instance = TestCommand901.new
52
+ instance.some_property = "different"
53
+ instance.some_property.should eq "different"
54
+ end
55
+ end
56
+
57
+ describe "#name=" do
58
+ it "should allow the name to be set as an instance variable" do
59
+ @command.name = "testing"
60
+ @command.name.should eq "testing"
61
+ end
62
+ end
63
+
64
+ describe "#description=" do
65
+ it "should allow the description to be set as an instance variable" do
66
+ @command.description = "testing"
67
+ @command.description.should eq "testing"
68
+ end
69
+ end
70
+
71
+ describe "#name" do
72
+ it "should allow the name to be set as a class variable" do
73
+ class TestCommand123 < Ppl::Application::Command
74
+ name "new_for_test"
75
+ end
76
+ command = TestCommand123.new
77
+ command.name.should eq "new_for_test"
78
+ end
79
+ end
80
+
81
+ describe "#desecription" do
82
+ it "should allow the description to be set as a class variable" do
83
+ class TestCommand123 < Ppl::Application::Command
84
+ description "desc_for_test"
85
+ end
86
+ command = TestCommand123.new
87
+ command.description.should eq "desc_for_test"
88
+ end
16
89
  end
17
90
 
18
91
  end
@@ -71,9 +71,15 @@ describe Ppl::Application::Shell do
71
71
  @command.should_receive(:options)
72
72
  @command.should_receive(:execute) { raise "Pool's Closed" }
73
73
  @router.should_receive(:route).and_return(@command)
74
-
75
74
  @output.should_receive(:error).with("ppl: Pool's Closed")
75
+ @shell.run(@input, @output)
76
+ end
76
77
 
78
+ it "should handle ContactNotFound errors nicely" do
79
+ @command.stub(:options)
80
+ @command.should_receive(:execute) { raise Ppl::Error::ContactNotFound, "example" }
81
+ @router.should_receive(:route).and_return(@command)
82
+ @output.should_receive(:error).with("ppl: Contact 'example' not found")
77
83
  @shell.run(@input, @output)
78
84
  end
79
85
 
@@ -26,9 +26,8 @@ describe Ppl::Command::Mutt do
26
26
  end
27
27
 
28
28
  it "should search the address book for the query" do
29
- @storage.should_receive(:load_address_book).and_return(@address_book)
30
29
  @input.arguments.push "query"
31
- @command.stub(:mutt_search) { |ab| [] }
30
+ @command.should_receive(:mutt_search).and_return([])
32
31
  @output.should_receive(:line).with("No matches")
33
32
  @command.execute(@input, @output).should eq false
34
33
  end
@@ -42,8 +41,10 @@ describe Ppl::Command::Mutt do
42
41
  @input.arguments.push "example"
43
42
 
44
43
  @storage.should_receive(:load_address_book).and_return(@address_book)
45
- @output.should_receive(:line).with("Searching database... 1 entries... 1 matching:")
46
- @output.should_receive(:line).with("test@example.org\tTest User")
44
+ @output.should_receive(:line) do |line|
45
+ line.should include "Searching address book... 1 entries... 1 matching:"
46
+ line.should include "test@example.org\tTest User"
47
+ end
47
48
  @command.execute(@input, @output).should eq true
48
49
  end
49
50
 
@@ -56,8 +57,10 @@ describe Ppl::Command::Mutt do
56
57
  @input.arguments.push "User"
57
58
 
58
59
  @storage.should_receive(:load_address_book).and_return(@address_book)
59
- @output.should_receive(:line).with("Searching database... 1 entries... 1 matching:")
60
- @output.should_receive(:line).with("test@example.org\tTest User")
60
+ @output.should_receive(:line) do |line|
61
+ line.should include "Searching address book... 1 entries... 1 matching:"
62
+ line.should include "test@example.org\tTest User"
63
+ end
61
64
  @command.execute(@input, @output).should eq true
62
65
  end
63
66
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ppl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.2
4
+ version: 1.5.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-23 00:00:00.000000000 Z
12
+ date: 2012-12-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: inifile
16
- requirement: &16217320 !ruby/object:Gem::Requirement
16
+ requirement: &19907800 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - =
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.0.2
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *16217320
24
+ version_requirements: *19907800
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rugged
27
- requirement: &16216640 !ruby/object:Gem::Requirement
27
+ requirement: &19907120 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - =
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.17.0.b6
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *16216640
35
+ version_requirements: *19907120
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: vpim
38
- requirement: &16215860 !ruby/object:Gem::Requirement
38
+ requirement: &19906320 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - =
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0.695'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *16215860
46
+ version_requirements: *19906320
47
47
  description: CLI Address Book
48
48
  email: henry@henrysmith.org
49
49
  executables: