taskmeister 1.0.0 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 591ce55195a674c8070990555d81b0adb170bbfb
4
- data.tar.gz: ba6c0b5b60a931b6b88ed9b1fbd4972593ddd6cc
3
+ metadata.gz: c3ed72f2ffd7c5abeff6d683b75dc8e0d8cb8fa1
4
+ data.tar.gz: 868ad94b5ddd220439631d2997897ca5f8aafcac
5
5
  SHA512:
6
- metadata.gz: e6b26c40298e84d9849c7938ffe0b9e0eeb7c75d8eece34a3d3f056383d6e1f5d6b740a0a420c53a7c2e5840f9813865754a5f5ce7656ab64e30bde23c3b2b11
7
- data.tar.gz: aa049e066b54e142feee77aea27e427e71c61557bfca4891f859ba7f499c680695dac19cd96f5d340b0533c65f8e8c58ed2257884b98932d960105ae6ade0664
6
+ metadata.gz: e9a06654fba462da119efeb967e71c96ef0791f3faa05108013edc9fdac5f39875aab18bb27ebd2bd51af2aec077e84fd51324bb9acd7e143fd60da451b3faa6
7
+ data.tar.gz: 89d3baf2c913ba4c40639cb183bc2895ed3ff5f82282e724bbcd9cf573c0d8db14708f73d2975afe5e6113edc32dfa30bd8807558ac8cf1b6f6a67c95a9c47fd
data/README.md CHANGED
@@ -4,9 +4,10 @@ Simple command line task management modelled after [t](http://stevelosh.com/proj
4
4
 
5
5
  I like the simplicity of t but there are a couple of changes I wanted.
6
6
 
7
- First: I like to have separate task lists per project. So I infer the task list
8
- name from the current project directory. It finds a project directory by walking
9
- up from the current directory until it finds a `.git` or `.hg` directory in it.
7
+ First: I like to have separate task lists per project but I want a single shell
8
+ alias for all of them. So I infer the task list name from the current project
9
+ directory. It finds a project directory by walking up from the current directory
10
+ until it finds a `.git` or `.hg` directory in it.
10
11
 
11
12
  Second: I like to have a short list of notes accompanying my tasks. You can add
12
13
  notes beneath your task. They can be edited via Vim with `taskmeister -e` or
@@ -16,14 +17,19 @@ Third: I format my task files in Markdown so that when I open them on my phone
16
17
  via a Markdown-enabled editor they look nice. The format is still simple:
17
18
 
18
19
  ```markdown
19
- Add authorisation - [id](aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)
20
+ # Update gems [](#aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)
20
21
 
21
- > Some notes to go with the task above.
22
- >
23
- > Maybe paste in some links or other interesting information for later.
22
+ # Refactor the widget model [∞](#ae0cce15-456d-48c0-a2e2-69d5f567e092)
23
+
24
+ # Update the README [∞](#a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
25
+
26
+ Some notes to go with the task above.
27
+
28
+ - item 1
29
+ - item 2
30
+
31
+ > Or a quote
24
32
 
25
- Refactor the task model - [id](ae0cce15-456d-48c0-a2e2-69d5f567e092)
26
- Update the README - [id](a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
27
33
  ```
28
34
 
29
35
  ## Installation
@@ -3,13 +3,14 @@ Feature: taskmeister adds a task to the list
3
3
  Scenario: Add a task to the list
4
4
  Given a file named "mylist.md" with:
5
5
  """
6
- Task one - [id](aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)
6
+ # Task one [](#e8fd82de-c379-496d-a77b-2873192e8ea8)
7
7
 
8
- > Notes line one
9
- > Notes line two
8
+ Notes line one
9
+ Notes line two
10
10
 
11
- Task two - [id](ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
- Task three - [id](a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
11
+ # Task two [](#ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
+
13
+ # Task three [∞](#a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
13
14
  """
14
15
  When I successfully run `taskmeister --list mylist.md A new task`
15
16
  And I successfully run `taskmeister --list mylist.md`
@@ -3,13 +3,14 @@ Feature: taskmeister removes finished tasks from the list
3
3
  Scenario: Complete a task in the list
4
4
  Given a file named "mylist.md" with:
5
5
  """
6
- Task one - [id](aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)
6
+ # Task one [](#a8fd82de-c379-496d-a77b-2873192e8ea8)
7
7
 
8
- > Notes line one
9
- > Notes line two
8
+ Notes line one
9
+ Notes line two
10
10
 
11
- Task two - [id](ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
- Task three - [id](a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
11
+ # Task two [](#ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
+
13
+ # Task three [∞](#a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
13
14
  """
14
15
  When I successfully run `taskmeister --list mylist.md --done a`
15
16
  And I successfully run `taskmeister --list mylist.md`
@@ -18,10 +19,10 @@ Task three - [id](a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
18
19
  Scenario: Delete the task list when you remove the last task
19
20
  Given a file named "mylist.md" with:
20
21
  """
21
- Task one - [id](aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)
22
+ # Task one [](#a8fd82de-c379-496d-a77b-2873192e8ea8)
22
23
 
23
- > Notes line one
24
- > Notes line two
24
+ Notes line one
25
+ Notes line two
25
26
  """
26
27
  When I successfully run `taskmeister --list mylist.md --done a`
27
28
  Then the file "mylist.md" should not exist
@@ -3,13 +3,14 @@ Feature: taskmeister opens vim to edit your task list
3
3
  Scenario: Edit entire task list
4
4
  Given a file named "mylist.md" with:
5
5
  """
6
- Task one - [id](aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)
6
+ # Task one [](#a8fd82de-c379-496d-a77b-2873192e8ea8)
7
7
 
8
- > Notes line one
9
- > Notes line two
8
+ Notes line one
9
+ Notes line two
10
10
 
11
- Task two - [id](ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
- Task three - [id](a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
11
+ # Task two [](#ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
+
13
+ # Task three [∞](#a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
13
14
  """
14
15
  And I double `vim`
15
16
  When I run `taskmeister --list mylist.md --edit`
@@ -19,16 +20,17 @@ Task three - [id](a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
19
20
  Scenario: Edit specific task in the list
20
21
  Given a file named "mylist.md" with:
21
22
  """
22
- Task one - [id](aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)
23
+ # Task one [](#a8fd82de-c379-496d-a77b-2873192e8ea8)
24
+
25
+ Notes line one
26
+ Notes line two
23
27
 
24
- > Notes line one
25
- > Notes line two
28
+ # Task two [∞](#ae0cce15-456d-48c0-a2e2-69d5f567e092)
26
29
 
27
- Task two - [id](ae0cce15-456d-48c0-a2e2-69d5f567e092)
28
- Task three - [id](a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
30
+ # Task three [](#a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
29
31
  """
30
32
  And I double `vim`
31
33
  When I run `taskmeister --list mylist.md --edit a`
32
- Then the double `vim` should have been run with "+/aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8" and file "mylist.md"
34
+ Then the double `vim` should have been run with "+/a8fd82de-c379-496d-a77b-2873192e8ea8" and file "mylist.md"
33
35
  And the exit status should be 0
34
36
 
@@ -3,13 +3,14 @@ Feature: taskmeister lists the contents of a task list
3
3
  Scenario: List tasks in list
4
4
  Given a file named "mylist.md" with:
5
5
  """
6
- Task one - [id](aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)
6
+ # Task one [](#a8fd82de-c379-496d-a77b-2873192e8ea8)
7
7
 
8
- > Notes line one
9
- > Notes line two
8
+ Notes line one
9
+ Notes line two
10
10
 
11
- Task two - [id](ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
- Task three - [id](a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
11
+ # Task two [](#ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
+
13
+ # Task three [∞](#a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
13
14
  """
14
15
  When I successfully run `taskmeister --list mylist.md`
15
16
  Then the output should contain "a - Task one »"
@@ -6,13 +6,14 @@ Feature: taskmeister infers the name of your task list from your current project
6
6
  And a directory named "project/child"
7
7
  And a file named "project.md" with:
8
8
  """
9
- Task one - [id](aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)
9
+ # Task one [](#a8fd82de-c379-496d-a77b-2873192e8ea8)
10
10
 
11
- > Notes line one
12
- > Notes line two
11
+ Notes line one
12
+ Notes line two
13
13
 
14
- Task two - [id](ae0cce15-456d-48c0-a2e2-69d5f567e092)
15
- Task three - [id](a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
14
+ # Task two [](#ae0cce15-456d-48c0-a2e2-69d5f567e092)
15
+
16
+ # Task three [∞](#a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
16
17
  """
17
18
  And I cd to "project/child"
18
19
  When I successfully run `taskmeister --task-dir ../../`
@@ -3,13 +3,14 @@ Feature: taskmeister replaces a task in the list
3
3
  Scenario: Replace text of task in list
4
4
  Given a file named "mylist.md" with:
5
5
  """
6
- Task one - [id](aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)
6
+ # Task one [](#e8fd82de-c379-496d-a77b-2873192e8ea8)
7
7
 
8
- > Notes line one
9
- > Notes line two
8
+ Notes line one
9
+ Notes line two
10
10
 
11
- Task two - [id](ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
- Task three - [id](a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
11
+ # Task two [](#ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
+
13
+ # Task three [∞](#a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
13
14
  """
14
15
  When I successfully run `taskmeister --list mylist.md -r a A new task`
15
16
  And I successfully run `taskmeister --list mylist.md`
@@ -3,16 +3,17 @@ Feature: taskmeister shows the details of a task in the list
3
3
  Scenario: Show task in list
4
4
  Given a file named "mylist.md" with:
5
5
  """
6
- Task one - [id](aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)
6
+ # Task one [](#a8fd82de-c379-496d-a77b-2873192e8ea8)
7
7
 
8
- > Notes line one
9
- > Notes line two
8
+ Notes line one
9
+ Notes line two
10
10
 
11
- Task two - [id](ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
- Task three - [id](a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
11
+ # Task two [](#ae0cce15-456d-48c0-a2e2-69d5f567e092)
12
+
13
+ # Task three [∞](#a5d4d3a9-2b9a-427a-9047-b47c6aec8f93)
13
14
  """
14
15
  When I successfully run `taskmeister --list mylist.md --show a`
15
- Then the output should contain "Task one - [id](aaf83a9b-02f7-4cc0-8ee1-4d98b98903b8)"
16
- And the output should contain "> Notes line one"
17
- And the output should contain "> Notes line two"
16
+ Then the output should contain "# Task one [](#a8fd82de-c379-496d-a77b-2873192e8ea8)"
17
+ And the output should contain "Notes line one"
18
+ And the output should contain "Notes line two"
18
19
 
@@ -6,3 +6,4 @@ require "taskmeister/task_list_writer"
6
6
  require "taskmeister/cli/task_list_name"
7
7
  require "taskmeister/cli/main"
8
8
  require "taskmeister/cli/options"
9
+ require "taskmeister/cli/commands"
@@ -0,0 +1,70 @@
1
+ require "ostruct"
2
+
3
+ module Taskmeister
4
+ module Cli
5
+ module Commands
6
+
7
+ class Command
8
+ def initialize(task_list, options=OpenStruct.new, stdout=STDOUT, kernel=Kernel)
9
+ @task_list = task_list
10
+ @options = options
11
+ @stdout = stdout
12
+ @kernel = kernel
13
+ end
14
+
15
+ def execute!
16
+ # Override this in derived class
17
+ end
18
+
19
+ protected
20
+
21
+ def write
22
+ Taskmeister::TaskListWriter.to_markdown_file(@task_list)
23
+ end
24
+ end
25
+
26
+ class List < Command
27
+ def execute!
28
+ @stdout.puts @task_list.to_short_list
29
+ end
30
+ end
31
+
32
+ class Show < Command
33
+ def execute!
34
+ @stdout.puts @task_list.markdown_for(@options.task_id)
35
+ end
36
+ end
37
+
38
+ class Add < Command
39
+ def execute!
40
+ @task_list.add(Taskmeister::Task.create(@options.task_text))
41
+ write
42
+ end
43
+ end
44
+
45
+ class Replace < Command
46
+ def execute!
47
+ @task_list.replace(@options.task_id, @options.task_text)
48
+ write
49
+ end
50
+ end
51
+
52
+ class Done < Command
53
+ def execute!
54
+ @task_list.complete(@options.task_id)
55
+ write
56
+ end
57
+ end
58
+
59
+ class Edit < Command
60
+ def execute!
61
+ task = @task_list[@options.task_id]
62
+
63
+ search_path = task ? "+/#{task.id} " : ""
64
+
65
+ system "vim #{search_path}#{@task_list.file_path}"
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -10,49 +10,18 @@ module Taskmeister
10
10
  def execute!
11
11
  options = Options.new(@stdout, @kernel).parse(@argv)
12
12
 
13
- task_list = Taskmeister::TaskListReader.from_markdown_file(task_list_path(options))
13
+ file_path = task_list_path(options)
14
+ task_list = Taskmeister::TaskListReader.from_markdown_file(file_path)
14
15
 
15
- run_command(options, task_list)
16
- end
17
-
18
- private
19
-
20
- def run_command(options, task_list)
21
- case options.command
22
- when Commands::LIST
23
- @stdout.puts task_list.to_short_list
24
-
25
- when Commands::SHOW
26
-
27
- @stdout.puts task_list.markdown_for(options.task_id)
28
-
29
- when Commands::EDIT
30
-
31
- task = task_list[options.task_id]
32
-
33
- search_path = task ? "+/#{task.id} " : ""
34
- system "vim #{search_path}#{task_list.file_path}"
35
-
36
- when Commands::ADD
16
+ command = options.command.new(task_list, options, @stdout, @kernel)
37
17
 
38
- task_list.add(Taskmeister::Task.create(options.task_text))
39
- update task_list
40
-
41
- when Commands::DONE
42
-
43
- task_list.complete(options.task_id)
44
- update task_list
45
-
46
- when Commands::REPLACE
47
-
48
- task_list.replace(options.task_id, options.task_text)
49
- update task_list
50
-
51
- end
18
+ command.execute!
52
19
 
53
20
  @kernel.exit 0
54
21
  end
55
22
 
23
+ private
24
+
56
25
  def task_list_path(options)
57
26
  Pathname.new(options.task_dir) + task_list_name(options)
58
27
  end
@@ -61,16 +30,12 @@ module Taskmeister
61
30
  task_list_name = options.list || TaskListName.from_project_dir(Pathname.getwd)
62
31
 
63
32
  unless task_list_name
64
- @stderr.puts "Could not find a project directory. Please specify a task list."
33
+ @stderr.puts "Could not find a project directory. Please specify a task list instead."
65
34
  @kernel.exit 1
66
35
  end
67
36
 
68
37
  task_list_name
69
38
  end
70
-
71
- def update(task_list)
72
- Taskmeister::TaskListWriter.to_markdown_file(task_list)
73
- end
74
39
  end
75
40
  end
76
41
  end
@@ -4,17 +4,8 @@ require "pathname"
4
4
 
5
5
  module Taskmeister
6
6
  module Cli
7
- module Commands
8
- ADD = "add"
9
- LIST = "list"
10
- REPLACE = "replace"
11
- EDIT = "edit"
12
- SHOW = "show"
13
- DONE = "done"
14
- end
15
-
16
7
  class Options
17
- def initialize(stdout = STDOUT, kernel = Kernel)
8
+ def initialize(stdout=STDOUT, kernel=Kernel)
18
9
  @stdout = stdout
19
10
  @kernel = kernel
20
11
  end
@@ -45,26 +36,26 @@ module Taskmeister
45
36
 
46
37
  opts.on("-d", "--done TASK_ID",
47
38
  "Finish a task") do |task_id|
48
- options.command = Commands::DONE
39
+ options.command = Commands::Done
49
40
  options.task_id = task_id
50
41
  end
51
42
 
52
43
  opts.on("-s", "--show TASK_ID",
53
44
  "Show a task list item and its notes") do |task_id|
54
- options.command = Commands::SHOW
45
+ options.command = Commands::Show
55
46
  options.task_id = task_id
56
47
  end
57
48
 
58
49
  opts.on("-e", "--edit [TASK_ID]",
59
50
  "Edit task list in Vim",
60
51
  " Will search for a specific task if TASK_ID is provided") do |task_id|
61
- options.command = Commands::EDIT
52
+ options.command = Commands::Edit
62
53
  options.task_id = task_id
63
54
  end
64
55
 
65
56
  opts.on("-r", "--replace TASK_ID",
66
57
  "Replace a task description") do |task_id|
67
- options.command = Commands::REPLACE
58
+ options.command = Commands::Replace
68
59
  options.task_id = task_id
69
60
  end
70
61
 
@@ -88,8 +79,8 @@ module Taskmeister
88
79
 
89
80
  # If there is TASK TEXT and the default command hasn't been overwritten
90
81
  # by the user, set the command to ADD
91
- if !task_text.empty? and options.command == Commands::LIST
92
- options.command = Commands::ADD
82
+ if !task_text.empty? and options.command == Commands::List
83
+ options.command = Commands::Add
93
84
  end
94
85
 
95
86
  options
@@ -99,7 +90,7 @@ module Taskmeister
99
90
 
100
91
  def default_options
101
92
  OpenStruct.new.tap do |o|
102
- o.command = Commands::LIST
93
+ o.command = Commands::List
103
94
  o.task_dir = Pathname.getwd
104
95
  end
105
96
  end
@@ -5,26 +5,21 @@ module Taskmeister
5
5
  attr_reader :text, :notes, :id
6
6
 
7
7
  def initialize(text, id, notes)
8
- @text, @id, @notes = text, id, notes
8
+ @text, @id, @notes = text, id, Array(notes)
9
9
  end
10
10
 
11
11
  def notes?
12
- notes && !notes.empty?
12
+ notes.any? { |ns| !ns.empty? }
13
13
  end
14
14
 
15
15
  def to_markdown
16
- [ "#{text} - [id](#{id})" ].tap do |a|
17
- return a unless notes.match(/\S/)
18
- a << ""
19
- a.concat notes.split("\n").map { |n|
20
- n.size > 0 ? "> #{n}" : ">"
21
- }
22
- a << ""
16
+ [ "# #{text} [](##{id})" ].tap do |a|
17
+ a.concat notes
23
18
  end
24
19
  end
25
20
 
26
21
  def self.create(text)
27
- self.new(text, SecureRandom.uuid, "")
22
+ self.new(text, SecureRandom.uuid, [""])
28
23
  end
29
24
 
30
25
  def self.from_markdown(lines)
@@ -32,13 +27,11 @@ module Taskmeister
32
27
 
33
28
  text, id = task_attributes(task)
34
29
 
35
- notes = notes.map { |l| l.gsub(/\A> ?/, "") }.join("\n")
36
-
37
30
  self.new(text, id, notes)
38
31
  end
39
32
 
40
33
  def self.task_attributes(line)
41
- matches = line.match(/\A(.+) - \[id\]\(([\w-]+)\)\z/)
34
+ matches = line.match(/#\s(.+)\s\[∞\]\(#([\w-]+)\)/)
42
35
 
43
36
  fail "Invalid task: #{line}" unless matches
44
37
 
@@ -3,9 +3,9 @@ module Taskmeister
3
3
  attr_reader :file_path
4
4
 
5
5
  def initialize(tasks, file_path)
6
- @file_path = file_path
6
+ @file_path = Pathname.new file_path
7
7
 
8
- @hash = {}
8
+ @shortIdToTask = {}
9
9
 
10
10
  tasks.each do |t|
11
11
  add(t)
@@ -15,23 +15,23 @@ module Taskmeister
15
15
  end
16
16
 
17
17
  def to_short_list
18
- longest_id = @hash.keys.max_by(&:length)
19
- @hash.map { |id, task|
18
+ longest_id = @shortIdToTask.keys.max_by(&:length)
19
+ @shortIdToTask.map { |id, task|
20
20
  marker = task.notes? ? " »" : ""
21
21
  "%-#{longest_id.length}s - %s%s" % [id, task.text, marker]
22
22
  }
23
23
  end
24
24
 
25
25
  def tasks
26
- @hash.values
26
+ @shortIdToTask.values
27
27
  end
28
28
 
29
29
  def [](key)
30
- @hash[key]
30
+ @shortIdToTask[key]
31
31
  end
32
32
 
33
33
  def empty?
34
- @hash.empty?
34
+ @shortIdToTask.empty?
35
35
  end
36
36
 
37
37
  def dirty?
@@ -40,12 +40,12 @@ module Taskmeister
40
40
 
41
41
  def add(task)
42
42
  prefix = assign_short_code_to_task(task)
43
- @hash[prefix] = task
43
+ @shortIdToTask[prefix] = task
44
44
  @dirty = true
45
45
  end
46
46
 
47
47
  def complete(short_id)
48
- removed_val = @hash.delete(short_id)
48
+ removed_val = @shortIdToTask.delete(short_id)
49
49
  @dirty = true if removed_val
50
50
  end
51
51
 
@@ -53,12 +53,12 @@ module Taskmeister
53
53
  task = self[short_id]
54
54
  return unless task
55
55
 
56
- @hash[short_id] = Task.new(new_text, task.id, task.notes)
56
+ @shortIdToTask[short_id] = Task.new(new_text, task.id, task.notes)
57
57
  @dirty = true
58
58
  end
59
59
 
60
60
  def markdown_for(short_id)
61
- return [] unless @hash.has_key?(short_id)
61
+ return [] unless @shortIdToTask.has_key?(short_id)
62
62
 
63
63
  self[short_id].to_markdown
64
64
  end
@@ -68,7 +68,7 @@ module Taskmeister
68
68
  def assign_short_code_to_task(task)
69
69
  task.id.length.times do |i|
70
70
  prefix = task.id.slice(0, i + 1)
71
- return prefix unless @hash.has_key?(prefix)
71
+ return prefix unless @shortIdToTask.has_key?(prefix)
72
72
  end
73
73
  end
74
74
  end
@@ -1,16 +1,19 @@
1
1
  module Taskmeister
2
2
  class TaskListReader
3
3
  def self.from_markdown(file_lines, file_path)
4
- grouped_lines = \
4
+ lines_grouped_by_task = \
5
5
  file_lines.map(&:chomp)
6
- .reject(&:empty?)
7
6
  .reduce([]) do |acc, l|
8
- acc << [l] if l.match(/\A[^\s>]/) # A new task
9
- acc.last << l if l.match(/\A>/) # A line of note for the latest task
10
- acc
7
+ acc.tap do |a|
8
+ if l.match(/#\s.+\s\[∞\]\(#[\w-]+\)/)
9
+ acc << [l] # A new task
10
+ else
11
+ acc.last << l # A line of note for the latest task
12
+ end
13
+ end
11
14
  end
12
15
 
13
- tasks = grouped_lines.map do |ls|
16
+ tasks = lines_grouped_by_task.map do |ls|
14
17
  Task.from_markdown ls
15
18
  end
16
19
 
@@ -1,3 +1,3 @@
1
1
  module Taskmeister
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -25,48 +25,59 @@ module Taskmeister
25
25
 
26
26
  describe "passed a list of simple tasks" do
27
27
  let(:lines) { [
28
- "Task number 1\n",
29
- "Task number 2\n"
28
+ "# Task number 1 [∞](#e8fd82de-c379-496d-a77b-2873192e8ea8)\n",
29
+ "\n",
30
+ "# Task number 2 [∞](#e9fd82de-c379-496d-a77b-2873192e8ea8)\n",
31
+ "\n"
30
32
  ]
31
33
  }
32
34
 
33
35
  it "creates a task for each line, stripping new lines" do
34
- expect(Task).to receive(:from_markdown).with([ "Task number 1" ])
35
- expect(Task).to receive(:from_markdown).with([ "Task number 2" ])
36
+ expect(Task).to receive(:from_markdown).with([ "# Task number 1 [∞](#e8fd82de-c379-496d-a77b-2873192e8ea8)", ""])
37
+ expect(Task).to receive(:from_markdown).with([ "# Task number 2 [∞](#e9fd82de-c379-496d-a77b-2873192e8ea8)", ""])
36
38
  it
37
39
  end
38
40
  end
39
41
 
40
42
  describe "passed a list of tasks with notes" do
41
43
  let(:lines) { [
42
- "Task number 1\n",
44
+ "# Task number 1 [∞](#e8fd82de-c379-496d-a77b-2873192e8ea8)\n",
45
+ "\n",
46
+ "note line 1\n",
47
+ "\n",
48
+ "\n",
49
+ "note line 2\n",
43
50
  "\n",
44
- "> note line 1\n",
45
- "> note line 2\n",
51
+ "# Task number 2 [∞](#18fd82de-c379-496d-a77b-2873192e8ea8)\n",
46
52
  "\n",
47
- "Task number 2\n",
48
- "Task number 3\n",
53
+ "# Task number 3 [∞](#e9fd82de-c379-496d-a77b-2873192e8ea8)\n",
49
54
  "\n",
50
- "> note line 3\n",
51
- "> note line 4\n",
52
- "",
53
- "",
55
+ "note line 3\n",
56
+ "note line 4\n",
57
+ "\n"
54
58
  ]
55
59
  }
56
60
 
57
61
  it "creates a task for each line with their associated notes, stripping newlines" do
58
62
  expect(Task).to receive(:from_markdown).with([
59
- "Task number 1",
60
- "> note line 1",
61
- "> note line 2",
63
+ "# Task number 1 [∞](#e8fd82de-c379-496d-a77b-2873192e8ea8)",
64
+ "",
65
+ "note line 1",
66
+ "",
67
+ "",
68
+ "note line 2",
69
+ "",
62
70
  ])
63
71
  expect(Task).to receive(:from_markdown).with([
64
- "Task number 2"
72
+ "# Task number 2 [∞](#18fd82de-c379-496d-a77b-2873192e8ea8)",
73
+ "",
65
74
  ])
66
75
  expect(Task).to receive(:from_markdown).with([
67
- "Task number 3",
68
- "> note line 3",
69
- "> note line 4",
76
+ "# Task number 3 [∞](#e9fd82de-c379-496d-a77b-2873192e8ea8)",
77
+ "",
78
+ "note line 3",
79
+ "note line 4",
80
+ ""
70
81
  ])
71
82
 
72
83
  it
@@ -4,13 +4,13 @@ require "taskmeister/task"
4
4
  module Taskmeister
5
5
  RSpec.describe TaskList do
6
6
 
7
- let(:task1) { Task.new("task 1", "78dc2561-8c9a-4780-a560-56e1e14f2ed3", nil) }
8
- let(:task2) { Task.new("task 2", "b2110029-ffa0-4e54-985a-2aa6d1bed53b", nil) }
7
+ let(:task1) { Task.new("task 1", "78dc2561-8c9a-4780-a560-56e1e14f2ed3", []) }
8
+ let(:task2) { Task.new("task 2", "b2110029-ffa0-4e54-985a-2aa6d1bed53b", []) }
9
9
  let(:task3) { Task.new("task 3", "1c890df0-97a5-4310-9b01-374983416af7", "a note") }
10
- let(:task4) { Task.new("task 4", "1c891df0-97a5-4310-9b01-374983416af7", nil) }
11
- let(:task5) { Task.new("task 5", "ef0915ee-3d11-4358-b12c-15a4ab0d1d26", nil) }
12
- let(:task6) { Task.new("task 6", "f2a0d281-f323-4909-8547-d4af5315a295", nil) }
13
- let(:task7) { Task.new("task 7", "f2a0d281-4323-4909-8547-d4af5315a295", nil) }
10
+ let(:task4) { Task.new("task 4", "1c891df0-97a5-4310-9b01-374983416af7", []) }
11
+ let(:task5) { Task.new("task 5", "ef0915ee-3d11-4358-b12c-15a4ab0d1d26", []) }
12
+ let(:task6) { Task.new("task 6", "f2a0d281-f323-4909-8547-d4af5315a295", []) }
13
+ let(:task7) { Task.new("task 7", "f2a0d281-4323-4909-8547-d4af5315a295", []) }
14
14
 
15
15
  let(:tasks) { [
16
16
  task1, task2, task3, task4, task5, task6, task7
@@ -18,8 +18,8 @@ module Taskmeister
18
18
 
19
19
  let(:list) { described_class.new(tasks, "fake file") }
20
20
 
21
- it "saves its file path" do
22
- expect(list.file_path).to eq "fake file"
21
+ it "initially saves its file path" do
22
+ expect(list.file_path).to eq Pathname.new("fake file")
23
23
  end
24
24
 
25
25
  it "is initially clean" do
@@ -5,24 +5,28 @@ module Taskmeister
5
5
  describe ".from_markdown" do
6
6
  subject { described_class.from_markdown(lines) }
7
7
 
8
- describe "passed a single valid line" do
8
+ describe "passed a task with an empty note" do
9
9
  let(:lines) { [
10
- "A task name - [id](78dc2561-8c9a-4780-a560-56e1e14f2ed3)"
10
+ "# A task name [](#78dc2561-8c9a-4780-a560-56e1e14f2ed3)",
11
+ "",
11
12
  ]}
12
13
 
13
14
  it "sets the name and id of the task" do
14
15
  expect(subject.id).to eq "78dc2561-8c9a-4780-a560-56e1e14f2ed3"
15
16
  expect(subject.text).to eq "A task name"
16
- expect(subject.notes).to eq ""
17
+ expect(subject.notes).to eq [""]
17
18
  end
18
19
  end
19
20
 
20
21
  describe "passed a single valid line and notes" do
21
22
  let(:lines) { [
22
- "A task name - [id](78dc2561-8c9a-4780-a560-56e1e14f2ed3)",
23
- "> line one of a note",
24
- ">",
25
- "> line two of a note"
23
+ "# A task name [](#78dc2561-8c9a-4780-a560-56e1e14f2ed3)",
24
+ "",
25
+ "note line 1",
26
+ "",
27
+ "",
28
+ "note line 2",
29
+ ""
26
30
  ]}
27
31
 
28
32
  it "sets the name and id of the task" do
@@ -30,8 +34,15 @@ module Taskmeister
30
34
  expect(subject.text).to eq "A task name"
31
35
  end
32
36
 
33
- it "concatenates together the notes of the task" do
34
- expect(subject.notes).to eq "line one of a note\n\nline two of a note"
37
+ it "sets the notes of the task" do
38
+ expect(subject.notes).to eq [
39
+ "",
40
+ "note line 1",
41
+ "",
42
+ "",
43
+ "note line 2",
44
+ ""
45
+ ]
35
46
  end
36
47
  end
37
48
 
@@ -47,33 +58,45 @@ module Taskmeister
47
58
  end
48
59
 
49
60
  describe ".create" do
50
- it "returns a task with the specified text and a new id" do
61
+ it "returns a task with the specified text, a new id, and empty notes" do
51
62
  task = described_class.create("My task text")
52
63
  expect(task.text).to eq "My task text"
53
64
  expect(task.id).to match(/[\w-]+/)
54
- expect(task.notes).to eq ""
65
+ expect(task.notes).to eq [""]
66
+ end
67
+ end
68
+
69
+ describe "#notes?" do
70
+ it "returns true if there is a non-empty string in the notes list" do
71
+ task = Task.new("My task text", "f23891df0-97a5-4310-9b01-374983416af7", ["", "a note", ""])
72
+ expect(task.notes?).to be_truthy
73
+ end
74
+
75
+ it "returns false if there is are only empty strings in the notes list" do
76
+ task = Task.new("My task text", "f23891df0-97a5-4310-9b01-374983416af7", ["", ""])
77
+ expect(task.notes?).to be_falsy
55
78
  end
56
79
  end
57
80
 
58
81
  describe "#to_markdown" do
59
82
  it "returns a list of markdown-formatted lines" do
60
- task = described_class.new("task 8", "f23891df0-97a5-4310-9b01-374983416af7", " ")
83
+ task = described_class.new("task 8", "f23891df0-97a5-4310-9b01-374983416af7", [""])
61
84
  expect(task.to_markdown).to eq [
62
- "task 8 - [id](f23891df0-97a5-4310-9b01-374983416af7)"
85
+ "# task 8 [](#f23891df0-97a5-4310-9b01-374983416af7)",
86
+ ""
63
87
  ]
64
88
  end
65
89
 
66
90
  it "returns a list of markdown-formatted lines including notes" do
67
91
  task = described_class.new("task 8", "f23891df0-97a5-4310-9b01-374983416af7",
68
- "First line of a note\nsecond line\n\nthird line")
92
+ ["", "First line of a note", "second line", "", "third line"])
69
93
  expect(task.to_markdown).to eq [
70
- "task 8 - [id](f23891df0-97a5-4310-9b01-374983416af7)",
94
+ "# task 8 [](#f23891df0-97a5-4310-9b01-374983416af7)",
71
95
  "",
72
- "> First line of a note",
73
- "> second line",
74
- ">",
75
- "> third line",
76
- ""
96
+ "First line of a note",
97
+ "second line",
98
+ "",
99
+ "third line"
77
100
  ]
78
101
  end
79
102
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taskmeister
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ray Grasso
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-30 00:00:00.000000000 Z
11
+ date: 2014-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -120,6 +120,7 @@ files:
120
120
  - features/step_definitions/command_double_steps.rb
121
121
  - features/support/env.rb
122
122
  - lib/taskmeister.rb
123
+ - lib/taskmeister/cli/commands.rb
123
124
  - lib/taskmeister/cli/main.rb
124
125
  - lib/taskmeister/cli/options.rb
125
126
  - lib/taskmeister/cli/task_list_name.rb
@@ -154,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
155
  version: '0'
155
156
  requirements: []
156
157
  rubyforge_project:
157
- rubygems_version: 2.2.2
158
+ rubygems_version: 2.4.1
158
159
  signing_key:
159
160
  specification_version: 4
160
161
  summary: Another command line task manager.