typing-cli 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- typing_cli-0.1.0/LICENSE +21 -0
- typing_cli-0.1.0/PKG-INFO +141 -0
- typing_cli-0.1.0/README.md +112 -0
- typing_cli-0.1.0/pyproject.toml +52 -0
- typing_cli-0.1.0/setup.cfg +4 -0
- typing_cli-0.1.0/src/typing_cli.egg-info/PKG-INFO +141 -0
- typing_cli-0.1.0/src/typing_cli.egg-info/SOURCES.txt +29 -0
- typing_cli-0.1.0/src/typing_cli.egg-info/dependency_links.txt +1 -0
- typing_cli-0.1.0/src/typing_cli.egg-info/entry_points.txt +3 -0
- typing_cli-0.1.0/src/typing_cli.egg-info/requires.txt +4 -0
- typing_cli-0.1.0/src/typing_cli.egg-info/top_level.txt +1 -0
- typing_cli-0.1.0/src/typingtest/__init__.py +3 -0
- typing_cli-0.1.0/src/typingtest/__main__.py +21 -0
- typing_cli-0.1.0/src/typingtest/core/__init__.py +0 -0
- typing_cli-0.1.0/src/typingtest/core/config.py +118 -0
- typing_cli-0.1.0/src/typingtest/core/generator.py +56 -0
- typing_cli-0.1.0/src/typingtest/core/stats.py +116 -0
- typing_cli-0.1.0/src/typingtest/core/tracker.py +106 -0
- typing_cli-0.1.0/src/typingtest/data/languages/english.json +24 -0
- typing_cli-0.1.0/src/typingtest/data/languages/french.json +24 -0
- typing_cli-0.1.0/src/typingtest/ui/__init__.py +0 -0
- typing_cli-0.1.0/src/typingtest/ui/app.py +184 -0
- typing_cli-0.1.0/src/typingtest/ui/screens/__init__.py +0 -0
- typing_cli-0.1.0/src/typingtest/ui/screens/history.py +99 -0
- typing_cli-0.1.0/src/typingtest/ui/screens/result.py +276 -0
- typing_cli-0.1.0/src/typingtest/ui/screens/splash.py +68 -0
- typing_cli-0.1.0/src/typingtest/ui/screens/typing_screen.py +438 -0
- typing_cli-0.1.0/src/typingtest/ui/widgets/__init__.py +0 -0
- typing_cli-0.1.0/src/typingtest/ui/widgets/character.py +273 -0
- typing_cli-0.1.0/src/typingtest/ui/widgets/stats_bar.py +124 -0
- typing_cli-0.1.0/src/typingtest/ui/widgets/typing_area.py +103 -0
typing_cli-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 lecoffre
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: typing-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A beautiful CLI typing test to practice your typing speed
|
|
5
|
+
Author: lecoffre
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/lecoffre/typing-cli
|
|
8
|
+
Project-URL: Repository, https://github.com/lecoffre/typing-cli
|
|
9
|
+
Project-URL: Issues, https://github.com/lecoffre/typing-cli/issues
|
|
10
|
+
Keywords: typing,test,cli,wpm,speed,terminal
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Games/Entertainment
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: textual>=0.50.0
|
|
25
|
+
Requires-Dist: click>=8.1.0
|
|
26
|
+
Requires-Dist: pyfiglet>=1.0.0
|
|
27
|
+
Requires-Dist: platformdirs>=4.0.0
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# ⌨️ typing-cli
|
|
31
|
+
|
|
32
|
+
A beautiful and fast CLI typing test — right from your terminal.
|
|
33
|
+
|
|
34
|
+
Practice your typing speed with real-time WPM tracking, accuracy stats, animated pixel-art F1 car, multiple languages, and color themes.
|
|
35
|
+
|
|
36
|
+
[](https://pypi.org/project/typing-cli/)
|
|
37
|
+
[](https://www.python.org/downloads/)
|
|
38
|
+
[](LICENSE)
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
__ _ ___
|
|
42
|
+
/ /___ ______ (_)___ ____ _ ____/ (_)
|
|
43
|
+
/ __/ / / / __ \/ / __ \/ __ `/ ____ / __/ / /
|
|
44
|
+
/ /_/ /_/ / /_/ / / / / / /_/ / /___// /_/ / /
|
|
45
|
+
\__/\__, / .___/_/_/ /_/\__, / \__/_/_/
|
|
46
|
+
/____/_/ /____/
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 🚀 Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install typing-cli
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
That's it. Works on **Windows**, **macOS**, and **Linux**.
|
|
56
|
+
|
|
57
|
+
### From source
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
git clone https://github.com/lecoffre/typing-cli.git
|
|
61
|
+
cd typing-cli
|
|
62
|
+
pip install -e .
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## ▶️ Usage
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
typing-cli
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The app launches in your terminal. Start typing!
|
|
72
|
+
|
|
73
|
+
## 🔄 Update
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install --upgrade typing-cli
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## ⌨️ Keyboard Shortcuts
|
|
80
|
+
|
|
81
|
+
| Shortcut | Action |
|
|
82
|
+
|----------------|----------------------------|
|
|
83
|
+
| `Tab` | Restart test |
|
|
84
|
+
| `Escape` | Back / Quit |
|
|
85
|
+
| `Ctrl+T` | Change theme |
|
|
86
|
+
| `Ctrl+L` | Change language |
|
|
87
|
+
| `Ctrl+M` | Switch mode (words/code) |
|
|
88
|
+
| `Ctrl+H` | View score history |
|
|
89
|
+
| `Ctrl++/-` | Zoom in/out |
|
|
90
|
+
| `Ctrl+Q` | Quit |
|
|
91
|
+
|
|
92
|
+
## 🌍 Languages
|
|
93
|
+
|
|
94
|
+
Built-in:
|
|
95
|
+
- 🇬🇧 English (200 most common words)
|
|
96
|
+
- 🇫🇷 French (200 most common words)
|
|
97
|
+
|
|
98
|
+
## 🎨 Themes
|
|
99
|
+
|
|
100
|
+
- **Midnight** — deep dark blues (default)
|
|
101
|
+
- **Forest** — earthy greens
|
|
102
|
+
- **Sunset** — warm amber tones
|
|
103
|
+
- **Ocean** — cool cyan palette
|
|
104
|
+
- **Mono** — minimal grayscale
|
|
105
|
+
|
|
106
|
+
## 📊 Features
|
|
107
|
+
|
|
108
|
+
- Real-time WPM & accuracy tracking
|
|
109
|
+
- Per-character coloring (correct / incorrect / cursor)
|
|
110
|
+
- Animated pixel-art F1 car reflecting your speed
|
|
111
|
+
- Gamification: streak, combo, milestones, rank system
|
|
112
|
+
- Code typing mode
|
|
113
|
+
- Score history with date, WPM, accuracy
|
|
114
|
+
- Multiple languages & themes
|
|
115
|
+
- Splash screen with ASCII art
|
|
116
|
+
- Clean, extensible architecture
|
|
117
|
+
|
|
118
|
+
## 🛠️ Development
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
git clone https://github.com/lecoffre/typing-cli.git
|
|
122
|
+
cd typing-cli
|
|
123
|
+
pip install -e .
|
|
124
|
+
|
|
125
|
+
# Run directly
|
|
126
|
+
python -m typingtest
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 🤝 Contributing
|
|
130
|
+
|
|
131
|
+
Contributions are welcome! Feel free to open issues and pull requests.
|
|
132
|
+
|
|
133
|
+
1. Fork the repo
|
|
134
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
135
|
+
3. Commit (`git commit -m 'Add amazing feature'`)
|
|
136
|
+
4. Push (`git push origin feature/amazing-feature`)
|
|
137
|
+
5. Open a Pull Request
|
|
138
|
+
|
|
139
|
+
## 📄 License
|
|
140
|
+
|
|
141
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# ⌨️ typing-cli
|
|
2
|
+
|
|
3
|
+
A beautiful and fast CLI typing test — right from your terminal.
|
|
4
|
+
|
|
5
|
+
Practice your typing speed with real-time WPM tracking, accuracy stats, animated pixel-art F1 car, multiple languages, and color themes.
|
|
6
|
+
|
|
7
|
+
[](https://pypi.org/project/typing-cli/)
|
|
8
|
+
[](https://www.python.org/downloads/)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
__ _ ___
|
|
13
|
+
/ /___ ______ (_)___ ____ _ ____/ (_)
|
|
14
|
+
/ __/ / / / __ \/ / __ \/ __ `/ ____ / __/ / /
|
|
15
|
+
/ /_/ /_/ / /_/ / / / / / /_/ / /___// /_/ / /
|
|
16
|
+
\__/\__, / .___/_/_/ /_/\__, / \__/_/_/
|
|
17
|
+
/____/_/ /____/
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 🚀 Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install typing-cli
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
That's it. Works on **Windows**, **macOS**, and **Linux**.
|
|
27
|
+
|
|
28
|
+
### From source
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/lecoffre/typing-cli.git
|
|
32
|
+
cd typing-cli
|
|
33
|
+
pip install -e .
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## ▶️ Usage
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
typing-cli
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The app launches in your terminal. Start typing!
|
|
43
|
+
|
|
44
|
+
## 🔄 Update
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install --upgrade typing-cli
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## ⌨️ Keyboard Shortcuts
|
|
51
|
+
|
|
52
|
+
| Shortcut | Action |
|
|
53
|
+
|----------------|----------------------------|
|
|
54
|
+
| `Tab` | Restart test |
|
|
55
|
+
| `Escape` | Back / Quit |
|
|
56
|
+
| `Ctrl+T` | Change theme |
|
|
57
|
+
| `Ctrl+L` | Change language |
|
|
58
|
+
| `Ctrl+M` | Switch mode (words/code) |
|
|
59
|
+
| `Ctrl+H` | View score history |
|
|
60
|
+
| `Ctrl++/-` | Zoom in/out |
|
|
61
|
+
| `Ctrl+Q` | Quit |
|
|
62
|
+
|
|
63
|
+
## 🌍 Languages
|
|
64
|
+
|
|
65
|
+
Built-in:
|
|
66
|
+
- 🇬🇧 English (200 most common words)
|
|
67
|
+
- 🇫🇷 French (200 most common words)
|
|
68
|
+
|
|
69
|
+
## 🎨 Themes
|
|
70
|
+
|
|
71
|
+
- **Midnight** — deep dark blues (default)
|
|
72
|
+
- **Forest** — earthy greens
|
|
73
|
+
- **Sunset** — warm amber tones
|
|
74
|
+
- **Ocean** — cool cyan palette
|
|
75
|
+
- **Mono** — minimal grayscale
|
|
76
|
+
|
|
77
|
+
## 📊 Features
|
|
78
|
+
|
|
79
|
+
- Real-time WPM & accuracy tracking
|
|
80
|
+
- Per-character coloring (correct / incorrect / cursor)
|
|
81
|
+
- Animated pixel-art F1 car reflecting your speed
|
|
82
|
+
- Gamification: streak, combo, milestones, rank system
|
|
83
|
+
- Code typing mode
|
|
84
|
+
- Score history with date, WPM, accuracy
|
|
85
|
+
- Multiple languages & themes
|
|
86
|
+
- Splash screen with ASCII art
|
|
87
|
+
- Clean, extensible architecture
|
|
88
|
+
|
|
89
|
+
## 🛠️ Development
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
git clone https://github.com/lecoffre/typing-cli.git
|
|
93
|
+
cd typing-cli
|
|
94
|
+
pip install -e .
|
|
95
|
+
|
|
96
|
+
# Run directly
|
|
97
|
+
python -m typingtest
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## 🤝 Contributing
|
|
101
|
+
|
|
102
|
+
Contributions are welcome! Feel free to open issues and pull requests.
|
|
103
|
+
|
|
104
|
+
1. Fork the repo
|
|
105
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
106
|
+
3. Commit (`git commit -m 'Add amazing feature'`)
|
|
107
|
+
4. Push (`git push origin feature/amazing-feature`)
|
|
108
|
+
5. Open a Pull Request
|
|
109
|
+
|
|
110
|
+
## 📄 License
|
|
111
|
+
|
|
112
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "typing-cli"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "A beautiful CLI typing test to practice your typing speed"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "lecoffre"},
|
|
14
|
+
]
|
|
15
|
+
keywords = ["typing", "test", "cli", "wpm", "speed", "terminal"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: End Users/Desktop",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Topic :: Games/Entertainment",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"textual>=0.50.0",
|
|
30
|
+
"click>=8.1.0",
|
|
31
|
+
"pyfiglet>=1.0.0",
|
|
32
|
+
"platformdirs>=4.0.0",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://github.com/lecoffre/typing-cli"
|
|
37
|
+
Repository = "https://github.com/lecoffre/typing-cli"
|
|
38
|
+
Issues = "https://github.com/lecoffre/typing-cli/issues"
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
typing-cli = "typingtest.__main__:main"
|
|
42
|
+
typing-test = "typingtest.__main__:main"
|
|
43
|
+
|
|
44
|
+
[tool.setuptools.packages.find]
|
|
45
|
+
where = ["src"]
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.package-data]
|
|
48
|
+
typingtest = ["data/languages/*.json", "ui/css/*.tcss"]
|
|
49
|
+
|
|
50
|
+
[tool.ruff]
|
|
51
|
+
target-version = "py310"
|
|
52
|
+
line-length = 100
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: typing-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A beautiful CLI typing test to practice your typing speed
|
|
5
|
+
Author: lecoffre
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/lecoffre/typing-cli
|
|
8
|
+
Project-URL: Repository, https://github.com/lecoffre/typing-cli
|
|
9
|
+
Project-URL: Issues, https://github.com/lecoffre/typing-cli/issues
|
|
10
|
+
Keywords: typing,test,cli,wpm,speed,terminal
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Games/Entertainment
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: textual>=0.50.0
|
|
25
|
+
Requires-Dist: click>=8.1.0
|
|
26
|
+
Requires-Dist: pyfiglet>=1.0.0
|
|
27
|
+
Requires-Dist: platformdirs>=4.0.0
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# ⌨️ typing-cli
|
|
31
|
+
|
|
32
|
+
A beautiful and fast CLI typing test — right from your terminal.
|
|
33
|
+
|
|
34
|
+
Practice your typing speed with real-time WPM tracking, accuracy stats, animated pixel-art F1 car, multiple languages, and color themes.
|
|
35
|
+
|
|
36
|
+
[](https://pypi.org/project/typing-cli/)
|
|
37
|
+
[](https://www.python.org/downloads/)
|
|
38
|
+
[](LICENSE)
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
__ _ ___
|
|
42
|
+
/ /___ ______ (_)___ ____ _ ____/ (_)
|
|
43
|
+
/ __/ / / / __ \/ / __ \/ __ `/ ____ / __/ / /
|
|
44
|
+
/ /_/ /_/ / /_/ / / / / / /_/ / /___// /_/ / /
|
|
45
|
+
\__/\__, / .___/_/_/ /_/\__, / \__/_/_/
|
|
46
|
+
/____/_/ /____/
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 🚀 Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install typing-cli
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
That's it. Works on **Windows**, **macOS**, and **Linux**.
|
|
56
|
+
|
|
57
|
+
### From source
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
git clone https://github.com/lecoffre/typing-cli.git
|
|
61
|
+
cd typing-cli
|
|
62
|
+
pip install -e .
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## ▶️ Usage
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
typing-cli
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The app launches in your terminal. Start typing!
|
|
72
|
+
|
|
73
|
+
## 🔄 Update
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install --upgrade typing-cli
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## ⌨️ Keyboard Shortcuts
|
|
80
|
+
|
|
81
|
+
| Shortcut | Action |
|
|
82
|
+
|----------------|----------------------------|
|
|
83
|
+
| `Tab` | Restart test |
|
|
84
|
+
| `Escape` | Back / Quit |
|
|
85
|
+
| `Ctrl+T` | Change theme |
|
|
86
|
+
| `Ctrl+L` | Change language |
|
|
87
|
+
| `Ctrl+M` | Switch mode (words/code) |
|
|
88
|
+
| `Ctrl+H` | View score history |
|
|
89
|
+
| `Ctrl++/-` | Zoom in/out |
|
|
90
|
+
| `Ctrl+Q` | Quit |
|
|
91
|
+
|
|
92
|
+
## 🌍 Languages
|
|
93
|
+
|
|
94
|
+
Built-in:
|
|
95
|
+
- 🇬🇧 English (200 most common words)
|
|
96
|
+
- 🇫🇷 French (200 most common words)
|
|
97
|
+
|
|
98
|
+
## 🎨 Themes
|
|
99
|
+
|
|
100
|
+
- **Midnight** — deep dark blues (default)
|
|
101
|
+
- **Forest** — earthy greens
|
|
102
|
+
- **Sunset** — warm amber tones
|
|
103
|
+
- **Ocean** — cool cyan palette
|
|
104
|
+
- **Mono** — minimal grayscale
|
|
105
|
+
|
|
106
|
+
## 📊 Features
|
|
107
|
+
|
|
108
|
+
- Real-time WPM & accuracy tracking
|
|
109
|
+
- Per-character coloring (correct / incorrect / cursor)
|
|
110
|
+
- Animated pixel-art F1 car reflecting your speed
|
|
111
|
+
- Gamification: streak, combo, milestones, rank system
|
|
112
|
+
- Code typing mode
|
|
113
|
+
- Score history with date, WPM, accuracy
|
|
114
|
+
- Multiple languages & themes
|
|
115
|
+
- Splash screen with ASCII art
|
|
116
|
+
- Clean, extensible architecture
|
|
117
|
+
|
|
118
|
+
## 🛠️ Development
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
git clone https://github.com/lecoffre/typing-cli.git
|
|
122
|
+
cd typing-cli
|
|
123
|
+
pip install -e .
|
|
124
|
+
|
|
125
|
+
# Run directly
|
|
126
|
+
python -m typingtest
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 🤝 Contributing
|
|
130
|
+
|
|
131
|
+
Contributions are welcome! Feel free to open issues and pull requests.
|
|
132
|
+
|
|
133
|
+
1. Fork the repo
|
|
134
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
135
|
+
3. Commit (`git commit -m 'Add amazing feature'`)
|
|
136
|
+
4. Push (`git push origin feature/amazing-feature`)
|
|
137
|
+
5. Open a Pull Request
|
|
138
|
+
|
|
139
|
+
## 📄 License
|
|
140
|
+
|
|
141
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/typing_cli.egg-info/PKG-INFO
|
|
5
|
+
src/typing_cli.egg-info/SOURCES.txt
|
|
6
|
+
src/typing_cli.egg-info/dependency_links.txt
|
|
7
|
+
src/typing_cli.egg-info/entry_points.txt
|
|
8
|
+
src/typing_cli.egg-info/requires.txt
|
|
9
|
+
src/typing_cli.egg-info/top_level.txt
|
|
10
|
+
src/typingtest/__init__.py
|
|
11
|
+
src/typingtest/__main__.py
|
|
12
|
+
src/typingtest/core/__init__.py
|
|
13
|
+
src/typingtest/core/config.py
|
|
14
|
+
src/typingtest/core/generator.py
|
|
15
|
+
src/typingtest/core/stats.py
|
|
16
|
+
src/typingtest/core/tracker.py
|
|
17
|
+
src/typingtest/data/languages/english.json
|
|
18
|
+
src/typingtest/data/languages/french.json
|
|
19
|
+
src/typingtest/ui/__init__.py
|
|
20
|
+
src/typingtest/ui/app.py
|
|
21
|
+
src/typingtest/ui/screens/__init__.py
|
|
22
|
+
src/typingtest/ui/screens/history.py
|
|
23
|
+
src/typingtest/ui/screens/result.py
|
|
24
|
+
src/typingtest/ui/screens/splash.py
|
|
25
|
+
src/typingtest/ui/screens/typing_screen.py
|
|
26
|
+
src/typingtest/ui/widgets/__init__.py
|
|
27
|
+
src/typingtest/ui/widgets/character.py
|
|
28
|
+
src/typingtest/ui/widgets/stats_bar.py
|
|
29
|
+
src/typingtest/ui/widgets/typing_area.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
typingtest
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""CLI entry point — `typing-cli` command."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from typingtest import __version__
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command(context_settings={"help_option_names": ["-h", "--help"]})
|
|
11
|
+
@click.version_option(__version__, "-v", "--version", prog_name="typing-cli")
|
|
12
|
+
def main() -> None:
|
|
13
|
+
"""⌨️ typing-cli — practice your typing speed in the terminal."""
|
|
14
|
+
from typingtest.ui.app import TypingTestApp
|
|
15
|
+
|
|
16
|
+
app = TypingTestApp()
|
|
17
|
+
app.run()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Configuration management — persist user settings and score history."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from platformdirs import user_config_dir, user_data_dir
|
|
10
|
+
|
|
11
|
+
APP_NAME = "typing-test"
|
|
12
|
+
|
|
13
|
+
CONFIG_DIR = Path(user_config_dir(APP_NAME, ensure_exists=True))
|
|
14
|
+
DATA_DIR = Path(user_data_dir(APP_NAME, ensure_exists=True))
|
|
15
|
+
|
|
16
|
+
CONFIG_FILE = CONFIG_DIR / "config.json"
|
|
17
|
+
HISTORY_FILE = DATA_DIR / "history.json"
|
|
18
|
+
|
|
19
|
+
DEFAULTS: dict[str, Any] = {
|
|
20
|
+
"language": "english",
|
|
21
|
+
"theme": "midnight",
|
|
22
|
+
"word_count": 30,
|
|
23
|
+
"zoom": 1,
|
|
24
|
+
"mode": "words", # "words" or "code"
|
|
25
|
+
"code_language": "python", # python, typescript, javascript, rust, go
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
THEMES = ["midnight", "forest", "sunset", "ocean", "mono"]
|
|
29
|
+
LANGUAGES = ["english", "french"]
|
|
30
|
+
MODES = ["words", "code"]
|
|
31
|
+
ZOOM_LEVELS = [0, 1, 2, 3] # 0=compact, 1=normal, 2=large, 3=extra-large
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# ── Zoom presets ──────────────────────────────────────────────────────
|
|
35
|
+
# Each level defines container width, padding, and letter spacing.
|
|
36
|
+
|
|
37
|
+
ZOOM_PRESETS: dict[int, dict[str, Any]] = {
|
|
38
|
+
0: {"width": 90, "padding_x": 1, "padding_y": 0, "line_height": 0, "letter_spacing": 0, "label": "compact"},
|
|
39
|
+
1: {"width": 76, "padding_x": 2, "padding_y": 1, "line_height": 0, "letter_spacing": 0, "label": "normal"},
|
|
40
|
+
2: {"width": 60, "padding_x": 3, "padding_y": 1, "line_height": 1, "letter_spacing": 1, "label": "large"},
|
|
41
|
+
3: {"width": 46, "padding_x": 4, "padding_y": 2, "line_height": 1, "letter_spacing": 2, "label": "x-large"},
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _load_json(path: Path) -> Any:
|
|
46
|
+
if path.exists():
|
|
47
|
+
return json.loads(path.read_text(encoding="utf-8"))
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _save_json(path: Path, data: Any) -> None:
|
|
52
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
53
|
+
path.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# ── Settings ──────────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def load_config() -> dict[str, Any]:
|
|
60
|
+
"""Load user settings, falling back to defaults."""
|
|
61
|
+
data = _load_json(CONFIG_FILE)
|
|
62
|
+
if data is None:
|
|
63
|
+
data = dict(DEFAULTS)
|
|
64
|
+
_save_json(CONFIG_FILE, data)
|
|
65
|
+
# back-fill any new keys added in future versions
|
|
66
|
+
for key, val in DEFAULTS.items():
|
|
67
|
+
data.setdefault(key, val)
|
|
68
|
+
return data
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def save_config(cfg: dict[str, Any]) -> None:
|
|
72
|
+
_save_json(CONFIG_FILE, cfg)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def cycle_option(cfg: dict[str, Any], key: str, options: list[str]) -> str:
|
|
76
|
+
"""Cycle a config value to the next option and persist."""
|
|
77
|
+
current = cfg.get(key, options[0])
|
|
78
|
+
idx = options.index(current) if current in options else -1
|
|
79
|
+
new_val = options[(idx + 1) % len(options)]
|
|
80
|
+
cfg[key] = new_val
|
|
81
|
+
save_config(cfg)
|
|
82
|
+
return new_val
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def zoom_in(cfg: dict[str, Any]) -> int:
|
|
86
|
+
"""Increase zoom level (capped at max)."""
|
|
87
|
+
current = cfg.get("zoom", 1)
|
|
88
|
+
new_val = min(current + 1, max(ZOOM_LEVELS))
|
|
89
|
+
cfg["zoom"] = new_val
|
|
90
|
+
save_config(cfg)
|
|
91
|
+
return new_val
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def zoom_out(cfg: dict[str, Any]) -> int:
|
|
95
|
+
"""Decrease zoom level (capped at min)."""
|
|
96
|
+
current = cfg.get("zoom", 1)
|
|
97
|
+
new_val = max(current - 1, min(ZOOM_LEVELS))
|
|
98
|
+
cfg["zoom"] = new_val
|
|
99
|
+
save_config(cfg)
|
|
100
|
+
return new_val
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# ── Score History ─────────────────────────────────────────────────────
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def load_history() -> list[dict[str, Any]]:
|
|
107
|
+
data = _load_json(HISTORY_FILE)
|
|
108
|
+
return data if isinstance(data, list) else []
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def save_score(entry: dict[str, Any]) -> None:
|
|
112
|
+
"""Append a score entry to history."""
|
|
113
|
+
history = load_history()
|
|
114
|
+
history.append(entry)
|
|
115
|
+
# keep last 100 scores
|
|
116
|
+
if len(history) > 100:
|
|
117
|
+
history = history[-100:]
|
|
118
|
+
_save_json(HISTORY_FILE, history)
|