gitnc 0.1.2__py3-none-any.whl
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.
- gitnc/__init__.py +3 -0
- gitnc/__main__.py +15 -0
- gitnc/app.py +4699 -0
- gitnc/git.py +1052 -0
- gitnc/terminal.py +230 -0
- gitnc/themes/__init__.py +25 -0
- gitnc/themes/atom-one-dark.yaml +100 -0
- gitnc/themes/atom-one-light.yaml +100 -0
- gitnc/themes/catppuccin-frappe.yaml +108 -0
- gitnc/themes/catppuccin-latte.yaml +101 -0
- gitnc/themes/catppuccin-macchiato.yaml +108 -0
- gitnc/themes/catppuccin-mocha.yaml +108 -0
- gitnc/themes/dracula.yaml +101 -0
- gitnc/themes/flexoki.yaml +103 -0
- gitnc/themes/gruvbox.yaml +102 -0
- gitnc/themes/midnight-commander.yaml +104 -0
- gitnc/themes/monokai.yaml +102 -0
- gitnc/themes/nord.yaml +106 -0
- gitnc/themes/rose-pine-dawn.yaml +107 -0
- gitnc/themes/rose-pine-moon.yaml +107 -0
- gitnc/themes/rose-pine.yaml +107 -0
- gitnc/themes/solarized-dark.yaml +104 -0
- gitnc/themes/solarized-light.yaml +104 -0
- gitnc/themes/textual-ansi.yaml +110 -0
- gitnc/themes/textual-dark.yaml +100 -0
- gitnc/themes/textual-light.yaml +101 -0
- gitnc/themes/tokyo-night.yaml +101 -0
- gitnc/ui_theme.py +268 -0
- gitnc-0.1.2.dist-info/METADATA +14 -0
- gitnc-0.1.2.dist-info/RECORD +33 -0
- gitnc-0.1.2.dist-info/WHEEL +4 -0
- gitnc-0.1.2.dist-info/entry_points.txt +2 -0
- gitnc-0.1.2.dist-info/licenses/LICENSE +232 -0
gitnc/terminal.py
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"""Terminal screen session management and git display helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import shlex
|
|
7
|
+
import shutil
|
|
8
|
+
import sys
|
|
9
|
+
from collections.abc import Callable, Mapping
|
|
10
|
+
|
|
11
|
+
from .git import GIT, GitCode, GitEntry, GitFilelist, GitStatus
|
|
12
|
+
|
|
13
|
+
PREVIOUS_SCREEN_TOGGLE_KEY = "\x0f"
|
|
14
|
+
|
|
15
|
+
# Midnight Commander exports `MC_SID` into the subshell it runs commands in,
|
|
16
|
+
# and `MC_TMPDIR` into its own environment, which a command started with the
|
|
17
|
+
# subshell disabled (`mc -u`) inherits. Either one means mc is our ancestor.
|
|
18
|
+
MIDNIGHT_COMMANDER_ENV_VARS = ("MC_SID", "MC_TMPDIR")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def started_from_midnight_commander(environ: Mapping[str, str] | None = None) -> bool:
|
|
22
|
+
"""Whether the process runs under Midnight Commander.
|
|
23
|
+
|
|
24
|
+
Under mc's subshell the keyboard doesn't reach us directly: mc reads the
|
|
25
|
+
terminal and forwards the keys to the subshell's pty, and it keeps its own
|
|
26
|
+
`Ctrl+O` — the key that toggles our previous screen — to switch back to
|
|
27
|
+
its panels, leaving this app running out of sight.
|
|
28
|
+
"""
|
|
29
|
+
env = os.environ if environ is None else environ
|
|
30
|
+
return any(env.get(name) for name in MIDNIGHT_COMMANDER_ENV_VARS)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Terminal:
|
|
34
|
+
"""Utility class for terminal screen management and git display helpers."""
|
|
35
|
+
|
|
36
|
+
def load_commits(self, path: str = ".") -> list:
|
|
37
|
+
return GIT(path).load_commits()
|
|
38
|
+
|
|
39
|
+
def load_file_diff(self, path: str, entry: GitEntry) -> str:
|
|
40
|
+
return GIT(path).load_file_diff(entry)
|
|
41
|
+
|
|
42
|
+
def load_status(self, path: str = ".") -> GitFilelist:
|
|
43
|
+
return GIT(path).load_status()
|
|
44
|
+
|
|
45
|
+
def status_markup(self, code: GitCode, filename: str) -> str:
|
|
46
|
+
label = code.value
|
|
47
|
+
if code.is_untracked:
|
|
48
|
+
color = "dim"
|
|
49
|
+
elif code.contains(GitStatus.ADDED):
|
|
50
|
+
color = "green"
|
|
51
|
+
elif code.contains(GitStatus.DELETED):
|
|
52
|
+
color = "red"
|
|
53
|
+
elif code.contains(GitStatus.RENAMED):
|
|
54
|
+
color = "cyan"
|
|
55
|
+
else:
|
|
56
|
+
color = "yellow"
|
|
57
|
+
return f"[{color}]{label}[/{color}] {filename}"
|
|
58
|
+
|
|
59
|
+
def _wait_for_toggle_key(
|
|
60
|
+
self, read_key: Callable[[], str], toggle_key: str = PREVIOUS_SCREEN_TOGGLE_KEY
|
|
61
|
+
) -> None:
|
|
62
|
+
while read_key() != toggle_key:
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
def _read_key_posix(self) -> str:
|
|
66
|
+
if not sys.stdin.isatty():
|
|
67
|
+
raise OSError("stdin is not a tty")
|
|
68
|
+
|
|
69
|
+
import termios
|
|
70
|
+
import tty
|
|
71
|
+
|
|
72
|
+
fd = sys.stdin.fileno()
|
|
73
|
+
saved = termios.tcgetattr(fd)
|
|
74
|
+
try:
|
|
75
|
+
tty.setraw(fd)
|
|
76
|
+
while True:
|
|
77
|
+
key = os.read(fd, 1)
|
|
78
|
+
if key:
|
|
79
|
+
return key.decode(errors="ignore")
|
|
80
|
+
finally:
|
|
81
|
+
termios.tcsetattr(fd, termios.TCSADRAIN, saved)
|
|
82
|
+
|
|
83
|
+
def _read_key_windows(self) -> str:
|
|
84
|
+
# Only reached when os.name == "nt"; the assert tells the type checker so,
|
|
85
|
+
# since msvcrt's stubs are Windows-only.
|
|
86
|
+
assert sys.platform == "win32"
|
|
87
|
+
import msvcrt
|
|
88
|
+
|
|
89
|
+
getwch = msvcrt.getwch
|
|
90
|
+
while True:
|
|
91
|
+
key = getwch()
|
|
92
|
+
if key in ("\x00", "\xe0"):
|
|
93
|
+
getwch()
|
|
94
|
+
continue
|
|
95
|
+
return key
|
|
96
|
+
|
|
97
|
+
def wait_for_previous_screen_toggle(self) -> None:
|
|
98
|
+
read_key = self._read_key_windows if os.name == "nt" else self._read_key_posix
|
|
99
|
+
self._wait_for_toggle_key(read_key)
|
|
100
|
+
|
|
101
|
+
def write_previous_screen(self, text: str) -> None:
|
|
102
|
+
"""Write `text` to the terminal the TUI was started from.
|
|
103
|
+
|
|
104
|
+
Only meaningful while the app is suspended: Textual has left the
|
|
105
|
+
alternate screen buffer by then, so the text lands on the previous
|
|
106
|
+
screen and stays in its scrollback — which is what makes it readable
|
|
107
|
+
again later, when `Ctrl+O` puts a shell on that same screen.
|
|
108
|
+
|
|
109
|
+
`sys.stdout` is read per call rather than captured, because
|
|
110
|
+
`App.suspend()` rebinds it to the real stdout for the length of the
|
|
111
|
+
block. A closed or redirected stream isn't worth failing the caller
|
|
112
|
+
over, so the write is best-effort.
|
|
113
|
+
"""
|
|
114
|
+
try:
|
|
115
|
+
sys.stdout.write(text)
|
|
116
|
+
sys.stdout.flush()
|
|
117
|
+
except (OSError, ValueError):
|
|
118
|
+
pass
|
|
119
|
+
|
|
120
|
+
def previous_screen_shell_command(self) -> list[str]:
|
|
121
|
+
env_var = "COMSPEC" if os.name == "nt" else "SHELL"
|
|
122
|
+
raw_shell = os.environ.get(env_var) or ("cmd.exe" if os.name == "nt" else "/bin/sh")
|
|
123
|
+
argv = shlex.split(raw_shell, posix=os.name != "nt")
|
|
124
|
+
if not argv:
|
|
125
|
+
raise OSError(f"{env_var} does not define a shell")
|
|
126
|
+
argv[0] = shutil.which(argv[0]) or argv[0]
|
|
127
|
+
if os.name != "nt" and "-i" not in argv[1:]:
|
|
128
|
+
argv.append("-i")
|
|
129
|
+
return argv
|
|
130
|
+
|
|
131
|
+
def _terminate_previous_screen_shell(self, pid: int) -> None:
|
|
132
|
+
import signal
|
|
133
|
+
import time
|
|
134
|
+
|
|
135
|
+
signals = (signal.SIGHUP, signal.SIGTERM, signal.SIGKILL)
|
|
136
|
+
for sig in signals:
|
|
137
|
+
try:
|
|
138
|
+
os.killpg(pid, sig)
|
|
139
|
+
except ProcessLookupError:
|
|
140
|
+
break
|
|
141
|
+
|
|
142
|
+
deadline = time.monotonic() + 0.2
|
|
143
|
+
while time.monotonic() < deadline:
|
|
144
|
+
waited_pid, _ = os.waitpid(pid, os.WNOHANG)
|
|
145
|
+
if waited_pid == pid:
|
|
146
|
+
return
|
|
147
|
+
time.sleep(0.01)
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
os.waitpid(pid, 0)
|
|
151
|
+
except ChildProcessError:
|
|
152
|
+
pass
|
|
153
|
+
|
|
154
|
+
def _run_previous_screen_shell_posix(
|
|
155
|
+
self, toggle_key: str = PREVIOUS_SCREEN_TOGGLE_KEY
|
|
156
|
+
) -> None:
|
|
157
|
+
import fcntl
|
|
158
|
+
import pty
|
|
159
|
+
import select
|
|
160
|
+
import termios
|
|
161
|
+
import tty
|
|
162
|
+
|
|
163
|
+
if not sys.stdin.isatty() or not sys.stdout.isatty():
|
|
164
|
+
raise OSError("stdin/stdout are not tty devices")
|
|
165
|
+
|
|
166
|
+
argv = self.previous_screen_shell_command()
|
|
167
|
+
pid, master_fd = pty.fork()
|
|
168
|
+
if pid == 0:
|
|
169
|
+
try:
|
|
170
|
+
os.execvpe(argv[0], argv, os.environ.copy())
|
|
171
|
+
except OSError as exc:
|
|
172
|
+
print(f"Unable to launch shell: {exc}", file=sys.stderr)
|
|
173
|
+
os._exit(1)
|
|
174
|
+
|
|
175
|
+
stdin_fd = sys.stdin.fileno()
|
|
176
|
+
stdout_fd = sys.stdout.fileno()
|
|
177
|
+
saved = termios.tcgetattr(stdin_fd)
|
|
178
|
+
toggle = toggle_key.encode()
|
|
179
|
+
toggled = False
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
try:
|
|
183
|
+
window_size = fcntl.ioctl(stdin_fd, termios.TIOCGWINSZ, b"\x00" * 8)
|
|
184
|
+
fcntl.ioctl(master_fd, termios.TIOCSWINSZ, window_size)
|
|
185
|
+
except OSError:
|
|
186
|
+
pass
|
|
187
|
+
|
|
188
|
+
tty.setraw(stdin_fd)
|
|
189
|
+
while True:
|
|
190
|
+
ready, _, _ = select.select([stdin_fd, master_fd], [], [])
|
|
191
|
+
if stdin_fd in ready:
|
|
192
|
+
try:
|
|
193
|
+
data = os.read(stdin_fd, 1024)
|
|
194
|
+
except OSError:
|
|
195
|
+
break
|
|
196
|
+
if not data:
|
|
197
|
+
break
|
|
198
|
+
toggle_at = data.find(toggle)
|
|
199
|
+
if toggle_at != -1:
|
|
200
|
+
if toggle_at:
|
|
201
|
+
os.write(master_fd, data[:toggle_at])
|
|
202
|
+
toggled = True
|
|
203
|
+
break
|
|
204
|
+
os.write(master_fd, data)
|
|
205
|
+
if master_fd in ready:
|
|
206
|
+
try:
|
|
207
|
+
output = os.read(master_fd, 4096)
|
|
208
|
+
except OSError:
|
|
209
|
+
break
|
|
210
|
+
if not output:
|
|
211
|
+
break
|
|
212
|
+
os.write(stdout_fd, output)
|
|
213
|
+
finally:
|
|
214
|
+
termios.tcsetattr(stdin_fd, termios.TCSADRAIN, saved)
|
|
215
|
+
os.close(master_fd)
|
|
216
|
+
|
|
217
|
+
if toggled:
|
|
218
|
+
self._terminate_previous_screen_shell(pid)
|
|
219
|
+
return
|
|
220
|
+
|
|
221
|
+
try:
|
|
222
|
+
os.waitpid(pid, 0)
|
|
223
|
+
except ChildProcessError:
|
|
224
|
+
pass
|
|
225
|
+
|
|
226
|
+
def run_previous_screen_session(self) -> None:
|
|
227
|
+
if os.name == "nt":
|
|
228
|
+
self.wait_for_previous_screen_toggle()
|
|
229
|
+
return
|
|
230
|
+
self._run_previous_screen_shell_posix()
|
gitnc/themes/__init__.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Theme definitions, one YAML file per theme.
|
|
2
|
+
|
|
3
|
+
Each ``*.yaml`` file in this package describes a single UITheme. The file
|
|
4
|
+
name (without extension) matches the theme's ``name`` field. ``load_all``
|
|
5
|
+
discovers every YAML file in the package directory and returns the
|
|
6
|
+
resulting ``UITheme`` instances.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from ..ui_theme import UITheme
|
|
14
|
+
|
|
15
|
+
THEMES_DIR = Path(__file__).resolve().parent
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def theme_files() -> list[Path]:
|
|
19
|
+
"""Return every theme YAML file in declaration-stable order."""
|
|
20
|
+
return sorted(THEMES_DIR.glob("*.yaml"))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def load_all() -> list[UITheme]:
|
|
24
|
+
"""Load every theme YAML file as a UITheme instance."""
|
|
25
|
+
return [UITheme.load(path) for path in theme_files()]
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Textual theme palette. These fields are forwarded to textual.theme.Theme,
|
|
2
|
+
# which colors the application chrome (borders, buttons, headers, scrollbars).
|
|
3
|
+
# `name` is the identifier shown in the Theme menu and persisted in settings.json.
|
|
4
|
+
# Color values accept any CSS-style color (hex, ansi_*, rgb()).
|
|
5
|
+
name: atom-one-dark
|
|
6
|
+
primary: '#61AFEF'
|
|
7
|
+
secondary: '#C678DD'
|
|
8
|
+
warning: '#DEB25B'
|
|
9
|
+
error: '#F06262'
|
|
10
|
+
success: '#62F062'
|
|
11
|
+
accent: '#A378C2'
|
|
12
|
+
foreground: '#ABB2BF'
|
|
13
|
+
background: '#282C34'
|
|
14
|
+
surface: '#3B414D'
|
|
15
|
+
panel: '#4F5666'
|
|
16
|
+
boost: null
|
|
17
|
+
|
|
18
|
+
# Theme behavior flags.
|
|
19
|
+
# `dark` selects dark-mode contrast defaults inside Textual.
|
|
20
|
+
# `luminosity_spread` / `text_alpha` tune Textual's automatic shade derivation.
|
|
21
|
+
# `variables` are passed through to Textual's CSS variable table
|
|
22
|
+
# (use kebab-case keys, e.g. `block-cursor-foreground`).
|
|
23
|
+
# `ansi: true` opts the theme into the terminal's own ANSI palette
|
|
24
|
+
# instead of fixed hex colors.
|
|
25
|
+
dark: true
|
|
26
|
+
luminosity_spread: 0.15
|
|
27
|
+
text_alpha: 0.95
|
|
28
|
+
variables: {}
|
|
29
|
+
ansi: false
|
|
30
|
+
|
|
31
|
+
# Status-code colors painted in the Status column of the file list.
|
|
32
|
+
# Values are Rich style strings (e.g. "bold yellow", "#ff8800").
|
|
33
|
+
status_modified: bold yellow
|
|
34
|
+
status_type_changed: 'bold #ff8800'
|
|
35
|
+
status_added: bold green
|
|
36
|
+
status_deleted: bold red
|
|
37
|
+
status_renamed: bold cyan
|
|
38
|
+
status_copied: bold blue
|
|
39
|
+
status_unmerged: 'bold #ff5555'
|
|
40
|
+
status_untracked: bold white
|
|
41
|
+
status_ignored: '#888888'
|
|
42
|
+
status_submodule: bold magenta
|
|
43
|
+
|
|
44
|
+
# Diff line rendering inside FileDiff.
|
|
45
|
+
# Added/removed lines get a foreground color and a dimmer matching line-number gutter.
|
|
46
|
+
diff_added_line: green
|
|
47
|
+
diff_added_line_number: green dim
|
|
48
|
+
diff_removed_line: red
|
|
49
|
+
diff_removed_line_number: red dim
|
|
50
|
+
diff_context_line_number: dim
|
|
51
|
+
|
|
52
|
+
# Commit detail rendering inside CommitDetail (git show output).
|
|
53
|
+
# The commit/Author/Date header block, and the @@ hunk markers of a patch.
|
|
54
|
+
commit_header_line: bold
|
|
55
|
+
diff_hunk_header: cyan
|
|
56
|
+
|
|
57
|
+
# Y/N hint shown at the bottom of the confirm dialog.
|
|
58
|
+
confirm_yes_key: b green
|
|
59
|
+
confirm_no_key: b red
|
|
60
|
+
|
|
61
|
+
# Warning text shown above the file list (e.g. submodule branch mismatches).
|
|
62
|
+
warning_text: bold red
|
|
63
|
+
|
|
64
|
+
# Faint hint text at the bottom of dialogs (e.g. "(Esc cancels)").
|
|
65
|
+
dialog_hint: dim
|
|
66
|
+
|
|
67
|
+
# Accelerator letter highlighted in the menu bar and in dropdown entries.
|
|
68
|
+
# Must stay readable on the menu bar ($menu-bar-background) and dropdown ($panel)
|
|
69
|
+
# backgrounds.
|
|
70
|
+
menu_mnemonic: bold underline
|
|
71
|
+
|
|
72
|
+
# Settings dialog checkbox mark color.
|
|
73
|
+
checkbox_mark: green
|
|
74
|
+
|
|
75
|
+
# Settings dialog text caret. It is drawn on the cell it sits on, so it
|
|
76
|
+
# swaps that cell's colors instead of painting one of its own.
|
|
77
|
+
text_caret: reverse
|
|
78
|
+
|
|
79
|
+
# Selected text in the commit message box (Shift+arrows). Empty keeps
|
|
80
|
+
# Textual's default: $primary lightened at 40% opacity over the background.
|
|
81
|
+
text_selection_background: ''
|
|
82
|
+
text_selection_foreground: ''
|
|
83
|
+
|
|
84
|
+
# Chrome colors for the menu bar and the footer. The defaults are Textual's
|
|
85
|
+
# own Header/Footer palette, so the bars match every other Textual app.
|
|
86
|
+
# Values may reference this theme's palette fields with `$name`.
|
|
87
|
+
menu_bar_background: $panel
|
|
88
|
+
menu_bar_foreground: $foreground
|
|
89
|
+
footer_background: $panel
|
|
90
|
+
footer_foreground: $foreground
|
|
91
|
+
|
|
92
|
+
# CSS variables emitted for the file-list cursor and multi-selection.
|
|
93
|
+
# Values may reference Textual palette variables with `$name` (e.g. `$primary`).
|
|
94
|
+
# References are resolved against this theme's own fields when the CSS is generated.
|
|
95
|
+
cursor_row_background: $primary
|
|
96
|
+
cursor_row_foreground: $foreground
|
|
97
|
+
selected_file_background: $warning 30%
|
|
98
|
+
selected_file_foreground: $success
|
|
99
|
+
selected_cursor_row_background: $primary
|
|
100
|
+
selected_cursor_row_foreground: $success
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Textual theme palette. These fields are forwarded to textual.theme.Theme,
|
|
2
|
+
# which colors the application chrome (borders, buttons, headers, scrollbars).
|
|
3
|
+
# `name` is the identifier shown in the Theme menu and persisted in settings.json.
|
|
4
|
+
# Color values accept any CSS-style color (hex, ansi_*, rgb()).
|
|
5
|
+
name: atom-one-light
|
|
6
|
+
primary: '#4078F2'
|
|
7
|
+
secondary: '#A626A4'
|
|
8
|
+
warning: '#D8D938'
|
|
9
|
+
error: '#F23F3F'
|
|
10
|
+
success: '#6CF23F'
|
|
11
|
+
accent: '#bf9232'
|
|
12
|
+
foreground: '#383A42'
|
|
13
|
+
background: '#FAFAFA'
|
|
14
|
+
surface: '#E0E0E0'
|
|
15
|
+
panel: '#CCCCCC'
|
|
16
|
+
boost: null
|
|
17
|
+
|
|
18
|
+
# Theme behavior flags.
|
|
19
|
+
# `dark` selects dark-mode contrast defaults inside Textual.
|
|
20
|
+
# `luminosity_spread` / `text_alpha` tune Textual's automatic shade derivation.
|
|
21
|
+
# `variables` are passed through to Textual's CSS variable table
|
|
22
|
+
# (use kebab-case keys, e.g. `block-cursor-foreground`).
|
|
23
|
+
# `ansi: true` opts the theme into the terminal's own ANSI palette
|
|
24
|
+
# instead of fixed hex colors.
|
|
25
|
+
dark: false
|
|
26
|
+
luminosity_spread: 0.15
|
|
27
|
+
text_alpha: 0.95
|
|
28
|
+
variables: {}
|
|
29
|
+
ansi: false
|
|
30
|
+
|
|
31
|
+
# Status-code colors painted in the Status column of the file list.
|
|
32
|
+
# Values are Rich style strings (e.g. "bold yellow", "#ff8800").
|
|
33
|
+
status_modified: bold yellow
|
|
34
|
+
status_type_changed: 'bold #ff8800'
|
|
35
|
+
status_added: bold green
|
|
36
|
+
status_deleted: bold red
|
|
37
|
+
status_renamed: bold cyan
|
|
38
|
+
status_copied: bold blue
|
|
39
|
+
status_unmerged: 'bold #ff5555'
|
|
40
|
+
status_untracked: bold white
|
|
41
|
+
status_ignored: '#888888'
|
|
42
|
+
status_submodule: bold magenta
|
|
43
|
+
|
|
44
|
+
# Diff line rendering inside FileDiff.
|
|
45
|
+
# Added/removed lines get a foreground color and a dimmer matching line-number gutter.
|
|
46
|
+
diff_added_line: green
|
|
47
|
+
diff_added_line_number: green dim
|
|
48
|
+
diff_removed_line: red
|
|
49
|
+
diff_removed_line_number: red dim
|
|
50
|
+
diff_context_line_number: dim
|
|
51
|
+
|
|
52
|
+
# Commit detail rendering inside CommitDetail (git show output).
|
|
53
|
+
# The commit/Author/Date header block, and the @@ hunk markers of a patch.
|
|
54
|
+
commit_header_line: bold
|
|
55
|
+
diff_hunk_header: cyan
|
|
56
|
+
|
|
57
|
+
# Y/N hint shown at the bottom of the confirm dialog.
|
|
58
|
+
confirm_yes_key: b green
|
|
59
|
+
confirm_no_key: b red
|
|
60
|
+
|
|
61
|
+
# Warning text shown above the file list (e.g. submodule branch mismatches).
|
|
62
|
+
warning_text: bold red
|
|
63
|
+
|
|
64
|
+
# Faint hint text at the bottom of dialogs (e.g. "(Esc cancels)").
|
|
65
|
+
dialog_hint: dim
|
|
66
|
+
|
|
67
|
+
# Accelerator letter highlighted in the menu bar and in dropdown entries.
|
|
68
|
+
# Must stay readable on the menu bar ($menu-bar-background) and dropdown ($panel)
|
|
69
|
+
# backgrounds.
|
|
70
|
+
menu_mnemonic: bold underline
|
|
71
|
+
|
|
72
|
+
# Settings dialog checkbox mark color.
|
|
73
|
+
checkbox_mark: green
|
|
74
|
+
|
|
75
|
+
# Settings dialog text caret. It is drawn on the cell it sits on, so it
|
|
76
|
+
# swaps that cell's colors instead of painting one of its own.
|
|
77
|
+
text_caret: reverse
|
|
78
|
+
|
|
79
|
+
# Selected text in the commit message box (Shift+arrows). Empty keeps
|
|
80
|
+
# Textual's default: $primary lightened at 40% opacity over the background.
|
|
81
|
+
text_selection_background: ''
|
|
82
|
+
text_selection_foreground: ''
|
|
83
|
+
|
|
84
|
+
# Chrome colors for the menu bar and the footer. The defaults are Textual's
|
|
85
|
+
# own Header/Footer palette, so the bars match every other Textual app.
|
|
86
|
+
# Values may reference this theme's palette fields with `$name`.
|
|
87
|
+
menu_bar_background: $panel
|
|
88
|
+
menu_bar_foreground: $foreground
|
|
89
|
+
footer_background: $panel
|
|
90
|
+
footer_foreground: $foreground
|
|
91
|
+
|
|
92
|
+
# CSS variables emitted for the file-list cursor and multi-selection.
|
|
93
|
+
# Values may reference Textual palette variables with `$name` (e.g. `$primary`).
|
|
94
|
+
# References are resolved against this theme's own fields when the CSS is generated.
|
|
95
|
+
cursor_row_background: $primary
|
|
96
|
+
cursor_row_foreground: $foreground
|
|
97
|
+
selected_file_background: $warning 30%
|
|
98
|
+
selected_file_foreground: $success
|
|
99
|
+
selected_cursor_row_background: $primary
|
|
100
|
+
selected_cursor_row_foreground: $success
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Textual theme palette. These fields are forwarded to textual.theme.Theme,
|
|
2
|
+
# which colors the application chrome (borders, buttons, headers, scrollbars).
|
|
3
|
+
# `name` is the identifier shown in the Theme menu and persisted in settings.json.
|
|
4
|
+
# Color values accept any CSS-style color (hex, ansi_*, rgb()).
|
|
5
|
+
name: catppuccin-frappe
|
|
6
|
+
primary: '#CA9EE6'
|
|
7
|
+
secondary: '#EF9F76'
|
|
8
|
+
warning: '#E5C890'
|
|
9
|
+
error: '#E78284'
|
|
10
|
+
success: '#A6D189'
|
|
11
|
+
accent: '#F4B8E4'
|
|
12
|
+
foreground: '#C6D0F5'
|
|
13
|
+
background: '#303446'
|
|
14
|
+
surface: '#414559'
|
|
15
|
+
panel: '#51576D'
|
|
16
|
+
boost: null
|
|
17
|
+
|
|
18
|
+
# Theme behavior flags.
|
|
19
|
+
# `dark` selects dark-mode contrast defaults inside Textual.
|
|
20
|
+
# `luminosity_spread` / `text_alpha` tune Textual's automatic shade derivation.
|
|
21
|
+
# `variables` are passed through to Textual's CSS variable table
|
|
22
|
+
# (use kebab-case keys, e.g. `block-cursor-foreground`).
|
|
23
|
+
# `ansi: true` opts the theme into the terminal's own ANSI palette
|
|
24
|
+
# instead of fixed hex colors.
|
|
25
|
+
dark: true
|
|
26
|
+
luminosity_spread: 0.15
|
|
27
|
+
text_alpha: 0.95
|
|
28
|
+
variables:
|
|
29
|
+
input-cursor-foreground: '#232634'
|
|
30
|
+
input-cursor-background: '#F2D5CF'
|
|
31
|
+
border: '#BABBF1'
|
|
32
|
+
border-blurred: '#838BA7'
|
|
33
|
+
footer-background: '#51576D'
|
|
34
|
+
block-cursor-foreground: '#292C3C'
|
|
35
|
+
block-cursor-text-style: none
|
|
36
|
+
button-color-foreground: '#303446'
|
|
37
|
+
ansi: false
|
|
38
|
+
|
|
39
|
+
# Status-code colors painted in the Status column of the file list.
|
|
40
|
+
# Values are Rich style strings (e.g. "bold yellow", "#ff8800").
|
|
41
|
+
status_modified: bold yellow
|
|
42
|
+
status_type_changed: 'bold #ff8800'
|
|
43
|
+
status_added: bold green
|
|
44
|
+
status_deleted: bold red
|
|
45
|
+
status_renamed: bold cyan
|
|
46
|
+
status_copied: bold blue
|
|
47
|
+
status_unmerged: 'bold #ff5555'
|
|
48
|
+
status_untracked: bold white
|
|
49
|
+
status_ignored: '#888888'
|
|
50
|
+
status_submodule: bold magenta
|
|
51
|
+
|
|
52
|
+
# Diff line rendering inside FileDiff.
|
|
53
|
+
# Added/removed lines get a foreground color and a dimmer matching line-number gutter.
|
|
54
|
+
diff_added_line: green
|
|
55
|
+
diff_added_line_number: green dim
|
|
56
|
+
diff_removed_line: red
|
|
57
|
+
diff_removed_line_number: red dim
|
|
58
|
+
diff_context_line_number: dim
|
|
59
|
+
|
|
60
|
+
# Commit detail rendering inside CommitDetail (git show output).
|
|
61
|
+
# The commit/Author/Date header block, and the @@ hunk markers of a patch.
|
|
62
|
+
commit_header_line: bold
|
|
63
|
+
diff_hunk_header: cyan
|
|
64
|
+
|
|
65
|
+
# Y/N hint shown at the bottom of the confirm dialog.
|
|
66
|
+
confirm_yes_key: b green
|
|
67
|
+
confirm_no_key: b red
|
|
68
|
+
|
|
69
|
+
# Warning text shown above the file list (e.g. submodule branch mismatches).
|
|
70
|
+
warning_text: bold red
|
|
71
|
+
|
|
72
|
+
# Faint hint text at the bottom of dialogs (e.g. "(Esc cancels)").
|
|
73
|
+
dialog_hint: dim
|
|
74
|
+
|
|
75
|
+
# Accelerator letter highlighted in the menu bar and in dropdown entries.
|
|
76
|
+
# Must stay readable on the menu bar ($menu-bar-background) and dropdown ($panel)
|
|
77
|
+
# backgrounds.
|
|
78
|
+
menu_mnemonic: bold underline
|
|
79
|
+
|
|
80
|
+
# Settings dialog checkbox mark color.
|
|
81
|
+
checkbox_mark: green
|
|
82
|
+
|
|
83
|
+
# Settings dialog text caret. It is drawn on the cell it sits on, so it
|
|
84
|
+
# swaps that cell's colors instead of painting one of its own.
|
|
85
|
+
text_caret: reverse
|
|
86
|
+
|
|
87
|
+
# Selected text in the commit message box (Shift+arrows). Empty keeps
|
|
88
|
+
# Textual's default: $primary lightened at 40% opacity over the background.
|
|
89
|
+
text_selection_background: '#949CBB 30%'
|
|
90
|
+
text_selection_foreground: ''
|
|
91
|
+
|
|
92
|
+
# Chrome colors for the menu bar and the footer. The defaults are Textual's
|
|
93
|
+
# own Header/Footer palette, so the bars match every other Textual app.
|
|
94
|
+
# Values may reference this theme's palette fields with `$name`.
|
|
95
|
+
menu_bar_background: $panel
|
|
96
|
+
menu_bar_foreground: $foreground
|
|
97
|
+
footer_background: $panel
|
|
98
|
+
footer_foreground: $foreground
|
|
99
|
+
|
|
100
|
+
# CSS variables emitted for the file-list cursor and multi-selection.
|
|
101
|
+
# Values may reference Textual palette variables with `$name` (e.g. `$primary`).
|
|
102
|
+
# References are resolved against this theme's own fields when the CSS is generated.
|
|
103
|
+
cursor_row_background: $primary
|
|
104
|
+
cursor_row_foreground: $foreground
|
|
105
|
+
selected_file_background: $warning 30%
|
|
106
|
+
selected_file_foreground: $success
|
|
107
|
+
selected_cursor_row_background: $primary
|
|
108
|
+
selected_cursor_row_foreground: $success
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Textual theme palette. These fields are forwarded to textual.theme.Theme,
|
|
2
|
+
# which colors the application chrome (borders, buttons, headers, scrollbars).
|
|
3
|
+
# `name` is the identifier shown in the Theme menu and persisted in settings.json.
|
|
4
|
+
# Color values accept any CSS-style color (hex, ansi_*, rgb()).
|
|
5
|
+
name: catppuccin-latte
|
|
6
|
+
primary: '#8839EF'
|
|
7
|
+
secondary: '#DC8A78'
|
|
8
|
+
warning: '#DF8E1D'
|
|
9
|
+
error: '#D20F39'
|
|
10
|
+
success: '#40A02B'
|
|
11
|
+
accent: '#FE640B'
|
|
12
|
+
foreground: '#4C4F69'
|
|
13
|
+
background: '#EFF1F5'
|
|
14
|
+
surface: '#E6E9EF'
|
|
15
|
+
panel: '#CCD0DA'
|
|
16
|
+
boost: null
|
|
17
|
+
|
|
18
|
+
# Theme behavior flags.
|
|
19
|
+
# `dark` selects dark-mode contrast defaults inside Textual.
|
|
20
|
+
# `luminosity_spread` / `text_alpha` tune Textual's automatic shade derivation.
|
|
21
|
+
# `variables` are passed through to Textual's CSS variable table
|
|
22
|
+
# (use kebab-case keys, e.g. `block-cursor-foreground`).
|
|
23
|
+
# `ansi: true` opts the theme into the terminal's own ANSI palette
|
|
24
|
+
# instead of fixed hex colors.
|
|
25
|
+
dark: false
|
|
26
|
+
luminosity_spread: 0.15
|
|
27
|
+
text_alpha: 0.95
|
|
28
|
+
variables:
|
|
29
|
+
button-color-foreground: '#EFF1F5'
|
|
30
|
+
ansi: false
|
|
31
|
+
|
|
32
|
+
# Status-code colors painted in the Status column of the file list.
|
|
33
|
+
# Values are Rich style strings (e.g. "bold yellow", "#ff8800").
|
|
34
|
+
status_modified: bold yellow
|
|
35
|
+
status_type_changed: 'bold #ff8800'
|
|
36
|
+
status_added: bold green
|
|
37
|
+
status_deleted: bold red
|
|
38
|
+
status_renamed: bold cyan
|
|
39
|
+
status_copied: bold blue
|
|
40
|
+
status_unmerged: 'bold #ff5555'
|
|
41
|
+
status_untracked: bold white
|
|
42
|
+
status_ignored: '#888888'
|
|
43
|
+
status_submodule: bold magenta
|
|
44
|
+
|
|
45
|
+
# Diff line rendering inside FileDiff.
|
|
46
|
+
# Added/removed lines get a foreground color and a dimmer matching line-number gutter.
|
|
47
|
+
diff_added_line: green
|
|
48
|
+
diff_added_line_number: green dim
|
|
49
|
+
diff_removed_line: red
|
|
50
|
+
diff_removed_line_number: red dim
|
|
51
|
+
diff_context_line_number: dim
|
|
52
|
+
|
|
53
|
+
# Commit detail rendering inside CommitDetail (git show output).
|
|
54
|
+
# The commit/Author/Date header block, and the @@ hunk markers of a patch.
|
|
55
|
+
commit_header_line: bold
|
|
56
|
+
diff_hunk_header: cyan
|
|
57
|
+
|
|
58
|
+
# Y/N hint shown at the bottom of the confirm dialog.
|
|
59
|
+
confirm_yes_key: b green
|
|
60
|
+
confirm_no_key: b red
|
|
61
|
+
|
|
62
|
+
# Warning text shown above the file list (e.g. submodule branch mismatches).
|
|
63
|
+
warning_text: bold red
|
|
64
|
+
|
|
65
|
+
# Faint hint text at the bottom of dialogs (e.g. "(Esc cancels)").
|
|
66
|
+
dialog_hint: dim
|
|
67
|
+
|
|
68
|
+
# Accelerator letter highlighted in the menu bar and in dropdown entries.
|
|
69
|
+
# Must stay readable on the menu bar ($menu-bar-background) and dropdown ($panel)
|
|
70
|
+
# backgrounds.
|
|
71
|
+
menu_mnemonic: bold underline
|
|
72
|
+
|
|
73
|
+
# Settings dialog checkbox mark color.
|
|
74
|
+
checkbox_mark: green
|
|
75
|
+
|
|
76
|
+
# Settings dialog text caret. It is drawn on the cell it sits on, so it
|
|
77
|
+
# swaps that cell's colors instead of painting one of its own.
|
|
78
|
+
text_caret: reverse
|
|
79
|
+
|
|
80
|
+
# Selected text in the commit message box (Shift+arrows). Empty keeps
|
|
81
|
+
# Textual's default: $primary lightened at 40% opacity over the background.
|
|
82
|
+
text_selection_background: ''
|
|
83
|
+
text_selection_foreground: ''
|
|
84
|
+
|
|
85
|
+
# Chrome colors for the menu bar and the footer. The defaults are Textual's
|
|
86
|
+
# own Header/Footer palette, so the bars match every other Textual app.
|
|
87
|
+
# Values may reference this theme's palette fields with `$name`.
|
|
88
|
+
menu_bar_background: $panel
|
|
89
|
+
menu_bar_foreground: $foreground
|
|
90
|
+
footer_background: $panel
|
|
91
|
+
footer_foreground: $foreground
|
|
92
|
+
|
|
93
|
+
# CSS variables emitted for the file-list cursor and multi-selection.
|
|
94
|
+
# Values may reference Textual palette variables with `$name` (e.g. `$primary`).
|
|
95
|
+
# References are resolved against this theme's own fields when the CSS is generated.
|
|
96
|
+
cursor_row_background: $primary
|
|
97
|
+
cursor_row_foreground: $foreground
|
|
98
|
+
selected_file_background: $warning 30%
|
|
99
|
+
selected_file_foreground: $success
|
|
100
|
+
selected_cursor_row_background: $primary
|
|
101
|
+
selected_cursor_row_foreground: $success
|