vermink 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.
- vermink-0.1.0/LICENSE +21 -0
- vermink-0.1.0/PKG-INFO +153 -0
- vermink-0.1.0/README.md +136 -0
- vermink-0.1.0/pyproject.toml +37 -0
- vermink-0.1.0/setup.cfg +4 -0
- vermink-0.1.0/tests/test_backends.py +155 -0
- vermink-0.1.0/tests/test_cli.py +98 -0
- vermink-0.1.0/tests/test_colors.py +100 -0
- vermink-0.1.0/tests/test_config.py +175 -0
- vermink-0.1.0/tests/test_manager.py +195 -0
- vermink-0.1.0/tests/test_segments.py +104 -0
- vermink-0.1.0/vermink/__init__.py +3 -0
- vermink-0.1.0/vermink/backends/__init__.py +5 -0
- vermink-0.1.0/vermink/backends/bash.py +73 -0
- vermink-0.1.0/vermink/backends/preview.py +90 -0
- vermink-0.1.0/vermink/backends/pwsh.py +117 -0
- vermink-0.1.0/vermink/backends/zsh.py +72 -0
- vermink-0.1.0/vermink/cli.py +179 -0
- vermink-0.1.0/vermink/colors.py +109 -0
- vermink-0.1.0/vermink/config.py +132 -0
- vermink-0.1.0/vermink/errors.py +21 -0
- vermink-0.1.0/vermink/manager.py +175 -0
- vermink-0.1.0/vermink/segments.py +130 -0
- vermink-0.1.0/vermink/themes.py +89 -0
- vermink-0.1.0/vermink.egg-info/PKG-INFO +153 -0
- vermink-0.1.0/vermink.egg-info/SOURCES.txt +28 -0
- vermink-0.1.0/vermink.egg-info/dependency_links.txt +1 -0
- vermink-0.1.0/vermink.egg-info/entry_points.txt +2 -0
- vermink-0.1.0/vermink.egg-info/requires.txt +3 -0
- vermink-0.1.0/vermink.egg-info/top_level.txt +1 -0
vermink-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 TSVMV
|
|
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.
|
vermink-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vermink
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Zero-dependency terminal theme engine: compile text themes into Zsh/Bash/PowerShell prompts
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Keywords: terminal,prompt,theme,zsh,bash,powershell
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Provides-Extra: test
|
|
15
|
+
Requires-Dist: pytest; extra == "test"
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
|
|
18
|
+
# vermink
|
|
19
|
+
|
|
20
|
+
零依赖终端美化引擎:把纯文本主题编译成 Zsh / Bash / PowerShell 的提示符与状态栏。
|
|
21
|
+
|
|
22
|
+
## 安装
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install vermink
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## 快速开始
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# 生成默认 dark 主题并安装到当前 shell
|
|
32
|
+
vermink init
|
|
33
|
+
|
|
34
|
+
# 预览主题效果(不修改任何文件)
|
|
35
|
+
vermink preview dark
|
|
36
|
+
|
|
37
|
+
# 列出所有主题
|
|
38
|
+
vermink list
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 子命令
|
|
42
|
+
|
|
43
|
+
| 命令 | 说明 |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `vermink init [--shell zsh\|bash\|pwsh]` | 生成默认 dark 主题并安装 |
|
|
46
|
+
| `vermink preview <主题名> [--plain]` | 终端预览渲染效果 |
|
|
47
|
+
| `vermink install <主题名> --shell zsh\|bash\|pwsh` | 安装到 shell 启动文件(自动备份) |
|
|
48
|
+
| `vermink uninstall --shell zsh\|bash\|pwsh` | 卸载并还原备份 |
|
|
49
|
+
| `vermink list [--shell zsh\|bash\|pwsh]` | 列出主题与当前生效主题 |
|
|
50
|
+
| `vermink show <主题名>` | 打印主题源配置 |
|
|
51
|
+
|
|
52
|
+
## 主题文件
|
|
53
|
+
|
|
54
|
+
主题文件使用 INI 格式,包含以下区块:
|
|
55
|
+
|
|
56
|
+
```ini
|
|
57
|
+
## vermink theme mytheme
|
|
58
|
+
|
|
59
|
+
[palette]
|
|
60
|
+
user = bright_green
|
|
61
|
+
host = bright_cyan
|
|
62
|
+
dir = bright_blue
|
|
63
|
+
git = bright_magenta
|
|
64
|
+
git_state = yellow
|
|
65
|
+
venv = bright_green
|
|
66
|
+
time = grey
|
|
67
|
+
exit_code = red
|
|
68
|
+
|
|
69
|
+
[prompt]
|
|
70
|
+
user
|
|
71
|
+
host
|
|
72
|
+
dir
|
|
73
|
+
git
|
|
74
|
+
git_state
|
|
75
|
+
|
|
76
|
+
[status]
|
|
77
|
+
venv
|
|
78
|
+
time
|
|
79
|
+
exit_code
|
|
80
|
+
|
|
81
|
+
[format]
|
|
82
|
+
user = user
|
|
83
|
+
host = host
|
|
84
|
+
dir = dir
|
|
85
|
+
git = git
|
|
86
|
+
git_state = git_state
|
|
87
|
+
venv = venv
|
|
88
|
+
time = time
|
|
89
|
+
exit_code = exit_code
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### 区块说明
|
|
93
|
+
|
|
94
|
+
- **[palette]**:定义颜色名称,支持命名色(如 `red`、`bright_green`)、256 色(如 `208`)、HEX 色(如 `#ff8800`)、修饰符(如 `bold`、`dim`)
|
|
95
|
+
- **[prompt]**:左侧提示符显示的片段列表
|
|
96
|
+
- **[status]**:状态栏显示的片段列表(Zsh 为 RPROMPT,Bash/Pwsh 合并到主提示符)
|
|
97
|
+
- **[format]**:将片段映射到配色名,设为 `none` 表示不着色
|
|
98
|
+
|
|
99
|
+
### 可用片段
|
|
100
|
+
|
|
101
|
+
| 片段 | 说明 |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| `user` | 当前用户名 |
|
|
104
|
+
| `host` | 主机名 |
|
|
105
|
+
| `dir` | 当前目录(~ 缩写) |
|
|
106
|
+
| `git` | Git 分支名 |
|
|
107
|
+
| `git_state` | Git 状态(`*` 有修改,`+` 有未跟踪文件) |
|
|
108
|
+
| `venv` | 虚拟环境名 |
|
|
109
|
+
| `time` | 当前时间(HH:MM) |
|
|
110
|
+
| `exit_code` | 上一条命令的退出码(非零时显示) |
|
|
111
|
+
|
|
112
|
+
### 内置主题
|
|
113
|
+
|
|
114
|
+
- **dark**:深色终端主题(默认)
|
|
115
|
+
- **light**:浅色终端主题
|
|
116
|
+
|
|
117
|
+
## 自定义主题
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# 保存主题到配置目录
|
|
121
|
+
vermink init --theme dark --name mytheme --no-install
|
|
122
|
+
|
|
123
|
+
# 编辑主题
|
|
124
|
+
vim ~/.config/vermink/themes/mytheme.conf
|
|
125
|
+
|
|
126
|
+
# 安装自定义主题
|
|
127
|
+
vermink install mytheme --shell zsh
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Shell 支持
|
|
131
|
+
|
|
132
|
+
| Shell | 提示符 | 状态栏 |
|
|
133
|
+
| --- | --- | --- |
|
|
134
|
+
| Zsh | PS1 | RPROMPT(右侧) |
|
|
135
|
+
| Bash | PS1(PROMPT_COMMAND) | 合并到主提示符 |
|
|
136
|
+
| PowerShell | prompt 函数 | 合并到主提示符 |
|
|
137
|
+
|
|
138
|
+
## 开发
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# 安装开发依赖
|
|
142
|
+
pip install -e ".[test]"
|
|
143
|
+
|
|
144
|
+
# 运行测试
|
|
145
|
+
pytest tests/
|
|
146
|
+
|
|
147
|
+
# 代码检查
|
|
148
|
+
ruff check .
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## 许可证
|
|
152
|
+
|
|
153
|
+
MIT
|
vermink-0.1.0/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# vermink
|
|
2
|
+
|
|
3
|
+
零依赖终端美化引擎:把纯文本主题编译成 Zsh / Bash / PowerShell 的提示符与状态栏。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install vermink
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 快速开始
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# 生成默认 dark 主题并安装到当前 shell
|
|
15
|
+
vermink init
|
|
16
|
+
|
|
17
|
+
# 预览主题效果(不修改任何文件)
|
|
18
|
+
vermink preview dark
|
|
19
|
+
|
|
20
|
+
# 列出所有主题
|
|
21
|
+
vermink list
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## 子命令
|
|
25
|
+
|
|
26
|
+
| 命令 | 说明 |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `vermink init [--shell zsh\|bash\|pwsh]` | 生成默认 dark 主题并安装 |
|
|
29
|
+
| `vermink preview <主题名> [--plain]` | 终端预览渲染效果 |
|
|
30
|
+
| `vermink install <主题名> --shell zsh\|bash\|pwsh` | 安装到 shell 启动文件(自动备份) |
|
|
31
|
+
| `vermink uninstall --shell zsh\|bash\|pwsh` | 卸载并还原备份 |
|
|
32
|
+
| `vermink list [--shell zsh\|bash\|pwsh]` | 列出主题与当前生效主题 |
|
|
33
|
+
| `vermink show <主题名>` | 打印主题源配置 |
|
|
34
|
+
|
|
35
|
+
## 主题文件
|
|
36
|
+
|
|
37
|
+
主题文件使用 INI 格式,包含以下区块:
|
|
38
|
+
|
|
39
|
+
```ini
|
|
40
|
+
## vermink theme mytheme
|
|
41
|
+
|
|
42
|
+
[palette]
|
|
43
|
+
user = bright_green
|
|
44
|
+
host = bright_cyan
|
|
45
|
+
dir = bright_blue
|
|
46
|
+
git = bright_magenta
|
|
47
|
+
git_state = yellow
|
|
48
|
+
venv = bright_green
|
|
49
|
+
time = grey
|
|
50
|
+
exit_code = red
|
|
51
|
+
|
|
52
|
+
[prompt]
|
|
53
|
+
user
|
|
54
|
+
host
|
|
55
|
+
dir
|
|
56
|
+
git
|
|
57
|
+
git_state
|
|
58
|
+
|
|
59
|
+
[status]
|
|
60
|
+
venv
|
|
61
|
+
time
|
|
62
|
+
exit_code
|
|
63
|
+
|
|
64
|
+
[format]
|
|
65
|
+
user = user
|
|
66
|
+
host = host
|
|
67
|
+
dir = dir
|
|
68
|
+
git = git
|
|
69
|
+
git_state = git_state
|
|
70
|
+
venv = venv
|
|
71
|
+
time = time
|
|
72
|
+
exit_code = exit_code
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 区块说明
|
|
76
|
+
|
|
77
|
+
- **[palette]**:定义颜色名称,支持命名色(如 `red`、`bright_green`)、256 色(如 `208`)、HEX 色(如 `#ff8800`)、修饰符(如 `bold`、`dim`)
|
|
78
|
+
- **[prompt]**:左侧提示符显示的片段列表
|
|
79
|
+
- **[status]**:状态栏显示的片段列表(Zsh 为 RPROMPT,Bash/Pwsh 合并到主提示符)
|
|
80
|
+
- **[format]**:将片段映射到配色名,设为 `none` 表示不着色
|
|
81
|
+
|
|
82
|
+
### 可用片段
|
|
83
|
+
|
|
84
|
+
| 片段 | 说明 |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| `user` | 当前用户名 |
|
|
87
|
+
| `host` | 主机名 |
|
|
88
|
+
| `dir` | 当前目录(~ 缩写) |
|
|
89
|
+
| `git` | Git 分支名 |
|
|
90
|
+
| `git_state` | Git 状态(`*` 有修改,`+` 有未跟踪文件) |
|
|
91
|
+
| `venv` | 虚拟环境名 |
|
|
92
|
+
| `time` | 当前时间(HH:MM) |
|
|
93
|
+
| `exit_code` | 上一条命令的退出码(非零时显示) |
|
|
94
|
+
|
|
95
|
+
### 内置主题
|
|
96
|
+
|
|
97
|
+
- **dark**:深色终端主题(默认)
|
|
98
|
+
- **light**:浅色终端主题
|
|
99
|
+
|
|
100
|
+
## 自定义主题
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# 保存主题到配置目录
|
|
104
|
+
vermink init --theme dark --name mytheme --no-install
|
|
105
|
+
|
|
106
|
+
# 编辑主题
|
|
107
|
+
vim ~/.config/vermink/themes/mytheme.conf
|
|
108
|
+
|
|
109
|
+
# 安装自定义主题
|
|
110
|
+
vermink install mytheme --shell zsh
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Shell 支持
|
|
114
|
+
|
|
115
|
+
| Shell | 提示符 | 状态栏 |
|
|
116
|
+
| --- | --- | --- |
|
|
117
|
+
| Zsh | PS1 | RPROMPT(右侧) |
|
|
118
|
+
| Bash | PS1(PROMPT_COMMAND) | 合并到主提示符 |
|
|
119
|
+
| PowerShell | prompt 函数 | 合并到主提示符 |
|
|
120
|
+
|
|
121
|
+
## 开发
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# 安装开发依赖
|
|
125
|
+
pip install -e ".[test]"
|
|
126
|
+
|
|
127
|
+
# 运行测试
|
|
128
|
+
pytest tests/
|
|
129
|
+
|
|
130
|
+
# 代码检查
|
|
131
|
+
ruff check .
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 许可证
|
|
135
|
+
|
|
136
|
+
MIT
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "vermink"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Zero-dependency terminal theme engine: compile text themes into Zsh/Bash/PowerShell prompts"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
keywords = ["terminal", "prompt", "theme", "zsh", "bash", "powershell"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"Programming Language :: Python :: 3.11",
|
|
16
|
+
"Programming Language :: Python :: 3.12",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
vermink = "vermink.cli:main"
|
|
22
|
+
|
|
23
|
+
[project.optional-dependencies]
|
|
24
|
+
test = ["pytest"]
|
|
25
|
+
|
|
26
|
+
[tool.setuptools.packages.find]
|
|
27
|
+
include = ["vermink*"]
|
|
28
|
+
|
|
29
|
+
[tool.ruff]
|
|
30
|
+
line-length = 100
|
|
31
|
+
target-version = "py311"
|
|
32
|
+
|
|
33
|
+
[tool.ruff.lint]
|
|
34
|
+
ignore = ["B905"]
|
|
35
|
+
|
|
36
|
+
[tool.ruff.lint.per-file-ignores]
|
|
37
|
+
"tests/*" = ["E501"]
|
vermink-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""Tests for vermink.backends module."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from vermink.backends import bash, preview, pwsh, zsh
|
|
6
|
+
from vermink.config import parse
|
|
7
|
+
from vermink.themes import BUILT_INS
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
def dark():
|
|
12
|
+
return parse(BUILT_INS["dark"], name="dark")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@pytest.fixture
|
|
16
|
+
def light():
|
|
17
|
+
return parse(BUILT_INS["light"], name="light")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pytest.fixture
|
|
21
|
+
def minimal():
|
|
22
|
+
return parse("[palette]\nuser = green\n[prompt]\nuser\n", name="minimal")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TestZsh:
|
|
26
|
+
def test_name(self):
|
|
27
|
+
assert zsh.name == "zsh"
|
|
28
|
+
|
|
29
|
+
def test_render_contains_ps1(self, dark):
|
|
30
|
+
text = zsh.render(dark)
|
|
31
|
+
assert "PS1=" in text
|
|
32
|
+
|
|
33
|
+
def test_render_contains_rprompt(self, dark):
|
|
34
|
+
text = zsh.render(dark)
|
|
35
|
+
assert "RPROMPT=" in text
|
|
36
|
+
|
|
37
|
+
def test_render_has_precmd(self, dark):
|
|
38
|
+
text = zsh.render(dark)
|
|
39
|
+
assert "_j_precmd" in text
|
|
40
|
+
assert "add-zsh-hook" in text
|
|
41
|
+
|
|
42
|
+
def test_render_has_functions(self, dark):
|
|
43
|
+
text = zsh.render(dark)
|
|
44
|
+
assert "__j_git_state" in text
|
|
45
|
+
assert "__j_venv" in text
|
|
46
|
+
assert "__j_exit_code" in text
|
|
47
|
+
|
|
48
|
+
def test_render_minimal(self, minimal):
|
|
49
|
+
text = zsh.render(minimal)
|
|
50
|
+
assert "PS1=" in text
|
|
51
|
+
assert "RPROMPT=" not in text
|
|
52
|
+
|
|
53
|
+
def test_no_status_no_rprompt(self, minimal):
|
|
54
|
+
text = zsh.render(minimal)
|
|
55
|
+
assert "RPROMPT" not in text
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class TestBash:
|
|
59
|
+
def test_name(self):
|
|
60
|
+
assert bash.name == "bash"
|
|
61
|
+
|
|
62
|
+
def test_render_contains_ps1(self, dark):
|
|
63
|
+
text = bash.render(dark)
|
|
64
|
+
assert "PS1=" in text
|
|
65
|
+
|
|
66
|
+
def test_render_contains_prompt_command(self, dark):
|
|
67
|
+
text = bash.render(dark)
|
|
68
|
+
assert "PROMPT_COMMAND=" in text
|
|
69
|
+
|
|
70
|
+
def test_render_has_functions(self, dark):
|
|
71
|
+
text = bash.render(dark)
|
|
72
|
+
assert "__j_git_branch" in text
|
|
73
|
+
assert "__j_git_state" in text
|
|
74
|
+
assert "__j_update_ps1" in text
|
|
75
|
+
|
|
76
|
+
def test_render_has_exit_code_capture(self, dark):
|
|
77
|
+
text = bash.render(dark)
|
|
78
|
+
assert "_J_EXIT=$?" in text
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class TestPwsh:
|
|
82
|
+
def test_name(self):
|
|
83
|
+
assert pwsh.name == "pwsh"
|
|
84
|
+
|
|
85
|
+
def test_render_has_prompt_function(self, dark):
|
|
86
|
+
text = pwsh.render(dark)
|
|
87
|
+
assert "function prompt" in text
|
|
88
|
+
|
|
89
|
+
def test_render_has_default_color(self, dark):
|
|
90
|
+
text = pwsh.render(dark)
|
|
91
|
+
assert "$__j_default_color" in text
|
|
92
|
+
|
|
93
|
+
def test_render_has_psreadline(self, dark):
|
|
94
|
+
text = pwsh.render(dark)
|
|
95
|
+
assert "Set-PSReadLineOption" in text
|
|
96
|
+
|
|
97
|
+
def test_render_has_exit_capture(self, dark):
|
|
98
|
+
text = pwsh.render(dark)
|
|
99
|
+
assert "$__j_last_exit = $LASTEXITCODE" in text
|
|
100
|
+
|
|
101
|
+
def test_render_uses_consolecolor(self, dark):
|
|
102
|
+
text = pwsh.render(dark)
|
|
103
|
+
assert "[ConsoleColor]::" in text
|
|
104
|
+
|
|
105
|
+
def test_render_has_functions(self, dark):
|
|
106
|
+
text = pwsh.render(dark)
|
|
107
|
+
assert "__j_set_color" in text
|
|
108
|
+
assert "__j_seg" in text
|
|
109
|
+
assert "__j_sep" in text
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class TestPreview:
|
|
113
|
+
def test_plain_output(self, dark):
|
|
114
|
+
text = preview.render(dark, plain=True)
|
|
115
|
+
assert "预览渲染" in text
|
|
116
|
+
assert "\x1b[" not in text
|
|
117
|
+
|
|
118
|
+
def test_contains_sample_data(self, dark):
|
|
119
|
+
text = preview.render(dark, plain=True)
|
|
120
|
+
assert "main" in text
|
|
121
|
+
assert "demo" in text
|
|
122
|
+
|
|
123
|
+
def test_contains_status_info(self, dark):
|
|
124
|
+
text = preview.render(dark, plain=True)
|
|
125
|
+
assert "x1" in text
|
|
126
|
+
|
|
127
|
+
def test_color_disabled_in_pipe(self, dark):
|
|
128
|
+
assert preview.color_enabled() is False
|
|
129
|
+
|
|
130
|
+
def test_note_present(self, dark):
|
|
131
|
+
text = preview.render(dark, plain=True)
|
|
132
|
+
assert "未修改任何文件" in text
|
|
133
|
+
|
|
134
|
+
def test_status_alignment_note(self, dark):
|
|
135
|
+
text = preview.render(dark, plain=True)
|
|
136
|
+
assert "RPROMPT" in text or "状态栏" in text
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class TestBackendConsistency:
|
|
140
|
+
def test_all_backends_render_same_segments(self, dark):
|
|
141
|
+
for backend in (zsh, bash, pwsh):
|
|
142
|
+
text = backend.render(dark)
|
|
143
|
+
assert len(text) > 0
|
|
144
|
+
|
|
145
|
+
def test_all_backends_handle_empty_status(self, minimal):
|
|
146
|
+
for backend in (zsh, bash, pwsh):
|
|
147
|
+
text = backend.render(minimal)
|
|
148
|
+
assert len(text) > 0
|
|
149
|
+
|
|
150
|
+
def test_all_builtins_render(self):
|
|
151
|
+
for name, source_text in BUILT_INS.items():
|
|
152
|
+
theme = parse(source_text, name=name)
|
|
153
|
+
for backend in (zsh, bash, pwsh):
|
|
154
|
+
text = backend.render(theme)
|
|
155
|
+
assert len(text) > 0, f"{backend.name} failed for {name}"
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Tests for vermink.cli module."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from vermink.cli import main
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestVersion:
|
|
9
|
+
def test_version(self, capsys):
|
|
10
|
+
with pytest.raises(SystemExit) as exc:
|
|
11
|
+
main(["--version"])
|
|
12
|
+
assert exc.value.code == 0
|
|
13
|
+
assert "0.1.0" in capsys.readouterr().out
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TestList:
|
|
17
|
+
def test_list_includes_builtins(self, capsys):
|
|
18
|
+
main(["list", "--shell", "zsh"])
|
|
19
|
+
out = capsys.readouterr().out
|
|
20
|
+
assert "dark" in out
|
|
21
|
+
assert "light" in out
|
|
22
|
+
assert "内置" in out
|
|
23
|
+
|
|
24
|
+
def test_list_no_rc(self, capsys, tmp_path):
|
|
25
|
+
main(["list", "--shell", "zsh", "--rc", str(tmp_path / ".zshrc")])
|
|
26
|
+
out = capsys.readouterr().out
|
|
27
|
+
assert "未安装" in out
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TestShow:
|
|
31
|
+
def test_show_builtin(self, capsys):
|
|
32
|
+
main(["show", "dark"])
|
|
33
|
+
out = capsys.readouterr().out
|
|
34
|
+
assert "[palette]" in out
|
|
35
|
+
assert "bright_green" in out
|
|
36
|
+
|
|
37
|
+
def test_show_unknown(self, capsys):
|
|
38
|
+
result = main(["show", "nonexistent"])
|
|
39
|
+
assert result == 1
|
|
40
|
+
assert "找不到" in capsys.readouterr().err
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class TestPreview:
|
|
44
|
+
def test_preview_plain(self, capsys):
|
|
45
|
+
main(["preview", "dark", "--plain"])
|
|
46
|
+
out = capsys.readouterr().out
|
|
47
|
+
assert "预览渲染" in out
|
|
48
|
+
assert "main" in out
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class TestInit:
|
|
52
|
+
def test_init_no_install(self, capsys, tmp_path):
|
|
53
|
+
theme_dir = tmp_path / "themes"
|
|
54
|
+
theme_dir.mkdir()
|
|
55
|
+
result = main(["init", "--theme", "dark", "--no-install", "--dir", str(theme_dir)])
|
|
56
|
+
assert result == 0
|
|
57
|
+
out = capsys.readouterr().out
|
|
58
|
+
assert "已保存" in out
|
|
59
|
+
|
|
60
|
+
def test_init_with_install(self, capsys, tmp_path):
|
|
61
|
+
rc = tmp_path / ".zshrc"
|
|
62
|
+
result = main(["init", "--theme", "dark", "--shell", "zsh", "--rc", str(rc)])
|
|
63
|
+
assert result == 0
|
|
64
|
+
assert rc.exists()
|
|
65
|
+
out = capsys.readouterr().out
|
|
66
|
+
assert "已安装" in out
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class TestInstall:
|
|
70
|
+
def test_install_theme(self, capsys, tmp_path):
|
|
71
|
+
rc = tmp_path / ".zshrc"
|
|
72
|
+
result = main(["install", "dark", "--shell", "zsh", "--rc", str(rc)])
|
|
73
|
+
assert result == 0
|
|
74
|
+
assert rc.exists()
|
|
75
|
+
out = capsys.readouterr().out
|
|
76
|
+
assert "已安装" in out
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class TestUninstall:
|
|
80
|
+
def test_uninstall(self, capsys, tmp_path):
|
|
81
|
+
rc = tmp_path / ".zshrc"
|
|
82
|
+
rc.write_text("# >>> vermink theme theme=dark\ncontent\n# <<< vermink theme\n")
|
|
83
|
+
result = main(["uninstall", "--shell", "zsh", "--rc", str(rc)])
|
|
84
|
+
assert result == 0
|
|
85
|
+
out = capsys.readouterr().out
|
|
86
|
+
assert "已卸载" in out
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class TestErrorHandling:
|
|
90
|
+
def test_unknown_command(self, capsys):
|
|
91
|
+
with pytest.raises(SystemExit) as exc:
|
|
92
|
+
main(["badcmd"])
|
|
93
|
+
assert exc.value.code == 2
|
|
94
|
+
|
|
95
|
+
def test_missing_theme_arg(self, capsys):
|
|
96
|
+
with pytest.raises(SystemExit) as exc:
|
|
97
|
+
main(["show"])
|
|
98
|
+
assert exc.value.code == 2
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Tests for vermink.colors module."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from vermink.colors import (
|
|
6
|
+
COLORS,
|
|
7
|
+
MODIFIERS,
|
|
8
|
+
POWERSHELL_COLORS,
|
|
9
|
+
name_for_sgr,
|
|
10
|
+
powershell_color,
|
|
11
|
+
resolve,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TestResolve:
|
|
16
|
+
def test_named_color(self):
|
|
17
|
+
assert resolve("red") == "31"
|
|
18
|
+
|
|
19
|
+
def test_bright_color(self):
|
|
20
|
+
assert resolve("bright_green") == "92"
|
|
21
|
+
|
|
22
|
+
def test_modifier(self):
|
|
23
|
+
assert resolve("bold") == "1"
|
|
24
|
+
|
|
25
|
+
def test_256_color(self):
|
|
26
|
+
assert resolve("208") == "38;5;208"
|
|
27
|
+
|
|
28
|
+
def test_hex_color(self):
|
|
29
|
+
assert resolve("#ff8800") == "38;2;255;136;0"
|
|
30
|
+
|
|
31
|
+
def test_composite(self):
|
|
32
|
+
assert resolve("bright_blue,bold") == "94;1"
|
|
33
|
+
|
|
34
|
+
def test_empty(self):
|
|
35
|
+
assert resolve("") == ""
|
|
36
|
+
|
|
37
|
+
def test_none_keyword(self):
|
|
38
|
+
assert resolve("none") == ""
|
|
39
|
+
|
|
40
|
+
def test_case_insensitive(self):
|
|
41
|
+
assert resolve("RED") == "31"
|
|
42
|
+
assert resolve("Bright_Green") == "92"
|
|
43
|
+
|
|
44
|
+
def test_unknown_color_raises(self):
|
|
45
|
+
with pytest.raises(Exception, match="未知颜色"):
|
|
46
|
+
resolve("not_a_color")
|
|
47
|
+
|
|
48
|
+
def test_invalid_hex_raises(self):
|
|
49
|
+
with pytest.raises(Exception, match="未知颜色"):
|
|
50
|
+
resolve("#gg0000")
|
|
51
|
+
|
|
52
|
+
def test_context_in_error(self):
|
|
53
|
+
with pytest.raises(Exception, match="配色 foo"):
|
|
54
|
+
resolve("bad", context="配色 foo")
|
|
55
|
+
|
|
56
|
+
def test_path_and_line_in_error(self):
|
|
57
|
+
with pytest.raises(Exception, match="theme.conf:42"):
|
|
58
|
+
resolve("bad", path="theme.conf", line=42)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class TestPowershellColor:
|
|
62
|
+
def test_named_color(self):
|
|
63
|
+
assert powershell_color("red") == "DarkRed"
|
|
64
|
+
|
|
65
|
+
def test_bright_color(self):
|
|
66
|
+
assert powershell_color("bright_green") == "Green"
|
|
67
|
+
|
|
68
|
+
def test_alias(self):
|
|
69
|
+
assert powershell_color("grey") == "Gray"
|
|
70
|
+
|
|
71
|
+
def test_unknown_returns_empty(self):
|
|
72
|
+
assert powershell_color("208") == ""
|
|
73
|
+
|
|
74
|
+
def test_hex_returns_empty(self):
|
|
75
|
+
assert powershell_color("#ff0000") == ""
|
|
76
|
+
|
|
77
|
+
def test_composite_returns_first(self):
|
|
78
|
+
assert powershell_color("bright_blue,bold") == "Blue"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class TestNameForSgr:
|
|
82
|
+
def test_basic_colors(self):
|
|
83
|
+
assert name_for_sgr("31") == "red"
|
|
84
|
+
assert name_for_sgr("92") == "bright_green"
|
|
85
|
+
|
|
86
|
+
def test_unknown_returns_empty(self):
|
|
87
|
+
assert name_for_sgr("999") == ""
|
|
88
|
+
|
|
89
|
+
def test_composite_returns_empty(self):
|
|
90
|
+
assert name_for_sgr("94;1") == ""
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class TestConstants:
|
|
94
|
+
def test_colors_is_subset_of_powershell(self):
|
|
95
|
+
for name in COLORS:
|
|
96
|
+
assert name in POWERSHELL_COLORS, f"{name} missing from POWERSHELL_COLORS"
|
|
97
|
+
|
|
98
|
+
def test_modifiers_not_in_colors(self):
|
|
99
|
+
for name in MODIFIERS:
|
|
100
|
+
assert name not in COLORS
|