tudu 0.0.4 → 0.0.5

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.
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ coverage
@@ -0,0 +1,4 @@
1
+ LineLength:
2
+ Enabled: false
3
+ ClassLength:
4
+ Enabled: false
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in tudu.gemspec
4
3
  gemspec
5
4
  gem "rspec", "~> 2.14.1"
6
5
  gem "thor", "~> 0.18.1"
7
6
  gem "simplecov", "~> 0.8.2"
7
+ gem "highline", "~> 1.6.20"
data/README.md CHANGED
@@ -32,6 +32,29 @@ Or install it yourself as:
32
32
  ┗ Tudufile :in current version, we not use this
33
33
  ~~~
34
34
 
35
+ ## DSL List
36
+ | dsl | mean |
37
+ |:----------- |:------------ |
38
+ | add 'task_name1', 'task_name2' |add tasks to todos |
39
+ | remove 'task_name1', 'task_name2' |remove tasks from [todos, doings, dones] |
40
+ | choose |choose first task from todos to doings |
41
+ | choose 'task_name' |choose task from todos to doings |
42
+ | done |complete task. doings to dones, and first todos to doings |
43
+ | done -p |complete task. doings to dones, and first todos to doings.after show progress |
44
+ | tasks |search all task from [todos, doings, dones] |
45
+ | tasks 'task_name' |search task from [todos, doings, dones] by keyword 'task_name' |
46
+ | tasks 'task_name' -c |search task from [todos, doings, dones] by keyword 'task_name' with categolized view |
47
+ | tasks 'task_name' -c --color |search task from [todos, doings, dones] by keyword 'task_name' with categolized view, colored|
48
+ | todos |search all task from todos |
49
+ | todos 'task_name' |search task from todos by keyword 'task_name' |
50
+ | doings |search all task from doings |
51
+ | doings 'task_name' |search task from doings by keyword 'task_name' |
52
+ | now |alias of doings command |
53
+ | now 'task_name' |alias of doings 'task_name' command |
54
+ | dones |search all task from dones |
55
+ | dones 'task_name' |search task from dones by keyword 'task_name' |
56
+ | progress |show tasks progress |
57
+
35
58
  ## Usage
36
59
  ### init
37
60
  * generate todos,doings,dones emptyfile
@@ -170,17 +193,35 @@ one
170
193
  $ tudu add one two three
171
194
  $ tudu choose one
172
195
  $ tudu done
173
- $tudu tasks -c
196
+ $ tudu tasks -c
174
197
  ========TODOS========
175
198
  three
176
-
177
199
  ========DOINGS========
178
200
  two
201
+ ========DONES========
202
+ one
203
+ ~~~
204
+
205
+ ### tasks show all tasks from [todos, doings, dones] with categorized option and colored option.
206
+ * tudu tasks -c --color
179
207
 
208
+ ~~~
209
+ $ tudu add one two three
210
+ $ tudu choose one
211
+ $ tudu done
212
+ $ tudu tasks -c
213
+ ========TODOS========
214
+ three
215
+ ========DOINGS========
216
+ two
180
217
  ========DONES========
181
218
  one
182
219
  ~~~
183
220
 
221
+ * image sample
222
+
223
+ <img src="./doc_image/colored_tasks.png" />
224
+
184
225
  ### show specific tasks from [todos, doings, dones].
185
226
  * tudu tasks search_word
186
227
 
@@ -252,6 +293,7 @@ if you want to do other operation, edit [todos, doings, dones] directly.
252
293
  it's only plain text, so you can edit freely.
253
294
 
254
295
  ## History
296
+ * version 0.0.5 : add color option to 'tasks'
255
297
  * version 0.0.4 : add 'progress'. add progress option to 'done'.
256
298
  * version 0.0.3 : add categorized option to 'tasks'.
257
299
  * version 0.0.2 : after execute 'done', if there is no todos and doings, display celebration message.
data/bin/tudu CHANGED
@@ -1,79 +1,80 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
-
4
- require 'tudu/version'
5
- require 'tudu_core'
6
- require "thor"
7
-
8
- module Tudu
9
- #= Tudu CLI
10
- class CLI < Thor
11
- class_option :help, :type => :boolean, :aliases => '-h', :desc => 'help message.'
12
- class_option :version, :type => :boolean, :desc => 'version'
13
-
14
- desc "init", "generate todos,doings,dones files"
15
- def init
16
- Tudu::Core.new.init
17
- end
18
-
19
- desc "add", "add tasks to todos file"
20
- def add(*args)
21
- puts args
22
- Tudu::Core.new.add *args
23
- end
24
-
25
- desc "remove", "remove tasks from todos,doings,dones file"
26
- def remove(*args)
27
- Tudu::Core.new.remove *args
28
- end
29
-
30
- desc "choose", "choose tasks from todos to doings file"
31
- def choose(*args)
32
- Tudu::Core.new.choose args.first
33
- end
34
-
35
- desc "done", "done tasks from doings to dones file. and choose task from todos's top task to doings"
36
- option :progress, :type => :boolean, :aliases => '-p', :desc => "display tasks progress"
37
- def done
38
- Tudu::Core.new.done
39
- progress if options[:progress]
40
- end
41
-
42
- desc "tasks", "search tasks from todos,doings,dones file. no args => get all tasks. set search word args, you get hit tasks"
43
- option :category, :type => :boolean, :aliases => '-c', :desc => "display categorized tasks"
44
- def tasks(*args)
45
- puts Tudu::Core.new.tasks args.first, options
46
- end
47
-
48
- desc "todos", "search tasks from todos file. no args => get all tasks. set search word args, you get hit tasks"
49
- def todos(*args)
50
- puts Tudu::Core.new.todos args.first
51
- end
52
-
53
- desc "doings", "search tasks from doings file. no args => get all tasks. set search word args, you get hit tasks"
54
- def doings(*args)
55
- puts Tudu::Core.new.doings args.first
56
- end
57
-
58
- desc "now", "search tasks from doings file. no args => get all tasks. set search word args, you get hit tasks"
59
- def now(*args)
60
- puts Tudu::Core.new.now args.first
61
- end
62
-
63
- desc "dones", "search tasks from dones file. no args => get all tasks. set search word args, you get hit tasks"
64
- def dones(*args)
65
- puts Tudu::Core.new.dones args.first
66
- end
67
-
68
- desc "progress", "display tasks progress"
69
- def progress
70
- puts Tudu::Core.new.progress
71
- end
72
-
73
- desc "version", "version"
74
- def version
75
- p Tudu::VERSION
76
- end
77
- end
78
- end
79
- Tudu::CLI.start(ARGV)
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require 'tudu/version'
5
+ require 'tudu_core'
6
+ require 'thor'
7
+
8
+ module Tudu
9
+ # = Tudu CLI
10
+ class CLI < Thor
11
+ class_option :help, type: :boolean, aliases: '-h', desc: 'help message.'
12
+ class_option :version, type: :boolean, desc: 'version'
13
+
14
+ desc 'init', 'generate todos,doings,dones files'
15
+ def init
16
+ Tudu::Core.new.init
17
+ end
18
+
19
+ desc 'add', 'add tasks to todos file'
20
+ def add(*args)
21
+ puts args
22
+ Tudu::Core.new.add(*args)
23
+ end
24
+
25
+ desc 'remove', 'remove tasks from todos,doings,dones file'
26
+ def remove(*args)
27
+ Tudu::Core.new.remove(*args)
28
+ end
29
+
30
+ desc 'choose', 'choose tasks from todos to doings file'
31
+ def choose(*args)
32
+ Tudu::Core.new.choose args.first
33
+ end
34
+
35
+ desc 'done', "done tasks from doings to dones file. and choose task from todos's top task to doings"
36
+ option :progress, type: :boolean, aliases: '-p', desc: 'display tasks progress'
37
+ def done
38
+ Tudu::Core.new.done
39
+ progress if options[:progress]
40
+ end
41
+
42
+ desc 'tasks', 'search tasks from todos,doings,dones file. no args => get all tasks. set search word args, you get hit tasks'
43
+ option :category, type: :boolean, aliases: '-c', desc: 'display categorized tasks'
44
+ option :color, type: :boolean, aliases: '-co', desc: 'display colored tasks'
45
+ def tasks(*args)
46
+ puts Tudu::Core.new.tasks args.first, options
47
+ end
48
+
49
+ desc 'todos', 'search tasks from todos file. no args => get all tasks. set search word args, you get hit tasks'
50
+ def todos(*args)
51
+ puts Tudu::Core.new.todos args.first
52
+ end
53
+
54
+ desc 'doings', 'search tasks from doings file. no args => get all tasks. set search word args, you get hit tasks'
55
+ def doings(*args)
56
+ puts Tudu::Core.new.doings args.first
57
+ end
58
+
59
+ desc 'now', 'search tasks from doings file. no args => get all tasks. set search word args, you get hit tasks'
60
+ def now(*args)
61
+ puts Tudu::Core.new.now args.first
62
+ end
63
+
64
+ desc 'dones', 'search tasks from dones file. no args => get all tasks. set search word args, you get hit tasks'
65
+ def dones(*args)
66
+ puts Tudu::Core.new.dones args.first
67
+ end
68
+
69
+ desc 'progress', 'display tasks progress'
70
+ def progress
71
+ puts Tudu::Core.new.progress
72
+ end
73
+
74
+ desc 'version', 'version'
75
+ def version
76
+ p Tudu::VERSION
77
+ end
78
+ end
79
+ end
80
+ Tudu::CLI.start(ARGV)
@@ -1,304 +1,319 @@
1
- # encoding: utf-8
2
-
3
- module Tudu
4
- #= Tudu::Tasks
5
- class Tasks
6
- #== Tudufile key
7
- TUDU_FILE_KEY = :tudufile
8
- #== todo key
9
- TUDU_TODO_KEY = :todo
10
- #== doing key
11
- TUDU_DOING_KEY = :doing
12
- #== done key
13
- TUDU_DONE_KEY = :done
14
- #== file's key
15
- TUDU_KEYS = [TUDU_FILE_KEY, TUDU_TODO_KEY, TUDU_DOING_KEY, TUDU_DONE_KEY]
16
-
17
- #== Tudufile file name
18
- TUDU_FILE = "Tudufile"
19
- #== Tudufile file name
20
- TUDU_DIR = "tudu"
21
- #== todo file name
22
- TUDU_TODOS_FILE = "todos"
23
- #== todo file path
24
- TUDU_TODOS_FILE_PATH = "./#{TUDU_DIR}/#{TUDU_TODOS_FILE}"
25
- #== doing file name
26
- TUDU_DOINGS_FILE = "doings"
27
- #== doing file path
28
- TUDU_DOINGS_FILE_PATH = "./#{TUDU_DIR}/#{TUDU_DOINGS_FILE}"
29
- #== done file name
30
- TUDU_DONES_FILE = "dones"
31
- #== done file path
32
- TUDU_DONES_FILE_PATH = "./#{TUDU_DIR}/#{TUDU_DONES_FILE}"
33
- #== file names
34
- INIT_FILES = {
35
- TUDU_FILE_KEY => TUDU_FILE,
36
- TUDU_TODO_KEY => TUDU_TODOS_FILE,
37
- TUDU_DOING_KEY => TUDU_DOINGS_FILE,
38
- TUDU_DONE_KEY => TUDU_DONES_FILE
39
- }
40
- #== task file names
41
- TASK_FILES = {
42
- TUDU_TODO_KEY => TUDU_TODOS_FILE,
43
- TUDU_DOING_KEY => TUDU_DOINGS_FILE,
44
- TUDU_DONE_KEY => TUDU_DONES_FILE
45
- }
46
-
47
- #== Tudufile file template
48
- TUDU_FILE_TEMPLATE =<<-EOS
49
- # encoding: utf-8
50
-
51
- # !!!!!!! in tudu ver 0.0.1 this file not using !!!!!!!
52
-
53
- # if you want to use notification, set target type. default => :none
54
- # you can set :none, :mail
55
- # target_type :mail
56
-
57
- # if you want to use notification, set targets. default => []
58
- # if you choose target_type none, you must not set targets.
59
- # if you choose mail, you must set target email addresses.
60
- # targets ["target1@abcdefg", "target2@abcdefg"]
61
- EOS
62
-
63
- #== todo file template
64
- TUDU_TODOS_FILE_TEMPLATE = ""
65
- #== doing file template
66
- TUDU_DOINGS_FILE_TEMPLATE = ""
67
- #== done file template
68
- TUDU_DONES_FILE_TEMPLATE = ""
69
-
70
- #== template files
71
- INIT_FILES_TEMPLATE = {
72
- TUDU_FILE_KEY => TUDU_FILE_TEMPLATE,
73
- TUDU_TODO_KEY => TUDU_TODOS_FILE_TEMPLATE,
74
- TUDU_DOING_KEY => TUDU_DOINGS_FILE_TEMPLATE,
75
- TUDU_DONE_KEY => TUDU_DONES_FILE_TEMPLATE
76
- }
77
-
78
- #== task type [todo, doing, done]
79
- attr_accessor :type
80
- #== task name [uniq]
81
- attr_accessor :name
82
-
83
- class << self
84
- #== add task to todos
85
- #=== Params
86
- #- task_names : add task name list
87
- def add(*task_names)
88
- task_names.each do |task_name|
89
- if find_tasks(task_name)
90
- puts "#{task_name} is already exists.";
91
- next
92
- end
93
- File.open(TUDU_TODOS_FILE_PATH, "a:UTF-8") {|f|f.puts task_name}
94
- puts "complete add todo '#{task_name}' to tudu/todos"
95
- end
96
- end
97
-
98
- #== remove task to todo
99
- #=== Params
100
- #- task_names : remove task name list
101
- def remove(*task_names)
102
- task_names.each do |task_name|
103
- can_find = false
104
- TASK_FILES.each_value do |rf|
105
- tasks = get_tasks_from_file(rf)
106
- next unless has_task?(tasks, task_name)
107
- remove_task(tasks, task_name, "./#{TUDU_DIR}/#{rf}")
108
- can_find = true
109
- break
110
- end
111
- puts "no such todo '#{task_name}'" unless can_find
112
- end
113
- end
114
-
115
- #== choose todo => doing task
116
- #=== Params
117
- #- task_name : target task name
118
- def choose(task_name)
119
- if get_todos.size == 0
120
- puts "todos is empty."
121
- return
122
- end
123
- if get_doings.size > 0
124
- puts "before choose, you must done current doings."
125
- return
126
- end
127
- task_name = get_first_todo_name_if_nil_or_empty task_name
128
- task = find_tasks(task_name)
129
- if task.nil?
130
- puts "#{task_name} not exists"
131
- return
132
- end
133
- unless task.todo?
134
- puts "#{task_name} is not exists in todos. #{task_name} in #{task.type}"
135
- return
136
- end
137
- remove task_name
138
- File.open(TUDU_DOINGS_FILE_PATH, "w:UTF-8") {|f|f.puts task_name}
139
- puts "complete add doings '#{task_name}'"
140
- end
141
-
142
- #== doing to done
143
- #- if doings size == 0, nothing todo.
144
- #- after move doing to done, next todo move to doing.
145
- def done
146
- return unless doings_to_dones
147
- todos_to_doings
148
- end
149
-
150
- #== get todos type tasks.
151
- #=== Returns
152
- # return Array[Tasks]
153
- def get_todos
154
- get_tasks(TUDU_TODOS_FILE)
155
- end
156
-
157
- #== get doings type tasks.
158
- #=== Returns
159
- # return Array[Tasks]
160
- def get_doings
161
- get_tasks(TUDU_DOINGS_FILE)
162
- end
163
-
164
- #== get dones type tasks.
165
- #=== Returns
166
- # return Array[Tasks]
167
- def get_dones
168
- get_tasks(TUDU_DONES_FILE)
169
- end
170
-
171
- #== get each type tasks.
172
- #=== Params
173
- #- type : task type.if use nil, you can get all types task.
174
- #=== Returns
175
- # return Array[Tasks]
176
- def get_tasks(type = nil)
177
- type.nil? ? get_all_tasks : get_each_tasks(type)
178
- end
179
-
180
- #== get each type tasks from file.
181
- #=== Params
182
- #- type : task type.
183
- #=== Returns
184
- # return Array[String]
185
- def get_tasks_from_file(file_name)
186
- File.read("./#{TUDU_DIR}/#{file_name}").split("\n")
187
- end
188
-
189
- #== filter tasklist by search_word.
190
- #=== Params
191
- #- tasks : task list.
192
- #- search_word : filtering word.
193
- #=== Returns
194
- # return filterd task list
195
- def filter_tasks(tasks, search_word)
196
- return tasks if search_word.nil?
197
- tasks.select {|task|task.name.match /.*#{search_word}.*/}
198
- end
199
-
200
- #== find task from all tasks.
201
- #=== Params
202
- #- task_name : task name.
203
- #=== Returns
204
- # return task
205
- def find_tasks(task_name)
206
- tasks = get_tasks
207
- tasks.select {|task|task.name == task_name}.first
208
- end
209
-
210
- #== display tasks progress
211
- #=== Returns
212
- # return progress
213
- def progress
214
- total_count = get_tasks.size
215
- dones_count = get_dones.size
216
- percent = total_count == 0 ? 0 : (dones_count.to_f / total_count.to_f * 100).round
217
- prefix = "#{dones_count}/#{total_count}|"
218
- done_bar = "="*(percent/10)
219
- rest_bar = " "*(10-(percent/10))
220
- progress_bar = "#{done_bar}>#{rest_bar}"
221
- sufix = "|#{percent}%"
222
- "#{prefix}#{progress_bar}#{sufix}"
223
- end
224
-
225
- private
226
- def get_first_todo_name_if_nil_or_empty(task_name)
227
- (task_name.nil? || task_name.empty?) ? get_todos.first.name : task_name
228
- end
229
-
230
- def get_each_tasks(type)
231
- tasks = []
232
- get_tasks_from_file(type).each {|task|tasks << Tasks.new(type, task)}
233
- tasks
234
- end
235
-
236
- def get_all_tasks
237
- tasks = []
238
- TASK_FILES.each_value {|each_type|tasks += get_each_tasks(each_type)}
239
- tasks
240
- end
241
-
242
- def has_task?(tasks, task_name)
243
- tasks.include? task_name
244
- end
245
-
246
- def remove_task(tasks, task_name, file_path)
247
- tasks.delete(task_name)
248
- contents = tasks.size == 0 ? "" : tasks.join("\n") + "\n"
249
- File.open(file_path, "w:UTF-8") {|wf|wf.print contents}
250
- puts "complete remove todo '#{task_name}' from #{file_path}"
251
- end
252
-
253
- def doings_to_dones
254
- _doings = get_doings
255
- if _doings.size == 0
256
- puts "there is no doing task.before done, you must choose task."
257
- return false
258
- end
259
- File.open(TUDU_DOINGS_FILE_PATH, "w:UTF-8") {|f|f.print ""}
260
- File.open(TUDU_DONES_FILE_PATH, "a:UTF-8") {|f|f.puts _doings.first.name}
261
- true
262
- end
263
-
264
- def todos_to_doings
265
- _todos = get_todos
266
- if _todos.size == 0
267
- puts "All Tasks Finish!!" if get_doings.size == 0
268
- return
269
- end
270
-
271
- deleted_todos = _todos.dup
272
- deleted_todos.delete_at 0
273
- File.open(TUDU_TODOS_FILE_PATH, "w:UTF-8") do |f|
274
- deleted_todos.each {|task|f.puts task.name}
275
- end
276
- File.open(TUDU_DOINGS_FILE_PATH, "w:UTF-8") {|f|f.puts _todos.first.name}
277
- end
278
- end
279
-
280
- #== init task with setting task type and task name.
281
- def initialize(type, name)
282
- @type, @name = type, name
283
- end
284
-
285
- def todo?
286
- @type == "todos"
287
- end
288
-
289
- def doing?
290
- @type == "doings"
291
- end
292
-
293
- def done?
294
- @type == "dones"
295
- end
296
-
297
- def ==(other)
298
- if self.name == other.name
299
- return true if self.type == other.type
300
- end
301
- false
302
- end
303
- end
304
- end
1
+ # encoding: utf-8
2
+
3
+ module Tudu
4
+ # = Tudu::Tasks
5
+ class Tasks
6
+ # == Tudufile key
7
+ TUDU_FILE_KEY = :tudufile
8
+ # == todo key
9
+ TUDU_TODO_KEY = :todo
10
+ # == doing key
11
+ TUDU_DOING_KEY = :doing
12
+ # == done key
13
+ TUDU_DONE_KEY = :done
14
+ # == file's key
15
+ TUDU_KEYS = [TUDU_FILE_KEY, TUDU_TODO_KEY, TUDU_DOING_KEY, TUDU_DONE_KEY]
16
+
17
+ # == Tudufile file name
18
+ TUDU_FILE = 'Tudufile'
19
+ # == Tudufile file name
20
+ TUDU_DIR = 'tudu'
21
+ # == todo file name
22
+ TUDU_TODOS_FILE = 'todos'
23
+ # == todo file path
24
+ TUDU_TODOS_FILE_PATH = "./#{TUDU_DIR}/#{TUDU_TODOS_FILE}"
25
+ # == doing file name
26
+ TUDU_DOINGS_FILE = 'doings'
27
+ # == doing file path
28
+ TUDU_DOINGS_FILE_PATH = "./#{TUDU_DIR}/#{TUDU_DOINGS_FILE}"
29
+ # == done file name
30
+ TUDU_DONES_FILE = 'dones'
31
+ # == done file path
32
+ TUDU_DONES_FILE_PATH = "./#{TUDU_DIR}/#{TUDU_DONES_FILE}"
33
+ # == file names
34
+ INIT_FILES = {
35
+ TUDU_FILE_KEY => TUDU_FILE,
36
+ TUDU_TODO_KEY => TUDU_TODOS_FILE,
37
+ TUDU_DOING_KEY => TUDU_DOINGS_FILE,
38
+ TUDU_DONE_KEY => TUDU_DONES_FILE
39
+ }
40
+ # == task file names
41
+ TASK_FILES = {
42
+ TUDU_TODO_KEY => TUDU_TODOS_FILE,
43
+ TUDU_DOING_KEY => TUDU_DOINGS_FILE,
44
+ TUDU_DONE_KEY => TUDU_DONES_FILE
45
+ }
46
+
47
+ # == Tudufile file template
48
+ TUDU_FILE_TEMPLATE = <<-EOS
49
+ # encoding: utf-8
50
+
51
+ # !!!!!!! in tudu ver 0.0.1 this file not using !!!!!!!
52
+
53
+ # if you want to use notification, set target type. default => :none
54
+ # you can set :none, :mail
55
+ # target_type :mail
56
+
57
+ # if you want to use notification, set targets. default => []
58
+ # if you choose target_type none, you must not set targets.
59
+ # if you choose mail, you must set target email addresses.
60
+ # targets ["target1@abcdefg", "target2@abcdefg"]
61
+ EOS
62
+
63
+ # == todo file template
64
+ TUDU_TODOS_FILE_TEMPLATE = ''
65
+ # == doing file template
66
+ TUDU_DOINGS_FILE_TEMPLATE = ''
67
+ # == done file template
68
+ TUDU_DONES_FILE_TEMPLATE = ''
69
+
70
+ # == template files
71
+ INIT_FILES_TEMPLATE = {
72
+ TUDU_FILE_KEY => TUDU_FILE_TEMPLATE,
73
+ TUDU_TODO_KEY => TUDU_TODOS_FILE_TEMPLATE,
74
+ TUDU_DOING_KEY => TUDU_DOINGS_FILE_TEMPLATE,
75
+ TUDU_DONE_KEY => TUDU_DONES_FILE_TEMPLATE
76
+ }
77
+
78
+ # == task type [todo, doing, done]
79
+ attr_accessor :type
80
+ # == task name [uniq]
81
+ attr_accessor :name
82
+
83
+ class << self
84
+ # == add task to todos
85
+ # === Params
86
+ #- task_names : add task name list
87
+ def add(*task_names)
88
+ task_names.each do |task_name|
89
+ if find_tasks(task_name)
90
+ puts "#{task_name} is already exists."
91
+ next
92
+ end
93
+ File.open(TUDU_TODOS_FILE_PATH, 'a:UTF-8') { |f|f.puts task_name }
94
+ puts "complete add todo '#{task_name}' to tudu/todos"
95
+ end
96
+ end
97
+
98
+ # == remove task to todo
99
+ # === Params
100
+ #- task_names : remove task name list
101
+ def remove(*task_names)
102
+ task_names.each { |task_name|remove_each_task(task_name) }
103
+ end
104
+
105
+ # == choose todo => doing task
106
+ # === Params
107
+ #- task_name : target task name
108
+ def choose(task_name)
109
+ return if when_choose_no_todos?
110
+ return unless when_choose_no_doings?
111
+ task_name = get_first_todo_name_if_nil_or_empty task_name
112
+ task = find_tasks(task_name)
113
+ return if when_choose_no_task?(task, task_name)
114
+ return unless when_choose_type_is_todo?(task, task_name)
115
+ remove task_name
116
+ File.open(TUDU_DOINGS_FILE_PATH, 'w:UTF-8') { |f|f.puts task_name }
117
+ puts "complete add doings '#{task_name}'"
118
+ end
119
+
120
+ # == doing to done
121
+ #- if doings size == 0, nothing todo.
122
+ #- after move doing to done, next todo move to doing.
123
+ def done
124
+ return unless doings_to_dones
125
+ todos_to_doings
126
+ end
127
+
128
+ # == get todos type tasks.
129
+ # === Returns
130
+ # return Array[Tasks]
131
+ def get_todos
132
+ get_tasks(TUDU_TODOS_FILE)
133
+ end
134
+
135
+ # == get doings type tasks.
136
+ # === Returns
137
+ # return Array[Tasks]
138
+ def get_doings
139
+ get_tasks(TUDU_DOINGS_FILE)
140
+ end
141
+
142
+ # == get dones type tasks.
143
+ # === Returns
144
+ # return Array[Tasks]
145
+ def get_dones
146
+ get_tasks(TUDU_DONES_FILE)
147
+ end
148
+
149
+ # == get each type tasks.
150
+ # === Params
151
+ #- type : task type.if use nil, you can get all types task.
152
+ # === Returns
153
+ # return Array[Tasks]
154
+ def get_tasks(type = nil)
155
+ type.nil? ? get_all_tasks : get_each_tasks(type)
156
+ end
157
+
158
+ # == get each type tasks from file.
159
+ # === Params
160
+ #- type : task type.
161
+ # === Returns
162
+ # return Array[String]
163
+ def get_tasks_from_file(file_name)
164
+ File.read("./#{TUDU_DIR}/#{file_name}").split("\n")
165
+ end
166
+
167
+ # == filter tasklist by search_word.
168
+ # === Params
169
+ #- tasks : task list.
170
+ #- search_word : filtering word.
171
+ # === Returns
172
+ # return filterd task list
173
+ def filter_tasks(tasks, search_word)
174
+ return tasks if search_word.nil?
175
+ tasks.select { |task|task.name.match /.*#{search_word}.*/ }
176
+ end
177
+
178
+ # == find task from all tasks.
179
+ # === Params
180
+ #- task_name : task name.
181
+ # === Returns
182
+ # return task
183
+ def find_tasks(task_name)
184
+ tasks = get_tasks
185
+ tasks.select { |task|task.name == task_name }.first
186
+ end
187
+
188
+ # == display tasks progress
189
+ # === Returns
190
+ # return progress
191
+ def progress
192
+ total_count = get_tasks.size
193
+ dones_count = get_dones.size
194
+ percent = total_count == 0 ? 0 : (dones_count.to_f / total_count.to_f * 100).round
195
+ prefix = "#{dones_count}/#{total_count}|"
196
+ done_bar = '=' * (percent / 10)
197
+ rest_bar = ' ' * (10 - (percent / 10))
198
+ progress_bar = "#{done_bar}>#{rest_bar}"
199
+ sufix = "|#{percent}%"
200
+ "#{prefix}#{progress_bar}#{sufix}"
201
+ end
202
+
203
+ private
204
+
205
+ def get_first_todo_name_if_nil_or_empty(task_name)
206
+ task_name.nil? || task_name.empty? ? get_todos.first.name : task_name
207
+ end
208
+
209
+ def get_each_tasks(type)
210
+ tasks = []
211
+ get_tasks_from_file(type).each { |task|tasks << Tasks.new(type, task) }
212
+ tasks
213
+ end
214
+
215
+ def get_all_tasks
216
+ tasks = []
217
+ TASK_FILES.each_value { |each_type|tasks += get_each_tasks(each_type) }
218
+ tasks
219
+ end
220
+
221
+ def has_task?(tasks, task_name)
222
+ tasks.include? task_name
223
+ end
224
+
225
+ def remove_each_task(task_name)
226
+ can_find = false
227
+ TASK_FILES.each_value do |rf|
228
+ tasks = get_tasks_from_file(rf)
229
+ next unless has_task?(tasks, task_name)
230
+ remove_task(tasks, task_name, "./#{TUDU_DIR}/#{rf}")
231
+ can_find = true
232
+ break
233
+ end
234
+ puts "no such todo '#{task_name}'" unless can_find
235
+ end
236
+
237
+ def remove_task(tasks, task_name, file_path)
238
+ tasks.delete(task_name)
239
+ contents = tasks.size == 0 ? '' : tasks.join("\n") + "\n"
240
+ File.open(file_path, 'w:UTF-8') { |wf|wf.print contents }
241
+ puts "complete remove todo '#{task_name}' from #{file_path}"
242
+ end
243
+
244
+ def when_choose_no_todos?
245
+ return false unless get_todos.size == 0
246
+ puts 'todos is empty.'
247
+ true
248
+ end
249
+
250
+ def when_choose_no_doings?
251
+ return true if get_doings.size == 0
252
+ puts 'todos is empty.'
253
+ false
254
+ end
255
+
256
+ def when_choose_no_task?(task, task_name)
257
+ return true if task.nil?
258
+ puts "#{task_name} not exists"
259
+ false
260
+ end
261
+
262
+ def when_choose_type_is_todo?(task, task_name)
263
+ return true if task.todo?
264
+ puts "#{task_name} is not exists in todos. #{task_name} in #{task.type}"
265
+ false
266
+ end
267
+
268
+ def doings_to_dones
269
+ _doings = get_doings
270
+ if _doings.size == 0
271
+ puts 'there is no doing task.before done, you must choose task.'
272
+ return false
273
+ end
274
+ File.open(TUDU_DOINGS_FILE_PATH, 'w:UTF-8') { |f|f.print '' }
275
+ File.open(TUDU_DONES_FILE_PATH, 'a:UTF-8') { |f|f.puts _doings.first.name }
276
+ true
277
+ end
278
+
279
+ def todos_to_doings
280
+ _todos = get_todos
281
+ return if finish?(_todos)
282
+ deleted_todos = _todos.dup
283
+ deleted_todos.delete_at 0
284
+ File.open(TUDU_TODOS_FILE_PATH, 'w:UTF-8') do |f|
285
+ deleted_todos.each { |task|f.puts task.name }
286
+ end
287
+ File.open(TUDU_DOINGS_FILE_PATH, 'w:UTF-8') { |f|f.puts _todos.first.name }
288
+ end
289
+
290
+ def finish?(_todos)
291
+ return false unless _todos.size == 0
292
+ puts 'All Tasks Finish!!' if get_doings.size == 0
293
+ true
294
+ end
295
+ end
296
+
297
+ # == init task with setting task type and task name.
298
+ def initialize(type, name)
299
+ @type, @name = type, name
300
+ end
301
+
302
+ def todo?
303
+ @type == 'todos'
304
+ end
305
+
306
+ def doing?
307
+ @type == 'doings'
308
+ end
309
+
310
+ def done?
311
+ @type == 'dones'
312
+ end
313
+
314
+ def ==(other)
315
+ return true if name == other.name && type == other.type
316
+ false
317
+ end
318
+ end
319
+ end