Compare commits

..

10 commits

8 changed files with 228 additions and 26 deletions

View file

@ -1,5 +1,5 @@
build: fasttyper
python setup.py sdist bdist_wheel
build: fasttyper dist
python3 setup.py sdist bdist_wheel
push:
twine upload dist/*

View file

@ -3,11 +3,24 @@
# About
_Fasttyper_ is minimalistic typing test based on user provided exercising text. It supports both reading from text files and stdin supporting wide range of usecases. The goal was to create it as simple as it can be, without any additional bloatware functionalities. That means that _Fasttyper_ doesn't come with build in test generator and you have to provide your own scripts generating tests. Some examples of such scrips are providen in [Usage section](#usage).
_Fasttyper_ is minimalistic typing test based on user provided exercising text. It supports both reading from text files and stdin supporting wide range of usecases. The goal was to create it as simple as it can be, without any additional bloatware functionalities. That means that _Fasttyper_ doesn't come with build in test generator and you have to provide your own scripts generating tests. Some examples of such scripts are provided in [Usage section](#usage).
# Table of contents
- [fasttyper](#fasttyper)
- [About](#about)
- [Installation](#installation)
- [Usage](#usage)
- [Running next test and stopping application](#running-next-test-and-stopping-application)
- [Configuring](#configuring)
- [Usage as module, piping stuff, custom scripts etc](#usage-as-module,-piping-stuff,-custom-scripts-etc)
- [When backspace does wierd shiet](#when-backspace-does-wierd-shiet)
- [Hiding cursor](#hiding-cursor)
- [Example scripts](#example-scripts)
# Installation
_Fasttyper_ is currently maintained on [PyPi](https://pypi.org/) Python Package Index. To install package simpply use:
_Fasttyper_ is currently maintained on [PyPi](https://pypi.org/) Python Package Index. To install package simply use:
`python3 -m pip install fasttyper`
@ -19,7 +32,7 @@ With installation of fasttyper you should have new executable - `fasttyper`. It
fasttyper
```
from command line. There are some avalibe options:
from command line. There are some available options:
```
usage: fasttyper [-h] [--config FILE] [--unclutter-backspace] [--no-cursor] [amount] [language]
@ -34,7 +47,7 @@ options:
configuration file
--unclutter-backspace, -b
unclutter backspace, when it raises ctrl+backspace instead
--no-cursor, -n disable cursos
--no-cursor, -n disable cursors
```
I personally use alias:
@ -53,7 +66,49 @@ To kill application (exit) press CTRL+C.
# Configuring
Fasttyper by default looks for config file in: `$HOME/.config/fasttyper/config.json`. You can provide different location for config file with `--config` argument, for example: `--config=~/.fasttyper.json`. Config has to be a json dict. Avalibe keys:
Default configuration:
```python
{
"user_input_valid_color": 3,
"user_input_invalid_color": 2,
"reference_text_color": 9,
"stats_template": "wpm: {stats.wpm:0.2f}, time: {stats.total_seconds:0.2f}s",
"stats_color": 5,
"stats_position": "top",
"summary_datafile": "~/.cache/fasttyper/datafile.csv",
"top_margin_percentage": 40,
"left_margin_percentage": 35,
"min_width": 80,
"lines_on_screen": 3,
"border": 1,
"logo": " ~ FastTyper ~ ",
"logo_color": 8,
"resume_text": " press <Tab> to continue, <Ctrl>C to exit ",
"resume_text_color": 9,
"summary_template": (
"wpm: {wpm:5.1f} | peak: {peak_wpm:5.1f}",
"raw: {raw_wpm:5.1f} | peak: {peak_raw_wpm:5.1f}",
"acc: {accuracy:5.1f}% | words: {correct_words}/{total_words}",
"time: {total_seconds:5.1f}s ",
),
"summary_centered": True,
"summary_color": 9,
"summary_lines": 4,
"summary_border": 0,
"random_capitalization": 0,
"random_punctuation": 0,
"sentence_mode": False,
"punctuation": ",.?!;:",
"sentence_ending": ".?!",
"amount": 25,
"language": "english",
"no_cursor": False,
"unclutter_backspace": False,
}
```
Fasttyper by default looks for config file in: `$HOME/.config/fasttyper/config.json`. You can provide different location for config file with `--config` argument, for example: `--config=~/.fasttyper.json`. Config has to be a json dict. Available keys:
- **user_input_valid_color** - integer, terminal color for valid text, by default it is 3
- **user_input_invalid_color** - integer, terminal color for invalid text, by default it is 2
@ -64,7 +119,9 @@ Fasttyper by default looks for config file in: `$HOME/.config/fasttyper/config.j
- **left_margin_percentage** - integer, percentage of screen used for left (and right) margin, by default 10
- **lines_on_screen** - integer, number of lines to display on screen, by default 3
Example config file with all default values in avalibe [here](https://github.com/ickyicky/fasttyper/blob/main/doc/example_config.json).
Also there are keys that override fault parameters for CLI args, like: amount and language will override Your default settings for runner, same goes for punctuation, sentence_mode etc.
Example config file with all default values in available [here](https://github.com/ickyicky/fasttyper/blob/main/doc/example_config.json).
Other example config files:
@ -92,13 +149,13 @@ Program also allows user to pipe text into it. Keep in mind, it only supports sp
`furtune | python3 -m fasttyper`
or if you want to randomize words from given file with shuf on for example all disctionaries in system:
or if you want to randomize words from given file with shuf on for example all dictionaries in system:
`shuf -n5 /usr/share/dict/* | python -m fasttyper`
You can use another similar projects set of words as well, for example to create test with 20 random words from [Monkeytype's](https://github.com/Miodec/monkeytype) english 100 dictionary use:
`curl -s https://raw.githubusercontent.com/Miodec/monkeytype/master/static/languages/english.json | python3 -c "import sys, json; print('\n'.join(json.load(sys.stdin)['words']))" | shuf -n20 | python3 -m fasttyper`
`curl -s https://raw.githubusercontent.com/monkeytypegame/monkeytype/master/frontend/static/languages/english.json | python3 -c "import sys, json; print('\n'.join(json.load(sys.stdin)['words']))" | shuf -n20 | python3 -m fasttyper`
To exit you can either finish test, use `KeyboardInterrupt` (CTRL+C) or tap **tab**. After you finish test, there will be summary printed, use enter to exit from it.
@ -128,6 +185,6 @@ function ff() {
```
`ff 50 english_1k`
This shell function shuffles N words from cached word list, and if given word list doesnt exist it download's it. It runs in loop, but does exit from it if you exit fasttyper with CTRL+C.
This shell function shuffles N words from cached word list, and if given word list doesn't exist it download's it. It runs in loop, but does exit from it if you exit fasttyper with CTRL+C.
The above script is avalible for download from doc folder.
The above script is available for download from doc folder.

View file

@ -53,8 +53,13 @@ class Buffer:
def _next_word(self):
self.current_word += 1
if self.current_char > 0:
self.stats.signal_valid() # space is a char after all
else:
self.stats.signal_invalid() # space after empty word
self.current_char = 0
self.stats.signal_valid() # space is a char after all
if self.current_word >= self.total_words:
self.stats.signal_stop(True)
@ -143,4 +148,4 @@ class Buffer:
if w != self.reference_words[i]:
count += 1
return count
return count + len(self.reference_words) - len(self.user_words)

View file

@ -24,7 +24,7 @@ class RuntimeConfig:
self.mode = mode
def initialize(config_path, rbuffer, backspace_debug, no_cursor, runtime_config):
def get_config(config_path):
try:
with open(os.path.expanduser(config_path)) as f:
configmap = json.load(f)
@ -32,6 +32,17 @@ def initialize(config_path, rbuffer, backspace_debug, no_cursor, runtime_config)
configmap = {}
config = Config(configmap)
return config
def initialize(config, rbuffer, backspace_debug, no_cursor, runtime_config):
if isinstance(config, str):
config = get_config(config)
backspace_debug = (
backspace_debug(config) if callable(backspace_debug) else backspace_debug
)
no_cursor = no_cursor(config) if callable(no_cursor) else no_cursor
text_box = TextBox(config)
summary = Summary(config)
@ -71,13 +82,21 @@ def get_parser():
"-b",
action="store_true",
help="unclutter backspace, when it raises ctrl+backspace instead",
default=False,
default=ValueFromConfig("unclutter_backspace"),
)
parser.add_argument(
"--no-cursor",
"-n",
action="store_true",
help="disable cursos",
default=False,
default=ValueFromConfig("no_cursor"),
)
return parser
class ValueFromConfig:
def __init__(self, key):
self.key = key
def __call__(self, config):
return config.get(self.key)

View file

@ -26,6 +26,15 @@ class Config:
"summary_color": 9,
"summary_lines": 4,
"summary_border": 0,
"random_capitalization": 0,
"random_punctuation": 0,
"sentence_mode": False,
"punctuation": ",.?!;:",
"sentence_ending": ".?!",
"amount": 25,
"language": "english",
"no_cursor": False,
"unclutter_backspace": False,
}
def __init__(self, configmap):

View file

@ -1,5 +1,5 @@
from .cli import initialize, get_parser, RuntimeConfig
from random import choice
from .cli import initialize, get_parser, RuntimeConfig, get_config, ValueFromConfig
from random import choice, random
import os
import requests
import pathlib
@ -33,23 +33,135 @@ def get_words(language):
return words
def generate_text(
words,
amount,
capitalization_factor,
punctuation_factor,
sentence_mode,
punctuation,
sentence_ending,
):
chosen_words = []
new_sentence = True
for _ in range(amount):
word = choice(words)
if sentence_mode and new_sentence:
word = word.capitalize()
new_sentence = False
elif capitalization_factor and capitalization_factor / 100 > random():
word = word.capitalize()
if punctuation_factor and punctuation_factor / 100 > random():
chosen_punctuation = choice(punctuation)
word = "".join((word, chosen_punctuation))
new_sentence = word[-1] in sentence_ending
chosen_words.append(word)
return " ".join(chosen_words)
def runner():
parser = get_parser()
parser.add_argument(
"amount", type=int, default=25, help="Amount of words", nargs="?"
"amount",
type=int,
default=ValueFromConfig("amount"),
help="Amount of words",
nargs="?",
)
parser.add_argument(
"language", type=str, default="english", help="Language", nargs="?"
"language",
type=str,
default=ValueFromConfig("language"),
help="Language",
nargs="?",
)
parser.add_argument(
"-rc",
"--random-capitalization",
type=int,
default=ValueFromConfig("random_capitalization"),
help="Percent of randomally capitalized words",
action="store",
)
parser.add_argument(
"-rp",
"--random-punctuation",
type=int,
default=ValueFromConfig("random_capitalization"),
help="Percent of words that will have randomally appender punctuation at the end",
action="store",
)
parser.add_argument(
"-sm",
"--sentence-mode",
default=ValueFromConfig("sentence_mode"),
help="Forces uppercase after sentence ending characters like dot or question mark and at the beggining of text",
action="store_true",
)
parser.add_argument(
"--punctuation",
type=str,
default=ValueFromConfig("punctuation"),
help="List of all punctuation characters",
action="store",
)
parser.add_argument(
"--sentence-ending",
type=str,
default=ValueFromConfig("sentence_ending"),
help="List of all punctuation characters that end sentence",
action="store",
)
args = parser.parse_args()
words = get_words(args.language)
config = get_config(args.config)
random_punctuation = (
args.random_punctuation(config)
if callable(args.random_punctuation)
else args.random_punctuation
)
random_capitalization = (
args.random_capitalization(config)
if callable(args.random_capitalization)
else args.random_capitalization
)
sentence_mode = (
args.sentence_mode(config)
if callable(args.sentence_mode)
else args.sentence_mode
)
punctuation = (
args.punctuation(config) if callable(args.punctuation) else args.punctuation
)
sentence_ending = (
args.sentence_ending(config)
if callable(args.sentence_ending)
else args.sentence_ending
)
amount = args.amount(config) if callable(args.amount) else args.amount
language = args.language(config) if callable(args.language) else args.language
words = get_words(language)
while True:
rbuffer = " ".join([choice(words) for _ in range(args.amount)])
rbuffer = generate_text(
words,
amount,
random_capitalization,
random_punctuation,
sentence_mode,
punctuation,
sentence_ending,
)
initialize(
args.config,
config,
rbuffer,
args.unclutter_backspace,
args.no_cursor,

View file

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2.3.0
current_version = 2.4.2
[wheel]
universal = 1

View file

@ -9,7 +9,7 @@ with open("requirements.txt", "r", encoding="utf-8") as fh:
setup(
name="fasttyper",
version="2.3.0",
version="2.4.2",
author="Piotr Domanski",
author_email="pi.domanski@gmail.com",
description="Minimalistic typing exercise",