@@ -11,6 +11,7 @@ use gpui::{
11
11
} ;
12
12
use language:: {
13
13
Anchor , Buffer , Capability , LanguageRegistry , LineEnding , OffsetRangeExt , Rope , TextBuffer ,
14
+ language_settings:: SoftWrap ,
14
15
} ;
15
16
use language_model:: { LanguageModelRequestMessage , LanguageModelToolSchemaFormat } ;
16
17
use project:: Project ;
@@ -274,7 +275,9 @@ pub struct EditFileToolCard {
274
275
project : Entity < Project > ,
275
276
diff_task : Option < Task < Result < ( ) > > > ,
276
277
preview_expanded : bool ,
278
+ error_expanded : bool ,
277
279
full_height_expanded : bool ,
280
+ total_lines : Option < u32 > ,
278
281
editor_unique_id : EntityId ,
279
282
}
280
283
@@ -293,11 +296,13 @@ impl EditFileToolCard {
293
296
window,
294
297
cx,
295
298
) ;
296
- editor. set_show_scrollbars ( false , cx) ;
297
299
editor. set_show_gutter ( false , cx) ;
298
300
editor. disable_inline_diagnostics ( ) ;
299
- editor. disable_scrolling ( cx) ;
300
301
editor. disable_expand_excerpt_buttons ( cx) ;
302
+ editor. set_soft_wrap_mode ( SoftWrap :: None , cx) ;
303
+ editor. scroll_manager . set_forbid_vertical_scroll ( true ) ;
304
+ editor. set_show_scrollbars ( false , cx) ;
305
+ editor. set_read_only ( true ) ;
301
306
editor. set_show_breakpoints ( false , cx) ;
302
307
editor. set_show_code_actions ( false , cx) ;
303
308
editor. set_show_git_diff_gutter ( false , cx) ;
@@ -312,7 +317,9 @@ impl EditFileToolCard {
312
317
multibuffer,
313
318
diff_task : None ,
314
319
preview_expanded : true ,
320
+ error_expanded : false ,
315
321
full_height_expanded : false ,
322
+ total_lines : None ,
316
323
}
317
324
}
318
325
@@ -329,7 +336,7 @@ impl EditFileToolCard {
329
336
let buffer_diff = build_buffer_diff ( old_text, & buffer, & language_registry, cx) . await ?;
330
337
331
338
this. update ( cx, |this, cx| {
332
- this. multibuffer . update ( cx, |multibuffer, cx| {
339
+ this. total_lines = this . multibuffer . update ( cx, |multibuffer, cx| {
333
340
let snapshot = buffer. read ( cx) . snapshot ( ) ;
334
341
let diff = buffer_diff. read ( cx) ;
335
342
let diff_hunk_ranges = diff
@@ -345,7 +352,10 @@ impl EditFileToolCard {
345
352
) ;
346
353
debug_assert ! ( is_newly_added) ;
347
354
multibuffer. add_diff ( buffer_diff, cx) ;
355
+ let end = multibuffer. len ( cx) ;
356
+ Some ( multibuffer. snapshot ( cx) . offset_to_point ( end) . row + 1 )
348
357
} ) ;
358
+
349
359
cx. notify ( ) ;
350
360
} )
351
361
} ) ) ;
@@ -360,7 +370,10 @@ impl ToolCard for EditFileToolCard {
360
370
workspace : WeakEntity < Workspace > ,
361
371
cx : & mut Context < Self > ,
362
372
) -> impl IntoElement {
363
- let failed = matches ! ( status, ToolUseStatus :: Error ( _) ) ;
373
+ let ( failed, error_message) = match status {
374
+ ToolUseStatus :: Error ( err) => ( true , Some ( err. to_string ( ) ) ) ,
375
+ _ => ( false , None ) ,
376
+ } ;
364
377
365
378
let path_label_button = h_flex ( )
366
379
. id ( ( "edit-tool-path-label-button" , self . editor_unique_id ) )
@@ -452,9 +465,26 @@ impl ToolCard for EditFileToolCard {
452
465
. map ( |container| {
453
466
if failed {
454
467
container. child (
455
- Icon :: new ( IconName :: Close )
456
- . size ( IconSize :: Small )
457
- . color ( Color :: Error ) ,
468
+ h_flex ( )
469
+ . gap_1 ( )
470
+ . child (
471
+ Icon :: new ( IconName :: Close )
472
+ . size ( IconSize :: Small )
473
+ . color ( Color :: Error ) ,
474
+ )
475
+ . child (
476
+ Disclosure :: new (
477
+ ( "edit-file-error-disclosure" , self . editor_unique_id ) ,
478
+ self . error_expanded ,
479
+ )
480
+ . opened_icon ( IconName :: ChevronUp )
481
+ . closed_icon ( IconName :: ChevronDown )
482
+ . on_click ( cx. listener (
483
+ move |this, _event, _window, _cx| {
484
+ this. error_expanded = !this. error_expanded ;
485
+ } ,
486
+ ) ) ,
487
+ ) ,
458
488
)
459
489
} else {
460
490
container. child (
@@ -473,8 +503,14 @@ impl ToolCard for EditFileToolCard {
473
503
}
474
504
} ) ;
475
505
476
- let editor = self . editor . update ( cx, |editor, cx| {
477
- editor. render ( window, cx) . into_any_element ( )
506
+ let ( editor, editor_line_height) = self . editor . update ( cx, |editor, cx| {
507
+ let line_height = editor
508
+ . style ( )
509
+ . map ( |style| style. text . line_height_in_pixels ( window. rem_size ( ) ) )
510
+ . unwrap_or_default ( ) ;
511
+
512
+ let element = editor. render ( window, cx) ;
513
+ ( element. into_any_element ( ) , line_height)
478
514
} ) ;
479
515
480
516
let ( full_height_icon, full_height_tooltip_label) = if self . full_height_expanded {
@@ -498,6 +534,9 @@ impl ToolCard for EditFileToolCard {
498
534
499
535
let border_color = cx. theme ( ) . colors ( ) . border . opacity ( 0.6 ) ;
500
536
537
+ const DEFAULT_COLLAPSED_LINES : u32 = 10 ;
538
+ let is_collapsible = self . total_lines . unwrap_or ( 0 ) > DEFAULT_COLLAPSED_LINES ;
539
+
501
540
v_flex ( )
502
541
. mb_2 ( )
503
542
. border_1 ( )
@@ -506,50 +545,79 @@ impl ToolCard for EditFileToolCard {
506
545
. rounded_lg ( )
507
546
. overflow_hidden ( )
508
547
. child ( codeblock_header)
509
- . when ( ! failed && self . preview_expanded , |card| {
548
+ . when ( failed && self . error_expanded , |card| {
510
549
card. child (
511
550
v_flex ( )
512
- . relative ( )
513
- . overflow_hidden ( )
551
+ . p_2 ( )
552
+ . gap_1 ( )
514
553
. border_t_1 ( )
554
+ . border_dashed ( )
515
555
. border_color ( border_color)
516
556
. bg ( cx. theme ( ) . colors ( ) . editor_background )
557
+ . rounded_b_md ( )
558
+ . child (
559
+ Label :: new ( "Error" )
560
+ . size ( LabelSize :: XSmall )
561
+ . color ( Color :: Error ) ,
562
+ )
563
+ . child (
564
+ div ( )
565
+ . rounded_md ( )
566
+ . text_ui_sm ( cx)
567
+ . bg ( cx. theme ( ) . colors ( ) . editor_background )
568
+ . children (
569
+ error_message
570
+ . map ( |error| div ( ) . child ( error) . into_any_element ( ) ) ,
571
+ ) ,
572
+ ) ,
573
+ )
574
+ } )
575
+ . when ( !failed && self . preview_expanded , |card| {
576
+ card. child (
577
+ v_flex ( )
578
+ . relative ( )
517
579
. map ( |editor_container| {
518
580
if self . full_height_expanded {
519
581
editor_container. h_full ( )
520
582
} else {
521
- editor_container. max_h_64 ( )
583
+ editor_container
584
+ . h ( DEFAULT_COLLAPSED_LINES as f32 * editor_line_height)
522
585
}
523
586
} )
524
- . child ( div ( ) . pl_1 ( ) . child ( editor) )
525
- . when ( !self . full_height_expanded , |editor_container| {
526
- editor_container. child ( gradient_overlay)
527
- } ) ,
528
- )
529
- } )
530
- . when ( !failed && self . preview_expanded , |card| {
531
- card. child (
532
- h_flex ( )
533
- . id ( ( "edit-tool-card-inner-hflex" , self . editor_unique_id ) )
534
- . flex_none ( )
535
- . cursor_pointer ( )
536
- . h_5 ( )
537
- . justify_center ( )
538
- . rounded_b_md ( )
587
+ . overflow_hidden ( )
539
588
. border_t_1 ( )
540
589
. border_color ( border_color)
541
590
. bg ( cx. theme ( ) . colors ( ) . editor_background )
542
- . hover ( |style| style. bg ( cx. theme ( ) . colors ( ) . element_hover . opacity ( 0.1 ) ) )
543
- . child (
544
- Icon :: new ( full_height_icon)
545
- . size ( IconSize :: Small )
546
- . color ( Color :: Muted ) ,
547
- )
548
- . tooltip ( Tooltip :: text ( full_height_tooltip_label) )
549
- . on_click ( cx. listener ( move |this, _event, _window, _cx| {
550
- this. full_height_expanded = !this. full_height_expanded ;
551
- } ) ) ,
591
+ . child ( div ( ) . pl_1 ( ) . child ( editor) )
592
+ . when (
593
+ !self . full_height_expanded && is_collapsible,
594
+ |editor_container| editor_container. child ( gradient_overlay) ,
595
+ ) ,
552
596
)
597
+ . when ( is_collapsible, |editor_container| {
598
+ editor_container. child (
599
+ h_flex ( )
600
+ . id ( ( "expand-button" , self . editor_unique_id ) )
601
+ . flex_none ( )
602
+ . cursor_pointer ( )
603
+ . h_5 ( )
604
+ . justify_center ( )
605
+ . rounded_b_md ( )
606
+ . border_t_1 ( )
607
+ . border_color ( border_color)
608
+ . bg ( cx. theme ( ) . colors ( ) . editor_background )
609
+ . hover ( |style| style. bg ( cx. theme ( ) . colors ( ) . element_hover . opacity ( 0.1 ) ) )
610
+ . child (
611
+ Icon :: new ( full_height_icon)
612
+ . size ( IconSize :: Small )
613
+ . color ( Color :: Muted ) ,
614
+ )
615
+ . tooltip ( Tooltip :: text ( full_height_tooltip_label) )
616
+ . on_click ( cx. listener ( move |this, _event, _window, _cx| {
617
+ this. full_height_expanded = !this. full_height_expanded ;
618
+ } ) ) ,
619
+ )
620
+ } )
553
621
} )
554
622
}
555
623
}
0 commit comments