|
@@ -65,6 +65,45 @@ type permissionDialogCmp struct {
|
|
|
selectOption *huh.Select[string]
|
|
selectOption *huh.Select[string]
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// formatDiff formats a diff string with colors for additions and deletions
|
|
|
|
|
+func formatDiff(diffText string) string {
|
|
|
|
|
+ lines := strings.Split(diffText, "\n")
|
|
|
|
|
+ var formattedLines []string
|
|
|
|
|
+
|
|
|
|
|
+ // Define styles for different line types
|
|
|
|
|
+ addStyle := lipgloss.NewStyle().Foreground(styles.Green)
|
|
|
|
|
+ removeStyle := lipgloss.NewStyle().Foreground(styles.Red)
|
|
|
|
|
+ headerStyle := lipgloss.NewStyle().Bold(true).Foreground(styles.Blue)
|
|
|
|
|
+ contextStyle := lipgloss.NewStyle().Foreground(styles.SubText0)
|
|
|
|
|
+
|
|
|
|
|
+ // Process each line
|
|
|
|
|
+ for _, line := range lines {
|
|
|
|
|
+ if strings.HasPrefix(line, "+") {
|
|
|
|
|
+ formattedLines = append(formattedLines, addStyle.Render(line))
|
|
|
|
|
+ } else if strings.HasPrefix(line, "-") {
|
|
|
|
|
+ formattedLines = append(formattedLines, removeStyle.Render(line))
|
|
|
|
|
+ } else if strings.HasPrefix(line, "Changes:") || strings.HasPrefix(line, " ...") {
|
|
|
|
|
+ formattedLines = append(formattedLines, headerStyle.Render(line))
|
|
|
|
|
+ } else if strings.HasPrefix(line, " ") {
|
|
|
|
|
+ formattedLines = append(formattedLines, contextStyle.Render(line))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ formattedLines = append(formattedLines, line)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Join all formatted lines
|
|
|
|
|
+ content := strings.Join(formattedLines, "\n")
|
|
|
|
|
+
|
|
|
|
|
+ // Create a bordered box for the content
|
|
|
|
|
+ contentStyle := lipgloss.NewStyle().
|
|
|
|
|
+ MarginTop(1).
|
|
|
|
|
+ Padding(0, 1).
|
|
|
|
|
+ Border(lipgloss.RoundedBorder()).
|
|
|
|
|
+ BorderForeground(styles.Flamingo)
|
|
|
|
|
+
|
|
|
|
|
+ return contentStyle.Render(content)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func (p *permissionDialogCmp) Init() tea.Cmd {
|
|
func (p *permissionDialogCmp) Init() tea.Cmd {
|
|
|
return nil
|
|
return nil
|
|
|
}
|
|
}
|
|
@@ -132,93 +171,159 @@ func (p *permissionDialogCmp) render() string {
|
|
|
lipgloss.JoinHorizontal(lipgloss.Left, keyStyle.Render("Path:"), " ", valueStyle.Render(p.permission.Path)),
|
|
lipgloss.JoinHorizontal(lipgloss.Left, keyStyle.Render("Path:"), " ", valueStyle.Render(p.permission.Path)),
|
|
|
" ",
|
|
" ",
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // Create the header content first so it can be used in all cases
|
|
|
|
|
+ headerContent := lipgloss.NewStyle().Padding(0, 1).Render(lipgloss.JoinVertical(lipgloss.Left, headerParts...))
|
|
|
|
|
+
|
|
|
r, _ := glamour.NewTermRenderer(
|
|
r, _ := glamour.NewTermRenderer(
|
|
|
glamour.WithStyles(styles.CatppuccinMarkdownStyle()),
|
|
glamour.WithStyles(styles.CatppuccinMarkdownStyle()),
|
|
|
glamour.WithWordWrap(p.width-10),
|
|
glamour.WithWordWrap(p.width-10),
|
|
|
glamour.WithEmoji(),
|
|
glamour.WithEmoji(),
|
|
|
)
|
|
)
|
|
|
- content := ""
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // Handle different tool types
|
|
|
switch p.permission.ToolName {
|
|
switch p.permission.ToolName {
|
|
|
case tools.BashToolName:
|
|
case tools.BashToolName:
|
|
|
pr := p.permission.Params.(tools.BashPermissionsParams)
|
|
pr := p.permission.Params.(tools.BashPermissionsParams)
|
|
|
headerParts = append(headerParts, keyStyle.Render("Command:"))
|
|
headerParts = append(headerParts, keyStyle.Render("Command:"))
|
|
|
- content = fmt.Sprintf("```bash\n%s\n```", pr.Command)
|
|
|
|
|
|
|
+ content := fmt.Sprintf("```bash\n%s\n```", pr.Command)
|
|
|
|
|
+
|
|
|
|
|
+ renderedContent, _ := r.Render(content)
|
|
|
|
|
+ p.contentViewPort.Width = p.width - 2 - 2
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate content height dynamically based on content
|
|
|
|
|
+ contentLines := len(strings.Split(renderedContent, "\n"))
|
|
|
|
|
+ // Set a reasonable min/max for the viewport height
|
|
|
|
|
+ minContentHeight := 3
|
|
|
|
|
+ maxContentHeight := p.height - lipgloss.Height(headerContent) - lipgloss.Height(form) - 2 - 2 - 1
|
|
|
|
|
+
|
|
|
|
|
+ // Add some padding to the content lines
|
|
|
|
|
+ contentHeight := contentLines + 2
|
|
|
|
|
+ if contentHeight < minContentHeight {
|
|
|
|
|
+ contentHeight = minContentHeight
|
|
|
|
|
+ }
|
|
|
|
|
+ if contentHeight > maxContentHeight {
|
|
|
|
|
+ contentHeight = maxContentHeight
|
|
|
|
|
+ }
|
|
|
|
|
+ p.contentViewPort.Height = contentHeight
|
|
|
|
|
+
|
|
|
|
|
+ p.contentViewPort.SetContent(renderedContent)
|
|
|
|
|
+
|
|
|
|
|
+ // Style the viewport
|
|
|
|
|
+ var contentBorder lipgloss.Border
|
|
|
|
|
+ var borderColor lipgloss.TerminalColor
|
|
|
|
|
+
|
|
|
|
|
+ if p.isViewportFocus {
|
|
|
|
|
+ contentBorder = lipgloss.DoubleBorder()
|
|
|
|
|
+ borderColor = styles.Blue
|
|
|
|
|
+ } else {
|
|
|
|
|
+ contentBorder = lipgloss.RoundedBorder()
|
|
|
|
|
+ borderColor = styles.Flamingo
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ contentStyle := lipgloss.NewStyle().
|
|
|
|
|
+ MarginTop(1).
|
|
|
|
|
+ Padding(0, 1).
|
|
|
|
|
+ Border(contentBorder).
|
|
|
|
|
+ BorderForeground(borderColor)
|
|
|
|
|
+
|
|
|
|
|
+ if p.isViewportFocus {
|
|
|
|
|
+ contentStyle = contentStyle.BorderBackground(styles.Surface0)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ contentFinal := contentStyle.Render(p.contentViewPort.View())
|
|
|
|
|
+
|
|
|
|
|
+ return lipgloss.JoinVertical(
|
|
|
|
|
+ lipgloss.Top,
|
|
|
|
|
+ headerContent,
|
|
|
|
|
+ contentFinal,
|
|
|
|
|
+ form,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
case tools.EditToolName:
|
|
case tools.EditToolName:
|
|
|
pr := p.permission.Params.(tools.EditPermissionsParams)
|
|
pr := p.permission.Params.(tools.EditPermissionsParams)
|
|
|
headerParts = append(headerParts, keyStyle.Render("Update"))
|
|
headerParts = append(headerParts, keyStyle.Render("Update"))
|
|
|
- content = fmt.Sprintf("```\n%s\n```", pr.Diff)
|
|
|
|
|
|
|
+ // Recreate header content with the updated headerParts
|
|
|
|
|
+ headerContent = lipgloss.NewStyle().Padding(0, 1).Render(lipgloss.JoinVertical(lipgloss.Left, headerParts...))
|
|
|
|
|
+ // Format the diff with colors instead of using markdown code block
|
|
|
|
|
+ formattedDiff := formatDiff(pr.Diff)
|
|
|
|
|
+ return lipgloss.JoinVertical(
|
|
|
|
|
+ lipgloss.Top,
|
|
|
|
|
+ headerContent,
|
|
|
|
|
+ formattedDiff,
|
|
|
|
|
+ form,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
case tools.WriteToolName:
|
|
case tools.WriteToolName:
|
|
|
pr := p.permission.Params.(tools.WritePermissionsParams)
|
|
pr := p.permission.Params.(tools.WritePermissionsParams)
|
|
|
headerParts = append(headerParts, keyStyle.Render("Content"))
|
|
headerParts = append(headerParts, keyStyle.Render("Content"))
|
|
|
- content = fmt.Sprintf("```\n%s\n```", pr.Content)
|
|
|
|
|
|
|
+ // Recreate header content with the updated headerParts
|
|
|
|
|
+ headerContent = lipgloss.NewStyle().Padding(0, 1).Render(lipgloss.JoinVertical(lipgloss.Left, headerParts...))
|
|
|
|
|
+ // Format the diff with colors instead of using markdown code block
|
|
|
|
|
+ formattedDiff := formatDiff(pr.Content)
|
|
|
|
|
+ return lipgloss.JoinVertical(
|
|
|
|
|
+ lipgloss.Top,
|
|
|
|
|
+ headerContent,
|
|
|
|
|
+ formattedDiff,
|
|
|
|
|
+ form,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
case tools.FetchToolName:
|
|
case tools.FetchToolName:
|
|
|
pr := p.permission.Params.(tools.FetchPermissionsParams)
|
|
pr := p.permission.Params.(tools.FetchPermissionsParams)
|
|
|
headerParts = append(headerParts, keyStyle.Render("URL: "+pr.URL))
|
|
headerParts = append(headerParts, keyStyle.Render("URL: "+pr.URL))
|
|
|
- default:
|
|
|
|
|
- content = p.permission.Description
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- renderedContent, _ := r.Render(content)
|
|
|
|
|
- headerContent := lipgloss.NewStyle().Padding(0, 1).Render(lipgloss.JoinVertical(lipgloss.Left, headerParts...))
|
|
|
|
|
- p.contentViewPort.Width = p.width - 2 - 2
|
|
|
|
|
-
|
|
|
|
|
- // Calculate content height dynamically based on content
|
|
|
|
|
- contentLines := len(strings.Split(renderedContent, "\n"))
|
|
|
|
|
- // Set a reasonable min/max for the viewport height
|
|
|
|
|
- minContentHeight := 3
|
|
|
|
|
- maxContentHeight := p.height - lipgloss.Height(headerContent) - lipgloss.Height(form) - 2 - 2 - 1
|
|
|
|
|
-
|
|
|
|
|
- // For bash commands, adjust height based on content length
|
|
|
|
|
- if p.permission.ToolName == tools.BashToolName {
|
|
|
|
|
- // Add some padding to the content lines
|
|
|
|
|
- contentHeight := contentLines + 2
|
|
|
|
|
- if contentHeight < minContentHeight {
|
|
|
|
|
- contentHeight = minContentHeight
|
|
|
|
|
|
|
+ content := p.permission.Description
|
|
|
|
|
+
|
|
|
|
|
+ renderedContent, _ := r.Render(content)
|
|
|
|
|
+ p.contentViewPort.Width = p.width - 2 - 2
|
|
|
|
|
+ p.contentViewPort.Height = p.height - lipgloss.Height(headerContent) - lipgloss.Height(form) - 2 - 2 - 1
|
|
|
|
|
+ p.contentViewPort.SetContent(renderedContent)
|
|
|
|
|
+
|
|
|
|
|
+ // Style the viewport
|
|
|
|
|
+ contentStyle := lipgloss.NewStyle().
|
|
|
|
|
+ MarginTop(1).
|
|
|
|
|
+ Padding(0, 1).
|
|
|
|
|
+ Border(lipgloss.RoundedBorder()).
|
|
|
|
|
+ BorderForeground(styles.Flamingo)
|
|
|
|
|
+
|
|
|
|
|
+ contentFinal := contentStyle.Render(p.contentViewPort.View())
|
|
|
|
|
+ if renderedContent == "" {
|
|
|
|
|
+ contentFinal = ""
|
|
|
}
|
|
}
|
|
|
- if contentHeight > maxContentHeight {
|
|
|
|
|
- contentHeight = maxContentHeight
|
|
|
|
|
|
|
+
|
|
|
|
|
+ return lipgloss.JoinVertical(
|
|
|
|
|
+ lipgloss.Top,
|
|
|
|
|
+ headerContent,
|
|
|
|
|
+ contentFinal,
|
|
|
|
|
+ form,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ default:
|
|
|
|
|
+ content := p.permission.Description
|
|
|
|
|
+
|
|
|
|
|
+ renderedContent, _ := r.Render(content)
|
|
|
|
|
+ p.contentViewPort.Width = p.width - 2 - 2
|
|
|
|
|
+ p.contentViewPort.Height = p.height - lipgloss.Height(headerContent) - lipgloss.Height(form) - 2 - 2 - 1
|
|
|
|
|
+ p.contentViewPort.SetContent(renderedContent)
|
|
|
|
|
+
|
|
|
|
|
+ // Style the viewport
|
|
|
|
|
+ contentStyle := lipgloss.NewStyle().
|
|
|
|
|
+ MarginTop(1).
|
|
|
|
|
+ Padding(0, 1).
|
|
|
|
|
+ Border(lipgloss.RoundedBorder()).
|
|
|
|
|
+ BorderForeground(styles.Flamingo)
|
|
|
|
|
+
|
|
|
|
|
+ contentFinal := contentStyle.Render(p.contentViewPort.View())
|
|
|
|
|
+ if renderedContent == "" {
|
|
|
|
|
+ contentFinal = ""
|
|
|
}
|
|
}
|
|
|
- p.contentViewPort.Height = contentHeight
|
|
|
|
|
- } else {
|
|
|
|
|
- // For other content types, use the full available height
|
|
|
|
|
- p.contentViewPort.Height = maxContentHeight
|
|
|
|
|
|
|
+
|
|
|
|
|
+ return lipgloss.JoinVertical(
|
|
|
|
|
+ lipgloss.Top,
|
|
|
|
|
+ headerContent,
|
|
|
|
|
+ contentFinal,
|
|
|
|
|
+ form,
|
|
|
|
|
+ )
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- p.contentViewPort.SetContent(renderedContent)
|
|
|
|
|
-
|
|
|
|
|
- // Make focus change more apparent with different border styles and colors
|
|
|
|
|
- var contentBorder lipgloss.Border
|
|
|
|
|
- var borderColor lipgloss.TerminalColor
|
|
|
|
|
-
|
|
|
|
|
- if p.isViewportFocus {
|
|
|
|
|
- contentBorder = lipgloss.DoubleBorder()
|
|
|
|
|
- borderColor = styles.Blue
|
|
|
|
|
- } else {
|
|
|
|
|
- contentBorder = lipgloss.RoundedBorder()
|
|
|
|
|
- borderColor = styles.Flamingo
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- contentStyle := lipgloss.NewStyle().
|
|
|
|
|
- MarginTop(1).
|
|
|
|
|
- Padding(0, 1).
|
|
|
|
|
- Border(contentBorder).
|
|
|
|
|
- BorderForeground(borderColor)
|
|
|
|
|
-
|
|
|
|
|
- if p.isViewportFocus {
|
|
|
|
|
- contentStyle = contentStyle.BorderBackground(styles.Surface0)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- contentFinal := contentStyle.Render(p.contentViewPort.View())
|
|
|
|
|
- if renderedContent == "" {
|
|
|
|
|
- contentFinal = ""
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return lipgloss.JoinVertical(
|
|
|
|
|
- lipgloss.Top,
|
|
|
|
|
- headerContent,
|
|
|
|
|
- contentFinal,
|
|
|
|
|
- form,
|
|
|
|
|
- )
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (p *permissionDialogCmp) View() string {
|
|
func (p *permissionDialogCmp) View() string {
|