commit ef7cd656eb53cd9aa1e20ee29f3fe2bd1c2ce7ea
parent c0f2af297b772d0f28580c35254171494d0a3c79
Author: Emma Weaver <emma@waeaves.com>
Date: Fri, 1 May 2026 11:43:35 -0400
fixed regex bug
Diffstat:
6 files changed, 68 insertions(+), 39 deletions(-)
diff --git a/examples/learn.sh b/examples/learn.sh
@@ -13,8 +13,8 @@ on
as
id
pg
-kb
-jm
+km
+jb
qw
yf
cr
diff --git a/examples/lesson.sh b/examples/lesson.sh
@@ -24,21 +24,21 @@ echo "If it gets too hard, don't be afraid to ctrl+C and redo previous lessons."
echo ""
echo "Introducing the new letters..."
-typie -l "$(./words.sh "$NEW_LETTERS" 5 10)"
-typie -l "$(./words.sh "$NEW_LETTERS" 5 10)"
+typie -l "$(./words.sh "$NEW_LETTERS" 6 12)"
+typie -l "$(./words.sh "$NEW_LETTERS" 6 12)"
echo "Integrating with some old letters..."
-typie "$(./words.sh "$(old_letters $EASY)$NEW_LETTERS" 5 10)"
-typie "$(./words.sh "$(old_letters $EASY)$NEW_LETTERS" 5 10)"
-typie "$(./words.sh "$(old_letters $EASY)$NEW_LETTERS" 5 10)"
-typie "$(./words.sh "$(old_letters $MEDIUM)$NEW_LETTERS" 5 10)"
-typie "$(./words.sh "$(old_letters $MEDIUM)$NEW_LETTERS" 5 10)"
-typie "$(./words.sh "$(old_letters $HARD)$NEW_LETTERS" 5 10)"
-typie "$(./words.sh "$(old_letters $HARD)$NEW_LETTERS" 5 10)"
+typie "$(./words.sh "$(old_letters $EASY)$NEW_LETTERS" 5 8)"
+typie "$(./words.sh "$(old_letters $EASY)$NEW_LETTERS" 5 8)"
+typie "$(./words.sh "$(old_letters $EASY)$NEW_LETTERS" 5 8)"
+typie "$(./words.sh "$(old_letters $MEDIUM)$NEW_LETTERS" 5 8)"
+typie "$(./words.sh "$(old_letters $MEDIUM)$NEW_LETTERS" 5 8)"
+typie "$(./words.sh "$(old_letters $HARD)$NEW_LETTERS" 5 8)"
+typie "$(./words.sh "$(old_letters $HARD)$NEW_LETTERS" 5 8)"
echo "All together now!"
-typie "$(./words.sh "$OLD_LETTERS$NEW_LETTERS" 5 10)"
-typie "$(./words.sh "$OLD_LETTERS$NEW_LETTERS" 5 10)"
-typie "$(./words.sh "$OLD_LETTERS$NEW_LETTERS" 5 10)"
+typie "$(./words.sh "$OLD_LETTERS$NEW_LETTERS" 5 8)"
+typie "$(./words.sh "$OLD_LETTERS$NEW_LETTERS" 5 8)"
+typie "$(./words.sh "$OLD_LETTERS$NEW_LETTERS" 5 8)"
echo "All done! :3"
diff --git a/examples/words.sh b/examples/words.sh
@@ -4,34 +4,32 @@ MIN_LENGTH=$2
MAX_LENGTH=$3
DICTFILE="dicts/20k.txt"
-if [ $CHARSET = "" ];then
+if [ $CHARSET = "" ]; then
echo "Requires charset argument."
exit 1
fi
-# filter the dictionary for words only involving the characters, len >= 4.
-WORDS="$(cat $DICTFILE | grep -x "[$CHARSET]*" | grep -x ".{5,}")"
+# filter the dictionary for words only involving the characters, len >= 5.
+WORDS="$(cat $DICTFILE | egrep "^[$CHARSET]{5,}$")"
+LENGTH="$(seq $MIN_LENGTH $MAX_LENGTH | shuf -n 1)"
WORD_COUNT="$(echo "$WORDS" | wc -l)"
FEW_WORDS="false"
-if [ "$WORD_COUNT" -lt "10" ]; then
+if [ "$WORD_COUNT" -lt "$LENGTH" ]; then
FEW_WORDS="true"
fi
get_word() {
- if [ "$(seq 3 | shuf -n 1)" = "1" ] || [ $FEW_WORDS = "true" ]; then
- ./letters.sh "$CHARSET" 4 6
- else
- echo "$WORDS" | shuf -n 1
- fi
+ ./letters.sh "$CHARSET" 4 6
}
-PROMPT="$(get_word)"
-
-LENGTH="$(seq $MIN_LENGTH $MAX_LENGTH | shuf -n 1)"
-for i in $(seq $LENGTH); do
- PROMPT="$PROMPT $(get_word)"
-done
-
-echo "$PROMPT"
+if [ $FEW_WORDS = "true" ]; then
+ PROMPT="$(get_word)"
+ for i in $(seq $LENGTH); do
+ PROMPT="$PROMPT $(get_word)"
+ done
+ echo "$PROMPT"
+else
+ echo "$WORDS" | shuf -n $LENGTH | tr '\n' ' '
+fi
diff --git a/main.c b/main.c
@@ -40,14 +40,15 @@ type(State * state)
case KEYPRESS_CORRECT: /* FALLTHROUGH */
state->chars_correct++;
+ if (state->prompt[state->index] == '\0')
+ return 0;
case KEYPRESS_INCORRECT:
state->chars_total++;
if (!started) {
started = TRUE;
state->start_millis = time(NULL);
+ fflush(stdout);
}
- if (state->prompt[state->index] == '\0')
- return 0;
break;
case KEYPRESS_ENTER:
@@ -56,6 +57,9 @@ type(State * state)
case KEYPRESS_BACKSPACE:
break;
+
+ case KEYPRESS_NONE:
+ break;
}
}
}
@@ -93,6 +97,18 @@ write_output(State state)
}
int
+get_length(const char * string)
+{
+ int index = 0;
+ for (;;) {
+ if (string[index] == '\0')
+ break;
+ index++;
+ }
+ return index;
+}
+
+int
main(int argc, const char * argv[])
{
struct termios termios_original;
@@ -109,6 +125,7 @@ main(int argc, const char * argv[])
exit(1);
}
state.prompt = argv[argc-1];
+ state.prompt_length = get_length(state.prompt);
tcgetattr(0, &termios_original);
setup_termios(termios_original);
diff --git a/typer.c b/typer.c
@@ -84,6 +84,10 @@ show_remaining(State * state)
char c;
printf(COLOR_RESET "\033[0K"); /* clear to end of line */
+
+ if (prompt[index] == '\0')
+ return;
+
for (;;) {
c = prompt[index];
if (c == '\0' || c == '\n')
@@ -114,9 +118,11 @@ skip(State * state, char input)
steps++;
state->index++;
}
- printf("%c", input);
- steps++;
- state->index++;
+ if (c != '\0') {
+ printf("%c", input);
+ steps++;
+ state->index++;
+ }
add_jump(state, steps);
}
@@ -146,6 +152,12 @@ on_incorrect(State * state, char c)
return;
}
+ if (expected_c == '\0') {
+ print_char(c);
+ add_jump(state, 0);
+ return;
+ }
+
if (
(input_blank && prompt_blank) ||
(!input_blank && !prompt_blank)
@@ -201,7 +213,6 @@ on_backspace(State * state)
int
on_enter(State * state)
{
- printf("\n\r" COLOR_RESET);
return KEYPRESS_ENTER;
}
@@ -217,6 +228,7 @@ int
handle_keypress(State * state)
{
char c = getchar();
+ char expected = state->prompt[state->index];
if (c == KEY_CTRL_C || c == KEY_CTRL_D || c == KEY_ESCAPE)
return KEYPRESS_EXIT;
@@ -228,8 +240,8 @@ handle_keypress(State * state)
on_backspace(state);
return KEYPRESS_BACKSPACE;
}
-
- if (c == state->prompt[state->index]) {
+
+ if (c == expected) {
on_correct(state, c);
return KEYPRESS_CORRECT;
}
diff --git a/typer.h b/typer.h
@@ -30,6 +30,7 @@
#define KEYPRESS_BACKSPACE 2
#define KEYPRESS_EXIT 3
#define KEYPRESS_ENTER 4
+#define KEYPRESS_NONE 5
typedef struct {
int * buffer;
@@ -39,6 +40,7 @@ typedef struct {
typedef struct {
/* the string being typed */
const char * prompt;
+ int prompt_length;
/* records how many characters are traversed by each keypress */
Jumps jumps;