@@ -65,6 +65,45 @@ type permissionDialogCmp struct {
6565 selectOption * huh.Select [string ]
6666}
6767
68+ // formatDiff formats a diff string with colors for additions and deletions
69+ func formatDiff (diffText string ) string {
70+ lines := strings .Split (diffText , "\n " )
71+ var formattedLines []string
72+
73+ // Define styles for different line types
74+ addStyle := lipgloss .NewStyle ().Foreground (styles .Green )
75+ removeStyle := lipgloss .NewStyle ().Foreground (styles .Red )
76+ headerStyle := lipgloss .NewStyle ().Bold (true ).Foreground (styles .Blue )
77+ contextStyle := lipgloss .NewStyle ().Foreground (styles .SubText0 )
78+
79+ // Process each line
80+ for _ , line := range lines {
81+ if strings .HasPrefix (line , "+" ) {
82+ formattedLines = append (formattedLines , addStyle .Render (line ))
83+ } else if strings .HasPrefix (line , "-" ) {
84+ formattedLines = append (formattedLines , removeStyle .Render (line ))
85+ } else if strings .HasPrefix (line , "Changes:" ) || strings .HasPrefix (line , " ..." ) {
86+ formattedLines = append (formattedLines , headerStyle .Render (line ))
87+ } else if strings .HasPrefix (line , " " ) {
88+ formattedLines = append (formattedLines , contextStyle .Render (line ))
89+ } else {
90+ formattedLines = append (formattedLines , line )
91+ }
92+ }
93+
94+ // Join all formatted lines
95+ content := strings .Join (formattedLines , "\n " )
96+
97+ // Create a bordered box for the content
98+ contentStyle := lipgloss .NewStyle ().
99+ MarginTop (1 ).
100+ Padding (0 , 1 ).
101+ Border (lipgloss .RoundedBorder ()).
102+ BorderForeground (styles .Flamingo )
103+
104+ return contentStyle .Render (content )
105+ }
106+
68107func (p * permissionDialogCmp ) Init () tea.Cmd {
69108 return nil
70109}
@@ -132,93 +171,159 @@ func (p *permissionDialogCmp) render() string {
132171 lipgloss .JoinHorizontal (lipgloss .Left , keyStyle .Render ("Path:" ), " " , valueStyle .Render (p .permission .Path )),
133172 " " ,
134173 }
174+
175+ // Create the header content first so it can be used in all cases
176+ headerContent := lipgloss .NewStyle ().Padding (0 , 1 ).Render (lipgloss .JoinVertical (lipgloss .Left , headerParts ... ))
177+
135178 r , _ := glamour .NewTermRenderer (
136179 glamour .WithStyles (styles .CatppuccinMarkdownStyle ()),
137180 glamour .WithWordWrap (p .width - 10 ),
138181 glamour .WithEmoji (),
139182 )
140- content := ""
183+
184+ // Handle different tool types
141185 switch p .permission .ToolName {
142186 case tools .BashToolName :
143187 pr := p .permission .Params .(tools.BashPermissionsParams )
144188 headerParts = append (headerParts , keyStyle .Render ("Command:" ))
145- content = fmt .Sprintf ("```bash\n %s\n ```" , pr .Command )
189+ content := fmt .Sprintf ("```bash\n %s\n ```" , pr .Command )
190+
191+ renderedContent , _ := r .Render (content )
192+ p .contentViewPort .Width = p .width - 2 - 2
193+
194+ // Calculate content height dynamically based on content
195+ contentLines := len (strings .Split (renderedContent , "\n " ))
196+ // Set a reasonable min/max for the viewport height
197+ minContentHeight := 3
198+ maxContentHeight := p .height - lipgloss .Height (headerContent ) - lipgloss .Height (form ) - 2 - 2 - 1
199+
200+ // Add some padding to the content lines
201+ contentHeight := contentLines + 2
202+ if contentHeight < minContentHeight {
203+ contentHeight = minContentHeight
204+ }
205+ if contentHeight > maxContentHeight {
206+ contentHeight = maxContentHeight
207+ }
208+ p .contentViewPort .Height = contentHeight
209+
210+ p .contentViewPort .SetContent (renderedContent )
211+
212+ // Style the viewport
213+ var contentBorder lipgloss.Border
214+ var borderColor lipgloss.TerminalColor
215+
216+ if p .isViewportFocus {
217+ contentBorder = lipgloss .DoubleBorder ()
218+ borderColor = styles .Blue
219+ } else {
220+ contentBorder = lipgloss .RoundedBorder ()
221+ borderColor = styles .Flamingo
222+ }
223+
224+ contentStyle := lipgloss .NewStyle ().
225+ MarginTop (1 ).
226+ Padding (0 , 1 ).
227+ Border (contentBorder ).
228+ BorderForeground (borderColor )
229+
230+ if p .isViewportFocus {
231+ contentStyle = contentStyle .BorderBackground (styles .Surface0 )
232+ }
233+
234+ contentFinal := contentStyle .Render (p .contentViewPort .View ())
235+
236+ return lipgloss .JoinVertical (
237+ lipgloss .Top ,
238+ headerContent ,
239+ contentFinal ,
240+ form ,
241+ )
242+
146243 case tools .EditToolName :
147244 pr := p .permission .Params .(tools.EditPermissionsParams )
148245 headerParts = append (headerParts , keyStyle .Render ("Update" ))
149- content = fmt .Sprintf ("```\n %s\n ```" , pr .Diff )
246+ // Recreate header content with the updated headerParts
247+ headerContent = lipgloss .NewStyle ().Padding (0 , 1 ).Render (lipgloss .JoinVertical (lipgloss .Left , headerParts ... ))
248+ // Format the diff with colors instead of using markdown code block
249+ formattedDiff := formatDiff (pr .Diff )
250+ return lipgloss .JoinVertical (
251+ lipgloss .Top ,
252+ headerContent ,
253+ formattedDiff ,
254+ form ,
255+ )
256+
150257 case tools .WriteToolName :
151258 pr := p .permission .Params .(tools.WritePermissionsParams )
152259 headerParts = append (headerParts , keyStyle .Render ("Content" ))
153- content = fmt .Sprintf ("```\n %s\n ```" , pr .Content )
260+ // Recreate header content with the updated headerParts
261+ headerContent = lipgloss .NewStyle ().Padding (0 , 1 ).Render (lipgloss .JoinVertical (lipgloss .Left , headerParts ... ))
262+ // Format the diff with colors instead of using markdown code block
263+ formattedDiff := formatDiff (pr .Content )
264+ return lipgloss .JoinVertical (
265+ lipgloss .Top ,
266+ headerContent ,
267+ formattedDiff ,
268+ form ,
269+ )
270+
154271 case tools .FetchToolName :
155272 pr := p .permission .Params .(tools.FetchPermissionsParams )
156273 headerParts = append (headerParts , keyStyle .Render ("URL: " + pr .URL ))
157- default :
158- content = p .permission .Description
159- }
160-
161- renderedContent , _ := r .Render (content )
162- headerContent := lipgloss .NewStyle ().Padding (0 , 1 ).Render (lipgloss .JoinVertical (lipgloss .Left , headerParts ... ))
163- p .contentViewPort .Width = p .width - 2 - 2
164-
165- // Calculate content height dynamically based on content
166- contentLines := len (strings .Split (renderedContent , "\n " ))
167- // Set a reasonable min/max for the viewport height
168- minContentHeight := 3
169- maxContentHeight := p .height - lipgloss .Height (headerContent ) - lipgloss .Height (form ) - 2 - 2 - 1
170-
171- // For bash commands, adjust height based on content length
172- if p .permission .ToolName == tools .BashToolName {
173- // Add some padding to the content lines
174- contentHeight := contentLines + 2
175- if contentHeight < minContentHeight {
176- contentHeight = minContentHeight
274+ content := p .permission .Description
275+
276+ renderedContent , _ := r .Render (content )
277+ p .contentViewPort .Width = p .width - 2 - 2
278+ p .contentViewPort .Height = p .height - lipgloss .Height (headerContent ) - lipgloss .Height (form ) - 2 - 2 - 1
279+ p .contentViewPort .SetContent (renderedContent )
280+
281+ // Style the viewport
282+ contentStyle := lipgloss .NewStyle ().
283+ MarginTop (1 ).
284+ Padding (0 , 1 ).
285+ Border (lipgloss .RoundedBorder ()).
286+ BorderForeground (styles .Flamingo )
287+
288+ contentFinal := contentStyle .Render (p .contentViewPort .View ())
289+ if renderedContent == "" {
290+ contentFinal = ""
177291 }
178- if contentHeight > maxContentHeight {
179- contentHeight = maxContentHeight
292+
293+ return lipgloss .JoinVertical (
294+ lipgloss .Top ,
295+ headerContent ,
296+ contentFinal ,
297+ form ,
298+ )
299+
300+ default :
301+ content := p .permission .Description
302+
303+ renderedContent , _ := r .Render (content )
304+ p .contentViewPort .Width = p .width - 2 - 2
305+ p .contentViewPort .Height = p .height - lipgloss .Height (headerContent ) - lipgloss .Height (form ) - 2 - 2 - 1
306+ p .contentViewPort .SetContent (renderedContent )
307+
308+ // Style the viewport
309+ contentStyle := lipgloss .NewStyle ().
310+ MarginTop (1 ).
311+ Padding (0 , 1 ).
312+ Border (lipgloss .RoundedBorder ()).
313+ BorderForeground (styles .Flamingo )
314+
315+ contentFinal := contentStyle .Render (p .contentViewPort .View ())
316+ if renderedContent == "" {
317+ contentFinal = ""
180318 }
181- p .contentViewPort .Height = contentHeight
182- } else {
183- // For other content types, use the full available height
184- p .contentViewPort .Height = maxContentHeight
319+
320+ return lipgloss .JoinVertical (
321+ lipgloss .Top ,
322+ headerContent ,
323+ contentFinal ,
324+ form ,
325+ )
185326 }
186-
187- p .contentViewPort .SetContent (renderedContent )
188-
189- // Make focus change more apparent with different border styles and colors
190- var contentBorder lipgloss.Border
191- var borderColor lipgloss.TerminalColor
192-
193- if p .isViewportFocus {
194- contentBorder = lipgloss .DoubleBorder ()
195- borderColor = styles .Blue
196- } else {
197- contentBorder = lipgloss .RoundedBorder ()
198- borderColor = styles .Flamingo
199- }
200-
201- contentStyle := lipgloss .NewStyle ().
202- MarginTop (1 ).
203- Padding (0 , 1 ).
204- Border (contentBorder ).
205- BorderForeground (borderColor )
206-
207- if p .isViewportFocus {
208- contentStyle = contentStyle .BorderBackground (styles .Surface0 )
209- }
210-
211- contentFinal := contentStyle .Render (p .contentViewPort .View ())
212- if renderedContent == "" {
213- contentFinal = ""
214- }
215-
216- return lipgloss .JoinVertical (
217- lipgloss .Top ,
218- headerContent ,
219- contentFinal ,
220- form ,
221- )
222327}
223328
224329func (p * permissionDialogCmp ) View () string {
0 commit comments