tasks_cli 0.1.1

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