git home / emma home
logo

typie

Minimal typing practice tool.
git clone https://git.y1.nz/archives/typie.tar.gz
README | Files | Log | Refs | LICENSE

commit ef7cd656eb53cd9aa1e20ee29f3fe2bd1c2ce7ea
parent c0f2af297b772d0f28580c35254171494d0a3c79
Author: Emma Weaver <emma@waeaves.com>
Date:   Fri,  1 May 2026 11:43:35 -0400

fixed regex bug

Diffstat:
Mexamples/learn.sh4++--
Mexamples/lesson.sh24++++++++++++------------
Mexamples/words.sh32+++++++++++++++-----------------
Mmain.c21+++++++++++++++++++--
Mtyper.c24++++++++++++++++++------
Mtyper.h2++
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;

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.