whatnext 3.2__tar.gz → 3.3__tar.gz

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.
Files changed (123) hide show
  1. {whatnext-3.2 → whatnext-3.3}/CHANGELOG.md +14 -0
  2. {whatnext-3.2 → whatnext-3.3}/PKG-INFO +1 -1
  3. {whatnext-3.2 → whatnext-3.3}/docs/next.md +6 -0
  4. {whatnext-3.2 → whatnext-3.3}/tasks/next.md +2 -2
  5. {whatnext-3.2 → whatnext-3.3}/tasks/summaries.md +1 -0
  6. {whatnext-3.2 → whatnext-3.3}/tests/colour.bats +49 -0
  7. whatnext-3.3/tests/next/wide.md +5 -0
  8. whatnext-3.3/tests/next/wrapped.md +4 -0
  9. {whatnext-3.2 → whatnext-3.3}/tests/next.bats +332 -54
  10. {whatnext-3.2 → whatnext-3.3}/tests/test_file.py +2 -0
  11. {whatnext-3.2 → whatnext-3.3}/whatnext/models.py +9 -1
  12. {whatnext-3.2 → whatnext-3.3}/whatnext/next.py +150 -67
  13. {whatnext-3.2 → whatnext-3.3}/whatnext/summary.py +10 -13
  14. {whatnext-3.2 → whatnext-3.3}/whatnext/whatnext.py +0 -1
  15. {whatnext-3.2 → whatnext-3.3}/.flake8 +0 -0
  16. {whatnext-3.2 → whatnext-3.3}/.github/dependabot.yml +0 -0
  17. {whatnext-3.2 → whatnext-3.3}/.github/workflows/publish.yml +0 -0
  18. {whatnext-3.2 → whatnext-3.3}/.github/workflows/tests.yml +0 -0
  19. {whatnext-3.2 → whatnext-3.3}/.gitignore +0 -0
  20. {whatnext-3.2 → whatnext-3.3}/.whatnext +0 -0
  21. {whatnext-3.2 → whatnext-3.3}/LICENCE +0 -0
  22. {whatnext-3.2 → whatnext-3.3}/LICENSE +0 -0
  23. {whatnext-3.2 → whatnext-3.3}/Makefile +0 -0
  24. {whatnext-3.2 → whatnext-3.3}/README.md +0 -0
  25. {whatnext-3.2 → whatnext-3.3}/archive/done/tasks.md +0 -0
  26. {whatnext-3.2 → whatnext-3.3}/docs/annotations.md +0 -0
  27. {whatnext-3.2 → whatnext-3.3}/docs/basics.md +0 -0
  28. {whatnext-3.2 → whatnext-3.3}/docs/deadlines.md +0 -0
  29. {whatnext-3.2 → whatnext-3.3}/docs/deferring.md +0 -0
  30. {whatnext-3.2 → whatnext-3.3}/docs/exclusions.md +0 -0
  31. {whatnext-3.2 → whatnext-3.3}/docs/index.md +0 -0
  32. {whatnext-3.2 → whatnext-3.3}/docs/installation.md +0 -0
  33. {whatnext-3.2 → whatnext-3.3}/docs/prioritisation.md +0 -0
  34. {whatnext-3.2 → whatnext-3.3}/docs/sequential.md +0 -0
  35. {whatnext-3.2 → whatnext-3.3}/docs/usage.md +0 -0
  36. {whatnext-3.2 → whatnext-3.3}/example/archived/projects/tangerine.md +0 -0
  37. {whatnext-3.2 → whatnext-3.3}/example/projects/curtain.md +0 -0
  38. {whatnext-3.2 → whatnext-3.3}/example/projects/fountain.md +0 -0
  39. {whatnext-3.2 → whatnext-3.3}/example/projects/harvest.md +0 -0
  40. {whatnext-3.2 → whatnext-3.3}/example/projects/obelisk.md +0 -0
  41. {whatnext-3.2 → whatnext-3.3}/example/projects/tinsel.md +0 -0
  42. {whatnext-3.2 → whatnext-3.3}/example/tasks.md +0 -0
  43. {whatnext-3.2 → whatnext-3.3}/example/template.md +0 -0
  44. {whatnext-3.2 → whatnext-3.3}/pyproject.toml +0 -0
  45. {whatnext-3.2 → whatnext-3.3}/scripts/update-usage-examples.py +0 -0
  46. {whatnext-3.2 → whatnext-3.3}/tasks/deferring.md +0 -0
  47. {whatnext-3.2 → whatnext-3.3}/tasks/documentation.md +0 -0
  48. {whatnext-3.2 → whatnext-3.3}/tasks/ignoring.md +0 -0
  49. {whatnext-3.2 → whatnext-3.3}/tasks/listing.md +0 -0
  50. {whatnext-3.2 → whatnext-3.3}/tasks/test_refactor.md +0 -0
  51. {whatnext-3.2 → whatnext-3.3}/tasks/version_0.1.md +0 -0
  52. {whatnext-3.2 → whatnext-3.3}/tasks/version_0.2.md +0 -0
  53. {whatnext-3.2 → whatnext-3.3}/tasks/version_0.3.md +0 -0
  54. {whatnext-3.2 → whatnext-3.3}/tasks/version_0.4.md +0 -0
  55. {whatnext-3.2 → whatnext-3.3}/tasks/version_0.5.md +0 -0
  56. {whatnext-3.2 → whatnext-3.3}/tasks/version_1.0.md +0 -0
  57. {whatnext-3.2 → whatnext-3.3}/tasks/version_1.1.md +0 -0
  58. {whatnext-3.2 → whatnext-3.3}/tasks/version_1.2.md +0 -0
  59. {whatnext-3.2 → whatnext-3.3}/tasks/version_1.3.md +0 -0
  60. {whatnext-3.2 → whatnext-3.3}/tasks.md +0 -0
  61. {whatnext-3.2 → whatnext-3.3}/tests/config/.whatnext +0 -0
  62. {whatnext-3.2 → whatnext-3.3}/tests/config/.whatnext.alt +0 -0
  63. {whatnext-3.2 → whatnext-3.3}/tests/config/apples.md +0 -0
  64. {whatnext-3.2 → whatnext-3.3}/tests/config/oranges.md +0 -0
  65. {whatnext-3.2 → whatnext-3.3}/tests/config-external +0 -0
  66. {whatnext-3.2 → whatnext-3.3}/tests/config.bats +0 -0
  67. {whatnext-3.2 → whatnext-3.3}/tests/deadline.bats +0 -0
  68. {whatnext-3.2 → whatnext-3.3}/tests/deferring/bare-after.md +0 -0
  69. {whatnext-3.2 → whatnext-3.3}/tests/deferring/circular-a.md +0 -0
  70. {whatnext-3.2 → whatnext-3.3}/tests/deferring/circular-b.md +0 -0
  71. {whatnext-3.2 → whatnext-3.3}/tests/deferring/deferred.md +0 -0
  72. {whatnext-3.2 → whatnext-3.3}/tests/deferring/duplicate-warnings.md +0 -0
  73. {whatnext-3.2 → whatnext-3.3}/tests/deferring/missing-dep.md +0 -0
  74. {whatnext-3.2 → whatnext-3.3}/tests/deferring/needs-absolute.md +0 -0
  75. {whatnext-3.2 → whatnext-3.3}/tests/deferring/needs-subdir.md +0 -0
  76. {whatnext-3.2 → whatnext-3.3}/tests/deferring/phase-misplaced.md +0 -0
  77. {whatnext-3.2 → whatnext-3.3}/tests/deferring/phases-empty.md +0 -0
  78. {whatnext-3.2 → whatnext-3.3}/tests/deferring/phases-partial.md +0 -0
  79. {whatnext-3.2 → whatnext-3.3}/tests/deferring/phases-queue.md +0 -0
  80. {whatnext-3.2 → whatnext-3.3}/tests/deferring/phases.md +0 -0
  81. {whatnext-3.2 → whatnext-3.3}/tests/deferring/regular.md +0 -0
  82. {whatnext-3.2 → whatnext-3.3}/tests/deferring/root-target.md +0 -0
  83. {whatnext-3.2 → whatnext-3.3}/tests/deferring/samename.md +0 -0
  84. {whatnext-3.2 → whatnext-3.3}/tests/deferring/subdir/needs-parent.md +0 -0
  85. {whatnext-3.2 → whatnext-3.3}/tests/deferring/subdir/needs-sibling.md +0 -0
  86. {whatnext-3.2 → whatnext-3.3}/tests/deferring/subdir/samename.md +0 -0
  87. {whatnext-3.2 → whatnext-3.3}/tests/deferring/subdir/target.md +0 -0
  88. {whatnext-3.2 → whatnext-3.3}/tests/deferring.bats +0 -0
  89. {whatnext-3.2 → whatnext-3.3}/tests/edit.bats +0 -0
  90. {whatnext-3.2 → whatnext-3.3}/tests/headerless/annotation.md +0 -0
  91. {whatnext-3.2 → whatnext-3.3}/tests/headerless/deadline.md +0 -0
  92. {whatnext-3.2 → whatnext-3.3}/tests/housekeeping.bats +0 -0
  93. {whatnext-3.2 → whatnext-3.3}/tests/invalid.md +0 -0
  94. {whatnext-3.2 → whatnext-3.3}/tests/list.bats +0 -0
  95. {whatnext-3.2 → whatnext-3.3}/tests/matching.bats +0 -0
  96. {whatnext-3.2 → whatnext-3.3}/tests/next/alternate.md +0 -0
  97. {whatnext-3.2 → whatnext-3.3}/tests/next/append-after.md +0 -0
  98. {whatnext-3.2 → whatnext-3.3}/tests/next/append.md +0 -0
  99. {whatnext-3.2 → whatnext-3.3}/tests/next/empty.md +0 -0
  100. {whatnext-3.2 → whatnext-3.3}/tests/next/insert.md +0 -0
  101. {whatnext-3.2 → whatnext-3.3}/tests/next/projects/alpha/tasks/things.md +0 -0
  102. {whatnext-3.2 → whatnext-3.3}/tests/next/projects/alpha/tasks.md +0 -0
  103. {whatnext-3.2 → whatnext-3.3}/tests/next/projects/beta/things.md +0 -0
  104. {whatnext-3.2 → whatnext-3.3}/tests/next/something.txt +0 -0
  105. {whatnext-3.2 → whatnext-3.3}/tests/next/tasks.md +0 -0
  106. {whatnext-3.2 → whatnext-3.3}/tests/notnext.bats +0 -0
  107. {whatnext-3.2 → whatnext-3.3}/tests/queue/all-complete.md +0 -0
  108. {whatnext-3.2 → whatnext-3.3}/tests/queue/blocked.md +0 -0
  109. {whatnext-3.2 → whatnext-3.3}/tests/queue/in-progress.md +0 -0
  110. {whatnext-3.2 → whatnext-3.3}/tests/queue/normal.md +0 -0
  111. {whatnext-3.2 → whatnext-3.3}/tests/queue/prioritised.md +0 -0
  112. {whatnext-3.2 → whatnext-3.3}/tests/queue.bats +0 -0
  113. {whatnext-3.2 → whatnext-3.3}/tests/summary.bats +0 -0
  114. {whatnext-3.2 → whatnext-3.3}/tests/test_defer.py +0 -0
  115. {whatnext-3.2 → whatnext-3.3}/tests/test_edit.py +0 -0
  116. {whatnext-3.2 → whatnext-3.3}/tests/test_limit.py +0 -0
  117. {whatnext-3.2 → whatnext-3.3}/tests/test_output.py +0 -0
  118. {whatnext-3.2 → whatnext-3.3}/tests/test_summary.py +0 -0
  119. {whatnext-3.2 → whatnext-3.3}/tests/test_task.py +0 -0
  120. {whatnext-3.2 → whatnext-3.3}/tests/usage.bats +0 -0
  121. {whatnext-3.2 → whatnext-3.3}/tests/version.bats +0 -0
  122. {whatnext-3.2 → whatnext-3.3}/whatnext/__init__.py +0 -0
  123. {whatnext-3.2 → whatnext-3.3}/whatnext/guide.txt +0 -0
@@ -1,6 +1,20 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## [v3.3] - 2026-04-13
5
+
6
+ **Added:**
7
+ - `next` reads from stdin when no task text is provided, allowing piping of
8
+ multiple tasks (one per line) into a file.
9
+ - `next` wraps the text of added tasks, to a default of 80 chars, which can be
10
+ overriden in the config `wrap_width` setting, or `WHATNEXT_WRAP_WIDTH`. If
11
+ the file has any existing lines longer than that, the file takes precedence
12
+ and the text is instead wrapped to match that longer width.
13
+ - `next --config {file}` specifies a non-default location config file,
14
+ or set `WHATNEXT_CONFIG`.
15
+ - Summary totals line is now shown in yellow as a differentiator.
16
+
17
+
4
18
  ## [v3.2] - 2026-04-09
5
19
 
6
20
  **Added:**
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: whatnext
3
- Version: 3.2
3
+ Version: 3.3
4
4
  Summary: A lister of tasks found in Markdown files
5
5
  Project-URL: Homepage, https://github.com/norm/whatnext
6
6
  Project-URL: Repository, https://github.com/norm/whatnext
@@ -63,3 +63,9 @@ Once the file is chosen, the file is checked for Markdown headings.
63
63
 
64
64
  If you would prefer the task is always added at the end of the file,
65
65
  set `$WHATNEXT_APPEND_ONLY` to a value, or use `next -a`.
66
+
67
+
68
+ ## The task text
69
+
70
+ The task text is all remaining arguments as a string. If no arguments remain,
71
+ `next` reads from stdin, with multiple lines making multiple tasks.
@@ -3,7 +3,7 @@
3
3
  - [X] next should add to tasks.md in cwd before home
4
4
  - [ ] next should have -e too, to edit task files
5
5
  - [X] show diff when adding task with next
6
- - [ ] next reads stdin to add multiple tasks at once?
7
- - [ ] wrap text to a maximum width when adding to the task file;
6
+ - [X] next reads stdin to add multiple tasks at once
7
+ - [X] wrap text to a maximum width when adding to the task file;
8
8
  .whatnext config and env var
9
9
  - [ ] directive in a file to tell `next` where to put new tasks
@@ -1,3 +1,4 @@
1
1
  Improvements to `--summary` output.
2
2
 
3
3
  - [X] show total %age progression across project, not just column totals
4
+ - [X] show total %age in a different colour
@@ -30,6 +30,31 @@ EOF
30
30
  [ $status -eq 0 ]
31
31
  }
32
32
 
33
+ @test "force colour output in summary" {
34
+ cd example
35
+
36
+ b=$'\033[34m'
37
+ r=$'\033[0m'
38
+ COLUMNS=40 \
39
+ WHATNEXT_TODAY=2025-01-01 \
40
+ run --separate-stderr \
41
+ whatnext \
42
+ --color \
43
+ --summary \
44
+ --open \
45
+ tasks.md
46
+
47
+ expected_output=$(sed -e 's/^ //' <<EOF
48
+ O
49
+ ${b}█████████████████████████${r} 3 tasks.md
50
+
51
+ █ Open
52
+ EOF
53
+ )
54
+ diff -u <(echo "$expected_output") <(echo "$output")
55
+ [ $status -eq 0 ]
56
+ }
57
+
33
58
  @test "disable colour output" {
34
59
  WHATNEXT_TODAY=2025-12-25 \
35
60
  WHATNEXT_COLOR=1 \
@@ -58,3 +83,27 @@ EOF
58
83
  diff -u <(echo "$expected_output") <(echo "$output")
59
84
  [ $status -eq 0 ]
60
85
  }
86
+
87
+ @test "disable colour output in summary" {
88
+ cd example
89
+
90
+ COLUMNS=40 \
91
+ WHATNEXT_TODAY=2025-01-01 \
92
+ WHATNEXT_COLOR=1 \
93
+ run --separate-stderr \
94
+ whatnext \
95
+ --no-color \
96
+ --summary \
97
+ --open \
98
+ tasks.md
99
+
100
+ expected_output=$(sed -e 's/^ //' <<" EOF"
101
+ O
102
+ █████████████████████████ 3 tasks.md
103
+
104
+ █ Open
105
+ EOF
106
+ )
107
+ diff -u <(echo "$expected_output") <(echo "$output")
108
+ [ $status -eq 0 ]
109
+ }
@@ -0,0 +1,5 @@
1
+ This line of context is deliberately written to be extraordinarily long, much longer than any task line in this file, to prove the script measures task width not arbitrary line width.
2
+
3
+ - [ ] short task
4
+ - [ ] another short task
5
+ - [ ] This is an existing task that is deliberately written to be wider than eighty characters on a single line
@@ -0,0 +1,4 @@
1
+ # Tasks @after tasks.md
2
+
3
+ - [ ] the continuation line is deliberately longer than the first line in
4
+ order to confirm that width detection occurs across the entire task not just the first line
@@ -15,32 +15,34 @@ function setup {
15
15
  }
16
16
 
17
17
  @test "shows usage" {
18
- expected_output=$(sed -e 's/^ //' <<" EOF"
19
- usage: next [-h] [--version] [-a] ...
18
+ expected_output=$(sed -e 's/^ //' <<-EOF
19
+ usage: next [-h] [--version] [-a] [--config CONFIG] ...
20
20
 
21
21
  Add a task to a Markdown (.md file) task list.
22
22
 
23
23
  positional arguments:
24
- text task text to add
24
+ text task text to add (if omitted, read from stdin)
25
25
 
26
26
  options:
27
- -h, --help show this help message and exit
28
- --version show program's version number and exit
29
- -a append to end of file, ignoring headings (or set
30
- WHATNEXT_APPEND_ONLY)
27
+ -h, --help show this help message and exit
28
+ --version show program's version number and exit
29
+ -a append to end of file, ignoring headings (or set
30
+ WHATNEXT_APPEND_ONLY)
31
+ --config CONFIG path to config file (default: WHATNEXT_CONFIG, or
32
+ '.whatnext')
31
33
 
32
34
  The file to add to is chosen indirectly:
33
35
 
34
36
  - if the first word of text is an absolute filename, use that
35
37
  - if the first word matches a file in the current directory, use that
36
- - if the first word matches a file in $WHATNEXT_PROJECT_DIR, use that
37
- - if the first word matches a file in $HOME, use that
38
- - if the first word matches a directory in $WHATNEXT_PROJECT_DIR:
38
+ - if the first word matches a file in \$WHATNEXT_PROJECT_DIR, use that
39
+ - if the first word matches a file in \$HOME, use that
40
+ - if the first word matches a directory in \$WHATNEXT_PROJECT_DIR:
39
41
  - if the second word matches a file
40
- $WHATNEXT_PROJECT_DIR/[project]/tasks/[word].md then use that
41
- - otherwise, use $WHATNEXT_PROJECT_DIR/[project]/tasks.md
42
+ \$WHATNEXT_PROJECT_DIR/[project]/tasks/[word].md then use that
43
+ - otherwise, use \$WHATNEXT_PROJECT_DIR/[project]/tasks.md
42
44
  - if tasks.md exists in the current directory, use that
43
- - otherwise, use $HOME/tasks.md
45
+ - otherwise, use \$HOME/tasks.md
44
46
 
45
47
  With the remaining text:
46
48
 
@@ -49,7 +51,7 @@ function setup {
49
51
  file, the task is added to that section
50
52
  - otherwise, the task is added above the first heading
51
53
  - otherwise, the task is added to the end of the file
52
- EOF
54
+ EOF
53
55
  )
54
56
 
55
57
  run next --help
@@ -58,28 +60,14 @@ function setup {
58
60
  [ $status -eq 0 ]
59
61
  }
60
62
 
61
- @test "without args does nothing" {
62
- expected_output=$(sed -e 's/^ //' <<" EOF"
63
- # Tasks
64
-
65
- - [ ] existing task
66
- EOF
67
- )
68
-
69
- run next
70
-
71
- diff -u <(echo "$expected_output") "$HOME/tasks.md"
72
- [ $status -eq 0 ]
73
- }
74
-
75
63
  @test "non-markdown file is treated as part of text" {
76
- expected_content=$(sed -e 's/^ //' <<" EOF"
64
+ expected_content=$(sed -e 's/^ //' <<-EOF
77
65
  - [ ] something.txt do something
78
66
 
79
67
  # Tasks
80
68
 
81
69
  - [ ] existing task
82
- EOF
70
+ EOF
83
71
  )
84
72
 
85
73
  run next something.txt do something
@@ -100,13 +88,13 @@ function setup {
100
88
  }
101
89
 
102
90
  @test "nonexistent file is treated as part of text" {
103
- expected_content=$(sed -e 's/^ //' <<" EOF"
91
+ expected_content=$(sed -e 's/^ //' <<-EOF
104
92
  - [ ] nonexistent.md do something
105
93
 
106
94
  # Tasks
107
95
 
108
96
  - [ ] existing task
109
- EOF
97
+ EOF
110
98
  )
111
99
 
112
100
  expected_output=$(sed -e 's/^ //' <<-EOF
@@ -129,13 +117,13 @@ function assert_task_added {
129
117
  local tasks_file="$1"
130
118
  local expected_message="$2"
131
119
 
132
- expected_content=$(sed -e 's/^ //' <<" EOF"
120
+ expected_content=$(sed -e 's/^ //' <<-EOF
133
121
  - [ ] do something
134
122
 
135
123
  # Tasks
136
124
 
137
125
  - [ ] existing task
138
- EOF
126
+ EOF
139
127
  )
140
128
 
141
129
  expected_output=$(sed -e 's/^ //' <<-EOF
@@ -206,13 +194,13 @@ function assert_task_added {
206
194
  }
207
195
 
208
196
  @test "adds to master task list without WHATNEXT_PROJECT_DIR" {
209
- expected_content=$(sed -e 's/^ //' <<" EOF"
197
+ expected_content=$(sed -e 's/^ //' <<-EOF
210
198
  - [ ] alpha do something
211
199
 
212
200
  # Tasks
213
201
 
214
202
  - [ ] existing task
215
- EOF
203
+ EOF
216
204
  )
217
205
  expected_output=$(sed -e 's/^ //' <<-EOF
218
206
  Updated ~/tasks.md:
@@ -249,9 +237,9 @@ function assert_task_added {
249
237
  }
250
238
 
251
239
  @test "creates project tasks file" {
252
- expected_content=$(sed -e 's/^ //' <<" EOF"
240
+ expected_content=$(sed -e 's/^ //' <<-EOF
253
241
  - [ ] do something
254
- EOF
242
+ EOF
255
243
  )
256
244
  expected_output=$(sed -e 's/^ //' <<-EOF
257
245
  Created ~/projects/beta/tasks.md:
@@ -267,9 +255,9 @@ function assert_task_added {
267
255
  }
268
256
 
269
257
  @test "does not add to things.md as it is not tried" {
270
- expected_content=$(sed -e 's/^ //' <<" EOF"
258
+ expected_content=$(sed -e 's/^ //' <<-EOF
271
259
  - [ ] things do something
272
- EOF
260
+ EOF
273
261
  )
274
262
 
275
263
  expected_output=$(sed -e 's/^ //' <<-EOF
@@ -335,13 +323,13 @@ function assert_task_added {
335
323
  }
336
324
 
337
325
  @test "adds to end of file" {
338
- expected_content=$(sed -e 's/^ //' <<" EOF"
326
+ expected_content=$(sed -e 's/^ //' <<-EOF
339
327
 
340
328
 
341
329
 
342
330
 
343
331
  - [ ] do something
344
- EOF
332
+ EOF
345
333
  )
346
334
 
347
335
  expected_output=$(sed -e 's/^ //' <<-EOF
@@ -360,7 +348,7 @@ function assert_task_added {
360
348
  }
361
349
 
362
350
  @test "test within file positioning" {
363
- expected_content=$(sed -e 's/^ //' <<" EOF"
351
+ expected_content=$(sed -e 's/^ //' <<-EOF
364
352
  This is an explanation.
365
353
 
366
354
  This section currently has no tasks.
@@ -398,7 +386,7 @@ function assert_task_added {
398
386
 
399
387
  - [ ] second to last task
400
388
  - [ ] last task
401
- EOF
389
+ EOF
402
390
  )
403
391
 
404
392
  run next insert.md do something
@@ -422,12 +410,12 @@ function assert_task_added {
422
410
  }
423
411
 
424
412
  @test "WHATNEXT_APPEND_ONLY set" {
425
- expected_content=$(sed -e 's/^ //' <<" EOF"
413
+ expected_content=$(sed -e 's/^ //' <<-EOF
426
414
  # Tasks
427
415
 
428
416
  - [ ] existing task
429
417
  - [ ] do something
430
- EOF
418
+ EOF
431
419
  )
432
420
  expected_output=$(sed -e 's/^ //' <<-EOF
433
421
  Updated ~/tasks.md:
@@ -446,12 +434,12 @@ function assert_task_added {
446
434
  }
447
435
 
448
436
  @test "append flag" {
449
- expected_content=$(sed -e 's/^ //' <<" EOF"
437
+ expected_content=$(sed -e 's/^ //' <<-EOF
450
438
  # Tasks
451
439
 
452
440
  - [ ] existing task
453
441
  - [ ] do something
454
- EOF
442
+ EOF
455
443
  )
456
444
 
457
445
  expected_output=$(sed -e 's/^ //' <<-EOF
@@ -470,13 +458,13 @@ function assert_task_added {
470
458
  }
471
459
 
472
460
  @test "flag-like text is not parsed as arguments" {
473
- expected_content=$(sed -e 's/^ //' <<" EOF"
461
+ expected_content=$(sed -e 's/^ //' <<-EOF
474
462
  - [ ] something -e something
475
463
 
476
464
  # Tasks
477
465
 
478
466
  - [ ] existing task
479
- EOF
467
+ EOF
480
468
  )
481
469
 
482
470
  expected_output=$(sed -e 's/^ //' <<-EOF
@@ -496,13 +484,13 @@ function assert_task_added {
496
484
  }
497
485
 
498
486
  @test "appending spaces out tasks" {
499
- expected_content=$(sed -e 's/^ //' <<" EOF"
487
+ expected_content=$(sed -e 's/^ //' <<-EOF
500
488
  # Tasks
501
489
 
502
490
  This is where things get added.
503
491
 
504
492
  - [ ] do something
505
- EOF
493
+ EOF
506
494
  )
507
495
 
508
496
  expected_output=$(sed -e 's/^ //' <<-EOF
@@ -522,7 +510,7 @@ function assert_task_added {
522
510
  }
523
511
 
524
512
  @test "append adds to end of file not after last task" {
525
- expected_content=$(sed -e 's/^ //' <<" EOF"
513
+ expected_content=$(sed -e 's/^ //' <<-EOF
526
514
  # Done
527
515
 
528
516
  - [X] completed task
@@ -530,7 +518,7 @@ function assert_task_added {
530
518
  # Next
531
519
 
532
520
  - [ ] do something
533
- EOF
521
+ EOF
534
522
  )
535
523
 
536
524
  expected_output=$(sed -e 's/^ //' <<-EOF
@@ -576,3 +564,293 @@ function assert_task_added {
576
564
  diff -u <(echo "$expected_output") <(echo "$output")
577
565
  [ $status -eq 0 ]
578
566
  }
567
+
568
+ @test "continuation line width is detected even when task is deferred" {
569
+ expected_content=$(sed -e 's/^ //' <<-EOF
570
+ - [ ] This new task is longer than eighty characters and exceeds the continuation width to prove
571
+ where it wraps
572
+
573
+ # Tasks @after tasks.md
574
+
575
+ - [ ] the continuation line is deliberately longer than the first line in
576
+ order to confirm that width detection occurs across the entire task not just the first line
577
+ EOF
578
+ )
579
+
580
+ WHATNEXT_WRAP_WIDTH=20 \
581
+ run next wrapped.md This new task is longer than eighty characters and exceeds the continuation width to prove where it wraps
582
+
583
+ diff -u <(echo "$expected_content") "$HOME/wrapped.md"
584
+ [ $status -eq 0 ]
585
+ }
586
+
587
+ @test "existing file with wider lines sets wrap width" {
588
+ expected_content=$(sed -e 's/^ //' <<-EOF
589
+ This line of context is deliberately written to be extraordinarily long, much longer than any task line in this file, to prove the script measures task width not arbitrary line width.
590
+
591
+ - [ ] short task
592
+ - [ ] another short task
593
+ - [ ] This is an existing task that is deliberately written to be wider than eighty characters on a single line
594
+ - [ ] Adding another long task that would normally wrap at eighty but should not wrap here because existing
595
+ tasks are wider
596
+ EOF
597
+ )
598
+
599
+ run next wide.md Adding another long task that would normally wrap at eighty but should not wrap here because existing tasks are wider
600
+
601
+ diff -u <(echo "$expected_content") "$HOME/wide.md"
602
+ [ $status -eq 0 ]
603
+ }
604
+
605
+ @test "file width beats narrower env var" {
606
+ expected_content=$(sed -e 's/^ //' <<-EOF
607
+ This line of context is deliberately written to be extraordinarily long, much longer than any task line in this file, to prove the script measures task width not arbitrary line width.
608
+
609
+ - [ ] short task
610
+ - [ ] another short task
611
+ - [ ] This is an existing task that is deliberately written to be wider than eighty characters on a single line
612
+ - [ ] This task would wrap at sixty if env var won but it does not because file width is authoritative
613
+ EOF
614
+ )
615
+
616
+ WHATNEXT_WRAP_WIDTH=60 \
617
+ run next wide.md This task would wrap at sixty if env var won but it does not because file width is authoritative
618
+
619
+ diff -u <(echo "$expected_content") "$HOME/wide.md"
620
+ [ $status -eq 0 ]
621
+ }
622
+
623
+ @test "env var sets width when file is narrower" {
624
+ expected_content=$(sed -e 's/^ //' <<-EOF
625
+ - [ ] This is a task that wraps at forty
626
+ characters
627
+
628
+ # Tasks
629
+
630
+ - [ ] existing task
631
+ EOF
632
+ )
633
+
634
+ WHATNEXT_WRAP_WIDTH=40 \
635
+ run next This is a task that wraps at forty characters
636
+
637
+ diff -u <(echo "$expected_content") "$HOME/tasks.md"
638
+ [ $status -eq 0 ]
639
+ }
640
+
641
+ @test "config sets width when file is narrower" {
642
+ expected_content=$(sed -e 's/^ //' <<-EOF
643
+ - [ ] This is a task that wraps at fifty
644
+ characters exactly
645
+
646
+ # Tasks
647
+
648
+ - [ ] existing task
649
+ EOF
650
+ )
651
+ echo 'wrap_width = 50' > "$HOME/.whatnext"
652
+
653
+ run next This is a task that wraps at fifty characters exactly
654
+
655
+ diff -u <(echo "$expected_content") "$HOME/tasks.md"
656
+ [ $status -eq 0 ]
657
+ }
658
+
659
+ @test "config file can be specified with --config" {
660
+ expected_content=$(sed -e 's/^ //' <<-EOF
661
+ - [ ] This is a task that wraps at fifty
662
+ characters exactly
663
+
664
+ # Tasks
665
+
666
+ - [ ] existing task
667
+ EOF
668
+ )
669
+ echo 'wrap_width = 50' > "$HOME/custom.toml"
670
+
671
+ run next --config custom.toml This is a task that wraps at fifty characters exactly
672
+
673
+ diff -u <(echo "$expected_content") "$HOME/tasks.md"
674
+ [ $status -eq 0 ]
675
+ }
676
+
677
+ @test "long task text wraps at 80 chars by default" {
678
+ expected_content=$(sed -e 's/^ //' <<-EOF
679
+ - [ ] This is a very long task description that should wrap because it exceeds
680
+ the default width of eighty characters
681
+
682
+ # Tasks
683
+
684
+ - [ ] existing task
685
+ EOF
686
+ )
687
+
688
+ run next This is a very long task description that should wrap because it exceeds the default width of eighty characters
689
+
690
+ diff -u <(echo "$expected_content") "$HOME/tasks.md"
691
+ [ $status -eq 0 ]
692
+ }
693
+
694
+ @test "stdin adds multiple tasks" {
695
+ expected_content=$(sed -e 's/^ //' <<-EOF
696
+ - [ ] first task
697
+ - [ ] second task
698
+ - [ ] third task
699
+
700
+ # Tasks
701
+
702
+ - [ ] existing task
703
+ EOF
704
+ )
705
+ expected_output=$(sed -e 's/^ //' <<-EOF
706
+ Updated ~/tasks.md:
707
+ +- [ ] first task
708
+ +- [ ] second task
709
+ +- [ ] third task
710
+ +
711
+ # Tasks
712
+
713
+ EOF
714
+ )
715
+
716
+ run bash -c 'printf "first task\nsecond task\nthird task\n" | next'
717
+
718
+ diff -u <(echo "$expected_content") "$HOME/tasks.md"
719
+ diff -u <(echo "$expected_output") <(echo "$output")
720
+ [ $status -eq 0 ]
721
+ }
722
+
723
+ @test "stdin with file specification" {
724
+ expected_content=$(sed -e 's/^ //' <<-EOF
725
+ - [ ] piped task
726
+
727
+ # Tasks
728
+
729
+ - [ ] existing task
730
+ EOF
731
+ )
732
+ expected_output=$(sed -e 's/^ //' <<-EOF
733
+ Updated ~/alternate.md:
734
+ +- [ ] piped task
735
+ +
736
+ # Tasks
737
+
738
+ EOF
739
+ )
740
+
741
+ run bash -c 'echo "piped task" | next alternate.md'
742
+
743
+ diff -u <(echo "$expected_content") "$HOME/alternate.md"
744
+ diff -u <(echo "$expected_output") <(echo "$output")
745
+ [ $status -eq 0 ]
746
+ }
747
+
748
+ @test "stdin with section specification" {
749
+ expected_content=$(sed -e 's/^ //' <<-EOF
750
+ This is an explanation.
751
+
752
+ This section currently has no tasks.
753
+
754
+ # First
755
+
756
+ - [ ] piped to section
757
+
758
+ # Second
759
+
760
+ #### Third
761
+
762
+ This section contains notes.
763
+
764
+ ## Fourth
765
+
766
+ A note.
767
+
768
+ - [ ] A task.
769
+
770
+ Another note.
771
+
772
+ # Second
773
+
774
+ There is no way to add a task here.
775
+
776
+ # Last
777
+
778
+ - [ ] second to last task
779
+ EOF
780
+ )
781
+ expected_output=$(sed -e 's/^ //' <<-EOF
782
+ Updated ~/insert.md (First):
783
+
784
+ # First
785
+ +
786
+ +- [ ] piped to section
787
+
788
+ # Second
789
+ EOF
790
+ )
791
+
792
+ run bash -c 'echo "piped to section" | next insert.md first'
793
+
794
+ diff -u <(echo "$expected_content") "$HOME/insert.md"
795
+ diff -u <(echo "$expected_output") <(echo "$output")
796
+ [ $status -eq 0 ]
797
+ }
798
+
799
+ @test "empty stdin does nothing" {
800
+ expected_content=$(sed -e 's/^ //' <<-EOF
801
+ # Tasks
802
+
803
+ - [ ] existing task
804
+ EOF
805
+ )
806
+
807
+ run bash -c 'echo -n "" | next'
808
+
809
+ diff -u <(echo "$expected_content") "$HOME/tasks.md"
810
+ diff -u <(echo "") <(echo "$output")
811
+ [ $status -eq 0 ]
812
+ }
813
+
814
+ @test "stdin blank lines are ignored" {
815
+ expected_content=$(sed -e 's/^ //' <<-EOF
816
+ - [ ] actual task
817
+ - [ ] another task
818
+
819
+ # Tasks
820
+
821
+ - [ ] existing task
822
+ EOF
823
+ )
824
+ expected_output=$(sed -e 's/^ //' <<-EOF
825
+ Updated ~/tasks.md:
826
+ +- [ ] actual task
827
+ +- [ ] another task
828
+ +
829
+ # Tasks
830
+
831
+ EOF
832
+ )
833
+
834
+ run bash -c 'printf "\nactual task\n\n\nanother task\n\n" | next'
835
+
836
+ diff -u <(echo "$expected_content") "$HOME/tasks.md"
837
+ diff -u <(echo "$expected_output") <(echo "$output")
838
+ [ $status -eq 0 ]
839
+ }
840
+
841
+ @test "stdin tasks are wrapped" {
842
+ expected_content=$(sed -e 's/^ //' <<-EOF
843
+ - [ ] This is a very long task that should wrap because it exceeds the default
844
+ width of eighty characters
845
+
846
+ # Tasks
847
+
848
+ - [ ] existing task
849
+ EOF
850
+ )
851
+
852
+ run bash -c 'echo "This is a very long task that should wrap because it exceeds the default width of eighty characters" | next'
853
+
854
+ diff -u <(echo "$expected_content") "$HOME/tasks.md"
855
+ [ $status -eq 0 ]
856
+ }