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/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()
@@ -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