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.
Files changed (31) hide show
  1. typing_cli-0.1.0/LICENSE +21 -0
  2. typing_cli-0.1.0/PKG-INFO +141 -0
  3. typing_cli-0.1.0/README.md +112 -0
  4. typing_cli-0.1.0/pyproject.toml +52 -0
  5. typing_cli-0.1.0/setup.cfg +4 -0
  6. typing_cli-0.1.0/src/typing_cli.egg-info/PKG-INFO +141 -0
  7. typing_cli-0.1.0/src/typing_cli.egg-info/SOURCES.txt +29 -0
  8. typing_cli-0.1.0/src/typing_cli.egg-info/dependency_links.txt +1 -0
  9. typing_cli-0.1.0/src/typing_cli.egg-info/entry_points.txt +3 -0
  10. typing_cli-0.1.0/src/typing_cli.egg-info/requires.txt +4 -0
  11. typing_cli-0.1.0/src/typing_cli.egg-info/top_level.txt +1 -0
  12. typing_cli-0.1.0/src/typingtest/__init__.py +3 -0
  13. typing_cli-0.1.0/src/typingtest/__main__.py +21 -0
  14. typing_cli-0.1.0/src/typingtest/core/__init__.py +0 -0
  15. typing_cli-0.1.0/src/typingtest/core/config.py +118 -0
  16. typing_cli-0.1.0/src/typingtest/core/generator.py +56 -0
  17. typing_cli-0.1.0/src/typingtest/core/stats.py +116 -0
  18. typing_cli-0.1.0/src/typingtest/core/tracker.py +106 -0
  19. typing_cli-0.1.0/src/typingtest/data/languages/english.json +24 -0
  20. typing_cli-0.1.0/src/typingtest/data/languages/french.json +24 -0
  21. typing_cli-0.1.0/src/typingtest/ui/__init__.py +0 -0
  22. typing_cli-0.1.0/src/typingtest/ui/app.py +184 -0
  23. typing_cli-0.1.0/src/typingtest/ui/screens/__init__.py +0 -0
  24. typing_cli-0.1.0/src/typingtest/ui/screens/history.py +99 -0
  25. typing_cli-0.1.0/src/typingtest/ui/screens/result.py +276 -0
  26. typing_cli-0.1.0/src/typingtest/ui/screens/splash.py +68 -0
  27. typing_cli-0.1.0/src/typingtest/ui/screens/typing_screen.py +438 -0
  28. typing_cli-0.1.0/src/typingtest/ui/widgets/__init__.py +0 -0
  29. typing_cli-0.1.0/src/typingtest/ui/widgets/character.py +273 -0
  30. typing_cli-0.1.0/src/typingtest/ui/widgets/stats_bar.py +124 -0
  31. typing_cli-0.1.0/src/typingtest/ui/widgets/typing_area.py +103 -0
@@ -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
+ [![PyPI version](https://img.shields.io/pypi/v/typing-cli.svg)](https://pypi.org/project/typing-cli/)
37
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
38
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](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
+ [![PyPI version](https://img.shields.io/pypi/v/typing-cli.svg)](https://pypi.org/project/typing-cli/)
8
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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
+ [![PyPI version](https://img.shields.io/pypi/v/typing-cli.svg)](https://pypi.org/project/typing-cli/)
37
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
38
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](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,3 @@
1
+ [console_scripts]
2
+ typing-cli = typingtest.__main__:main
3
+ typing-test = typingtest.__main__:main
@@ -0,0 +1,4 @@
1
+ textual>=0.50.0
2
+ click>=8.1.0
3
+ pyfiglet>=1.0.0
4
+ platformdirs>=4.0.0
@@ -0,0 +1 @@
1
+ typingtest
@@ -0,0 +1,3 @@
1
+ """typing-cli — A beautiful CLI typing test."""
2
+
3
+ __version__ = "0.1.0"
@@ -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)