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 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
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in tasks_cli.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "rspec", "~> 3.0"
data/bin/tasks ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "tasks_cli"
5
+
6
+ TasksCLI::CLI.start(ARGV)
@@ -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
@@ -0,0 +1,3 @@
1
+ module TasksCLI
2
+ VERSION = "0.1.1"
3
+ 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: []