ppl 0.3.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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
+