gitux 0.1.0__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.
- gitux/__init__.py +3 -0
- gitux/__main__.py +6 -0
- gitux/cli.py +35 -0
- gitux/domain/__init__.py +27 -0
- gitux/domain/models.py +180 -0
- gitux/git/__init__.py +57 -0
- gitux/git/commands.py +392 -0
- gitux/git/exceptions.py +9 -0
- gitux/git/parser.py +83 -0
- gitux/presenter/__init__.py +6 -0
- gitux/presenter/commit_presenter.py +107 -0
- gitux/presenter/repo_presenter.py +119 -0
- gitux/ui/__init__.py +1 -0
- gitux/ui/app.py +452 -0
- gitux/ui/gitux.tcss +323 -0
- gitux/ui/widgets/__init__.py +24 -0
- gitux/ui/widgets/block_container.py +61 -0
- gitux/ui/widgets/branch_screen.py +54 -0
- gitux/ui/widgets/changed_files.py +187 -0
- gitux/ui/widgets/commit_log.py +197 -0
- gitux/ui/widgets/commit_screen.py +110 -0
- gitux/ui/widgets/diff_viewer.py +149 -0
- gitux/ui/widgets/gitux_footer.py +44 -0
- gitux/ui/widgets/header.py +81 -0
- gitux/ui/widgets/help_screen.py +74 -0
- gitux/ui/widgets/repo_stats_bar.py +212 -0
- gitux/utils/__init__.py +1 -0
- gitux-0.1.0.dist-info/METADATA +174 -0
- gitux-0.1.0.dist-info/RECORD +32 -0
- gitux-0.1.0.dist-info/WHEEL +4 -0
- gitux-0.1.0.dist-info/entry_points.txt +2 -0
- gitux-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"""Repo stats bar — one-line repository statistics below the top app bar."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from rich.cells import cell_len
|
|
7
|
+
from rich.text import Text
|
|
8
|
+
from textual.widgets import Static
|
|
9
|
+
|
|
10
|
+
from gitux.domain import FileCounts, HeadSummary
|
|
11
|
+
|
|
12
|
+
_MAX_USER_CHARS: int = 16
|
|
13
|
+
_MAX_REPO_CHARS: int = 32
|
|
14
|
+
_MAX_REMOTE_CHARS: int = 32
|
|
15
|
+
_MAX_HEAD_SUBJECT_CHARS: int = 40
|
|
16
|
+
_DEFAULT_RENDER_WIDTH: int = 200 # unmounted fallback so bare _render_text() is full
|
|
17
|
+
_PADDING_COLS: int = 2 # matches `padding: 0 1` on #stats-bar
|
|
18
|
+
|
|
19
|
+
# drop priority, LOWEST first (head is never dropped)
|
|
20
|
+
_SEGMENT_PRIORITY: tuple[str, ...] = ("ahead_behind", "remote", "repo", "user", "files", "date", "head")
|
|
21
|
+
|
|
22
|
+
_PREFIX_CELLS: int = 13 # " ■ REPO STATS"
|
|
23
|
+
_SEPARATOR_CELLS: int = 3 # " │ "
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _format_relative_time(epoch: int, *, now: float | None = None) -> str:
|
|
27
|
+
"""Format an epoch seconds as a relative English string (floor division)."""
|
|
28
|
+
now = time.time() if now is None else now
|
|
29
|
+
delta = max(0, int(now - epoch))
|
|
30
|
+
if delta < 60:
|
|
31
|
+
return "just now"
|
|
32
|
+
if delta < 90:
|
|
33
|
+
return "1 minute ago"
|
|
34
|
+
if delta < 2700:
|
|
35
|
+
return f"{delta // 60} minutes ago"
|
|
36
|
+
if delta < 5400:
|
|
37
|
+
return "1 hour ago"
|
|
38
|
+
if delta < 86400:
|
|
39
|
+
return f"{delta // 3600} hours ago"
|
|
40
|
+
if delta < 129600:
|
|
41
|
+
return "1 day ago"
|
|
42
|
+
if delta < 604800:
|
|
43
|
+
return f"{delta // 86400} days ago"
|
|
44
|
+
if delta < 2592000:
|
|
45
|
+
return f"{delta // 604800} weeks ago"
|
|
46
|
+
if delta < 31536000:
|
|
47
|
+
return f"{delta // 2592000} months ago"
|
|
48
|
+
return f"{delta // 31536000} years ago"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class RepoStatsBar(Static):
|
|
52
|
+
"""Single-line stats bar fed by ``GituxApp._refresh_all``.
|
|
53
|
+
|
|
54
|
+
Renders: `` ■ REPO STATS │ user │ hash subject │ date │ +s ~m ?u [!c] │ ↑a ↓b │ remote``.
|
|
55
|
+
Uses hybrid B3 truncation: hard caps + width-adaptive segment drop.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def __init__(self, **kwargs) -> None:
|
|
59
|
+
super().__init__("", **kwargs)
|
|
60
|
+
self._user: str = ""
|
|
61
|
+
self._head_summary: HeadSummary | None = None
|
|
62
|
+
self._file_counts: FileCounts | None = None
|
|
63
|
+
self._ahead = 0
|
|
64
|
+
self._behind = 0
|
|
65
|
+
self._remote = "(local)"
|
|
66
|
+
self._remote_branch = ""
|
|
67
|
+
self._repo_name: str = ""
|
|
68
|
+
|
|
69
|
+
def update_stats(
|
|
70
|
+
self,
|
|
71
|
+
user: str = "",
|
|
72
|
+
head_summary: HeadSummary | None = None,
|
|
73
|
+
file_counts: FileCounts | None = None,
|
|
74
|
+
ahead: int = 0,
|
|
75
|
+
behind: int = 0,
|
|
76
|
+
remote: str = "(local)",
|
|
77
|
+
remote_branch: str = "",
|
|
78
|
+
repo_name: str = "",
|
|
79
|
+
) -> None:
|
|
80
|
+
"""Render the stats bar with the given repo state (safe defaults included)."""
|
|
81
|
+
self._remote = remote or "(local)"
|
|
82
|
+
self._remote_branch = remote_branch if remote else ""
|
|
83
|
+
self._user = user
|
|
84
|
+
self._head_summary = head_summary
|
|
85
|
+
self._file_counts = file_counts
|
|
86
|
+
self._ahead = ahead
|
|
87
|
+
self._behind = behind
|
|
88
|
+
self._repo_name = repo_name
|
|
89
|
+
self.update(self._render_text())
|
|
90
|
+
|
|
91
|
+
def _build_segments(self) -> list[dict[str, Any]]:
|
|
92
|
+
"""Build segments in locked visual order with text, style, and drop info."""
|
|
93
|
+
segments: list[dict[str, Any]] = []
|
|
94
|
+
|
|
95
|
+
if self._repo_name:
|
|
96
|
+
segments.append({
|
|
97
|
+
"name": "repo",
|
|
98
|
+
"plain": self._repo_name[:_MAX_REPO_CHARS],
|
|
99
|
+
"style": "bold #e4e1ed",
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
segments.append({
|
|
103
|
+
"name": "user",
|
|
104
|
+
"plain": (self._user or "unknown")[:_MAX_USER_CHARS],
|
|
105
|
+
"style": "#e4e1ed",
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
summary = self._head_summary
|
|
109
|
+
if summary is None:
|
|
110
|
+
segments.append({
|
|
111
|
+
"name": "head",
|
|
112
|
+
"plain": "(no commits)",
|
|
113
|
+
"hash": "",
|
|
114
|
+
"subject": "(no commits)",
|
|
115
|
+
"style": "#e4e1ed",
|
|
116
|
+
})
|
|
117
|
+
else:
|
|
118
|
+
subject = summary.subject
|
|
119
|
+
if len(subject) > _MAX_HEAD_SUBJECT_CHARS:
|
|
120
|
+
subject = subject[: _MAX_HEAD_SUBJECT_CHARS - 1] + "\u2026"
|
|
121
|
+
segments.append({
|
|
122
|
+
"name": "head",
|
|
123
|
+
"plain": subject,
|
|
124
|
+
"hash": "",
|
|
125
|
+
"subject": subject,
|
|
126
|
+
"style": "#e4e1ed",
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
if summary is not None:
|
|
130
|
+
segments.append({
|
|
131
|
+
"name": "date",
|
|
132
|
+
"plain": _format_relative_time(summary.epoch),
|
|
133
|
+
"style": "#c7c4d7",
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
counts = self._file_counts or FileCounts(0, 0, 0, 0)
|
|
137
|
+
files = f"+{counts.staged} ~{counts.modified} ?{counts.untracked}"
|
|
138
|
+
if counts.conflicts > 0:
|
|
139
|
+
files += f" !{counts.conflicts}"
|
|
140
|
+
segments.append({
|
|
141
|
+
"name": "files",
|
|
142
|
+
"plain": files,
|
|
143
|
+
"style": "#c7c4d7",
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
segments.append({
|
|
147
|
+
"name": "ahead_behind",
|
|
148
|
+
"plain": f"\u2191{self._ahead} \u2193{self._behind}",
|
|
149
|
+
"style": "bold #c0c1ff",
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
remote_slug = (
|
|
153
|
+
f"{self._remote}/{self._remote_branch}" if self._remote_branch else self._remote
|
|
154
|
+
)
|
|
155
|
+
segments.append({
|
|
156
|
+
"name": "remote",
|
|
157
|
+
"plain": remote_slug[:_MAX_REMOTE_CHARS],
|
|
158
|
+
"style": "#e4e1ed",
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
return segments
|
|
162
|
+
|
|
163
|
+
def _total_cells(self, segments: list[dict[str, Any]]) -> int:
|
|
164
|
+
"""Total rendered cell width of all segments plus prefix and separators."""
|
|
165
|
+
return (
|
|
166
|
+
_PREFIX_CELLS
|
|
167
|
+
+ sum(cell_len(seg["plain"]) for seg in segments)
|
|
168
|
+
+ _SEPARATOR_CELLS * (len(segments) - 1)
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def _fit_segments(self, segments: list[dict[str, Any]], width: int) -> list[dict[str, Any]]:
|
|
172
|
+
"""Drop lowest-priority segments, then elide the head subject to fit width."""
|
|
173
|
+
total = self._total_cells(segments)
|
|
174
|
+
while total > width and len(segments) > 1:
|
|
175
|
+
droppable = [seg for seg in segments if seg["name"] != "head"]
|
|
176
|
+
if not droppable:
|
|
177
|
+
break
|
|
178
|
+
to_drop = min(droppable, key=lambda seg: _SEGMENT_PRIORITY.index(seg["name"]))
|
|
179
|
+
segments.remove(to_drop)
|
|
180
|
+
total = self._total_cells(segments)
|
|
181
|
+
|
|
182
|
+
if len(segments) == 1 and total > width:
|
|
183
|
+
head = segments[0]
|
|
184
|
+
hash_len = cell_len(head["hash"])
|
|
185
|
+
avail = width - _PREFIX_CELLS - hash_len - 1
|
|
186
|
+
if avail < 1:
|
|
187
|
+
if head["hash"]:
|
|
188
|
+
head["plain"] = head["hash"]
|
|
189
|
+
else:
|
|
190
|
+
head["plain"] = head["plain"][: max(0, width - _PREFIX_CELLS)]
|
|
191
|
+
else:
|
|
192
|
+
elided = head["subject"][: avail - 1] + "\u2026"
|
|
193
|
+
head["plain"] = (
|
|
194
|
+
f"{head['hash']} {elided}" if head["hash"] else elided
|
|
195
|
+
)
|
|
196
|
+
return segments
|
|
197
|
+
|
|
198
|
+
def _render_text(self, width: int | None = None) -> Text:
|
|
199
|
+
"""Render the stats line, dropping segments to fit the given width."""
|
|
200
|
+
if width is None:
|
|
201
|
+
width = self.size.width - _PADDING_COLS if self.is_mounted else 0
|
|
202
|
+
if width <= 0:
|
|
203
|
+
width = _DEFAULT_RENDER_WIDTH
|
|
204
|
+
segments = self._build_segments()
|
|
205
|
+
segments = self._fit_segments(segments, width)
|
|
206
|
+
|
|
207
|
+
text = Text(no_wrap=True)
|
|
208
|
+
text.append(" \u25a0 REPO STATS", style="bold #c0c1ff")
|
|
209
|
+
for seg in segments:
|
|
210
|
+
text.append(" \u2502 ", style="#c7c4d7")
|
|
211
|
+
text.append(seg["plain"], style=seg["style"])
|
|
212
|
+
return text
|
gitux/utils/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Utility functions, config, and exceptions."""
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: gitux
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A beautiful, minimalist TUI for Git.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Hector-2710/gitux
|
|
6
|
+
Project-URL: Repository, https://github.com/Hector-2710/gitux
|
|
7
|
+
Project-URL: Issues, https://github.com/Hector-2710/gitux/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/Hector-2710/gitux/releases
|
|
9
|
+
Author: Hector-2710
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: developer-tools,git,terminal,textual,tui,version-control
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
22
|
+
Classifier: Topic :: Terminals
|
|
23
|
+
Requires-Python: >=3.12
|
|
24
|
+
Requires-Dist: psutil>=7.2.2
|
|
25
|
+
Requires-Dist: textual>=8.2.8
|
|
26
|
+
Requires-Dist: typer>=0.27.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# GITUX
|
|
33
|
+
|
|
34
|
+
[](https://pypi.org/project/gitux/)
|
|
35
|
+
[](https://pypi.org/project/gitux/)
|
|
36
|
+
[](https://github.com/Hector-2710/gitux/blob/main/LICENSE)
|
|
37
|
+
|
|
38
|
+
A beautiful, minimalist TUI for Git.
|
|
39
|
+
|
|
40
|
+
GITUX is a terminal user interface for Git that prioritizes design and user experience. It wraps Git commands in a clean, visually appealing interface — so you can work with Git without leaving the terminal, and enjoy doing it.
|
|
41
|
+
|
|
42
|
+
## Why GITUX?
|
|
43
|
+
|
|
44
|
+
Most Git TUIs are functional but not beautiful. GITUX is built with the belief that developer tools should be both powerful and pleasant to look at.
|
|
45
|
+
|
|
46
|
+
- **Minimalist** — No clutter, no overwhelming menus. Just what you need.
|
|
47
|
+
- **Beautiful** — Clean colors, thoughtful spacing, modern aesthetics.
|
|
48
|
+
- **Fast** — Direct subprocess calls to Git, no heavy abstractions.
|
|
49
|
+
|
|
50
|
+
## Features
|
|
51
|
+
|
|
52
|
+
- View repository status with color-coded file states
|
|
53
|
+
- Browse commit history with details
|
|
54
|
+
- Stage and commit files with messages
|
|
55
|
+
- View diffs between files
|
|
56
|
+
- Manage branches (create, switch, delete)
|
|
57
|
+
- Merge branches
|
|
58
|
+
- Push to remote
|
|
59
|
+
- Performance metrics (startup time, memory usage)
|
|
60
|
+
|
|
61
|
+
## Installation
|
|
62
|
+
|
|
63
|
+
**Recommended — with [pipx](https://pipx.pypa.io/) or [uv](https://docs.astral.sh/uv/) (isolated install):**
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# With pipx
|
|
67
|
+
pipx install gitux
|
|
68
|
+
|
|
69
|
+
# Or with uv
|
|
70
|
+
uv tool install gitux
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Or with pip:**
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
pip install gitux
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
> **Requirements:** Python 3.12+ and `git` installed on your system.
|
|
80
|
+
|
|
81
|
+
<details>
|
|
82
|
+
<summary>Install from source (for development)</summary>
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
git clone https://github.com/Hector-2710/gitux.git
|
|
86
|
+
cd gitux
|
|
87
|
+
uv sync --all-extras
|
|
88
|
+
uv run gitux
|
|
89
|
+
```
|
|
90
|
+
</details>
|
|
91
|
+
|
|
92
|
+
## Usage
|
|
93
|
+
|
|
94
|
+
Inside any Git repository, just run:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
gitux
|
|
98
|
+
|
|
99
|
+
# Show version
|
|
100
|
+
gitux --version
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Keybindings
|
|
104
|
+
|
|
105
|
+
| Key | Action |
|
|
106
|
+
|-----|--------|
|
|
107
|
+
| `Tab` | Next section (Files / Commits / Diff) |
|
|
108
|
+
| `↑` / `↓` or `j` / `k` | Scroll active section |
|
|
109
|
+
| `s` / `Enter` | Stage / unstage file |
|
|
110
|
+
| `a` / `A` | Stage all / unstage all files |
|
|
111
|
+
| `c` | Focus commit message |
|
|
112
|
+
| `Ctrl+Enter` | Create commit |
|
|
113
|
+
| `Ctrl+p` | Push to remote |
|
|
114
|
+
| `r` | Refresh status |
|
|
115
|
+
| `b` | Branches panel |
|
|
116
|
+
| `?` | Show help |
|
|
117
|
+
| `q` | Quit GITUX |
|
|
118
|
+
|
|
119
|
+
## Stack
|
|
120
|
+
|
|
121
|
+
| Component | Technology | Purpose |
|
|
122
|
+
|-----------|------------|---------|
|
|
123
|
+
| Language | Python 3.12+ | Core runtime |
|
|
124
|
+
| TUI | Textual | Terminal interface with CSS styling |
|
|
125
|
+
| CLI | Typer | Command-line entry point |
|
|
126
|
+
| Git | subprocess + git CLI | Git operations |
|
|
127
|
+
| Metrics | psutil | Performance measurement |
|
|
128
|
+
|
|
129
|
+
## Development
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Install dev dependencies
|
|
133
|
+
uv sync --all-extras
|
|
134
|
+
|
|
135
|
+
# Run tests
|
|
136
|
+
uv run pytest
|
|
137
|
+
|
|
138
|
+
# Run linter
|
|
139
|
+
uv run ruff check .
|
|
140
|
+
|
|
141
|
+
# Format code
|
|
142
|
+
uv run ruff format .
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Project Structure
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
gitux/
|
|
149
|
+
├── src/
|
|
150
|
+
│ └── gitux/
|
|
151
|
+
│ ├── __init__.py
|
|
152
|
+
│ ├── __main__.py
|
|
153
|
+
│ ├── cli.py # Typer entry point
|
|
154
|
+
│ ├── domain/ # Data models
|
|
155
|
+
│ ├── git/ # Git infrastructure
|
|
156
|
+
│ ├── presenter/ # Business logic
|
|
157
|
+
│ ├── ui/ # Textual TUI
|
|
158
|
+
│ ├── metrics/ # Performance metrics
|
|
159
|
+
│ └── utils/ # Config, exceptions
|
|
160
|
+
├── tests/
|
|
161
|
+
│ ├── unit/
|
|
162
|
+
│ ├── integration/
|
|
163
|
+
│ └── e2e/
|
|
164
|
+
├── docs/
|
|
165
|
+
│ ├── context.md
|
|
166
|
+
│ ├── container.md
|
|
167
|
+
│ └── diagrams/
|
|
168
|
+
├── pyproject.toml
|
|
169
|
+
└── README.md
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
MIT
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
gitux/__init__.py,sha256=ZtE4fY4VU33_y0OW_7530O4vAqxBRLt45K8zWxX8IbI,74
|
|
2
|
+
gitux/__main__.py,sha256=75MHbiT5XYsOtCTWw1ju6L8Xz2zPxVJiMt27KL9baKI,117
|
|
3
|
+
gitux/cli.py,sha256=1pLTZl5BKZS8Uy4s9V7_krorUwk9kkr_rVwi3rIJhsU,644
|
|
4
|
+
gitux/domain/__init__.py,sha256=bGqvXT1enNUc4x55VP0c_mfOGZyhm52oe5uTAnfz_XU,747
|
|
5
|
+
gitux/domain/models.py,sha256=ZkIhxXE57CEtOhcPFzsrR-rvHC1iof6swvc045-7bTA,4786
|
|
6
|
+
gitux/git/__init__.py,sha256=33wGQqeWR0gvFkEOyBwcDSMCiNTglqrCVs2tUCMgTos,1151
|
|
7
|
+
gitux/git/commands.py,sha256=OllqC0fm7Jd_xyW85C-qeLaW8IBSi29d92YwuWgvM7Y,12114
|
|
8
|
+
gitux/git/exceptions.py,sha256=N7VAPdnLp-SX3QEaTZx0RhCLhzgdZsB-CWU9SkAKZGQ,230
|
|
9
|
+
gitux/git/parser.py,sha256=AAOKhBfhXMkUVDPVFezRwr1ls5tuA_SsiFlGAxfxTtA,2444
|
|
10
|
+
gitux/presenter/__init__.py,sha256=El3zvXJUr-YdwttEJVGUsS2U3aL-q-KVmKrBfhCOba8,223
|
|
11
|
+
gitux/presenter/commit_presenter.py,sha256=_848SmJpI9VbIhmUaSNR9UyZUnma0cYrOK0k5Rk6g4k,3719
|
|
12
|
+
gitux/presenter/repo_presenter.py,sha256=rMMNQfOEiObDhxUHGkXa6jJBAP3iivX6gnuzi4DSEjM,3889
|
|
13
|
+
gitux/ui/__init__.py,sha256=80z8YKUTs8g7W6DueSYCDUFQsyonCJfwTFoxyzpQAKc,30
|
|
14
|
+
gitux/ui/app.py,sha256=7rPaI3Pm1bIiR387W18daMNUyTFpSo85p4S8yl6fxgE,16680
|
|
15
|
+
gitux/ui/gitux.tcss,sha256=v30PtisCxD3-EijS7bon7pw_97w11oz-BKoee0QsGE8,4941
|
|
16
|
+
gitux/ui/widgets/__init__.py,sha256=vfXQoRgr5dDXUXBwh2BzUmHifDOlDV6mKOWKwCKdV0c,827
|
|
17
|
+
gitux/ui/widgets/block_container.py,sha256=ligGTYr3V9vupZQs191muwh6SGWbE8Z9Xm3b5aeinpo,2210
|
|
18
|
+
gitux/ui/widgets/branch_screen.py,sha256=YhwnJt1kbGbHo0UbT6WoSiVvJ5EdvmtvflMc62trjvo,2069
|
|
19
|
+
gitux/ui/widgets/changed_files.py,sha256=ADTC0H9Rmf0ONOYCZvQyS6DOhcBwGGMqJXWzLuw5AU4,6833
|
|
20
|
+
gitux/ui/widgets/commit_log.py,sha256=FvKhFFoje_eC18yYo0EN2GOXd25ybkkTMYUoiMtrn7o,6704
|
|
21
|
+
gitux/ui/widgets/commit_screen.py,sha256=sLbnQlfEwRisK7E1u__6NDVjXS1pwQIrGNnsDQKUVGU,4120
|
|
22
|
+
gitux/ui/widgets/diff_viewer.py,sha256=WxR9PQNgghHcTxXvwLToLhZrlvf9IJ-GEBiJhP7UoTg,4559
|
|
23
|
+
gitux/ui/widgets/gitux_footer.py,sha256=XsoAOj9Lc17AGQ5j9InfiwWi39Lg690YH051LvcwY-Q,1513
|
|
24
|
+
gitux/ui/widgets/header.py,sha256=ftwQCexmlp2aT-MS2vFPthVQc62dVwZehMA4B_A_CDI,2736
|
|
25
|
+
gitux/ui/widgets/help_screen.py,sha256=fnuyMqKOAVED93LRi_BSn15OZg58pfwX99svRzPMdn8,2699
|
|
26
|
+
gitux/ui/widgets/repo_stats_bar.py,sha256=SlPzgHqZho75HZDGNXOi1V6FpsW1oDwBI1Bi2uC3vCg,7464
|
|
27
|
+
gitux/utils/__init__.py,sha256=PLILUN4DpXkq9aaU8KyZoL5z_UAZw8qGYMMcHXf8qUs,49
|
|
28
|
+
gitux-0.1.0.dist-info/METADATA,sha256=fT13Xgn-qvwmCbrqfkv-Nthn36ieXCHubKcnnSXpwQ4,4834
|
|
29
|
+
gitux-0.1.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
30
|
+
gitux-0.1.0.dist-info/entry_points.txt,sha256=pGB4oUGZz7AieLAwGrMUtFAWXm2gag2IcCi_wUho19k,41
|
|
31
|
+
gitux-0.1.0.dist-info/licenses/LICENSE,sha256=pj_7arY6WRVNI7xLBUOxewGZGxorLPu6GpF-kLO0SSM,1068
|
|
32
|
+
gitux-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hector-2710
|
|
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.
|