tasks_cli 0.1.1
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.
- checksums.yaml +7 -0
- data/Gemfile +7 -0
- data/bin/tasks +6 -0
- data/lib/tasks_cli/cli.rb +58 -0
- data/lib/tasks_cli/task.rb +74 -0
- data/lib/tasks_cli/task_manager.rb +100 -0
- data/lib/tasks_cli/version.rb +3 -0
- data/lib/tasks_cli.rb +45 -0
- data/tasks +248 -0
- data/tasks_cli.gemspec +35 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1b2feeb892f58ae854a0761cd6e5c0faff6b794815628921c151b90fbc343f1a
|
4
|
+
data.tar.gz: 0da27041da8f50808ac78f46f2bf5ddfe9557bda9defd57802120ad5da268c5a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f8f1127576598a441dc39de0775f84f9d716bf48d5278af9d7759c9881511495b40d737d562d6c196aa047a8b6ba6217a5a9e064f558df9bae3dc23612eeacc2
|
7
|
+
data.tar.gz: 12493dcc828745b56a824a536c6bf9094ba6b3ed0e0636bbe3740c6d6e1393389a1893a8981c4ecfcaca675f4413d4cd9f117c820d6b4be3810377f347ba23d1
|
data/Gemfile
ADDED
data/bin/tasks
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "rainbow"
|
3
|
+
|
4
|
+
module TasksCLI
|
5
|
+
class CLI < Thor
|
6
|
+
desc "list", "List all tasks"
|
7
|
+
def list
|
8
|
+
manager = TaskManager.new
|
9
|
+
print_tasks(manager.all_tasks)
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "filter FIELD:VALUE", "Filter tasks by field and value"
|
13
|
+
def filter(filter_string)
|
14
|
+
manager = TaskManager.new
|
15
|
+
key, value = filter_string.split(':')
|
16
|
+
filtered_tasks = manager.filter_tasks({ key => value })
|
17
|
+
print_tasks(filtered_tasks)
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "view NUMBER", "View details of a specific task"
|
21
|
+
def view(number)
|
22
|
+
manager = TaskManager.new
|
23
|
+
task = manager.find_task(number)
|
24
|
+
if task
|
25
|
+
puts task.detailed_view
|
26
|
+
else
|
27
|
+
puts Rainbow("Task not found").red
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "update NUMBER STATUS", "Update the status of a task"
|
32
|
+
def update(number, status)
|
33
|
+
manager = TaskManager.new
|
34
|
+
manager.update_status(number, status)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def print_tasks(tasks)
|
40
|
+
if tasks.empty?
|
41
|
+
puts Rainbow("No tasks found.").yellow
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
puts Rainbow("\n%-10s %-30s %-15s %-10s %-25s" % ["Number", "Name", "Status", "Priority", "Last Updated"]).underline
|
46
|
+
tasks.each do |task|
|
47
|
+
puts "%-10s %-30s %-15s %-10s %-25s" % [
|
48
|
+
Rainbow(task.number).cyan,
|
49
|
+
Rainbow(task.name.to_s.truncate(30)).magenta,
|
50
|
+
task.status_colored,
|
51
|
+
task.priority_colored,
|
52
|
+
Rainbow(task.updated_at).blue
|
53
|
+
]
|
54
|
+
end
|
55
|
+
puts "\nTotal tasks: #{Rainbow(tasks.count).green}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'rainbow'
|
2
|
+
|
3
|
+
module TasksCLI
|
4
|
+
class Task
|
5
|
+
attr_reader :epic, :number, :name, :description, :priority, :status, :relates_to, :blocked_by, :updated_at
|
6
|
+
|
7
|
+
def initialize(row)
|
8
|
+
@epic = extract_value(row[0])
|
9
|
+
@number = extract_value(row[1])
|
10
|
+
@name = extract_value(row[2])
|
11
|
+
@description = extract_value(row[3])
|
12
|
+
@priority = extract_value(row[4])
|
13
|
+
@status = extract_value(row[5])
|
14
|
+
@relates_to = extract_value(row[6])
|
15
|
+
@blocked_by = extract_value(row[7])
|
16
|
+
@updated_at = extract_value(row[8]) || Time.now.iso8601
|
17
|
+
end
|
18
|
+
|
19
|
+
def extract_value(field)
|
20
|
+
return field if field.is_a?(String)
|
21
|
+
field.is_a?(Array) ? field[1].to_s.strip : field.to_s.strip
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
"#{Rainbow(@number).cyan}: #{Rainbow(@name).bright} (#{status_colored}) - Priority: #{priority_colored} - Updated: #{@updated_at}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def detailed_view
|
29
|
+
<<~TASK
|
30
|
+
#{Rainbow("Epic:").bright} #{@epic}
|
31
|
+
#{Rainbow("Number:").bright} #{Rainbow(@number).cyan}
|
32
|
+
#{Rainbow("Name:").bright} #{Rainbow(@name).bright}
|
33
|
+
#{Rainbow("Description:").bright} #{@description}
|
34
|
+
#{Rainbow("Priority:").bright} #{priority_colored}
|
35
|
+
#{Rainbow("Status:").bright} #{status_colored}
|
36
|
+
#{Rainbow("Relates To:").bright} #{@relates_to}
|
37
|
+
#{Rainbow("Blocked By:").bright} #{@blocked_by}
|
38
|
+
#{Rainbow("Last Updated:").bright} #{@updated_at}
|
39
|
+
TASK
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_csv
|
43
|
+
[@epic, @number, @name, @description, @priority, @status, @relates_to, @blocked_by, @updated_at]
|
44
|
+
end
|
45
|
+
|
46
|
+
def matches?(field, value)
|
47
|
+
send(field.to_sym).to_s.downcase.include?(value.to_s.downcase)
|
48
|
+
rescue NoMethodError
|
49
|
+
false
|
50
|
+
end
|
51
|
+
|
52
|
+
def update_timestamp
|
53
|
+
@updated_at = Time.now.iso8601
|
54
|
+
end
|
55
|
+
|
56
|
+
def status_colored
|
57
|
+
case @status.downcase
|
58
|
+
when 'to do' then Rainbow(@status).red
|
59
|
+
when 'in progress' then Rainbow(@status).yellow
|
60
|
+
when 'done' then Rainbow(@status).green
|
61
|
+
else Rainbow(@status).white
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def priority_colored
|
66
|
+
case @priority.downcase
|
67
|
+
when 'high' then Rainbow(@priority).red
|
68
|
+
when 'medium' then Rainbow(@priority).yellow
|
69
|
+
when 'low' then Rainbow(@priority).green
|
70
|
+
else Rainbow(@priority).white
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'csv'
|
2
|
+
require 'json'
|
3
|
+
require 'rainbow'
|
4
|
+
|
5
|
+
module TasksCLI
|
6
|
+
class TaskManager
|
7
|
+
def initialize
|
8
|
+
@file_path = File.expand_path('~/tasks.csv')
|
9
|
+
load_tasks
|
10
|
+
end
|
11
|
+
|
12
|
+
def load_tasks
|
13
|
+
@tasks = []
|
14
|
+
CSV.foreach(@file_path, headers: false) do |row|
|
15
|
+
next if row == ["Epic Name", "Ticket Number", "Ticket Name", "Ticket Description", "Priority", "Status", "Relates To", "Blocked By"]
|
16
|
+
begin
|
17
|
+
parsed_row = row.map { |field| parse_field(field) }
|
18
|
+
@tasks << Task.new(parsed_row)
|
19
|
+
rescue => e
|
20
|
+
puts "Error processing row: #{row.inspect}"
|
21
|
+
puts "Error message: #{e.message}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
rescue CSV::MalformedCSVError => e
|
25
|
+
puts Rainbow("Error reading CSV: #{e.message}. Trying to parse with alternative method...").red
|
26
|
+
parse_csv_manually
|
27
|
+
rescue => e
|
28
|
+
puts Rainbow("Unexpected error while loading tasks: #{e.message}").red
|
29
|
+
puts e.backtrace
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse_field(field)
|
33
|
+
return field unless field.start_with?('[') && field.end_with?(']')
|
34
|
+
parsed = JSON.parse(field.gsub('=>', ':'))
|
35
|
+
[parsed[0], parsed[1]]
|
36
|
+
rescue JSON::ParserError
|
37
|
+
[nil, field]
|
38
|
+
end
|
39
|
+
|
40
|
+
def parse_csv_manually
|
41
|
+
@tasks = []
|
42
|
+
lines = File.readlines(@file_path)
|
43
|
+
lines[1..-1].each do |line|
|
44
|
+
fields = line.strip.split(',')
|
45
|
+
parsed_fields = fields.map { |field| parse_field(field) }
|
46
|
+
@tasks << Task.new(parsed_fields)
|
47
|
+
rescue => e
|
48
|
+
puts "Error processing line: #{line}"
|
49
|
+
puts "Error message: #{e.message}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def save_tasks(task_number)
|
54
|
+
lines = File.readlines(@file_path)
|
55
|
+
File.open(@file_path, 'w') do |file|
|
56
|
+
file.puts lines[0].chomp # Write header as is
|
57
|
+
lines[1..-1].each do |line|
|
58
|
+
fields = line.strip.split(',').map { |f| parse_field(f) }
|
59
|
+
if fields[1][1] == task_number
|
60
|
+
task = find_task(task_number)
|
61
|
+
updated_line = task.to_csv.map.with_index { |value, index| [fields[index][0], value].to_s }.join(',')
|
62
|
+
file.puts updated_line
|
63
|
+
else
|
64
|
+
file.puts line.chomp # Write unchanged lines as is
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def all_tasks
|
71
|
+
@tasks
|
72
|
+
end
|
73
|
+
|
74
|
+
def filter_tasks(criteria)
|
75
|
+
@tasks.select do |task|
|
76
|
+
criteria.all? { |field, value| task.matches?(field, value) }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_task(number)
|
81
|
+
@tasks.find { |task| task.number == number }
|
82
|
+
end
|
83
|
+
|
84
|
+
def update_status(number, new_status)
|
85
|
+
task = find_task(number)
|
86
|
+
if task
|
87
|
+
old_status = task.status
|
88
|
+
task.instance_variable_set(:@status, new_status)
|
89
|
+
task.update_timestamp
|
90
|
+
save_tasks(number)
|
91
|
+
TasksCLI.logger.info("Updated status of task #{number} from #{old_status} to #{new_status}")
|
92
|
+
puts Rainbow("Updated status of task #{number} from #{old_status} to #{new_status}").green
|
93
|
+
puts Rainbow("Last updated: #{TasksCLI.format_date(task.updated_at)}").cyan
|
94
|
+
else
|
95
|
+
TasksCLI.logger.warn("Task not found: #{number}")
|
96
|
+
puts Rainbow("Task not found").red
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
data/lib/tasks_cli.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require "tasks_cli/version"
|
2
|
+
require "tasks_cli/cli"
|
3
|
+
require "tasks_cli/task"
|
4
|
+
require "tasks_cli/task_manager"
|
5
|
+
require "logger"
|
6
|
+
|
7
|
+
module TasksCLI
|
8
|
+
class Error < StandardError; end
|
9
|
+
|
10
|
+
# Configuration
|
11
|
+
@config = {
|
12
|
+
csv_path: File.expand_path('~/tasks.csv'),
|
13
|
+
date_format: '%Y-%m-%d %H:%M:%S'
|
14
|
+
}
|
15
|
+
|
16
|
+
class << self
|
17
|
+
attr_accessor :config
|
18
|
+
|
19
|
+
def configure
|
20
|
+
yield(config) if block_given?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Utility methods
|
25
|
+
def self.format_date(date)
|
26
|
+
date.strftime(config[:date_format])
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.parse_date(date_string)
|
30
|
+
DateTime.strptime(date_string, config[:date_format])
|
31
|
+
end
|
32
|
+
|
33
|
+
# Version information
|
34
|
+
def self.version
|
35
|
+
VERSION
|
36
|
+
end
|
37
|
+
|
38
|
+
# Logging
|
39
|
+
def self.logger
|
40
|
+
@logger ||= Logger.new(STDOUT).tap do |log|
|
41
|
+
log.progname = 'TasksCLI'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
```
|
data/tasks
ADDED
@@ -0,0 +1,248 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
require 'optparse'
|
5
|
+
require 'rainbow'
|
6
|
+
require 'time'
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
Rainbow.enabled = true
|
10
|
+
|
11
|
+
class Task
|
12
|
+
attr_reader :epic, :number, :name, :description, :priority, :status, :relates_to, :blocked_by, :updated_at
|
13
|
+
|
14
|
+
def initialize(row)
|
15
|
+
@epic = extract_value(row[0])
|
16
|
+
@number = extract_value(row[1])
|
17
|
+
@name = extract_value(row[2])
|
18
|
+
@description = extract_value(row[3])
|
19
|
+
@priority = extract_value(row[4])
|
20
|
+
@status = extract_value(row[5])
|
21
|
+
@relates_to = extract_value(row[6])
|
22
|
+
@blocked_by = extract_value(row[7])
|
23
|
+
@updated_at = extract_value(row[8]) || Time.now.iso8601
|
24
|
+
end
|
25
|
+
|
26
|
+
def extract_value(field)
|
27
|
+
return field if field.is_a?(String)
|
28
|
+
field.is_a?(Array) ? field[1].to_s.strip : field.to_s.strip
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"#{Rainbow(@number).cyan}: #{Rainbow(@name).bright} (#{status_colored}) - Priority: #{priority_colored} - Updated: #{@updated_at}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def detailed_view
|
36
|
+
<<~TASK
|
37
|
+
#{Rainbow("Epic:").bright} #{@epic}
|
38
|
+
#{Rainbow("Number:").bright} #{Rainbow(@number).cyan}
|
39
|
+
#{Rainbow("Name:").bright} #{Rainbow(@name).bright}
|
40
|
+
#{Rainbow("Description:").bright} #{@description}
|
41
|
+
#{Rainbow("Priority:").bright} #{priority_colored}
|
42
|
+
#{Rainbow("Status:").bright} #{status_colored}
|
43
|
+
#{Rainbow("Relates To:").bright} #{@relates_to}
|
44
|
+
#{Rainbow("Blocked By:").bright} #{@blocked_by}
|
45
|
+
#{Rainbow("Last Updated:").bright} #{@updated_at}
|
46
|
+
TASK
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_csv
|
50
|
+
[@epic, @number, @name, @description, @priority, @status, @relates_to, @blocked_by, @updated_at]
|
51
|
+
end
|
52
|
+
|
53
|
+
def matches?(field, value)
|
54
|
+
send(field.to_sym).to_s.downcase.include?(value.to_s.downcase)
|
55
|
+
rescue NoMethodError
|
56
|
+
false
|
57
|
+
end
|
58
|
+
|
59
|
+
def update_timestamp
|
60
|
+
@updated_at = Time.now.iso8601
|
61
|
+
end
|
62
|
+
|
63
|
+
def status_colored
|
64
|
+
case @status.downcase
|
65
|
+
when 'to do' then Rainbow(@status).red
|
66
|
+
when 'in progress' then Rainbow(@status).yellow
|
67
|
+
when 'done' then Rainbow(@status).green
|
68
|
+
else Rainbow(@status).white
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def priority_colored
|
73
|
+
case @priority.downcase
|
74
|
+
when 'high' then Rainbow(@priority).red
|
75
|
+
when 'medium' then Rainbow(@priority).yellow
|
76
|
+
when 'low' then Rainbow(@priority).green
|
77
|
+
else Rainbow(@priority).white
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class TaskManager
|
83
|
+
def initialize(file_path)
|
84
|
+
@file_path = file_path
|
85
|
+
load_tasks
|
86
|
+
end
|
87
|
+
|
88
|
+
def load_tasks
|
89
|
+
@tasks = []
|
90
|
+
CSV.foreach(@file_path, headers: false) do |row|
|
91
|
+
next if row == ["Epic Name", "Ticket Number", "Ticket Name", "Ticket Description", "Priority", "Status", "Relates To", "Blocked By"]
|
92
|
+
begin
|
93
|
+
parsed_row = row.map do |field|
|
94
|
+
parse_field(field)
|
95
|
+
end
|
96
|
+
@tasks << Task.new(parsed_row)
|
97
|
+
rescue => e
|
98
|
+
puts "Error processing row: #{row.inspect}"
|
99
|
+
puts "Error message: #{e.message}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
rescue CSV::MalformedCSVError => e
|
103
|
+
puts Rainbow("Error reading CSV: #{e.message}. Trying to parse with alternative method...").red
|
104
|
+
parse_csv_manually
|
105
|
+
rescue => e
|
106
|
+
puts Rainbow("Unexpected error while loading tasks: #{e.message}").red
|
107
|
+
puts e.backtrace
|
108
|
+
end
|
109
|
+
|
110
|
+
def parse_field(field)
|
111
|
+
return field unless field.start_with?('[') && field.end_with?(']')
|
112
|
+
parsed = JSON.parse(field.gsub('=>', ':'))
|
113
|
+
[parsed[0], parsed[1]]
|
114
|
+
rescue JSON::ParserError
|
115
|
+
[nil, field]
|
116
|
+
end
|
117
|
+
|
118
|
+
def parse_csv_manually
|
119
|
+
@tasks = []
|
120
|
+
lines = File.readlines(@file_path)
|
121
|
+
lines[1..-1].each do |line|
|
122
|
+
fields = line.strip.split(',')
|
123
|
+
parsed_fields = fields.map { |field| parse_field(field) }
|
124
|
+
@tasks << Task.new(parsed_fields)
|
125
|
+
rescue => e
|
126
|
+
puts "Error processing line: #{line}"
|
127
|
+
puts "Error message: #{e.message}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def save_tasks(task_number)
|
132
|
+
lines = File.readlines(@file_path)
|
133
|
+
File.open(@file_path, 'w') do |file|
|
134
|
+
file.puts lines[0].chomp # Write header as is
|
135
|
+
lines[1..-1].each do |line|
|
136
|
+
fields = line.strip.split(',').map { |f| parse_field(f) }
|
137
|
+
if fields[1][1] == task_number
|
138
|
+
task = find_task(task_number)
|
139
|
+
updated_line = task.to_csv.map { |value| [fields[_1][0], value].to_s }.join(',')
|
140
|
+
file.puts updated_line
|
141
|
+
else
|
142
|
+
file.puts line.chomp # Write unchanged lines as is
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def all_tasks
|
149
|
+
@tasks
|
150
|
+
end
|
151
|
+
|
152
|
+
def filter_tasks(criteria)
|
153
|
+
@tasks.select do |task|
|
154
|
+
criteria.all? { |field, value| task.matches?(field, value) }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def find_task(number)
|
159
|
+
@tasks.find { |task| task.number == number }
|
160
|
+
end
|
161
|
+
|
162
|
+
def update_status(number, new_status)
|
163
|
+
task = find_task(number)
|
164
|
+
if task
|
165
|
+
old_status = task.status
|
166
|
+
task.instance_variable_set(:@status, new_status)
|
167
|
+
task.update_timestamp
|
168
|
+
save_tasks(number)
|
169
|
+
puts Rainbow("Updated status of task #{number} from #{old_status} to #{new_status}").green
|
170
|
+
puts Rainbow("Last updated: #{task.updated_at}").cyan
|
171
|
+
else
|
172
|
+
puts Rainbow("Task not found").red
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def print_tasks(tasks)
|
178
|
+
if tasks.empty?
|
179
|
+
puts Rainbow("No tasks found.").yellow
|
180
|
+
return
|
181
|
+
end
|
182
|
+
|
183
|
+
puts Rainbow("\n%-10s %-30s %-15s %-10s %-25s" % ["Number", "Name", "Status", "Priority", "Last Updated"]).underline
|
184
|
+
tasks.each do |task|
|
185
|
+
puts "%-10s %-30s %-15s %-10s %-25s" % [
|
186
|
+
Rainbow(task.number).cyan,
|
187
|
+
Rainbow(task.name.to_s.truncate(30)).magenta,
|
188
|
+
task.status_colored,
|
189
|
+
task.priority_colored,
|
190
|
+
Rainbow(task.updated_at).blue
|
191
|
+
]
|
192
|
+
end
|
193
|
+
puts "\nTotal tasks: #{Rainbow(tasks.count).green}"
|
194
|
+
end
|
195
|
+
|
196
|
+
# Main program
|
197
|
+
if __FILE__ == $0
|
198
|
+
begin
|
199
|
+
file_path = File.expand_path('~/tasks.csv') # Store the CSV in the user's home directory
|
200
|
+
manager = TaskManager.new(file_path)
|
201
|
+
|
202
|
+
options = {}
|
203
|
+
OptionParser.new do |opts|
|
204
|
+
opts.banner = "Usage: tasks [options]"
|
205
|
+
|
206
|
+
opts.on("-a", "--all", "View all tasks") do
|
207
|
+
options[:all] = true
|
208
|
+
end
|
209
|
+
|
210
|
+
opts.on("-f FIELD:VALUE", "--filter FIELD:VALUE", "Filter tasks by field and value (can be used multiple times)") do |f|
|
211
|
+
options[:filter] ||= {}
|
212
|
+
key, value = f.split(':')
|
213
|
+
options[:filter][key] = value
|
214
|
+
end
|
215
|
+
|
216
|
+
opts.on("-v NUMBER", "--view NUMBER", "View a single task") do |v|
|
217
|
+
options[:view] = v
|
218
|
+
end
|
219
|
+
|
220
|
+
opts.on("-u NUMBER,STATUS", "--update NUMBER,STATUS", Array, "Update a task's status") do |u|
|
221
|
+
options[:update] = u
|
222
|
+
end
|
223
|
+
end.parse!
|
224
|
+
|
225
|
+
if options[:all]
|
226
|
+
print_tasks(manager.all_tasks)
|
227
|
+
elsif options[:filter]
|
228
|
+
print_tasks(manager.filter_tasks(options[:filter]))
|
229
|
+
elsif options[:view]
|
230
|
+
task = manager.find_task(options[:view])
|
231
|
+
if task
|
232
|
+
puts task.detailed_view
|
233
|
+
else
|
234
|
+
puts Rainbow("Task not found").red
|
235
|
+
end
|
236
|
+
elsif options[:update]
|
237
|
+
number, status = options[:update]
|
238
|
+
manager.update_status(number, status)
|
239
|
+
else
|
240
|
+
puts Rainbow("No valid option provided. Use -h for help.").yellow
|
241
|
+
end
|
242
|
+
rescue Errno::ENOENT
|
243
|
+
puts Rainbow("Error: CSV file '#{file_path}' not found. Please ensure the file exists.").red
|
244
|
+
rescue => e
|
245
|
+
puts Rainbow("An unexpected error occurred: #{e.message}").red
|
246
|
+
puts e.backtrace
|
247
|
+
end
|
248
|
+
end
|
data/tasks_cli.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'lib/tasks_cli/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "tasks_cli"
|
5
|
+
spec.version = TasksCLI::VERSION
|
6
|
+
spec.authors = ["adilw3nomad"]
|
7
|
+
spec.email = ["adil@w3nomad.com"]
|
8
|
+
|
9
|
+
spec.summary = %q{A simple CLI for managing tasks}
|
10
|
+
spec.description = %q{A command-line interface for managing tasks stored in a CSV file}
|
11
|
+
spec.homepage = "https://github.com/adilw3nomad/tasks_cli"
|
12
|
+
spec.license = "MIT"
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
|
14
|
+
|
15
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
16
|
+
spec.metadata["source_code_uri"] = "https://github.com/adilw3nomad/tasks_cli"
|
17
|
+
spec.metadata["changelog_uri"] = "https://github.com/adilw3nomad/tasks_cli/blob/master/CHANGELOG.md"
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
23
|
+
f.match(%r{^(test|spec|features)/}) ||
|
24
|
+
f.match(/^tasks_cli-.*\.gem$/) ||
|
25
|
+
f.match(/^\.git/) ||
|
26
|
+
f.match(/^\.github/)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
spec.bindir = "exe"
|
30
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
|
33
|
+
spec.add_dependency "thor", "~> 1.0"
|
34
|
+
spec.add_dependency "rainbow", "~> 3.0"
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tasks_cli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- adilw3nomad
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-09-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rainbow
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
description: A command-line interface for managing tasks stored in a CSV file
|
42
|
+
email:
|
43
|
+
- adil@w3nomad.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- Gemfile
|
49
|
+
- bin/tasks
|
50
|
+
- lib/tasks_cli.rb
|
51
|
+
- lib/tasks_cli/cli.rb
|
52
|
+
- lib/tasks_cli/task.rb
|
53
|
+
- lib/tasks_cli/task_manager.rb
|
54
|
+
- lib/tasks_cli/version.rb
|
55
|
+
- tasks
|
56
|
+
- tasks_cli.gemspec
|
57
|
+
homepage: https://github.com/adilw3nomad/tasks_cli
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
metadata:
|
61
|
+
homepage_uri: https://github.com/adilw3nomad/tasks_cli
|
62
|
+
source_code_uri: https://github.com/adilw3nomad/tasks_cli
|
63
|
+
changelog_uri: https://github.com/adilw3nomad/tasks_cli/blob/master/CHANGELOG.md
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 2.3.0
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubygems_version: 3.5.16
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: A simple CLI for managing tasks
|
83
|
+
test_files: []
|