vimniscient 0.2.0__py3-none-any.whl

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 (80) hide show
  1. vimniscient/__init__.py +3 -0
  2. vimniscient/__main__.py +3 -0
  3. vimniscient/answer.py +113 -0
  4. vimniscient/app.py +310 -0
  5. vimniscient/cards/foot.yaml +19 -0
  6. vimniscient/cards/lazyvim.yaml +80 -0
  7. vimniscient/cards/shell.yaml +22 -0
  8. vimniscient/cards/vim.yaml +95 -0
  9. vimniscient/cards/zathura.yaml +32 -0
  10. vimniscient/cards.py +200 -0
  11. vimniscient/cli.py +98 -0
  12. vimniscient/drills/omarchy.yaml +88 -0
  13. vimniscient/drills.py +198 -0
  14. vimniscient/endless.py +60 -0
  15. vimniscient/generate.py +102 -0
  16. vimniscient/habits.py +116 -0
  17. vimniscient/keys.py +14 -0
  18. vimniscient/lessons/sources.md +59 -0
  19. vimniscient/lessons/w1d1-words.yaml +223 -0
  20. vimniscient/lessons/w1d2-pairs.yaml +188 -0
  21. vimniscient/lessons/w1d3-sentences.yaml +247 -0
  22. vimniscient/lessons/w1d4-find.yaml +184 -0
  23. vimniscient/lessons/w1d5-lines.yaml +249 -0
  24. vimniscient/lessons/w1d6-counts.yaml +351 -0
  25. vimniscient/lessons/w1d7-review.yaml +222 -0
  26. vimniscient/lessons/w2d1-dot.yaml +195 -0
  27. vimniscient/lessons/w2d2-search.yaml +194 -0
  28. vimniscient/lessons/w2d3-cgn.yaml +196 -0
  29. vimniscient/lessons/w2d4-case-numbers.yaml +201 -0
  30. vimniscient/lessons/w2d5-insert.yaml +229 -0
  31. vimniscient/lessons/w2d6-visual.yaml +206 -0
  32. vimniscient/lessons/w2d7-review.yaml +197 -0
  33. vimniscient/lessons/w3d1-macros.yaml +240 -0
  34. vimniscient/lessons/w3d2-macros-more.yaml +170 -0
  35. vimniscient/lessons/w3d3-registers.yaml +230 -0
  36. vimniscient/lessons/w3d4-marks.yaml +188 -0
  37. vimniscient/lessons/w3d5-visual-block.yaml +201 -0
  38. vimniscient/lessons/w3d6-substitute.yaml +290 -0
  39. vimniscient/lessons/w3d7-review.yaml +204 -0
  40. vimniscient/lessons/w4d1-ranges.yaml +214 -0
  41. vimniscient/lessons/w4d2-sort-filter.yaml +243 -0
  42. vimniscient/lessons/w4d3-regex.yaml +167 -0
  43. vimniscient/lessons/w4d4-norm.yaml +158 -0
  44. vimniscient/lessons/w4d5-motions.yaml +149 -0
  45. vimniscient/lessons/w4d6-indent.yaml +143 -0
  46. vimniscient/lessons/w4d7-review.yaml +175 -0
  47. vimniscient/lessons/w5d1-arguments.yaml +133 -0
  48. vimniscient/lessons/w5d2-any-quote-bracket.yaml +136 -0
  49. vimniscient/lessons/w5d3-functions.yaml +193 -0
  50. vimniscient/lessons/w5d4-small-objects.yaml +185 -0
  51. vimniscient/lessons/w5d5-comments.yaml +161 -0
  52. vimniscient/lessons/w5d6-review.yaml +120 -0
  53. vimniscient/lessons/w6d1-code.yaml +157 -0
  54. vimniscient/lessons/w6d2-notes.yaml +163 -0
  55. vimniscient/lessons/w6d3-data.yaml +145 -0
  56. vimniscient/lessons.py +184 -0
  57. vimniscient/mnemonics.py +141 -0
  58. vimniscient/mnemonics.yaml +124 -0
  59. vimniscient/nvim/keymaps.lua +25 -0
  60. vimniscient/nvim/runner.lua +711 -0
  61. vimniscient/progress.py +496 -0
  62. vimniscient/reminders.py +220 -0
  63. vimniscient/session.py +152 -0
  64. vimniscient/settings.py +33 -0
  65. vimniscient/srs.py +56 -0
  66. vimniscient/today.py +189 -0
  67. vimniscient/ui/__init__.py +1 -0
  68. vimniscient/ui/builtin_lessons.py +99 -0
  69. vimniscient/ui/cards.py +160 -0
  70. vimniscient/ui/common.py +129 -0
  71. vimniscient/ui/drills.py +163 -0
  72. vimniscient/ui/lesson.py +193 -0
  73. vimniscient/ui/main.py +217 -0
  74. vimniscient/ui/stats.py +145 -0
  75. vimniscient/vimgolf.py +97 -0
  76. vimniscient-0.2.0.dist-info/METADATA +322 -0
  77. vimniscient-0.2.0.dist-info/RECORD +80 -0
  78. vimniscient-0.2.0.dist-info/WHEEL +4 -0
  79. vimniscient-0.2.0.dist-info/entry_points.txt +2 -0
  80. vimniscient-0.2.0.dist-info/licenses/LICENSE +661 -0
@@ -0,0 +1,222 @@
1
+ week: 1
2
+ day: 7
3
+ review: true
4
+ title: Week 1 review
5
+ intro: |
6
+ A mix of everything from this week. Try each one before reaching for
7
+ `:Hint`, and try to match the reference keystroke count. Mixing topics like
8
+ this is harder than doing one at a time, and that's the point: you have to
9
+ pick the right command, not just repeat the last one.
10
+ keys: [ciw, ci(, das, dd, daw, ct, ">ip", "3f,"]
11
+ tasks:
12
+ - goal: 'Fix what c stands for: change.'
13
+ ft: python
14
+ start: |-
15
+ keys = {"c": "▮copy"}
16
+ target: |-
17
+ keys = {"c": "change"}
18
+ solution: 'ciwchange<Esc>'
19
+ hint: 'ciw or ci" both work.'
20
+ variants:
21
+ - goal: 'Fix what y stands for: yank.'
22
+ start: |-
23
+ keys = {"y": "▮yell"}
24
+ target: |-
25
+ keys = {"y": "yank"}
26
+ solution: 'ciwyank<Esc>'
27
+ - goal: 'Fix what d stands for: delete.'
28
+ start: |-
29
+ keys = {"d": "▮duplicate"}
30
+ target: |-
31
+ keys = {"d": "delete"}
32
+ solution: 'ciwdelete<Esc>'
33
+ - goal: 'Fix what p stands for: put.'
34
+ start: |-
35
+ keys = {"p": "▮paste"}
36
+ target: |-
37
+ keys = {"p": "put"}
38
+ solution: 'ciwput<Esc>'
39
+ - goal: 'Fix what t stands for: till.'
40
+ start: |-
41
+ keys = {"t": "▮to"}
42
+ target: |-
43
+ keys = {"t": "till"}
44
+ solution: 'ciwtill<Esc>'
45
+ - goal: 'Replace all three arguments with space.'
46
+ ft: python
47
+ start: |-
48
+ remember(▮cram, cram, cram)
49
+ target: |-
50
+ remember(space)
51
+ solution: 'ci(space<Esc>'
52
+ hint: 'ci( changes everything inside the parentheses.'
53
+ variants:
54
+ - goal: 'Replace all three arguments with test.'
55
+ start: |-
56
+ learn(▮read, read, read)
57
+ target: |-
58
+ learn(test)
59
+ solution: 'ci(test<Esc>'
60
+ - goal: 'Replace both arguments with retrieve.'
61
+ start: |-
62
+ retain(▮reread, reread)
63
+ target: |-
64
+ retain(retrieve)
65
+ solution: 'ci(retrieve<Esc>'
66
+ - goal: 'Replace all three arguments with later.'
67
+ start: |-
68
+ review(▮now, now, now)
69
+ target: |-
70
+ review(later)
71
+ solution: 'ci(later<Esc>'
72
+ - goal: 'Replace all the arguments with 4.'
73
+ start: |-
74
+ chunks(▮1, 2, 3, 4, 5, 6, 7)
75
+ target: |-
76
+ chunks(4)
77
+ solution: 'ci(4<Esc>'
78
+ - goal: 'Delete the wrong sentence.'
79
+ start: |-
80
+ d deletes. ▮y means yell. c changes.
81
+ target: |-
82
+ d deletes. c changes.
83
+ solution: 'das'
84
+ hint: 'das deletes a sentence and its trailing space.'
85
+ variants:
86
+ - goal: 'Delete the wrong sentence.'
87
+ start: |-
88
+ Testing helps recall. ▮Rereading beats testing. Spacing helps too.
89
+ target: |-
90
+ Testing helps recall. Spacing helps too.
91
+ - start: |-
92
+ y yanks. ▮p means paste. P puts above.
93
+ target: |-
94
+ y yanks. P puts above.
95
+ - start: |-
96
+ Sleep helps memory. ▮Cramming beats spacing. Review tomorrow.
97
+ target: |-
98
+ Sleep helps memory. Review tomorrow.
99
+ - start: |-
100
+ f finds. ▮t means to. F looks back.
101
+ target: |-
102
+ f finds. F looks back.
103
+ - goal: 'Delete the cramming and highlighting imports.'
104
+ ft: python
105
+ start: |-
106
+ import spacing
107
+ ▮import cramming
108
+ import highlighting
109
+ import testing
110
+ target: |-
111
+ import spacing
112
+ import testing
113
+ solution: '2dd'
114
+ hint: 'A count works on dd too.'
115
+ variants:
116
+ - goal: 'Delete the cram and reread imports.'
117
+ start: |-
118
+ import sleep
119
+ ▮import cram
120
+ import reread
121
+ import retrieval
122
+ target: |-
123
+ import sleep
124
+ import retrieval
125
+ - goal: 'Delete the highlight and reread imports.'
126
+ start: |-
127
+ import testing
128
+ ▮import highlight
129
+ import reread
130
+ import spacing
131
+ target: |-
132
+ import testing
133
+ import spacing
134
+ - goal: 'Delete the blocking and massing imports.'
135
+ start: |-
136
+ import interleaving
137
+ ▮import blocking
138
+ import massing
139
+ import sleep
140
+ target: |-
141
+ import interleaving
142
+ import sleep
143
+ - goal: 'Delete the copy and paste imports (Vim says yank and put).'
144
+ start: |-
145
+ import yank
146
+ ▮import copy
147
+ import paste
148
+ import put
149
+ target: |-
150
+ import yank
151
+ import put
152
+ - goal: 'Change the subdomain to www.'
153
+ start: |-
154
+ url = 'https://▮old.vimhelp.org'
155
+ target: |-
156
+ url = 'https://www.vimhelp.org'
157
+ solution: 'ciwwww<Esc>'
158
+ hint: 'A dot ends a word, so ciw only takes "old". ct. works too.'
159
+ variants:
160
+ - goal: 'Change the subdomain to www.'
161
+ start: |-
162
+ url = 'https://▮test.wals.info'
163
+ target: |-
164
+ url = 'https://www.wals.info'
165
+ - start: |-
166
+ url = 'https://▮old.neovim.io'
167
+ target: |-
168
+ url = 'https://www.neovim.io'
169
+ - start: |-
170
+ url = 'https://▮beta.vim.org'
171
+ target: |-
172
+ url = 'https://www.vim.org'
173
+ - start: |-
174
+ url = 'https://▮m.wikipedia.org'
175
+ target: |-
176
+ url = 'https://www.wikipedia.org'
177
+ - goal: 'Indent the body of the function.'
178
+ ft: python
179
+ start: |-
180
+ def shift_right():
181
+ ▮arrow = ">"
182
+ return arrow
183
+ target: |-
184
+ def shift_right():
185
+ arrow = ">"
186
+ return arrow
187
+ solution: '>j'
188
+ hint: '> with a motion indents lines: >j indents this line and the next.'
189
+ variants:
190
+ - goal: 'Indent the body of the function.'
191
+ start: |-
192
+ def review():
193
+ ▮due = tomorrow
194
+ return due
195
+ target: |-
196
+ def review():
197
+ due = tomorrow
198
+ return due
199
+ - start: |-
200
+ def chunk():
201
+ ▮size = 4
202
+ return size
203
+ target: |-
204
+ def chunk():
205
+ size = 4
206
+ return size
207
+ - start: |-
208
+ def put():
209
+ ▮text = yanked
210
+ return text
211
+ target: |-
212
+ def put():
213
+ text = yanked
214
+ return text
215
+ - start: |-
216
+ def sleep():
217
+ ▮memories = stable
218
+ return memories
219
+ target: |-
220
+ def sleep():
221
+ memories = stable
222
+ return memories
@@ -0,0 +1,195 @@
1
+ week: 2
2
+ day: 1
3
+ title: The dot command
4
+ intro: |
5
+ `.` repeats your last change: the whole thing, including the text you
6
+ typed in insert mode. Read it as a full stop that says *again*. Make one
7
+ change carefully, then move and press `.` wherever it should happen again.
8
+ This is the most useful key in Vim.
9
+ keys: ['.', 'A;<Esc>j.', '>>j.', 'dw..']
10
+ tasks:
11
+ - goal: 'Change both "cram" to "space".'
12
+ start: |-
13
+ memory = ▮cram + cram
14
+ target: |-
15
+ memory = space + space
16
+ solution: 'ciwspace<Esc>ww.'
17
+ hint: 'Change the first one with ciw, jump to the second with w w, then press .'
18
+ variants:
19
+ - goal: 'Change both "reread" to "test".'
20
+ start: |-
21
+ recall = ▮reread * reread
22
+ target: |-
23
+ recall = test * test
24
+ solution: 'ciwtest<Esc>ww.'
25
+ - goal: 'Change both "reread" to "test".'
26
+ start: |-
27
+ memory = ▮reread + reread
28
+ target: |-
29
+ memory = test + test
30
+ solution: 'ciwtest<Esc>ww.'
31
+ - goal: 'Change both "once" to "again".'
32
+ start: |-
33
+ dot = ▮once + once
34
+ target: |-
35
+ dot = again + again
36
+ solution: 'ciwagain<Esc>ww.'
37
+ - goal: 'Change both "hour" to "day".'
38
+ start: |-
39
+ gap = ▮hour * hour
40
+ target: |-
41
+ gap = day * day
42
+ solution: 'ciwday<Esc>ww.'
43
+ - goal: 'Add a semicolon to every line.'
44
+ start: |-
45
+ ▮let full_stop = "."
46
+ let again = "."
47
+ let repeat = "."
48
+ target: |-
49
+ let full_stop = ".";
50
+ let again = ".";
51
+ let repeat = ".";
52
+ solution: 'A;<Esc>j.j.'
53
+ hint: 'A;<Esc> on the first line, then j . j .'
54
+ variants:
55
+ - goal: 'Add a semicolon to every line.'
56
+ start: |-
57
+ ▮let day1 = review
58
+ let day3 = review
59
+ let day7 = review
60
+ target: |-
61
+ let day1 = review;
62
+ let day3 = review;
63
+ let day7 = review;
64
+ - start: |-
65
+ ▮let say = "once"
66
+ let again = "twice"
67
+ let repeat = "thrice"
68
+ target: |-
69
+ let say = "once";
70
+ let again = "twice";
71
+ let repeat = "thrice";
72
+ - start: |-
73
+ ▮let encode = 1
74
+ let store = 2
75
+ let retrieve = 3
76
+ target: |-
77
+ let encode = 1;
78
+ let store = 2;
79
+ let retrieve = 3;
80
+ - start: |-
81
+ ▮let chunk_a = 4
82
+ let chunk_b = 4
83
+ let chunk_c = 4
84
+ target: |-
85
+ let chunk_a = 4;
86
+ let chunk_b = 4;
87
+ let chunk_c = 4;
88
+ - goal: 'Indent both lines.'
89
+ start: |-
90
+ ▮the dot says
91
+ it again
92
+ target: |2-
93
+ the dot says
94
+ it again
95
+ solution: '>>j.'
96
+ hint: '>> indents one line; . repeats it on the next.'
97
+ variants:
98
+ - goal: 'Indent both lines.'
99
+ start: |-
100
+ ▮encode
101
+ retrieve
102
+ target: |2-
103
+ encode
104
+ retrieve
105
+ - start: |-
106
+ ▮repeat
107
+ the change
108
+ target: |-
109
+ ␣ repeat
110
+ the change
111
+ - start: |-
112
+ ▮cognitive
113
+ associative
114
+ target: |-
115
+ ␣ cognitive
116
+ associative
117
+ - start: |-
118
+ ▮space it
119
+ test it
120
+ target: |-
121
+ ␣ space it
122
+ test it
123
+ - goal: 'Delete all three "again".'
124
+ start: |-
125
+ The dot ▮again again again repeats the last change.
126
+ target: |-
127
+ The dot repeats the last change.
128
+ solution: 'dw..'
129
+ hint: 'dw once, then . twice. (3dw is just as short.)'
130
+ variants:
131
+ - goal: 'Delete all three "cram".'
132
+ start: |-
133
+ Massed ▮cram cram cram practice fades fast.
134
+ target: |-
135
+ Massed practice fades fast.
136
+ - goal: 'Delete all three extra "soon".'
137
+ start: |-
138
+ Spaced reviews ▮soon soon soon beat one long cram.
139
+ target: |-
140
+ Spaced reviews beat one long cram.
141
+ - goal: 'Delete the three extra "page".'
142
+ start: |-
143
+ Rereading the page ▮page page page feels fluent.
144
+ target: |-
145
+ Rereading the page feels fluent.
146
+ - goal: 'Delete all three "dot".'
147
+ start: |-
148
+ The . key ▮dot dot dot repeats your last change.
149
+ target: |-
150
+ The . key repeats your last change.
151
+ - goal: 'Turn the lines into a list with "- ".'
152
+ start: |-
153
+ ▮make one change
154
+ move
155
+ press the dot
156
+ target: |-
157
+ - make one change
158
+ - move
159
+ - press the dot
160
+ solution: 'I- <Esc>j.j.'
161
+ hint: 'I- <Esc> once, then j . j .'
162
+ variants:
163
+ - goal: 'Turn the lines into a list with "- ".'
164
+ start: |-
165
+ ▮test yourself
166
+ space it out
167
+ sleep on it
168
+ target: |-
169
+ - test yourself
170
+ - space it out
171
+ - sleep on it
172
+ - start: |-
173
+ ▮encode
174
+ store
175
+ retrieve
176
+ target: |-
177
+ - encode
178
+ - store
179
+ - retrieve
180
+ - start: |-
181
+ ▮I inserts at the start
182
+ j moves down
183
+ the dot repeats
184
+ target: |-
185
+ - I inserts at the start
186
+ - j moves down
187
+ - the dot repeats
188
+ - start: |-
189
+ ▮cognitive
190
+ associative
191
+ autonomous
192
+ target: |-
193
+ - cognitive
194
+ - associative
195
+ - autonomous
@@ -0,0 +1,194 @@
1
+ week: 2
2
+ day: 2
3
+ title: Searching as a motion
4
+ intro: |
5
+ `/text<Enter>` jumps to the next match (the slash leans forward),
6
+ `?text<Enter>` to the previous one (a question asks back). `n` repeats it,
7
+ `N` the other way. `*` stars the word under the cursor and looks for it
8
+ everywhere. A search is a motion, so `d/STOP<Enter>` deletes up to the
9
+ match. In your setup a lowercase search ignores case and an uppercase
10
+ letter makes it exact (smartcase).
11
+ keys: [/, "?", n, N, "*", d/]
12
+ tasks:
13
+ - goal: 'Change "backwards" to "ahead".'
14
+ start: |-
15
+ ▮The slash leans forward,
16
+ so it searches backwards
17
+ target: |-
18
+ The slash leans forward,
19
+ so it searches ahead
20
+ solution: '/b<CR>cwahead<Esc>'
21
+ hint: 'Search for as little as you need. /b<Enter> lands on backwards already.'
22
+ variants:
23
+ - goal: 'Change "slowly" to "fast".'
24
+ start: |-
25
+ ▮Forgetting starts
26
+ slowly, then levels off
27
+ target: |-
28
+ Forgetting starts
29
+ fast, then levels off
30
+ solution: '/sl<CR>cwfast<Esc>'
31
+ hint: 'Search for as little as you need. /sl<Enter> lands on slowly already.'
32
+ - goal: 'Change "back" to "forward".'
33
+ start: |-
34
+ ▮Searching forward,
35
+ the slash leans back
36
+ target: |-
37
+ Searching forward,
38
+ the slash leans forward
39
+ solution: '/b<CR>cwforward<Esc>'
40
+ - goal: 'Change "faster" to "slower".'
41
+ start: |-
42
+ ▮Spaced practice
43
+ fades faster than massed
44
+ target: |-
45
+ Spaced practice
46
+ fades slower than massed
47
+ solution: '/fas<CR>cwslower<Esc>'
48
+ - goal: 'Change "guess" to "match".'
49
+ start: |-
50
+ ▮Search is a motion:
51
+ d/ deletes up to a guess
52
+ target: |-
53
+ Search is a motion:
54
+ d/ deletes up to a match
55
+ solution: '/g<CR>cwmatch<Esc>'
56
+ - goal: 'Delete the hedging before "Search".'
57
+ start: |-
58
+ ▮er, like, honestly, Search is a motion
59
+ target: |-
60
+ Search is a motion
61
+ solution: 'd/S<CR>'
62
+ hint: 'd/S<Enter> deletes up to the next S (uppercase, so the search is exact).'
63
+ variants:
64
+ - goal: 'Delete the hedging before "Testing".'
65
+ start: |-
66
+ ▮um, well, you know, Testing beats rereading
67
+ target: |-
68
+ Testing beats rereading
69
+ solution: 'd/T<CR>'
70
+ hint: 'd/T<Enter> deletes up to the next T (uppercase, so the search is exact).'
71
+ - goal: 'Delete the hedging before "Slash".'
72
+ start: |-
73
+ ▮so, basically, Slash leans forward
74
+ target: |-
75
+ Slash leans forward
76
+ solution: 'd/S<CR>'
77
+ - goal: 'Delete the hedging before "Spacing".'
78
+ start: |-
79
+ ▮well, sort of, Spacing beats cramming
80
+ target: |-
81
+ Spacing beats cramming
82
+ solution: 'd/S<CR>'
83
+ - goal: 'Delete the hedging before "Retrieval".'
84
+ start: |-
85
+ ▮well, anyway, Retrieval builds memory
86
+ target: |-
87
+ Retrieval builds memory
88
+ solution: 'd/R<CR>'
89
+ - goal: 'Rename the second "starred" to found.'
90
+ ft: python
91
+ start: |-
92
+ ▮starred = "this word"
93
+ next_one = starred
94
+ target: |-
95
+ starred = "this word"
96
+ next_one = found
97
+ solution: '*ciwfound<Esc>'
98
+ hint: '* stars the word under the cursor and jumps to its next match.'
99
+ variants:
100
+ - goal: 'Rename the second whole word "interval" to n.'
101
+ start: |-
102
+ ▮interval = 1
103
+ interval_days = interval * 2
104
+ target: |-
105
+ interval = 1
106
+ interval_days = n * 2
107
+ solution: '*ciwn<Esc>'
108
+ hint: '* only matches whole words, so it skips interval_days.'
109
+ - goal: 'Rename the second whole word "star" to match.'
110
+ start: |-
111
+ ▮star = "*"
112
+ found = star
113
+ target: |-
114
+ star = "*"
115
+ found = match
116
+ solution: '*ciwmatch<Esc>'
117
+ - goal: 'Rename the second whole word "chunk" to n.'
118
+ start: |-
119
+ ▮chunk = 4
120
+ chunk_count = chunk + 1
121
+ target: |-
122
+ chunk = 4
123
+ chunk_count = n + 1
124
+ solution: '*ciwn<Esc>'
125
+ - goal: 'Rename the second whole word "gap" to days.'
126
+ start: |-
127
+ ▮gap = 7
128
+ next_review = today + gap
129
+ target: |-
130
+ gap = 7
131
+ next_review = today + days
132
+ solution: '*ciwdays<Esc>'
133
+ - goal: 'Delete the third "next".'
134
+ start: |-
135
+ n means ▮next, and N means the next next one back.
136
+ target: |-
137
+ n means next, and N means the next one back.
138
+ solution: '*ndaw'
139
+ hint: '* goes to the second next, n to the third, daw deletes it.'
140
+ variants:
141
+ - goal: 'Delete the third "yourself".'
142
+ start: |-
143
+ Test ▮yourself, then space it, then test yourself yourself again.
144
+ target: |-
145
+ Test yourself, then space it, then test yourself again.
146
+ hint: '* goes to the second yourself, n to the third, daw deletes it.'
147
+ - goal: 'Delete the third "star".'
148
+ start: |-
149
+ The ▮star finds the next star, then the star star after.
150
+ target: |-
151
+ The star finds the next star, then the star after.
152
+ - goal: 'Delete the third "it".'
153
+ start: |-
154
+ Space ▮it out, test it, then test it it again.
155
+ target: |-
156
+ Space it out, test it, then test it again.
157
+ - goal: 'Delete the third "back".'
158
+ start: |-
159
+ N goes ▮back, n goes on, so go back back once.
160
+ target: |-
161
+ N goes back, n goes on, so go back once.
162
+ - goal: 'Change the last "forward" to "backward", searching backwards.'
163
+ start: |-
164
+ / leans forward and searches forward; ? asks forward, from the en▮d.
165
+ target: |-
166
+ / leans forward and searches forward; ? asks backward, from the end.
167
+ solution: '?fo<CR>cwbackward<Esc>'
168
+ hint: '?fo<Enter> asks backwards from the cursor.'
169
+ variants:
170
+ - goal: 'Change the last "restudy" to "testing", searching backwards.'
171
+ start: |-
172
+ Restudy wins after five minutes; restudy wins after a we▮ek.
173
+ target: |-
174
+ Restudy wins after five minutes; testing wins after a week.
175
+ solution: '?res<CR>cwtesting<Esc>'
176
+ hint: '?res<Enter> searches backwards for the start of restudy.'
177
+ - goal: 'Change the last "forward" to "backward", searching backwards.'
178
+ start: |-
179
+ ? asks backward; / leans forward; ? looks forward from the en▮d.
180
+ target: |-
181
+ ? asks backward; / leans forward; ? looks backward from the end.
182
+ solution: '?fo<CR>cwbackward<Esc>'
183
+ - goal: 'Change the last "seven" to "four", searching backwards.'
184
+ start: |-
185
+ Miller said seven; Cowan said seven▮.
186
+ target: |-
187
+ Miller said seven; Cowan said four.
188
+ solution: '?se<CR>cwfour<Esc>'
189
+ - goal: 'Change the last "wins" to "loses", searching backwards.'
190
+ start: |-
191
+ Cramming wins at first; cramming wins in the lon▮g run.
192
+ target: |-
193
+ Cramming wins at first; cramming loses in the long run.
194
+ solution: '?w<CR>cwloses<Esc>'