Skip to content

Commit d688f4a

Browse files
committedOct 26, 2024·
feat: ignore the space key
fixes #218
1 parent 483097d commit d688f4a

File tree

2 files changed

+96
-78
lines changed

2 files changed

+96
-78
lines changed
 

‎packages/keybr-textinput/lib/textinput.test.ts

+90-56
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ test("allow empty text", (t) => {
2626
t.throws(() => {
2727
textInput.appendChar(A, 100);
2828
});
29+
30+
t.throws(() => {
31+
textInput.appendChar(Space, 100);
32+
});
2933
});
3034

3135
test("advance to completion", (t) => {
@@ -177,35 +181,25 @@ test("accumulate and delete garbage", (t) => {
177181
t.false(textInput.completed);
178182
});
179183

180-
test("emoji", (t) => {
181-
const textInput = new TextInput("🍬🍭", {
182-
stopOnError: true,
183-
forgiveErrors: true,
184+
test("limit garbage length", (t) => {
185+
const textInput = new TextInput("abc", {
186+
stopOnError: false,
187+
forgiveErrors: false,
184188
spaceSkipsWords: true,
185189
});
186190

191+
for (let i = 1; i <= 100; i++) {
192+
t.is(textInput.appendChar(X, i * 100), Feedback.Failed);
193+
}
194+
187195
t.is(stepsString(textInput.steps), "");
188-
t.is(charsString(textInput.chars), "[🍬]|🍭");
189-
t.is(textInput.length, 2);
196+
t.is(charsString(textInput.chars), "*x|*x|*x|*x|*x|*x|*x|*x|*x|*x|[a]|b|c");
197+
t.is(textInput.length, 3);
190198
t.is(textInput.pos, 0);
191199
t.false(textInput.completed);
192-
193-
t.is(textInput.appendChar(0x1f36c, 100), Feedback.Succeeded);
194-
t.is(stepsString(textInput.steps), "🍬,100");
195-
t.is(charsString(textInput.chars), "🍬|[🍭]");
196-
t.is(textInput.length, 2);
197-
t.is(textInput.pos, 1);
198-
t.false(textInput.completed);
199-
200-
t.is(textInput.appendChar(0x1f36d, 200), Feedback.Succeeded);
201-
t.is(stepsString(textInput.steps), "🍬,100|🍭,200");
202-
t.is(charsString(textInput.chars), "🍬|🍭");
203-
t.is(textInput.length, 2);
204-
t.is(textInput.pos, 2);
205-
t.true(textInput.completed);
206200
});
207201

208-
test("handle backspace at the start of text", (t) => {
202+
test("handle backspace at the start of a word", (t) => {
209203
const textInput = new TextInput("abc", {
210204
stopOnError: false,
211205
forgiveErrors: false,
@@ -249,7 +243,7 @@ test("handle backspace at the start of text", (t) => {
249243
t.false(textInput.completed);
250244
});
251245

252-
test("handle backspace in the middle of text", (t) => {
246+
test("handle backspace in the middle of a word", (t) => {
253247
const textInput = new TextInput("abc", {
254248
stopOnError: false,
255249
forgiveErrors: false,
@@ -302,24 +296,6 @@ test("handle backspace in the middle of text", (t) => {
302296
t.false(textInput.completed);
303297
});
304298

305-
test("limit garbage length", (t) => {
306-
const textInput = new TextInput("abc", {
307-
stopOnError: false,
308-
forgiveErrors: false,
309-
spaceSkipsWords: true,
310-
});
311-
312-
for (let i = 1; i <= 100; i++) {
313-
t.is(textInput.appendChar(X, i * 100), Feedback.Failed);
314-
}
315-
316-
t.is(stepsString(textInput.steps), "");
317-
t.is(charsString(textInput.chars), "*x|*x|*x|*x|*x|*x|*x|*x|*x|*x|[a]|b|c");
318-
t.is(textInput.length, 3);
319-
t.is(textInput.pos, 0);
320-
t.false(textInput.completed);
321-
});
322-
323299
test("forgive an inserted character", (t) => {
324300
const textInput = new TextInput("abc", {
325301
stopOnError: true,
@@ -465,16 +441,39 @@ test("recover from a forgiven error", (t) => {
465441
t.true(textInput.completed);
466442
});
467443

468-
test("ignore whitespace keys at the start of text", (t) => {
444+
test("ignore the whitespace key", (t) => {
469445
const textInput = new TextInput("text", {
470446
stopOnError: true,
471-
forgiveErrors: false,
472-
spaceSkipsWords: true,
447+
forgiveErrors: true,
448+
spaceSkipsWords: false,
473449
});
474450

475451
t.is(textInput.appendChar(Space, 100), Feedback.Succeeded);
476452
t.is(stepsString(textInput.steps), "");
477453
t.is(charsString(textInput.chars), "[t]|e|x|t");
454+
t.is(textInput.length, 4);
455+
t.is(textInput.pos, 0);
456+
t.false(textInput.completed);
457+
458+
t.is(textInput.appendChar(T, 200), Feedback.Succeeded);
459+
t.is(stepsString(textInput.steps), "t,200");
460+
t.is(charsString(textInput.chars), "t|[e]|x|t");
461+
t.is(textInput.length, 4);
462+
t.is(textInput.pos, 1);
463+
t.false(textInput.completed);
464+
465+
t.is(textInput.appendChar(Space, 300), Feedback.Succeeded);
466+
t.is(stepsString(textInput.steps), "t,200");
467+
t.is(charsString(textInput.chars), "t|[e]|x|t");
468+
t.is(textInput.length, 4);
469+
t.is(textInput.pos, 1);
470+
t.false(textInput.completed);
471+
472+
t.is(textInput.appendChar(E, 400), Feedback.Succeeded);
473+
t.is(stepsString(textInput.steps), "t,200|e,400");
474+
t.is(charsString(textInput.chars), "t|e|[x]|t");
475+
t.is(textInput.length, 4);
476+
t.is(textInput.pos, 2);
478477
t.false(textInput.completed);
479478
});
480479

@@ -485,26 +484,33 @@ test("space in garbage", (t) => {
485484
spaceSkipsWords: false,
486485
});
487486

488-
t.is(textInput.appendChar(A, 100), Feedback.Succeeded);
487+
t.is(textInput.appendChar(X, 100), Feedback.Failed);
489488
t.is(textInput.appendChar(Space, 200), Feedback.Failed);
490-
t.is(stepsString(textInput.steps), "a,100");
491-
t.is(charsString(textInput.chars), "a|* |[b]|c");
489+
t.is(stepsString(textInput.steps), "");
490+
t.is(charsString(textInput.chars), "*x|* |[a]|b|c");
492491
t.is(textInput.length, 3);
493-
t.is(textInput.pos, 1);
492+
t.is(textInput.pos, 0);
494493
t.false(textInput.completed);
495494

496495
t.is(textInput.clearChar(), Feedback.Succeeded);
497-
t.is(stepsString(textInput.steps), "a,100");
498-
t.is(charsString(textInput.chars), "a|[b]|c");
496+
t.is(stepsString(textInput.steps), "");
497+
t.is(charsString(textInput.chars), "*x|[a]|b|c");
499498
t.is(textInput.length, 3);
500-
t.is(textInput.pos, 1);
499+
t.is(textInput.pos, 0);
501500
t.false(textInput.completed);
502501

503-
t.is(textInput.appendChar(B, 400), Feedback.Recovered);
504-
t.is(stepsString(textInput.steps), "a,100|!b,400");
505-
t.is(charsString(textInput.chars), "a|!b|[c]");
502+
t.is(textInput.clearChar(), Feedback.Succeeded);
503+
t.is(stepsString(textInput.steps), "");
504+
t.is(charsString(textInput.chars), "[a]|b|c");
506505
t.is(textInput.length, 3);
507-
t.is(textInput.pos, 2);
506+
t.is(textInput.pos, 0);
507+
t.false(textInput.completed);
508+
509+
t.is(textInput.appendChar(A, 500), Feedback.Recovered);
510+
t.is(stepsString(textInput.steps), "!a,500");
511+
t.is(charsString(textInput.chars), "!a|[b]|c");
512+
t.is(textInput.length, 3);
513+
t.is(textInput.pos, 1);
508514
t.false(textInput.completed);
509515
});
510516

@@ -534,7 +540,7 @@ test("space skips words at the beginning of a word, ignore space", (t) => {
534540
t.is(charsString(textInput.chars), "x| |[a]|b|c");
535541
t.false(textInput.completed);
536542

537-
t.is(textInput.appendChar(Space, 300), Feedback.Failed);
543+
t.is(textInput.appendChar(Space, 300), Feedback.Succeeded);
538544
t.is(stepsString(textInput.steps), "x,100| ,200");
539545
t.is(charsString(textInput.chars), "x| |[a]|b|c");
540546
t.false(textInput.completed);
@@ -648,7 +654,7 @@ test("normalize characters", (t) => {
648654
t.true(textInput.completed);
649655
});
650656

651-
test("handle whitespace", (t) => {
657+
test("whitespace", (t) => {
652658
const textInput = new TextInput("a ", {
653659
stopOnError: true,
654660
forgiveErrors: false,
@@ -663,6 +669,34 @@ test("handle whitespace", (t) => {
663669
t.true(textInput.completed);
664670
});
665671

672+
test("emoji", (t) => {
673+
const textInput = new TextInput("🍬🍭", {
674+
stopOnError: true,
675+
forgiveErrors: true,
676+
spaceSkipsWords: true,
677+
});
678+
679+
t.is(stepsString(textInput.steps), "");
680+
t.is(charsString(textInput.chars), "[🍬]|🍭");
681+
t.is(textInput.length, 2);
682+
t.is(textInput.pos, 0);
683+
t.false(textInput.completed);
684+
685+
t.is(textInput.appendChar(0x1f36c, 100), Feedback.Succeeded);
686+
t.is(stepsString(textInput.steps), "🍬,100");
687+
t.is(charsString(textInput.chars), "🍬|[🍭]");
688+
t.is(textInput.length, 2);
689+
t.is(textInput.pos, 1);
690+
t.false(textInput.completed);
691+
692+
t.is(textInput.appendChar(0x1f36d, 200), Feedback.Succeeded);
693+
t.is(stepsString(textInput.steps), "🍬,100|🍭,200");
694+
t.is(charsString(textInput.chars), "🍬|🍭");
695+
t.is(textInput.length, 2);
696+
t.is(textInput.pos, 2);
697+
t.true(textInput.completed);
698+
});
699+
666700
function stepsString(steps: readonly Step[]): string {
667701
return steps
668702
.map(({ codePoint, timeStamp, typo }) => {

‎packages/keybr-textinput/lib/textinput.ts

+6-22
Original file line numberDiff line numberDiff line change
@@ -149,38 +149,23 @@ export class TextInput {
149149

150150
#appendChar(codePoint: CodePoint, timeStamp: number): Feedback {
151151
if (this.completed) {
152-
// Cannot enter any more characters if already completed.
153152
throw new Error();
154153
}
155154

156-
// Handle whitespace at the beginning of text.
157-
if (
158-
this.pos === 0 &&
159-
this.#garbage.length === 0 &&
160-
!this.#typo &&
161-
codePoint === 0x0020
162-
) {
163-
return Feedback.Succeeded;
164-
}
165-
166-
// Handle the space key.
167155
if (this.at(this.pos).codePoint !== 0x0020 && codePoint === 0x0020) {
168156
if (
169-
this.#garbage.length === 0 &&
170-
(this.pos === 0 || this.at(this.pos - 1).codePoint === 0x0020)
157+
this.spaceSkipsWords &&
158+
((this.pos > 0 && this.at(this.pos - 1).codePoint !== 0x0020) ||
159+
this.#typo)
171160
) {
172-
// At the beginning of a word.
173-
this.#typo = true;
174-
return Feedback.Failed;
175-
}
176-
if (this.spaceSkipsWords) {
177-
// Inside a word.
178161
this.#skipWord(timeStamp);
179162
return Feedback.Recovered;
180163
}
164+
if (this.#garbage.length === 0 && !this.#typo) {
165+
return Feedback.Succeeded;
166+
}
181167
}
182168

183-
// Handle correct input.
184169
if (
185170
filterText.normalize(this.at(this.pos).codePoint) === codePoint &&
186171
(this.forgiveErrors || this.#garbage.length === 0)
@@ -196,7 +181,6 @@ export class TextInput {
196181
}
197182
}
198183

199-
// Handle incorrect input.
200184
this.#typo = true;
201185
if (!this.stopOnError || this.forgiveErrors) {
202186
if (this.#garbage.length < garbageBufferLength) {

0 commit comments

Comments
 (0)
Please sign in to comment.