Git Product home page Git Product logo

toipe's Introduction

toipe

A trusty terminal typing tester.

Crates.io badge Lints and checks badge docs.rs badge

Usage

Install

From GitHub

Go to the latest release, scroll down to "Assets" and download the correct file for your platform (.zip in case of Mac OS, .tar.gz in case of Linux). Unzip the file and run the toipe binary inside.

From Cargo

Alternatively, if you have the cargo tool (part of the Rust toolchain) installed on your system, you can use:

cargo install toipe

Run typing test

toipe looks best on a nice terminal (such as Alacritty) with color and style support.

If installed through GitHub, run the binary (found inside the zip/tar.gz file after extracting) directly:

./toipe

If installed through cargo, use:

toipe

Keyboard shortcuts

See toipe --help for a list of keyboard shortcuts (the list can also be found here).

Show less or more text

To change the number of words shown in each test, use the -n flag (default: 30):

toipe -n 10
toipe -n 100

Use a different word list

By default, a list of top 250 English words (top250) is used and random words are selected from it. See toipe -h for a list of available built-in word lists.

To use the OS provided word list instead, use:

toipe -w os

Note: the OS word list varies a lot from system to system and usually has more than 100,000 words. This can lead to difficult and esoteric words appearing in the test, reducing your typing speed.

You can provide your own word list too (Note: the word list must meet these assumptions):

toipe -f /path/to/word/list

Add punctuation to test

By default, only lowercase words are shown. To add punctuation and sentence case, use the -p flag:

toipe -p

Platform support

  • toipe was only tested on Linux and Mac OS. If you find any problems, please open an issue.
  • Windows is not supported yet. Follow this issue for updates. It should work on WSL though.

License

MIT

toipe's People

Contributors

b0ney avatar benliepert avatar deepsourcebot avatar gabevenberg avatar idevtier avatar istudyatuni avatar nate-sys avatar notjedi avatar property404 avatar samyak2 avatar u32int avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

toipe's Issues

Extra space at the end of certain tests

What?

Some tests automatically end as soon as you enter the last character but some others will require you to press space following the last word in order to end.

Context

This case was explicitly handled here:

toipe/src/tui.rs

Lines 407 to 411 in 063fc4f

// last line wasn't added in loop
// last line doesn't have an extra space at the end
// - the typing test stops as soon as the user types last char
// - won't hang there waiting for user to type space
lines.push(Text::from(line.join(" ")).with_faint());

I'm not sure why it still causes an issue.

Originally reported by user "Merulox" in a YouTube comment (I did not find a way to link to a comment directly).

Support non-english text

What and why?

Currently, the word selection algorithm in toipe only supports English ASCII characters. Any other characters (including ASCII special characters will be ignored).

This is not good because the world doesn't only write in English :). Especially for a typing test app which can be used to measure and improve speeds in other languages too.

Once this is implemented, it would also be good to have built-in word lists for more languages (maybe even auto-detect the user's locale and change word list based on it?)

How?

The changes need to be done in RawWordSelector (source code).

  • Currently, it uses raw bytes (b'a', b'z', etc.) to compare and store characters. This needs to be changed to use the char type.
  • It tracks starting positions of each character in a fixed length array of 26 characters. This needs to be made more general.
  • Use unicode lowercase instead of ASCII -
    let line = buffer.to_ascii_lowercase();
  • Do not use is_ascii_alphabetic here -
    while word.len() < 2 || word.len() > 8 || !word.chars().all(|c| c.is_ascii_alphabetic()) {

This may require some more changes that I'm not yet aware of.

Please drop a comment if you find any inconsistencies or problems with this idea :)

Add support for punctuation

Monkeytyper has a mode that adds randomized punctuation to words in a test, such as a period/comma/colon/semicolon at the end of a word (periods making the next word capitalized), a dash between words, or surrounding the word with a delimiter, such as parentheses or quotes.

Would be nice to emulate this, to simulate english prose with all its punctuation without resorting to full book exerpts.

Make toipe installable through various packages managers

What and why?

Currently, toipe has to be installed either by downloading the binary directly from the releases or using cargo. It would be nice to have it installable through built-in package managers.

How?

Some package managers that I want to target (having no idea how to do so or how involved these processes are):

  • Nix
  • AUR
  • Fedora's core repo (to make it install through dnf)
    • Maybe OpenSUSE too
  • Debian
  • Flatpak (does this make sense for a CLI app?)
  • Homebrew

[enhancement] Resetting the cursor

After exiting toipe, the cursor will change into cursor::SteadyBlock and I find myself having to run reset in my terminal. It would be nice if the cursor could return to its original state after exiting toipe.

ctrl+h to backspace

Can you add ctrl+h to backspace? I use ctrl+h to backspace on my terminal and in my terminal based editors. Thanks.

Show error if terminal size is too small

What and why?

If the terminal size is too small, the lines (of words) overlap with each other and the cursor starts at the last line.

It would be nice to show an error and ask the user to maximize their window (or increase the size) to use toipe.

How?

termion provides terminal_size to detect the size of the terminal. The difficulty arises in selecting a good threshold for the minimum size. It can be calculated based on the config (number of words) on the fly or can be fixed.

Context

Suggestion from reddit: https://www.reddit.com/r/rust/comments/tvamfz/comment/i3giuga/

not working with cusotm words list

I have a txt file 243 word and when i try to open it with topie using the -f flag it shows nothing inside the app (I'm sure about the path and i tried absolute path too)

Only exit on `r` or `q` on the results page

Issue

Toipe exits when you press any key on the results page (though, it will restart if r was pressed). I might instinctively press space or enter after the last letter in the typing test, causing toipe to exit without getting a chance to look at the result.

Solution

Do not go forward from the results page unless one of the known keys - r or q - is pressed.

Refactor UI components to be more modular

What?

Currently, the terminal UI in toipe is rendered by directly writing to stdout with cursor positioning and colors provided by termion.

Example:

toipe/src/lib.rs

Lines 263 to 271 in fae3005

write!(
self.stdout,
"{}{}{}{}{}",
cursor::Goto(sizex / 2, sizey / 2 - 2),
cursor::Left(line.len() as u16 / 2),
color::Fg(color::Blue),
line,
color::Fg(color::Reset),
)?;

This code looks a bit ugly and we need to manually position items by changing the arguments given to cursor::Goto. For example, sizey / 2 - 2 means two lines above the middle line. If I want to add another line to that list and move all of them down, I need to change this part of every line.

The cursor::Left(line.len() as u16 / 2) part positions the text in the center - this snippet is repeated for every line. What's even worse is if the text in that line includes special characters such as colors, this will not work because it will consider those hidden characters too! To get around that, I use this hack:

toipe/src/lib.rs

Lines 285 to 299 in fae3005

let line = format!(
"Speed: {}{:.1} wpm{} (words per minute)",
color::Fg(color::Green),
results.wpm(),
color::Fg(color::Reset)
);
// do not consider length of formatting characters
let zerowidths = format!("{}{}", color::Fg(color::Green), color::Fg(color::Reset));
write!(
self.stdout,
"{}{}{}",
cursor::Goto(sizex / 2, sizey / 2),
cursor::Left((line.len() - zerowidths.len()) as u16 / 2),
line,
)?;

As you can see, I need to repeat the formatting characters again in a separate string containing only them and then subtract their length from line.len() like cursor::Left((line.len() - zerowidths.len()) as u16 / 2).

How to fix?

Honestly, I'm not sure. I opened this issue to force myself to document the problem.

The solution will definitely involve abstracting this UI rendering into a different module. Abstracting the cursor::Gotos is simple - take a vec/iter/slice of strings and change the y-position when printing each one such that they are approximately in the middle. cursor::Left(line.len() as u16 / 2) is easy too, as long as the given string contains single-width characters. I'm not sure how zero-width and other characters can be handled here. Perhaps this problem is solved elsewhere?

I'm always open to suggestions!

Support longer text - more than 10 words

What?

Currently, toipe only gives you 10 words to write. This is because I'm printing all of the text on a single line. This is what happens if I try to print more words!

Toipe in the terminal showing a long line of words filling the whole line and wrapping over to the next

I want to be able to cut the text between words and display them on different lines. This would be easy in a web app with CSS :), but I'll need to re-implement this feature here.

How to fix?

  • Split the text based on width of terminal - consider max length to be around 50% of the total width
  • Only split text between words - do not cut words in half!
  • Move the cursor down when done with a line
  • Move the cursor up when backspaced from the next line

That's a lot of work! ๐Ÿ˜ฌ

UI Refactor

This needs to be fixed after #2 since that will rework a lot of the UI code

I'm missing OS wordlist from install

Firstly I tried typing 'toipe -w' as suggested to get a list of default wordlists, however, I only got an error instead 'error: The argument '--wordlist ' requires a value but none was supplied' which isn't a big deal since you can get them with --help. Anyways, I tried using 'toipe -w os' seeing it in the list of defaults but it gives me error: Error: ToipeError: No such file or directory (os error 2). Anyone know how to fix this and get the OS list?

Binary size - compress word lists?

What?

As new word lists get added (#17, 7c049c5, #27), the size of the final release binary increases since these are embedded directly into it.

Binary size does not matter much, but it would be nice to have it as small as reasonably possible.

How?

This issue has been opened to discuss possible ways to reduce the binary size further.

Some of my ideas:

Compression

The word lists could be compressed using a lightweight compression algo (TBD) at compile time i.e., the word lists will stay the same as they are, but will be embedded into the binary after compressing them. At run time, they will need to be decompressed before using them.

The compression library needs to be lightweight because I wouldn't want to add more bloat from the library than what it saves in compression xD.

It would also be nice to keep the syntax of including word lists similar to the existing approach - include_str!("word_lists/top250") i.e., through a macro.

Host on the internet

A way to avoid embedding the word lists into the binary is to host them somewhere (probaby GitHub?) and have the app download them as required. This will reduce the baggage on the binary, but it's only useful when there are an extremely large number of large word lists. I'm also opposed to the idea of making what is a fully offline app into an internet connected app.

A custom format

This is a crazy one. What if toipe had its own custom format to store word lists in that is optimized only for storing a list of words. It will be a binary format, but I'm not sure of anything else.

Additional context

A change related to binary size was suggested before - #23 (fixed in #24)

To measure the binary size, use:

cargo build --release
ls -lah target/release/toipe

Build fails on Windows because of termion

The build fails on Windows as the termion library isn't supported on Windows

Perhaps Windows support should then be removed from the README, or an alternative would be to use a cross-platform terminal library, such as crossterm

cargo build --release
   Compiling indexmap v1.8.1
   Compiling rand_chacha v0.3.1
   Compiling termion v1.5.6
   Compiling proc-macro-error v1.0.4
error[E0433]: failed to resolve: maybe a missing crate `sys`?
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\lib.rs:24:9
   |
24 | pub use sys::size::terminal_size;
   |         ^^^ maybe a missing crate `sys`?

error[E0433]: failed to resolve: maybe a missing crate `sys`?
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\lib.rs:27:9
   |
27 | pub use sys::tty::{is_tty, get_tty};
   |         ^^^ maybe a missing crate `sys`?

error[E0433]: failed to resolve: maybe a missing crate `sys`?
 --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\async.rs:5:5
  |
5 | use sys::tty::get_tty;
  |     ^^^ maybe a missing crate `sys`?

error[E0433]: failed to resolve: maybe a missing crate `sys`?
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:28:5
   |
28 | use sys::attr::{get_terminal_attr, raw_terminal_attr, set_terminal_attr};
   |     ^^^ maybe a missing crate `sys`?

error[E0432]: unresolved import `sys`
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:29:5
   |
29 | use sys::Termios;
   |     ^^^ maybe a missing crate `sys`?

error[E0425]: cannot find function `get_tty` in this scope
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\async.rs:14:36
   |
14 |     thread::spawn(move || for i in get_tty().unwrap().bytes() {
   |                                    ^^^^^^^ not found in this scope

error[E0425]: cannot find function `get_tty` in this scope
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\async.rs:43:36
   |
43 |     thread::spawn(move || for i in get_tty().unwrap().bytes() {
   |                                    ^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:45:9
   |
45 |         set_terminal_attr(&self.prev_ios).unwrap();
   |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `get_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:102:23
    |
102 |         let mut ios = get_terminal_attr()?;
    |                       ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `raw_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:105:9
    |
105 |         raw_terminal_attr(&mut ios);
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:107:9
    |
107 |         set_terminal_attr(&ios)?;
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:119:9
    |
119 |         set_terminal_attr(&self.prev_ios)?;
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `get_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:125:23
    |
125 |         let mut ios = get_terminal_attr()?;
    |                       ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `raw_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:126:9
    |
126 |         raw_terminal_attr(&mut ios);
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:127:9
    |
127 |         set_terminal_attr(&ios)?;
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

Some errors have detailed explanations: E0425, E0432, E0433.
For more information about an error, try `rustc --explain E0425`.
error: could not compile `termion` due to 15 previous errors
warning: build failed, waiting for other jobs to finish...
error: build failed
```cargo build --release
   Compiling indexmap v1.8.1
   Compiling rand_chacha v0.3.1
   Compiling termion v1.5.6
   Compiling proc-macro-error v1.0.4
error[E0433]: failed to resolve: maybe a missing crate `sys`?
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\lib.rs:24:9
   |
24 | pub use sys::size::terminal_size;
   |         ^^^ maybe a missing crate `sys`?

error[E0433]: failed to resolve: maybe a missing crate `sys`?
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\lib.rs:27:9
   |
27 | pub use sys::tty::{is_tty, get_tty};
   |         ^^^ maybe a missing crate `sys`?

error[E0433]: failed to resolve: maybe a missing crate `sys`?
 --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\async.rs:5:5
  |
5 | use sys::tty::get_tty;
  |     ^^^ maybe a missing crate `sys`?

error[E0433]: failed to resolve: maybe a missing crate `sys`?
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:28:5
   |
28 | use sys::attr::{get_terminal_attr, raw_terminal_attr, set_terminal_attr};
   |     ^^^ maybe a missing crate `sys`?

error[E0432]: unresolved import `sys`
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:29:5
   |
29 | use sys::Termios;
   |     ^^^ maybe a missing crate `sys`?

error[E0425]: cannot find function `get_tty` in this scope
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\async.rs:14:36
   |
14 |     thread::spawn(move || for i in get_tty().unwrap().bytes() {
   |                                    ^^^^^^^ not found in this scope

error[E0425]: cannot find function `get_tty` in this scope
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\async.rs:43:36
   |
43 |     thread::spawn(move || for i in get_tty().unwrap().bytes() {
   |                                    ^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
  --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:45:9
   |
45 |         set_terminal_attr(&self.prev_ios).unwrap();
   |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `get_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:102:23
    |
102 |         let mut ios = get_terminal_attr()?;
    |                       ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `raw_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:105:9
    |
105 |         raw_terminal_attr(&mut ios);
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:107:9
    |
107 |         set_terminal_attr(&ios)?;
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:119:9
    |
119 |         set_terminal_attr(&self.prev_ios)?;
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `get_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:125:23
    |
125 |         let mut ios = get_terminal_attr()?;
    |                       ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `raw_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:126:9
    |
126 |         raw_terminal_attr(&mut ios);
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
   --> C:\Users\Fumnanya\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\termion-1.5.6\src\raw.rs:127:9
    |
127 |         set_terminal_attr(&ios)?;
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

Some errors have detailed explanations: E0425, E0432, E0433.
For more information about an error, try `rustc --explain E0425`.
error: could not compile `termion` due to 15 previous errors
warning: build failed, waiting for other jobs to finish...
error: build failed

[Suggestion] Remove debug info from release builds

Rust 1.59 introduced new feature - creating stripped binaries. Results for hello-world app (target x86_64-unknown-linux-gnu):

$ cargo build --release
   Compiling hello-world v0.1.0 (//hello-world)
    Finished release [optimized] target(s) in 0.94s
$ du -h target/release/hello-world
3.6M	target/release/hello-world
# enable here
$ cargo build --release           
   Compiling hello-world v0.1.0 (//hello-world)
    Finished release [optimized] target(s) in 0.29s
$ du -h target/release/hello-world
308K	target/release/hello-world

with stripping all symbol information:

[profile.release]
strip = true

Handle terminal resize gracefully

What?

When the terminal is resized in the middle of a typing test, the text wraps around weirdly. A ctrl-r fixes this but it would be nice to not interrupt the test.

Although, a terminal resize in the middle of a test might be unlikely.

How?

Termion, the library toipe uses for terminal rendering, doesn't seem to have an event for resizes: https://gitlab.redox-os.org/redox-os/termion/-/issues/151

So this will be tricky to implement. I'm not sure how to do this yet

Fix WPM score

What and why?

Currently, the WPM (words per minute) score is calculated as such:

wpm = (correctly typed characters / minutes) / (number of words / number of chars)

The (number of words / number of chars) is an estimate of the average number of chars in a word.

This has a few issues:

  • Among a sentence with shorter words (A bit of bet of bat of beet) and a sentence with same number of words but with words being larger (Exceptional extraordinary excitable pepperoni paggliacci postmodern extravagant audacious), the WPM will be disproportionately higher in the former as the number of chars in a word is shorter even though a lot less characters have been typed.
  • This does not consider uncorrected errors. There is no penalty for uncorrected errors. There is no incentive to correct errors as it takes some time and disrupts the rhythm.

A big thank you to Darrien Glasser (author of terminal-typeracer) for explaining the issue thoroughly and providing the solution: https://www.reddit.com/r/rust/comments/tvamfz/comment/i3ewppb/

How?

A good way to calculate the WPM can be found here. To summarize, the final WPM will be:

wpm = ((correctly typed characters) / 5 - (uncorrected errors)) / minutes

A change will have to be made in correctly typed characters since currently the counter will keep increasing if the same char is backspaced and typed repeatedly.

Minor bug

I found a very minor bug (which don't influence the gameplay or anything else) in the program :
If you write a single word, and then press ctrl + c, you can get like more than 2000wpm, and the program says that you took 0s for 30 words.

Build failed from Cargo

cargo install toipe
    Updating crates.io index
  Downloaded toipe v0.4.1
  Downloaded 1 crate (510.6 KB) in 0.99s
  Installing toipe v0.4.1
  Downloaded os_str_bytes v6.6.1
  Downloaded termcolor v1.4.0
  Downloaded clap_derive v3.2.25
  Downloaded clap v3.2.25
  Downloaded once_cell v1.18.0
  Downloaded termion v1.5.6
  Downloaded bisection v0.1.0
  Downloaded numtoa v0.1.0
  Downloaded libc v0.2.150
  Downloaded 9 crates (1.1 MB) in 1.50s
   Compiling version_check v0.9.4
   Compiling proc-macro2 v1.0.70
   Compiling unicode-ident v1.0.12
   Compiling winapi v0.3.9
   Compiling syn v1.0.109
   Compiling autocfg v1.1.0
   Compiling cfg-if v1.0.0
   Compiling libc v0.2.150
   Compiling getrandom v0.2.11
   Compiling rand_core v0.6.4
   Compiling ppv-lite86 v0.2.17
   Compiling proc-macro-error-attr v1.0.4
   Compiling proc-macro-error v1.0.4
   Compiling indexmap v1.9.3
   Compiling heck v0.4.1
   Compiling os_str_bytes v6.6.1
   Compiling hashbrown v0.12.3
   Compiling rand_chacha v0.3.1
   Compiling textwrap v0.16.0
   Compiling quote v1.0.33
   Compiling clap_lex v0.2.4
   Compiling bitflags v1.3.2
   Compiling once_cell v1.18.0
   Compiling numtoa v0.1.0
   Compiling strsim v0.10.0
   Compiling termion v1.5.6
   Compiling rand v0.8.5
error[E0433]: failed to resolve: maybe a missing crate `sys`?
  --> C:\Users\user\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.6\src\lib.rs:24:9
   |
24 | pub use sys::size::terminal_size;
   |         ^^^ maybe a missing crate `sys`?
   |
   = help: consider adding `extern crate sys` to use the `sys` crate

error[E0433]: failed to resolve: maybe a missing crate `sys`?
  --> C:\Users\user\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.6\src\lib.rs:27:9
   |
27 | pub use sys::tty::{is_tty, get_tty};
   |         ^^^ maybe a missing crate `sys`?
   |
   = help: consider adding `extern crate sys` to use the `sys` crate

error[E0433]: failed to resolve: maybe a missing crate `sys`?
 --> C:\Users\user\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.6\src\async.rs:5:5
  |
5 | use sys::tty::get_tty;
  |     ^^^ maybe a missing crate `sys`?
  |
  = help: consider adding `extern crate sys` to use the `sys` crate

error[E0433]: failed to resolve: maybe a missing crate `sys`?
  --> C:\Users\user\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.6\src\raw.rs:28:5
   |
28 | use sys::attr::{get_terminal_attr, raw_terminal_attr, set_terminal_attr};
   |     ^^^ maybe a missing crate `sys`?
   |
   = help: consider adding `extern crate sys` to use the `sys` crate

error[E0432]: unresolved import `sys`
  --> C:\Users\user\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.6\src\raw.rs:29:5
   |
29 | use sys::Termios;
   |     ^^^ maybe a missing crate `sys`?
   |
   = help: consider adding `extern crate sys` to use the `sys` crate

   Compiling bisection v0.1.0
   Compiling winapi-util v0.1.6
   Compiling atty v0.2.14
   Compiling termcolor v1.4.0
Some errors have detailed explanations: E0432, E0433.
For more information about an error, try `rustc --explain E0432`.
error: could not compile `termion` due to 5 previous errors
warning: build failed, waiting for other jobs to finish...
error: failed to compile `toipe v0.4.1`, intermediate artifacts can be found at `C:\Users\user\AppData\Local\Temp\cargo-installLhhYfs`

Env; Windows 10

Panic if can't find OS wordlist

On Arch Linux, guess I don't have an OS wordlist:

thread 'main' panicked at 'calledResult::unwrap()on anErrvalue: ToipeError { msg: "No such file or directory (os error 2)" }', /home/ben/.cargo/registry/src/github.com-1ecc6299db9ec823/toipe-0.4.0/src/main.rs:9:40 note: run withRUST_BACKTRACE=1environment variable to display a backtrace
Could print a warning or just use the default word list? I can write a fix for this since I want an excuse to do rust

Add support for long words

Hi there,

I want to address this issue and add support for long words.

It goes into an infinite loop when given a file with exclusively long words (length > 8). Link to line. This issue may also occur for files all filled with single chars or containing non-ASCII chars.

Replicate:

cat /usr/share/dict/words | awk 'length($0) >= 9' | head -n 5 > long-words
toipe -f long-words

At the least, it shouldn't hang. I don't know how best to handle this yet.

To support long words would you want to add a config (instead of this)? Or remove this check if the source is a custom word list file?

Problem with custom word list

I have i test file with 60 words in it, and when i run toipe -f words -n 10 there will words that occurs multiple times , also the words that are at the end of the text file don't even show up at all [the words at the first line or two occurs the most]

Larger wordlists

What and why?

Currently, the only built-in word list is the top 250 words list. This is very limiting as words will often repeat again in the same line and multiple times throughout a test.

It would be nice to have these word lists too:

  • top 500
  • top 1000
  • top 2500
  • top 5000
  • top 10000 (added in #27)
  • top 25000 (added in #27)
  • More?

How?

More info about the existing word list: https://docs.rs/toipe/latest/toipe/wordlists/constant.TOP_250.html

The word list needs to be added in this directory: https://github.com/Samyak2/toipe/tree/main/src/word_lists

and it needs to be listed here: https://github.com/Samyak2/toipe/blob/main/src/wordlists.rs

Add support for phrases and code

What?

Currently, toipe selects random words from a list of words. This is fine if you want to measure an ideal speed without punctuation, proper language, etc. (Note: some people are slower when typing random words compared to actual phrases while others are not. I'm in the latter group).

It would be nice to allow complete phrases, perhaps out of a book, to be type tested against. This will require a much different "word list" and selection algorithm than the one that is present.

An extension to this idea is to allow type tests against code or programs. This will have additional nuances like keeping indentation.

Why?

There were several requests on reddit:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.