toodledo 1.0.2 → 1.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.
@@ -0,0 +1,9 @@
1
+ module Toodledo
2
+ module CommandLine
3
+ class ContextFormatter
4
+ def format(context)
5
+ return "<#{context.server_id}> -- @[#{context.name}]"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,7 +1,79 @@
1
1
 
2
2
  module Toodledo
3
3
  module CommandLine
4
- class DeleteCommand < BaseCommand
4
+
5
+ class DeleteCommand < CmdParse::Command
6
+ def initialize(client)
7
+ super('delete', true)
8
+ self.short_desc = "Deletes a context"
9
+
10
+ self.add_command(DeleteContextCommand.new(client))
11
+ self.add_command(DeleteGoalCommand.new(client))
12
+ self.add_command(DeleteFolderCommand.new(client))
13
+
14
+ self.add_command(DeleteTaskCommand.new(client), true)
15
+ end
16
+
17
+ end
18
+
19
+ class DeleteContextCommand < BaseCommand
20
+ def initialize(client)
21
+ super(client, 'context', false)
22
+ self.short_desc = "Deletes a context"
23
+ end
24
+
25
+ def execute(args)
26
+ Toodledo.begin(client.logger) do |session|
27
+ line = args.join(' ')
28
+ client.delete_context(session, line)
29
+ end
30
+
31
+ return 0
32
+ rescue ItemNotFoundError => e
33
+ puts e.message
34
+ return -1
35
+ end
36
+ end
37
+
38
+ class DeleteFolderCommand < BaseCommand
39
+ def initialize(client)
40
+ super(client, 'folder', false)
41
+ self.short_desc = "Deletes a folder"
42
+ end
43
+
44
+ def execute(args)
45
+ Toodledo.begin(client.logger) do |session|
46
+ line = args.join(' ')
47
+ client.delete_folder(session, line)
48
+ end
49
+
50
+ return 0
51
+ rescue ItemNotFoundError => e
52
+ puts e.message
53
+ return -1
54
+ end
55
+ end
56
+
57
+ class DeleteGoalCommand < BaseCommand
58
+ def initialize(client)
59
+ super(client, 'goal', false)
60
+ self.short_desc = "Deletes a goal"
61
+ end
62
+
63
+ def execute(args)
64
+ Toodledo.begin(client.logger) do |session|
65
+ line = args.join(' ')
66
+ client.delete_goal(session, line)
67
+ end
68
+
69
+ return 0
70
+ rescue ItemNotFoundError => e
71
+ puts e.message
72
+ return -1
73
+ end
74
+ end
75
+
76
+ class DeleteTaskCommand < BaseCommand
5
77
  def initialize(client)
6
78
  super(client, 'delete', false)
7
79
  self.short_desc = "Deletes a task"
@@ -20,5 +92,7 @@ module Toodledo
20
92
  return -1
21
93
  end
22
94
  end
95
+
96
+
23
97
  end
24
98
  end
@@ -0,0 +1,9 @@
1
+ module Toodledo
2
+ module CommandLine
3
+ class FolderFormatter
4
+ def format(folder)
5
+ return "<#{folder.server_id}> -- *[#{folder.name}]"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,26 @@
1
+ require 'toodledo/goal'
2
+
3
+ module Toodledo
4
+ module CommandLine
5
+ class GoalFormatter
6
+ def format(goal)
7
+ msg = "<#{goal.server_id}> -- #{readable_level(goal.level)} ^[#{goal.name}]"
8
+ if (goal.contributes != Goal::NO_GOAL)
9
+ msg += " (Contributes to: ^[#{goal.contributes.name}])"
10
+ end
11
+ return msg
12
+ end
13
+
14
+ def readable_level(level)
15
+ case level
16
+ when Goal::LIFE_LEVEL
17
+ return 'life'
18
+ when Goal::MEDIUM_LEVEL
19
+ return 'medium'
20
+ when Goal::SHORT_LEVEL
21
+ return 'short'
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,43 @@
1
+ require 'toodledo/command_line/parser_helper'
2
+ require 'logger'
3
+
4
+ module Toodledo
5
+
6
+ module CommandLine
7
+ # Runs the interactive client.
8
+ class InteractiveCommand < BaseCommand
9
+
10
+ def initialize(client)
11
+ super(client, 'interactive', false)
12
+ self.short_desc = "Interactive client"
13
+ self.description = "The interactive command line client."
14
+ end
15
+
16
+ def execute(args)
17
+ Toodledo.begin(client.logger) do |session|
18
+ command_loop(session)
19
+ end
20
+ end
21
+
22
+ def command_loop(session)
23
+ loop do
24
+ begin
25
+ input = ask("> ") do |q|
26
+ q.readline = true
27
+ end
28
+
29
+ input.strip!
30
+
31
+ client.execute_command(session, input)
32
+ rescue Toodledo::ItemNotFoundError => infe
33
+ puts "Item not found: #{infe}"
34
+ rescue Toodledo::ServerError => se
35
+ puts "Server Error: #{se}"
36
+ rescue RuntimeError => re
37
+ puts "Error: #{re}"
38
+ end
39
+ end # loop
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,32 @@
1
+ #
2
+ #
3
+ #
4
+
5
+
6
+ module Toodledo
7
+ module CommandLine
8
+
9
+
10
+ #
11
+ # List Folders
12
+ #
13
+ class ListFoldersCommand < BaseCommand
14
+ def initialize(client)
15
+ super(client, 'folders', false)
16
+ self.short_desc = "List folders"
17
+ self.description = "Lists the folders in Toodledo."
18
+ end
19
+
20
+ def execute(args)
21
+
22
+ Toodledo.begin(client.logger) do |session|
23
+ line = args.join(' ')
24
+ return client.list_folders(session, line)
25
+ end
26
+
27
+ return 0
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ #
2
+ #
3
+ #
4
+
5
+
6
+ module Toodledo
7
+ module CommandLine
8
+
9
+ #
10
+ # List Goals
11
+ #
12
+ class ListGoalsCommand < BaseCommand
13
+ def initialize(client)
14
+ super(client, 'goals', false)
15
+ self.short_desc = "List goals"
16
+ self.description = "Lists the goals in Toodledo."
17
+ end
18
+
19
+ def execute(args)
20
+
21
+ Toodledo.begin(client.logger) do |session|
22
+ line = args.join(' ')
23
+ return client.list_goals(session, line)
24
+ end
25
+
26
+ return 0
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -1,14 +1,19 @@
1
1
 
2
2
  module Toodledo
3
3
  module CommandLine
4
- class ListCommand < BaseCommand
4
+
5
+ #
6
+ # Lists the tasks.
7
+ #
8
+ class ListTasksCommand < BaseCommand
5
9
  def initialize(client)
6
- super(client, 'list', false)
10
+ super(client, 'tasks', false)
7
11
  self.short_desc = "List tasks"
8
12
  self.description = "Lists the tasks in Toodledo."
9
13
  end
10
14
 
11
15
  def execute(args)
16
+
12
17
  Toodledo.begin(client.logger) do |session|
13
18
  line = args.join(' ')
14
19
  return client.list_tasks(session, line)
@@ -17,5 +22,7 @@ module Toodledo
17
22
  return 0
18
23
  end
19
24
  end
25
+
26
+
20
27
  end
21
28
  end
@@ -1,18 +1,32 @@
1
+ require 'toodledo/priority'
1
2
 
2
3
  module Toodledo
3
4
 
4
5
  module CommandLine
5
6
 
6
- #
7
+ #
7
8
  # Methods to parse a string and identify it as a Toodledo symbol.
8
- #
9
+ #
9
10
  module ParserHelper
10
-
11
+
11
12
  FOLDER_REGEXP = /\*((\w+)|\[(.*?)\])/
12
13
 
13
- GOAL_REGEXP = /\$((\w+)|\[(.*?)\])/
14
+ GOAL_REGEXP = /\^((\w+)|\[(.*?)\])/
14
15
 
15
16
  CONTEXT_REGEXP = /\@((\w+)|\[(.*?)\])/
17
+
18
+ PRIORITY_REGEXP = /!(top|high|medium|low|negative)/
19
+
20
+ # Note that level must exist at the beginning of the line
21
+ LEVEL_REGEXP = /^(life|medium|short)/
22
+
23
+ # Don't include level regexp
24
+ REGEXP_LIST = [
25
+ FOLDER_REGEXP,
26
+ GOAL_REGEXP,
27
+ CONTEXT_REGEXP,
28
+ PRIORITY_REGEXP
29
+ ]
16
30
 
17
31
  # Parses a context in the format @Context or @[Spaced Context]
18
32
  def parse_context(input)
@@ -28,20 +42,63 @@ module Toodledo
28
42
  return strip_brackets(match_data[1])
29
43
  end
30
44
 
31
- # Parses a goal in the format $Goal or $[Spaced Goal]
45
+ # Parses a goal in the format ^Goal or ^[Spaced Goal]
32
46
  def parse_goal(input)
33
47
  match_data = GOAL_REGEXP.match(input)
34
48
  return match_data if (match_data == nil)
35
49
  return strip_brackets(match_data[1])
36
50
  end
37
51
 
38
- # Returns the bit after we've looked for *Folder, @Context & $Goal
39
- def parse_remainder(line)
52
+ # Parses priority in the format !priority (top, high, medium, low,
53
+ # negative)
54
+ def parse_priority(input)
55
+ match_data = PRIORITY_REGEXP.match(input)
56
+ if (match_data == nil)
57
+ return nil
58
+ end
40
59
 
60
+ p = match_data[1]
61
+ case p
62
+ when 'top'
63
+ return Toodledo::Priority::TOP
64
+ when 'high'
65
+ return Toodledo::Priority::HIGH
66
+ when 'medium'
67
+ return Toodledo::Priority::MEDIUM
68
+ when 'low'
69
+ return Toodledo::Priority::LOW
70
+ when 'negative'
71
+ return Toodledo::Priority::NEGATIVE
72
+ else
73
+ return nil
74
+ end
75
+ end
76
+
77
+ def parse_level(input)
78
+ match_data = LEVEL_REGEXP.match(input)
79
+ if (match_data == nil)
80
+ return nil
81
+ end
82
+
83
+ p = match_data[1]
84
+ case p
85
+ when 'life'
86
+ return Toodledo::Goal::LIFE_LEVEL
87
+ when 'medium'
88
+ return Toodledo::Goal::MEDIUM_LEVEL
89
+ when 'short'
90
+ return Toodledo::Goal::SHORT_LEVEL
91
+ else
92
+ return nil
93
+ end
94
+ end
95
+
96
+ # Returns the bit after we've looked for *Folder, @Context & ^Goal
97
+ def parse_remainder(line)
41
98
  input = line
42
99
 
43
100
  # Strip out anything that isn't folder, goal or context.
44
- for regexp in [ FOLDER_REGEXP, GOAL_REGEXP, CONTEXT_REGEXP]
101
+ for regexp in REGEXP_LIST
45
102
  input = input.sub(regexp, '')
46
103
  end
47
104
 
@@ -0,0 +1,31 @@
1
+ require 'toodledo/command_line/parser_helper'
2
+ require 'logger'
3
+
4
+ module Toodledo
5
+
6
+ module CommandLine
7
+ # Runs the stdin client.
8
+ class StdinCommand < BaseCommand
9
+
10
+ def initialize(client)
11
+ super(client, 'stdin', false)
12
+ self.short_desc = "Takes standard input"
13
+ self.description = "Useful for pipes and redirected files"
14
+ end
15
+
16
+ def execute(args)
17
+ Toodledo.begin(client.logger) do |session|
18
+ $stdin.each do |line|
19
+ line.strip!
20
+
21
+ if (line == nil || line.empty?)
22
+ return 0
23
+ end
24
+
25
+ client.execute_command(session, line)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,102 @@
1
+
2
+ module Toodledo
3
+ module CommandLine
4
+ class TaskFormatter
5
+
6
+ # Formats the task for a command line.
7
+ def format(task)
8
+ fancyp = '!' + readable_priority(task.priority)
9
+
10
+ msg = "<#{task.server_id}> -- #{fancyp}"
11
+
12
+ if (task.folder != Folder::NO_FOLDER)
13
+ msg += " *[#{task.folder.name}]"
14
+ end
15
+
16
+ if (task.context != Context::NO_CONTEXT)
17
+ msg += " @[#{task.context.name}]"
18
+ end
19
+
20
+ if (task.goal != Goal::NO_GOAL)
21
+ msg += " ^[#{task.goal.name}]"
22
+ end
23
+
24
+ if (task.repeat != Repeat::NONE)
25
+ msg += " repeat[#{readable_repeat(task.repeat)}]"
26
+ end
27
+
28
+ if (task.duedate != nil)
29
+ fmt = '%m/%d/%Y %I:%M %p'
30
+ msg += " \#[#{task.duedatemodifier}#{task.duedate.strftime(fmt)}]"
31
+ end
32
+
33
+ if (task.tag != nil)
34
+ msg += " tag[#{task.tag}]"
35
+ end
36
+
37
+ if (task.parent_id != nil)
38
+ msg += " parent[#{task.parent_id}]"
39
+ end
40
+
41
+ if (task.length != nil)
42
+ msg += " length[#{task.length}]"
43
+ end
44
+
45
+ if (task.timer != nil)
46
+ msg += " timer[#{task.timer}]"
47
+ end
48
+
49
+ # Use the highline color library
50
+ msg += " #{task.title}"
51
+
52
+ if (task.note != nil)
53
+ msg += "\n #{task.note}"
54
+ end
55
+
56
+ return msg
57
+ end
58
+
59
+ def readable_priority(priority)
60
+ case priority
61
+ when Priority::TOP
62
+ return 'top'
63
+ when Priority::HIGH
64
+ return 'high'
65
+ when Priority::MEDIUM
66
+ return 'medium'
67
+ when Priority::LOW
68
+ return 'low'
69
+ when Priority::NEGATIVE
70
+ return 'negative'
71
+ else
72
+ return ''
73
+ end
74
+ end
75
+
76
+ def readable_repeat(repeat)
77
+ case repeat
78
+ when Repeat::NONE
79
+ ''
80
+ when Repeat::WEEKLY
81
+ "weekly"
82
+ when Repeat::MONTHLY
83
+ "monthly"
84
+ when Repeat::YEARLY
85
+ "yearly"
86
+ when Repeat::DAILY
87
+ "daily"
88
+ when Repeat::BIWEEKLY
89
+ "biweekly"
90
+ when Repeat::BIMONTHLY
91
+ "bimonthly"
92
+ when Repeat::SEMIANNUALLY
93
+ "semiannually"
94
+ when Repeat::QUARTERLY
95
+ "quarterly"
96
+ else
97
+ ''
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end