Skip to content

Commit dab40b0

Browse files
committed
fix failing tests, more changes:
- enhanced history log output - fixed a bug with files panel where the full path would show up for a child node, instead of just the node's own name - added welcome message to status panel Signed-off-by: Ayush <mail@ayuch.dev>
1 parent 2314b8e commit dab40b0

File tree

5 files changed

+98
-34
lines changed

5 files changed

+98
-34
lines changed

internal/git/log.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (g *GitCommands) GetCommitLogsGraph() ([]CommitLog, error) {
3535
options := LogOptions{
3636
Graph: true,
3737
Format: format,
38-
Color: "never",
38+
Color: "always",
3939
All: true,
4040
}
4141

internal/tui/constants.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,38 @@ const (
6868
treePrefix = " "
6969
treePrefixLast = " "
7070
)
71+
72+
// --- Hyperlink URLs ---
73+
const (
74+
githubMainPage = "https://github.com/gitxtui/gitx"
75+
docsPage = "https://gitxtui.github.io/docs/"
76+
)
77+
78+
const (
79+
asciiArt = `
80+
WELCOME TO
81+
82+
██████╗ ██╗████████╗██╗ ██╗
83+
██╔════╝ ██║╚══██╔══╝╚██╗██╔╝
84+
██║ ███╗██║ ██║ ╚███╔╝
85+
██║ ██║██║ ██║ ██╔██╗
86+
╚██████╔╝██║ ██║ ██╔╝ ██╗
87+
╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝
88+
89+
%s
90+
`
91+
welcomeMsg = `
92+
○ User: %s
93+
Welcome to GITx, your terminal-based Git helper, inspired by lazygit.
94+
Here is a great tutorial to learn about git: %s
95+
`
96+
97+
// asciiArt alternative, named "_" to remove unused warnings
98+
_ = `
99+
▗▄▄▖▗▄▄▄▖▗▄▄▄▖
100+
▐▌ █ █ ▄ ▄
101+
▐▌▝▜▌ █ █ ▀▄▀
102+
▝▚▄▞▘▗▄█▄▖ █ ▄▀ ▀▄
103+
104+
`
105+
)

internal/tui/theme.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ type Theme struct {
9898
HelpButton lipgloss.Style
9999
ScrollbarThumb lipgloss.Style
100100
SelectedLine lipgloss.Style
101+
Hyperlink lipgloss.Style
102+
WelcomeHeading lipgloss.Style
103+
WelcomeMsg lipgloss.Style
104+
UserName lipgloss.Style
101105
GitStaged lipgloss.Style
102106
GitUnstaged lipgloss.Style
103107
GitUntracked lipgloss.Style
@@ -155,6 +159,10 @@ func NewThemeFromPalette(p Palette) Theme {
155159
HelpButton: lipgloss.NewStyle().Foreground(lipgloss.Color(p.Bg)).Background(lipgloss.Color(p.Green)).Margin(0, 1),
156160
ScrollbarThumb: lipgloss.NewStyle().Foreground(lipgloss.Color(p.BrightGreen)),
157161
SelectedLine: lipgloss.NewStyle().Background(lipgloss.Color(p.DarkBlue)).Foreground(lipgloss.Color(p.BrightWhite)),
162+
Hyperlink: lipgloss.NewStyle().Foreground(lipgloss.Color(p.BrightBlue)).Underline(true),
163+
WelcomeHeading: lipgloss.NewStyle().Foreground(lipgloss.Color(p.BrightCyan)),
164+
WelcomeMsg: lipgloss.NewStyle().Foreground(lipgloss.Color(p.BrightGreen)),
165+
UserName: lipgloss.NewStyle().Foreground(lipgloss.Color(p.Magenta)),
158166
GitStaged: lipgloss.NewStyle().Foreground(lipgloss.Color(p.Green)),
159167
GitUnstaged: lipgloss.NewStyle().Foreground(lipgloss.Color(p.Red)),
160168
GitUntracked: lipgloss.NewStyle().Foreground(lipgloss.Color(p.BrightBlack)),

internal/tui/update.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
5656
selectedPath = parts[3]
5757
}
5858
}
59+
5960
oldCursor := m.panels[msg.panel].cursor
6061

6162
if msg.panel == FilesPanel {
@@ -134,13 +135,19 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
134135
}
135136

136137
if m.focusedPanel != oldFocus {
137-
// When focus changes, update the active source panel if necessary
138+
// When focus changes, reset scroll for the Stash and Secondary panels
139+
if m.focusedPanel == StashPanel || m.focusedPanel == SecondaryPanel {
140+
m.panels[m.focusedPanel].viewport.GotoTop()
141+
}
142+
143+
// Update the active source panel and main panel content if the new focus is a source panel
138144
if m.focusedPanel != MainPanel && m.focusedPanel != SecondaryPanel {
139145
m.activeSourcePanel = m.focusedPanel
140-
m.panels[MainPanel].viewport.GotoTop() // Reset scroll on focus change
146+
m.panels[MainPanel].viewport.GotoTop() // Reset main panel scroll on source change
141147
cmd = m.updateMainPanel()
142148
cmds = append(cmds, cmd)
143149
}
150+
144151
m = m.recalculateLayout()
145152
}
146153

@@ -208,6 +215,13 @@ func (m Model) fetchPanelContent(panel Panel) tea.Cmd {
208215
content = strings.TrimSpace(builder.String())
209216
}
210217
}
218+
case SecondaryPanel:
219+
url := m.theme.Hyperlink.Render(githubMainPage)
220+
content = strings.Join([]string{
221+
"\t--- Feature in development! ---",
222+
"\n\t* This panel will contain all the command logs and history for of TUI app.",
223+
fmt.Sprintf("\t* visit for more details: %s.", url),
224+
}, "\n")
211225
}
212226

213227
if err != nil {
@@ -226,7 +240,10 @@ func (m *Model) updateMainPanel() tea.Cmd {
226240
switch m.activeSourcePanel {
227241
case StatusPanel:
228242
userName, _ := m.git.GetUserName()
229-
content = fmt.Sprintf("Hello, %s!\n\nWelcome to gitx.\n\nHere is a great tutorial to learn about git: https://g.co/kgs/Qd3w3S\n", userName)
243+
url := m.theme.Hyperlink.Render(docsPage)
244+
msgHeading := m.theme.WelcomeHeading.Render(asciiArt)
245+
msgBody := fmt.Sprintf(welcomeMsg, m.theme.UserName.Render(userName), url)
246+
content = fmt.Sprintf(msgHeading, m.theme.WelcomeMsg.Render(msgBody))
230247
case FilesPanel:
231248
if m.panels[FilesPanel].cursor < len(m.panels[FilesPanel].lines) {
232249
line := m.panels[FilesPanel].lines[m.panels[FilesPanel].cursor]
@@ -238,7 +255,7 @@ func (m *Model) updateMainPanel() tea.Cmd {
238255

239256
if path != "" {
240257
if status == "" { // It's a directory
241-
content, err = m.git.ShowDiff(git.DiffOptions{Color: true, Commit1: path})
258+
content, err = m.git.ShowDiff(git.DiffOptions{Color: true, Commit1: "HEAD", Commit2: path})
242259
} else { // It's a file
243260
stagedChanges := status[0] != ' ' && status[0] != '?'
244261
unstagedChanges := status[1] != ' '

internal/tui/view.go

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
// Package tui contains the logic for the terminal user interface of the application.
21
package tui
32

43
import (
54
"fmt"
5+
"regexp"
66
"strings"
77

88
"github.com/charmbracelet/bubbles/key"
@@ -11,6 +11,14 @@ import (
1111
zone "github.com/lrstanley/bubblezone"
1212
)
1313

14+
// ansiRegex is used to strip ANSI escape codes from strings.
15+
var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;]*m`)
16+
17+
// stripAnsi removes ANSI escape codes from a string.
18+
func stripAnsi(str string) string {
19+
return ansiRegex.ReplaceAllString(str, "")
20+
}
21+
1422
// View is the main render function for the application.
1523
func (m Model) View() string {
1624
if m.showHelp {
@@ -89,7 +97,21 @@ func (m Model) renderPanel(title string, width, height int, panel Panel) string
8997
var finalLine string
9098

9199
if i == p.cursor && isFocused {
92-
cleanLine := strings.ReplaceAll(line, "\t", " ")
100+
var cleanLine string
101+
// For the selected line, strip any existing ANSI codes before applying selection style.
102+
if panel == FilesPanel {
103+
// For files panel, don't show the hidden path in the selection.
104+
parts := strings.Split(line, "\t")
105+
if len(parts) >= 3 {
106+
cleanLine = fmt.Sprintf("%s %s %s", parts[0], parts[1], parts[2])
107+
} else {
108+
cleanLine = line
109+
}
110+
} else {
111+
cleanLine = stripAnsi(line)
112+
}
113+
114+
cleanLine = strings.ReplaceAll(cleanLine, "\t", " ") // Also replace tabs
93115
selectionStyle := m.theme.SelectedLine.Width(contentWidth)
94116
finalLine = selectionStyle.Render(cleanLine)
95117
} else {
@@ -259,23 +281,22 @@ func styleUnselectedLine(line string, panel Panel, theme Theme) string {
259281
case CommitsPanel:
260282
parts := strings.SplitN(line, "\t", 4)
261283
if len(parts) != 4 {
262-
return styleGraph(line, theme) // Render graph-only lines.
284+
// This is a graph-only line, already colored by git.
285+
// We just replace the placeholder node with a styled one.
286+
return strings.ReplaceAll(line, "○", theme.GraphNode.Render("○"))
263287
}
264288
graph, sha, author, subject := parts[0], parts[1], parts[2], parts[3]
265-
styledGraph := styleGraph(graph, theme)
266-
styledSHA := theme.CommitSHA.Render(sha)
267289

268-
styledAuthor := theme.CommitAuthor.Render(author)
269-
270-
commitNodeIndex := strings.Index(graph, graphNodeChar)
271-
if commitNodeIndex != -1 {
272-
authorColorStyle := theme.GraphColors[commitNodeIndex%len(theme.GraphColors)]
273-
styledAuthor = authorColorStyle.Render(author)
274-
}
290+
// The graph string is already colored by git, but we style the node.
291+
styledGraph := strings.ReplaceAll(graph, "○", theme.GraphNode.Render("○"))
275292

293+
// Apply our theme's styles to the other parts.
294+
styledSHA := theme.CommitSHA.Render(sha)
295+
styledAuthor := theme.CommitAuthor.Render(author)
276296
if strings.HasPrefix(strings.ToLower(subject), "merge") {
277297
styledAuthor = theme.CommitMerge.Render(author)
278298
}
299+
279300
final := lipgloss.JoinHorizontal(lipgloss.Left, styledSHA, " ", styledAuthor, " ", subject)
280301
return fmt.Sprintf("%s %s", styledGraph, final)
281302
case StashPanel:
@@ -316,20 +337,3 @@ func styleChar(char byte, style lipgloss.Style) string {
316337
}
317338
return style.Render(string(char))
318339
}
319-
320-
// styleGraph applies colors to the git log graph characters.
321-
func styleGraph(graph string, theme Theme) string {
322-
var styled strings.Builder
323-
for i, char := range graph {
324-
switch char {
325-
case '|', '\\', '/':
326-
color := theme.GraphColors[i%len(theme.GraphColors)]
327-
styled.WriteString(color.Render(string(char)))
328-
case '○':
329-
styled.WriteString(theme.GraphNode.Render("○"))
330-
default:
331-
styled.WriteString(string(char))
332-
}
333-
}
334-
return styled.String()
335-
}

0 commit comments

Comments
 (0)