ppl 0.3.0 → 0.9.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.
Files changed (97) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +4 -0
  4. data/README.md +1 -3
  5. data/lib/ppl/adapter/storage/disk.rb +27 -7
  6. data/lib/ppl/adapter/storage/factory.rb +26 -0
  7. data/lib/ppl/adapter/storage/git.rb +101 -0
  8. data/lib/ppl/adapter/storage.rb +4 -0
  9. data/lib/ppl/adapter/vcard/vpim.rb +16 -0
  10. data/lib/ppl/application/bootstrap.rb +23 -10
  11. data/lib/ppl/application/command.rb +3 -0
  12. data/lib/ppl/application/command_suite.rb +8 -0
  13. data/lib/ppl/application/configuration.rb +50 -0
  14. data/lib/ppl/application/output.rb +1 -0
  15. data/lib/ppl/application/shell.rb +21 -0
  16. data/lib/ppl/command/add.rb +34 -0
  17. data/lib/ppl/command/bday.rb +72 -0
  18. data/lib/ppl/command/email.rb +55 -0
  19. data/lib/ppl/command/help.rb +43 -0
  20. data/lib/ppl/command/init.rb +26 -0
  21. data/lib/ppl/command/ls.rb +26 -0
  22. data/lib/ppl/command/mv.rb +42 -0
  23. data/lib/ppl/command/name.rb +54 -0
  24. data/lib/ppl/command/org.rb +55 -0
  25. data/lib/ppl/command/phone.rb +55 -0
  26. data/lib/ppl/command/rm.rb +26 -0
  27. data/lib/ppl/command/show.rb +31 -0
  28. data/lib/ppl/entity/contact.rb +2 -0
  29. data/lib/ppl/format/address_book/birthdays.rb +34 -0
  30. data/lib/ppl/format/address_book/email_addresses.rb +34 -0
  31. data/lib/ppl/format/address_book/names.rb +34 -0
  32. data/lib/ppl/format/address_book/one_line.rb +34 -0
  33. data/lib/ppl/format/address_book/organizations.rb +34 -0
  34. data/lib/ppl/format/address_book/phone_numbers.rb +34 -0
  35. data/lib/ppl/format/address_book.rb +9 -0
  36. data/lib/ppl/format/contact/birthday.rb +13 -0
  37. data/lib/ppl/format/contact/email_address.rb +13 -0
  38. data/lib/ppl/format/contact/full.rb +55 -0
  39. data/lib/ppl/format/contact/name.rb +15 -0
  40. data/lib/ppl/format/contact/organization.rb +13 -0
  41. data/lib/ppl/format/contact/phone_number.rb +13 -0
  42. data/lib/ppl/format/contact.rb +9 -0
  43. data/lib/ppl/format/table.rb +48 -0
  44. data/lib/ppl.rb +33 -11
  45. data/ppl.gemspec +1 -1
  46. data/spec/ppl/adapter/storage/disk_spec.rb +57 -10
  47. data/spec/ppl/adapter/storage/factory_spec.rb +34 -0
  48. data/spec/ppl/adapter/storage/git_spec.rb +114 -0
  49. data/spec/ppl/adapter/storage_spec.rb +6 -0
  50. data/spec/ppl/adapter/vcard/vpim_spec.rb +34 -0
  51. data/spec/ppl/application/bootstrap_spec.rb +42 -4
  52. data/spec/ppl/application/command_suite_spec.rb +8 -0
  53. data/spec/ppl/application/configuration_spec.rb +32 -0
  54. data/spec/ppl/application/shell_spec.rb +4 -0
  55. data/spec/ppl/command/{contact_add_spec.rb → add_spec.rb} +2 -2
  56. data/spec/ppl/command/bday_spec.rb +56 -0
  57. data/spec/ppl/command/email_spec.rb +56 -0
  58. data/spec/ppl/command/help_spec.rb +79 -0
  59. data/spec/ppl/command/init_spec.rb +40 -0
  60. data/spec/ppl/command/ls_spec.rb +32 -0
  61. data/spec/ppl/command/mv_spec.rb +62 -0
  62. data/spec/ppl/command/name_spec.rb +59 -0
  63. data/spec/ppl/command/org_spec.rb +57 -0
  64. data/spec/ppl/command/phone_spec.rb +55 -0
  65. data/spec/ppl/command/{contact_delete_spec.rb → rm_spec.rb} +8 -2
  66. data/spec/ppl/command/{contact_show_spec.rb → show_spec.rb} +12 -6
  67. data/spec/ppl/format/address_book/birthdays_spec.rb +38 -0
  68. data/spec/ppl/format/address_book/email_addresses_spec.rb +38 -0
  69. data/spec/ppl/format/address_book/names_spec.rb +38 -0
  70. data/spec/ppl/format/address_book/one_line_spec.rb +41 -0
  71. data/spec/ppl/format/address_book/organizations_spec.rb +38 -0
  72. data/spec/ppl/format/address_book/phone_numbers_spec.rb +38 -0
  73. data/spec/ppl/format/address_book_spec.rb +18 -0
  74. data/spec/ppl/format/contact/birthday_spec.rb +23 -0
  75. data/spec/ppl/format/contact/email_address_spec.rb +23 -0
  76. data/spec/ppl/format/contact/full_spec.rb +44 -0
  77. data/spec/ppl/format/contact/name_spec.rb +23 -0
  78. data/spec/ppl/format/contact/organization_spec.rb +23 -0
  79. data/spec/ppl/format/contact/phone_number_spec.rb +23 -0
  80. data/spec/ppl/format/contact_spec.rb +17 -0
  81. data/spec/ppl/format/table_spec.rb +72 -0
  82. metadata +61 -19
  83. data/lib/ppl/command/command_list.rb +0 -21
  84. data/lib/ppl/command/contact_add.rb +0 -26
  85. data/lib/ppl/command/contact_delete.rb +0 -16
  86. data/lib/ppl/command/contact_list.rb +0 -24
  87. data/lib/ppl/command/contact_rename.rb +0 -23
  88. data/lib/ppl/command/contact_show.rb +0 -20
  89. data/lib/ppl/command/set_birthday.rb +0 -30
  90. data/lib/ppl/command/set_email.rb +0 -23
  91. data/lib/ppl/command/set_name.rb +0 -28
  92. data/spec/ppl/command/command_list_spec.rb +0 -37
  93. data/spec/ppl/command/contact_list_spec.rb +0 -15
  94. data/spec/ppl/command/contact_rename_spec.rb +0 -42
  95. data/spec/ppl/command/set_birthday_spec.rb +0 -50
  96. data/spec/ppl/command/set_email_spec.rb +0 -38
  97. data/spec/ppl/command/set_name_spec.rb +0 -45
@@ -0,0 +1,26 @@
1
+
2
+ class Ppl::Command::Ls < Ppl::Application::Command
3
+
4
+ attr_writer :format
5
+
6
+ def initialize
7
+ @name = "ls"
8
+ @description = "List all contacts"
9
+
10
+ @format = Ppl::Format::AddressBook::OneLine.new
11
+ end
12
+
13
+ def options(parser, options)
14
+ parser.banner = "usage: ppl ls"
15
+ end
16
+
17
+ def execute(input, output)
18
+ address_book = @storage.load_address_book
19
+ formatted = @format.process(address_book)
20
+
21
+ output.line(formatted)
22
+ return true
23
+ end
24
+
25
+ end
26
+
@@ -0,0 +1,42 @@
1
+
2
+ class Ppl::Command::Mv < Ppl::Application::Command
3
+
4
+ def initialize
5
+ @name = "mv"
6
+ @description = "Rename a contact"
7
+ end
8
+
9
+ def options(parser, options)
10
+ parser.banner = "usage: ppl mv <contact> <new ID>"
11
+ end
12
+
13
+ def execute(input, output)
14
+ old_id = input.arguments.shift
15
+ new_id = input.arguments.shift
16
+
17
+ if old_id.nil?
18
+ raise Ppl::Error::IncorrectUsage, "No contact specified"
19
+ end
20
+
21
+ if new_id.nil?
22
+ raise Ppl::Error::IncorrectUsage, "No new ID specified"
23
+ end
24
+
25
+ old_contact = @storage.require_contact(old_id)
26
+ new_contact = @storage.load_contact(new_id)
27
+
28
+ if !new_contact.nil?
29
+ output.error("There is already a contact with ID '#{new_id}'")
30
+ return false
31
+ end
32
+
33
+ @storage.delete_contact(old_contact)
34
+
35
+ old_contact.id = new_id
36
+ @storage.save_contact(old_contact)
37
+
38
+ return true
39
+ end
40
+
41
+ end
42
+
@@ -0,0 +1,54 @@
1
+
2
+ class Ppl::Command::Name < Ppl::Application::Command
3
+
4
+ attr_writer :show_format
5
+ attr_writer :list_format
6
+
7
+ def initialize
8
+ @name = "name"
9
+ @description = "List, show or change names"
10
+ @show_format = Ppl::Format::Contact::Name.new
11
+ @list_format = Ppl::Format::AddressBook::Names.new
12
+ end
13
+
14
+ def options(parser, options)
15
+ parser.banner = "usage: ppl name <contact> [<name>]"
16
+ end
17
+
18
+ def execute(input, output)
19
+ action = determine_action(input)
20
+ send(action, input, output)
21
+ end
22
+
23
+ private
24
+
25
+ def determine_action(input)
26
+ if input.arguments[0].nil?
27
+ :list_names
28
+ elsif input.arguments[1].nil?
29
+ :show_name
30
+ else
31
+ :set_name
32
+ end
33
+ end
34
+
35
+ def list_names(input, output)
36
+ address_book = @storage.load_address_book
37
+ name_list = @list_format.process(address_book)
38
+ output.line(name_list)
39
+ end
40
+
41
+ def show_name(input, output)
42
+ contact = @storage.require_contact(input.arguments[0])
43
+ name = @show_format.process(contact)
44
+ output.line(name)
45
+ end
46
+
47
+ def set_name(input, output)
48
+ contact = @storage.require_contact(input.arguments[0])
49
+ contact.name = input.arguments[1].dup
50
+ @storage.save_contact(contact)
51
+ end
52
+
53
+ end
54
+
@@ -0,0 +1,55 @@
1
+
2
+ class Ppl::Command::Org < Ppl::Application::Command
3
+
4
+ attr_writer :show_format
5
+ attr_writer :list_format
6
+
7
+ def initialize
8
+ @name = "org"
9
+ @description = "List, show or change organizations"
10
+ @show_format = Ppl::Format::Contact::Organization.new
11
+ @list_format = Ppl::Format::AddressBook::Organizations.new
12
+ end
13
+
14
+ def options(parser, options)
15
+ parser.banner = "usage: ppl org <contact> [<organization>]"
16
+ end
17
+
18
+ def execute(input, output)
19
+ action = determine_action(input)
20
+ send(action, input, output)
21
+ end
22
+
23
+
24
+ private
25
+
26
+ def determine_action(input)
27
+ if input.arguments[0].nil?
28
+ :list_organizations
29
+ elsif input.arguments[1].nil?
30
+ :show_organization
31
+ else
32
+ :set_organization
33
+ end
34
+ end
35
+
36
+ def list_organizations(input, output)
37
+ address_book = @storage.load_address_book
38
+ org_list = @list_format.process(address_book)
39
+ output.line(org_list)
40
+ end
41
+
42
+ def show_organization(input, output)
43
+ contact = @storage.require_contact(input.arguments[0])
44
+ organization = @show_format.process(contact)
45
+ output.line(organization)
46
+ end
47
+
48
+ def set_organization(input, output)
49
+ contact = @storage.require_contact(input.arguments[0])
50
+ contact.organization = input.arguments[1].dup
51
+ @storage.save_contact(contact)
52
+ end
53
+
54
+ end
55
+
@@ -0,0 +1,55 @@
1
+
2
+ class Ppl::Command::Phone < Ppl::Application::Command
3
+
4
+ attr_writer :show_format
5
+ attr_writer :list_format
6
+
7
+ def initialize
8
+ @name = "phone"
9
+ @description = "List, show or change phone numbers"
10
+ @show_format = Ppl::Format::Contact::PhoneNumber.new
11
+ @list_format = Ppl::Format::AddressBook::PhoneNumbers.new
12
+ end
13
+
14
+ def options(parser, options)
15
+ parser.banner = "usage: ppl phone <contact> [<number>]"
16
+ end
17
+
18
+ def execute(input, output)
19
+ action = determine_action(input)
20
+ send(action, input, output)
21
+ end
22
+
23
+
24
+ private
25
+
26
+ def determine_action(input)
27
+ if input.arguments[0].nil?
28
+ :list_phone_numbers
29
+ elsif input.arguments[1].nil?
30
+ :show_phone_number
31
+ else
32
+ :set_phone_number
33
+ end
34
+ end
35
+
36
+ def list_phone_numbers(input, output)
37
+ address_book = @storage.load_address_book
38
+ number_list = @list_format.process(address_book)
39
+ output.line(number_list)
40
+ end
41
+
42
+ def show_phone_number(input, output)
43
+ contact = @storage.require_contact(input.arguments[0])
44
+ number = @show_format.process(contact)
45
+ output.line(number)
46
+ end
47
+
48
+ def set_phone_number(input, output)
49
+ contact = @storage.require_contact(input.arguments[0])
50
+ contact.phone_number = input.arguments[1]
51
+ @storage.save_contact(contact)
52
+ end
53
+
54
+ end
55
+
@@ -0,0 +1,26 @@
1
+
2
+ class Ppl::Command::Rm < Ppl::Application::Command
3
+
4
+ def initialize
5
+ @name = "rm"
6
+ @description = "Delete a contact"
7
+ end
8
+
9
+ def options(parser, options)
10
+ parser.banner = "usage: ppl rm <contact>"
11
+ end
12
+
13
+ def execute(input, output)
14
+ contact_id = input.arguments.first
15
+
16
+ if contact_id.nil?
17
+ raise Ppl::Error::IncorrectUsage, "No contact specified"
18
+ end
19
+
20
+ contact = @storage.require_contact(contact_id)
21
+ @storage.delete_contact(contact)
22
+ return true
23
+ end
24
+
25
+ end
26
+
@@ -0,0 +1,31 @@
1
+
2
+ class Ppl::Command::Show < Ppl::Application::Command
3
+
4
+ attr_writer :format
5
+
6
+ def initialize
7
+ @name = "show"
8
+ @description = "Display the full details of a contact"
9
+
10
+ @format = Ppl::Format::Contact::Full.new
11
+ end
12
+
13
+ def options(parser, options)
14
+ parser.banner = "usage: ppl show <contact>"
15
+ end
16
+
17
+ def execute(input, output)
18
+ contact_id = input.arguments.shift
19
+ if contact_id.nil?
20
+ raise Ppl::Error::IncorrectUsage, "No contact specified"
21
+ end
22
+
23
+ contact = @storage.require_contact(contact_id)
24
+ formatted = @format.process(contact)
25
+
26
+ output.line(formatted)
27
+ return true
28
+ end
29
+
30
+ end
31
+
@@ -5,6 +5,8 @@ class Ppl::Entity::Contact
5
5
  attr_accessor :name
6
6
  attr_accessor :email_address
7
7
  attr_accessor :birthday
8
+ attr_accessor :phone_number
9
+ attr_accessor :organization
8
10
 
9
11
  end
10
12
 
@@ -0,0 +1,34 @@
1
+
2
+ class Ppl::Format::AddressBook::Birthdays < Ppl::Format::AddressBook
3
+
4
+ attr_writer :table
5
+
6
+ def initialize
7
+ @table = Ppl::Format::Table.new([:id, :birthday])
8
+ end
9
+
10
+ def process(address_book)
11
+ address_book.each { |contact| add_row(contact) }
12
+ @table.to_s
13
+ end
14
+
15
+
16
+ private
17
+
18
+ def add_row(contact)
19
+ id = sprintf("%s:", contact.id)
20
+ birthday = nil
21
+
22
+ if !contact.birthday.nil?
23
+ birthday = contact.birthday.strftime("%Y-%m-%d")
24
+ end
25
+
26
+ @table.add_row({
27
+ :id => id,
28
+ :birthday => birthday,
29
+ })
30
+ end
31
+
32
+
33
+ end
34
+
@@ -0,0 +1,34 @@
1
+
2
+ class Ppl::Format::AddressBook::EmailAddresses < Ppl::Format::AddressBook
3
+
4
+ attr_writer :table
5
+
6
+ def initialize
7
+ @table = Ppl::Format::Table.new([:id, :email_address])
8
+ end
9
+
10
+ def process(address_book)
11
+ address_book.each { |contact| add_row(contact) }
12
+ @table.to_s
13
+ end
14
+
15
+
16
+ private
17
+
18
+ def add_row(contact)
19
+ id = sprintf("%s:", contact.id)
20
+ email_address = nil
21
+
22
+ if !contact.email_address.nil?
23
+ email_address = contact.email_address
24
+ end
25
+
26
+ @table.add_row({
27
+ :id => id,
28
+ :email_address => email_address,
29
+ })
30
+ end
31
+
32
+
33
+ end
34
+
@@ -0,0 +1,34 @@
1
+
2
+ class Ppl::Format::AddressBook::Names < Ppl::Format::AddressBook
3
+
4
+ attr_writer :table
5
+
6
+ def initialize
7
+ @table = Ppl::Format::Table.new([:id, :name])
8
+ end
9
+
10
+ def process(address_book)
11
+ address_book.each { |contact| add_row(contact) }
12
+ @table.to_s
13
+ end
14
+
15
+
16
+ private
17
+
18
+ def add_row(contact)
19
+ id = sprintf("%s:", contact.id)
20
+ name = nil
21
+
22
+ if !contact.name.nil?
23
+ name = contact.name
24
+ end
25
+
26
+ @table.add_row({
27
+ :id => id,
28
+ :name => name,
29
+ })
30
+ end
31
+
32
+
33
+ end
34
+
@@ -0,0 +1,34 @@
1
+
2
+ class Ppl::Format::AddressBook::OneLine < Ppl::Format::AddressBook
3
+
4
+ attr_writer :table
5
+
6
+ def initialize
7
+ @table = Ppl::Format::Table.new([:id, :name, :email])
8
+ end
9
+
10
+ def process(address_book)
11
+ address_book.each { |contact| add_row(contact) }
12
+ @table.to_s
13
+ end
14
+
15
+ private
16
+
17
+ def add_row(contact)
18
+ id = sprintf("%s:", contact.id)
19
+ name = contact.name
20
+ email = nil
21
+
22
+ if !contact.email_address.nil?
23
+ email = sprintf("<%s>", contact.email_address)
24
+ end
25
+
26
+ @table.add_row({
27
+ :id => id,
28
+ :name => name,
29
+ :email => email,
30
+ })
31
+ end
32
+
33
+ end
34
+
@@ -0,0 +1,34 @@
1
+
2
+ class Ppl::Format::AddressBook::Organizations < Ppl::Format::AddressBook
3
+
4
+ attr_writer :table
5
+
6
+ def initialize
7
+ @table = Ppl::Format::Table.new([:id, :organization])
8
+ end
9
+
10
+ def process(address_book)
11
+ address_book.each { |contact| add_row(contact) }
12
+ @table.to_s
13
+ end
14
+
15
+
16
+ private
17
+
18
+ def add_row(contact)
19
+ contact_id = sprintf("%s:", contact.id)
20
+ organization = nil
21
+
22
+ if !contact.organization.nil?
23
+ organization = contact.organization
24
+ end
25
+
26
+ @table.add_row({
27
+ :id => contact_id,
28
+ :organization => organization,
29
+ })
30
+ end
31
+
32
+
33
+ end
34
+
@@ -0,0 +1,34 @@
1
+
2
+ class Ppl::Format::AddressBook::PhoneNumbers < Ppl::Format::AddressBook
3
+
4
+ attr_writer :table
5
+
6
+ def initialize
7
+ @table = Ppl::Format::Table.new([:id, :phone_number])
8
+ end
9
+
10
+ def process(address_book)
11
+ address_book.each { |contact| add_row(contact) }
12
+ @table.to_s
13
+ end
14
+
15
+
16
+ private
17
+
18
+ def add_row(contact)
19
+ contact_id = sprintf("%s:", contact.id)
20
+ phone_number = nil
21
+
22
+ if !contact.phone_number.nil?
23
+ phone_number = contact.phone_number
24
+ end
25
+
26
+ @table.add_row({
27
+ :id => contact_id,
28
+ :phone_number => phone_number,
29
+ })
30
+ end
31
+
32
+
33
+ end
34
+
@@ -0,0 +1,9 @@
1
+
2
+ class Ppl::Format::AddressBook
3
+
4
+ def process(address_book)
5
+ raise NotImplementedError
6
+ end
7
+
8
+ end
9
+
@@ -0,0 +1,13 @@
1
+
2
+ class Ppl::Format::Contact::Birthday < Ppl::Format::Contact
3
+
4
+ def process(contact)
5
+ output = ""
6
+ if !contact.birthday.nil?
7
+ output += contact.birthday.strftime("%Y-%m-%d")
8
+ end
9
+ return output
10
+ end
11
+
12
+ end
13
+
@@ -0,0 +1,13 @@
1
+
2
+ class Ppl::Format::Contact::EmailAddress < Ppl::Format::Contact
3
+
4
+ def process(contact)
5
+ output = ""
6
+ if !contact.email_address.nil?
7
+ output += contact.email_address
8
+ end
9
+ return output
10
+ end
11
+
12
+ end
13
+
@@ -0,0 +1,55 @@
1
+
2
+ class Ppl::Format::Contact::Full < Ppl::Format::Contact
3
+
4
+ def process(contact)
5
+ lines = []
6
+
7
+ first_line = first_line(contact)
8
+ if first_line != ""
9
+ lines.push(first_line)
10
+ end
11
+
12
+ vitals = vitals(contact)
13
+ if vitals != ""
14
+ lines.push("")
15
+ lines.push(vitals)
16
+ lines.push("")
17
+ lines.push("")
18
+ end
19
+
20
+ return lines.join("\n")
21
+ end
22
+
23
+ private
24
+
25
+ def first_line(contact)
26
+ line = ""
27
+ if !contact.name.nil?
28
+ line += contact.name
29
+ end
30
+ if !contact.email_address.nil?
31
+ line += " <#{contact.email_address}>"
32
+ end
33
+ return line
34
+ end
35
+
36
+ def vitals(contact)
37
+ vitals = []
38
+ if !contact.birthday.nil?
39
+ vitals.push(format_vital("Birthday", contact.birthday.strftime("%Y-%m-%d")))
40
+ end
41
+ if !contact.phone_number.nil?
42
+ vitals.push(format_vital("Telephone", contact.phone_number))
43
+ end
44
+ if !contact.organization.nil?
45
+ vitals.push(format_vital("Organization", contact.organization))
46
+ end
47
+ return vitals.join("\n")
48
+ end
49
+
50
+ def format_vital(name, value)
51
+ return sprintf(" %-12s %s", name, value)
52
+ end
53
+
54
+ end
55
+
@@ -0,0 +1,15 @@
1
+
2
+ class Ppl::Format::Contact::Name < Ppl::Format::Contact
3
+
4
+ def process(contact)
5
+ output = ""
6
+
7
+ if !contact.name.nil?
8
+ output += contact.name
9
+ end
10
+
11
+ return output
12
+ end
13
+
14
+ end
15
+
@@ -0,0 +1,13 @@
1
+
2
+ class Ppl::Format::Contact::Organization < Ppl::Format::Contact
3
+
4
+ def process(contact)
5
+ output = ""
6
+ if !contact.organization.nil?
7
+ output += contact.organization
8
+ end
9
+ return output
10
+ end
11
+
12
+ end
13
+
@@ -0,0 +1,13 @@
1
+
2
+ class Ppl::Format::Contact::PhoneNumber < Ppl::Format::Contact
3
+
4
+ def process(contact)
5
+ output = ""
6
+ if !contact.phone_number.nil?
7
+ output += contact.phone_number
8
+ end
9
+ return output
10
+ end
11
+
12
+ end
13
+
@@ -0,0 +1,9 @@
1
+
2
+ class Ppl::Format::Contact
3
+
4
+ def process(contact)
5
+ raise NotImplementedError
6
+ end
7
+
8
+ end
9
+