buffer_view.rs

   1use super::{
   2    buffer, movement, Anchor, Bias, Buffer, BufferElement, DisplayMap, DisplayPoint, Point,
   3    ToOffset, ToPoint,
   4};
   5use crate::{settings::Settings, watch, workspace};
   6use anyhow::Result;
   7use easy_parallel::Parallel;
   8use gpui::{
   9    fonts::{FontCache, Properties as FontProperties},
  10    keymap::Binding,
  11    text_layout, App, AppContext, Element, Entity, ModelHandle, View, ViewContext, WeakViewHandle,
  12};
  13use gpui::{geometry::vector::Vector2F, TextLayoutCache};
  14use parking_lot::Mutex;
  15use smallvec::SmallVec;
  16use smol::Timer;
  17use std::{
  18    cmp::{self, Ordering},
  19    fmt::Write,
  20    mem,
  21    ops::Range,
  22    sync::Arc,
  23    time::Duration,
  24};
  25
  26const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  27
  28pub fn init(app: &mut App) {
  29    app.add_bindings(vec![
  30        Binding::new("backspace", "buffer:backspace", Some("BufferView")),
  31        Binding::new("enter", "buffer:newline", Some("BufferView")),
  32        Binding::new("up", "buffer:move_up", Some("BufferView")),
  33        Binding::new("down", "buffer:move_down", Some("BufferView")),
  34        Binding::new("left", "buffer:move_left", Some("BufferView")),
  35        Binding::new("right", "buffer:move_right", Some("BufferView")),
  36        Binding::new("shift-up", "buffer:select_up", Some("BufferView")),
  37        Binding::new("shift-down", "buffer:select_down", Some("BufferView")),
  38        Binding::new("shift-left", "buffer:select_left", Some("BufferView")),
  39        Binding::new("shift-right", "buffer:select_right", Some("BufferView")),
  40        Binding::new("pageup", "buffer:page_up", Some("BufferView")),
  41        Binding::new("pagedown", "buffer:page_down", Some("BufferView")),
  42        Binding::new("alt-cmd-[", "buffer:fold", Some("BufferView")),
  43        Binding::new("alt-cmd-]", "buffer:unfold", Some("BufferView")),
  44        Binding::new(
  45            "alt-cmd-f",
  46            "buffer:fold_selected_ranges",
  47            Some("BufferView"),
  48        ),
  49    ]);
  50
  51    app.add_action("buffer:scroll", BufferView::scroll);
  52    app.add_action("buffer:select", BufferView::select);
  53    app.add_action("buffer:insert", BufferView::insert);
  54    app.add_action("buffer:newline", BufferView::newline);
  55    app.add_action("buffer:backspace", BufferView::backspace);
  56    app.add_action("buffer:move_up", BufferView::move_up);
  57    app.add_action("buffer:move_down", BufferView::move_down);
  58    app.add_action("buffer:move_left", BufferView::move_left);
  59    app.add_action("buffer:move_right", BufferView::move_right);
  60    app.add_action("buffer:select_up", BufferView::select_up);
  61    app.add_action("buffer:select_down", BufferView::select_down);
  62    app.add_action("buffer:select_left", BufferView::select_left);
  63    app.add_action("buffer:select_right", BufferView::select_right);
  64    app.add_action("buffer:page_up", BufferView::page_up);
  65    app.add_action("buffer:page_down", BufferView::page_down);
  66    app.add_action("buffer:fold", BufferView::fold);
  67    app.add_action("buffer:unfold", BufferView::unfold);
  68    app.add_action(
  69        "buffer:fold_selected_ranges",
  70        BufferView::fold_selected_ranges,
  71    );
  72}
  73
  74pub enum SelectAction {
  75    Begin {
  76        position: DisplayPoint,
  77        add: bool,
  78    },
  79    Update {
  80        position: DisplayPoint,
  81        scroll_position: Vector2F,
  82    },
  83    End,
  84}
  85
  86// impl workspace::Item for Buffer {
  87//     type View = BufferView;
  88
  89//     fn build_view(
  90//         buffer: ModelHandle<Self>,
  91//         settings: watch::Receiver<Settings>,
  92//         ctx: &mut ViewContext<Self::View>,
  93//     ) -> Self::View {
  94//         BufferView::for_buffer(buffer, settings, ctx)
  95//     }
  96// }
  97
  98pub struct BufferView {
  99    handle: WeakViewHandle<Self>,
 100    buffer: ModelHandle<Buffer>,
 101    display_map: ModelHandle<DisplayMap>,
 102    selections: Vec<Selection>,
 103    pending_selection: Option<Selection>,
 104    scroll_position: Mutex<Vector2F>,
 105    autoscroll_requested: Mutex<bool>,
 106    settings: watch::Receiver<Settings>,
 107    focused: bool,
 108    cursors_visible: bool,
 109    blink_epoch: usize,
 110    blinking_paused: bool,
 111    single_line: bool,
 112}
 113
 114impl BufferView {
 115    pub fn single_line(settings: watch::Receiver<Settings>, ctx: &mut ViewContext<Self>) -> Self {
 116        let buffer = ctx.add_model(|_| Buffer::new(0, String::new()));
 117        let mut view = Self::for_buffer(buffer, settings, ctx);
 118        view.single_line = true;
 119        view
 120    }
 121
 122    pub fn for_buffer(
 123        buffer: ModelHandle<Buffer>,
 124        settings: watch::Receiver<Settings>,
 125        ctx: &mut ViewContext<Self>,
 126    ) -> Self {
 127        settings.notify_view_on_change(ctx);
 128
 129        ctx.observe(&buffer, Self::on_buffer_changed);
 130        ctx.subscribe_to_model(&buffer, Self::on_buffer_event);
 131        let display_map = ctx.add_model(|ctx| {
 132            DisplayMap::new(
 133                buffer.clone(),
 134                smol::block_on(settings.read()).tab_size,
 135                ctx,
 136            )
 137        });
 138        ctx.observe(&display_map, Self::on_display_map_changed);
 139
 140        let buffer_ref = buffer.as_ref(ctx);
 141        Self {
 142            handle: ctx.handle(),
 143            buffer,
 144            display_map,
 145            selections: vec![Selection {
 146                start: buffer_ref.anchor_before(0).unwrap(),
 147                end: buffer_ref.anchor_before(0).unwrap(),
 148                reversed: false,
 149                goal_column: None,
 150            }],
 151            pending_selection: None,
 152            scroll_position: Mutex::new(Vector2F::zero()),
 153            autoscroll_requested: Mutex::new(false),
 154            settings,
 155            focused: false,
 156            cursors_visible: false,
 157            blink_epoch: 0,
 158            blinking_paused: false,
 159            single_line: false,
 160        }
 161    }
 162
 163    pub fn buffer(&self) -> &ModelHandle<Buffer> {
 164        &self.buffer
 165    }
 166
 167    pub fn is_gutter_visible(&self) -> bool {
 168        !self.single_line
 169    }
 170
 171    fn scroll(&mut self, scroll_position: &Vector2F, ctx: &mut ViewContext<Self>) {
 172        *self.scroll_position.lock() = *scroll_position;
 173        ctx.notify();
 174    }
 175
 176    pub fn scroll_position(&self) -> Vector2F {
 177        *self.scroll_position.lock()
 178    }
 179
 180    pub fn clamp_scroll_left(&self, max: f32) {
 181        let mut scroll_position = self.scroll_position.lock();
 182        let scroll_left = scroll_position.x();
 183        scroll_position.set_x(scroll_left.min(max));
 184    }
 185
 186    pub fn autoscroll_vertically(
 187        &self,
 188        viewport_height: f32,
 189        line_height: f32,
 190        app: &AppContext,
 191    ) -> bool {
 192        let mut scroll_position = self.scroll_position.lock();
 193        let scroll_top = scroll_position.y();
 194        scroll_position.set_y(scroll_top.min(self.max_point(app).row().saturating_sub(1) as f32));
 195
 196        let mut autoscroll_requested = self.autoscroll_requested.lock();
 197        if *autoscroll_requested {
 198            *autoscroll_requested = false;
 199        } else {
 200            return false;
 201        }
 202
 203        let map = self.display_map.as_ref(app);
 204        let visible_lines = viewport_height / line_height;
 205        let first_cursor_top = self
 206            .selections
 207            .first()
 208            .unwrap()
 209            .head()
 210            .to_display_point(map, app)
 211            .unwrap()
 212            .row() as f32;
 213        let last_cursor_bottom = self
 214            .selections
 215            .last()
 216            .unwrap()
 217            .head()
 218            .to_display_point(map, app)
 219            .unwrap()
 220            .row() as f32
 221            + 1.0;
 222
 223        let margin = ((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0)
 224            .floor()
 225            .min(3.0);
 226        if margin < 0.0 {
 227            return false;
 228        }
 229
 230        let target_top = (first_cursor_top - margin).max(0.0);
 231        let target_bottom = last_cursor_bottom + margin;
 232        let start_row = scroll_position.y();
 233        let end_row = start_row + visible_lines;
 234
 235        if target_top < start_row {
 236            scroll_position.set_y(target_top);
 237        } else if target_bottom >= end_row {
 238            scroll_position.set_y(target_bottom - visible_lines);
 239        }
 240
 241        true
 242    }
 243
 244    pub fn autoscroll_horizontally(
 245        &self,
 246        start_row: u32,
 247        viewport_width: f32,
 248        scroll_width: f32,
 249        max_glyph_width: f32,
 250        layouts: &[Arc<text_layout::Line>],
 251        app: &AppContext,
 252    ) {
 253        let map = self.display_map.as_ref(app);
 254
 255        let mut target_left = std::f32::INFINITY;
 256        let mut target_right = 0.0_f32;
 257        for selection in &self.selections {
 258            let head = selection.head().to_display_point(map, app).unwrap();
 259            let start_column = head.column().saturating_sub(3);
 260            let end_column = cmp::min(map.line_len(head.row(), app).unwrap(), head.column() + 3);
 261            target_left = target_left
 262                .min(layouts[(head.row() - start_row) as usize].x_for_index(start_column as usize));
 263            target_right = target_right.max(
 264                layouts[(head.row() - start_row) as usize].x_for_index(end_column as usize)
 265                    + max_glyph_width,
 266            );
 267        }
 268        target_right = target_right.min(scroll_width);
 269
 270        if target_right - target_left > viewport_width {
 271            return;
 272        }
 273
 274        let mut scroll_position = self.scroll_position.lock();
 275        let scroll_left = scroll_position.x() * max_glyph_width;
 276        let scroll_right = scroll_left + viewport_width;
 277
 278        if target_left < scroll_left {
 279            scroll_position.set_x(target_left / max_glyph_width);
 280        } else if target_right > scroll_right {
 281            scroll_position.set_x((target_right - viewport_width) / max_glyph_width);
 282        }
 283    }
 284
 285    fn select(&mut self, arg: &SelectAction, ctx: &mut ViewContext<Self>) {
 286        match arg {
 287            SelectAction::Begin { position, add } => self.begin_selection(*position, *add, ctx),
 288            SelectAction::Update {
 289                position,
 290                scroll_position,
 291            } => self.update_selection(*position, *scroll_position, ctx),
 292            SelectAction::End => self.end_selection(ctx),
 293        }
 294    }
 295
 296    fn begin_selection(&mut self, position: DisplayPoint, add: bool, ctx: &mut ViewContext<Self>) {
 297        if !self.focused {
 298            ctx.focus_self();
 299            ctx.emit(Event::Activate);
 300        }
 301
 302        let display_map = self.display_map.as_ref(ctx);
 303        let cursor = display_map
 304            .anchor_before(position, Bias::Left, ctx.app())
 305            .unwrap();
 306        let selection = Selection {
 307            start: cursor.clone(),
 308            end: cursor,
 309            reversed: false,
 310            goal_column: None,
 311        };
 312
 313        if !add {
 314            self.selections.clear();
 315        }
 316        self.pending_selection = Some(selection);
 317
 318        ctx.notify();
 319    }
 320
 321    fn update_selection(
 322        &mut self,
 323        position: DisplayPoint,
 324        scroll_position: Vector2F,
 325        ctx: &mut ViewContext<Self>,
 326    ) {
 327        let buffer = self.buffer.as_ref(ctx);
 328        let map = self.display_map.as_ref(ctx);
 329        let cursor = map.anchor_before(position, Bias::Left, ctx.app()).unwrap();
 330        if let Some(selection) = self.pending_selection.as_mut() {
 331            selection.set_head(buffer, cursor);
 332        } else {
 333            log::error!("update_selection dispatched with no pending selection");
 334            return;
 335        }
 336
 337        *self.scroll_position.lock() = scroll_position;
 338
 339        ctx.notify();
 340    }
 341
 342    fn end_selection(&mut self, ctx: &mut ViewContext<Self>) {
 343        if let Some(selection) = self.pending_selection.take() {
 344            let ix = self.selection_insertion_index(&selection.start, ctx.app());
 345            self.selections.insert(ix, selection);
 346            self.merge_selections(ctx.app());
 347            ctx.notify();
 348        } else {
 349            log::error!("end_selection dispatched with no pending selection");
 350        }
 351    }
 352
 353    pub fn is_selecting(&self) -> bool {
 354        self.pending_selection.is_some()
 355    }
 356
 357    #[cfg(test)]
 358    fn select_ranges<T>(&mut self, ranges: T, ctx: &mut ViewContext<Self>) -> Result<()>
 359    where
 360        T: IntoIterator<Item = Range<DisplayPoint>>,
 361    {
 362        let buffer = self.buffer.as_ref(ctx);
 363        let map = self.display_map.as_ref(ctx);
 364        let mut selections = Vec::new();
 365        for range in ranges {
 366            selections.push(Selection {
 367                start: map.anchor_after(range.start, Bias::Left, ctx.app())?,
 368                end: map.anchor_before(range.end, Bias::Left, ctx.app())?,
 369                reversed: false,
 370                goal_column: None,
 371            });
 372        }
 373        selections.sort_unstable_by(|a, b| a.start.cmp(&b.start, buffer).unwrap());
 374        self.selections = selections;
 375        self.merge_selections(ctx.app());
 376        ctx.notify();
 377        Ok(())
 378    }
 379
 380    fn insert(&mut self, text: &String, ctx: &mut ViewContext<Self>) {
 381        let buffer = self.buffer.as_ref(ctx);
 382        let mut offset_ranges = SmallVec::<[Range<usize>; 32]>::new();
 383        for selection in &self.selections {
 384            let start = selection.start.to_offset(buffer).unwrap();
 385            let end = selection.end.to_offset(buffer).unwrap();
 386            offset_ranges.push(start..end);
 387        }
 388
 389        self.buffer.update(ctx, |buffer, ctx| {
 390            if let Err(error) = buffer.edit(offset_ranges.iter().cloned(), text.as_str(), Some(ctx))
 391            {
 392                log::error!("error inserting text: {}", error);
 393            };
 394        });
 395
 396        let buffer = self.buffer.as_ref(ctx);
 397        let char_count = text.chars().count() as isize;
 398        let mut delta = 0_isize;
 399        self.selections = offset_ranges
 400            .into_iter()
 401            .map(|range| {
 402                let start = range.start as isize;
 403                let end = range.end as isize;
 404                let anchor = buffer
 405                    .anchor_before((start + delta + char_count) as usize)
 406                    .unwrap();
 407                let deleted_count = end - start;
 408                delta += char_count - deleted_count;
 409                Selection {
 410                    start: anchor.clone(),
 411                    end: anchor,
 412                    reversed: false,
 413                    goal_column: None,
 414                }
 415            })
 416            .collect();
 417
 418        self.pause_cursor_blinking(ctx);
 419        *self.autoscroll_requested.lock() = true;
 420    }
 421
 422    fn newline(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 423        if self.single_line {
 424            ctx.propagate_action();
 425        } else {
 426            self.insert(&"\n".into(), ctx);
 427        }
 428    }
 429
 430    pub fn backspace(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 431        self.select_left(&(), ctx);
 432        self.insert(&String::new(), ctx);
 433    }
 434
 435    pub fn move_left(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 436        {
 437            let app = ctx.app();
 438            let map = self.display_map.as_ref(ctx);
 439            for selection in &mut self.selections {
 440                let start = selection.start.to_display_point(map, app).unwrap();
 441                let end = selection.end.to_display_point(map, app).unwrap();
 442
 443                if start != end {
 444                    selection.end = selection.start.clone();
 445                } else {
 446                    let cursor = map
 447                        .anchor_before(movement::left(map, start, app).unwrap(), Bias::Left, app)
 448                        .unwrap();
 449                    selection.start = cursor.clone();
 450                    selection.end = cursor;
 451                }
 452                selection.reversed = false;
 453                selection.goal_column = None;
 454            }
 455        }
 456        self.changed_selections(ctx);
 457    }
 458
 459    pub fn select_left(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 460        {
 461            let buffer = self.buffer.as_ref(ctx);
 462            let map = self.display_map.as_ref(ctx);
 463            for selection in &mut self.selections {
 464                let head = selection.head().to_display_point(map, ctx.app()).unwrap();
 465                let cursor = map
 466                    .anchor_before(
 467                        movement::left(map, head, ctx.app()).unwrap(),
 468                        Bias::Left,
 469                        ctx.app(),
 470                    )
 471                    .unwrap();
 472                selection.set_head(&buffer, cursor);
 473                selection.goal_column = None;
 474            }
 475        }
 476        self.changed_selections(ctx);
 477    }
 478
 479    pub fn move_right(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 480        {
 481            let app = ctx.app();
 482            let map = self.display_map.as_ref(app);
 483            for selection in &mut self.selections {
 484                let start = selection.start.to_display_point(map, app).unwrap();
 485                let end = selection.end.to_display_point(map, app).unwrap();
 486
 487                if start != end {
 488                    selection.start = selection.end.clone();
 489                } else {
 490                    let cursor = map
 491                        .anchor_before(movement::right(map, end, app).unwrap(), Bias::Right, app)
 492                        .unwrap();
 493                    selection.start = cursor.clone();
 494                    selection.end = cursor;
 495                }
 496                selection.reversed = false;
 497                selection.goal_column = None;
 498            }
 499        }
 500        self.changed_selections(ctx);
 501    }
 502
 503    pub fn select_right(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 504        {
 505            let buffer = self.buffer.as_ref(ctx);
 506            let app = ctx.app();
 507            let map = self.display_map.as_ref(app);
 508            for selection in &mut self.selections {
 509                let head = selection.head().to_display_point(map, ctx.app()).unwrap();
 510                let cursor = map
 511                    .anchor_before(movement::right(map, head, app).unwrap(), Bias::Right, app)
 512                    .unwrap();
 513                selection.set_head(&buffer, cursor);
 514                selection.goal_column = None;
 515            }
 516        }
 517        self.changed_selections(ctx);
 518    }
 519
 520    pub fn move_up(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 521        if self.single_line {
 522            ctx.propagate_action();
 523        } else {
 524            let app = ctx.app();
 525            let map = self.display_map.as_ref(app);
 526            for selection in &mut self.selections {
 527                let start = selection.start.to_display_point(map, app).unwrap();
 528                let end = selection.end.to_display_point(map, app).unwrap();
 529                if start != end {
 530                    selection.goal_column = None;
 531                }
 532
 533                let (start, goal_column) =
 534                    movement::up(map, start, selection.goal_column, app).unwrap();
 535                let cursor = map.anchor_before(start, Bias::Left, app).unwrap();
 536                selection.start = cursor.clone();
 537                selection.end = cursor;
 538                selection.goal_column = goal_column;
 539                selection.reversed = false;
 540            }
 541            self.changed_selections(ctx);
 542        }
 543    }
 544
 545    pub fn select_up(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 546        if self.single_line {
 547            ctx.propagate_action();
 548        } else {
 549            let app = ctx.app();
 550            let buffer = self.buffer.as_ref(app);
 551            let map = self.display_map.as_ref(app);
 552            for selection in &mut self.selections {
 553                let head = selection.head().to_display_point(map, app).unwrap();
 554                let (head, goal_column) =
 555                    movement::up(map, head, selection.goal_column, app).unwrap();
 556                selection.set_head(&buffer, map.anchor_before(head, Bias::Left, app).unwrap());
 557                selection.goal_column = goal_column;
 558            }
 559            self.changed_selections(ctx);
 560        }
 561    }
 562
 563    pub fn move_down(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 564        if self.single_line {
 565            ctx.propagate_action();
 566        } else {
 567            let app = ctx.app();
 568            let map = self.display_map.as_ref(app);
 569            for selection in &mut self.selections {
 570                let start = selection.start.to_display_point(map, app).unwrap();
 571                let end = selection.end.to_display_point(map, app).unwrap();
 572                if start != end {
 573                    selection.goal_column = None;
 574                }
 575
 576                let (start, goal_column) =
 577                    movement::down(map, end, selection.goal_column, app).unwrap();
 578                let cursor = map.anchor_before(start, Bias::Right, app).unwrap();
 579                selection.start = cursor.clone();
 580                selection.end = cursor;
 581                selection.goal_column = goal_column;
 582                selection.reversed = false;
 583            }
 584            self.changed_selections(ctx);
 585        }
 586    }
 587
 588    pub fn select_down(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 589        if self.single_line {
 590            ctx.propagate_action();
 591        } else {
 592            let app = ctx.app();
 593            let buffer = self.buffer.as_ref(ctx);
 594            let map = self.display_map.as_ref(ctx);
 595            for selection in &mut self.selections {
 596                let head = selection.head().to_display_point(map, app).unwrap();
 597                let (head, goal_column) =
 598                    movement::down(map, head, selection.goal_column, app).unwrap();
 599                selection.set_head(&buffer, map.anchor_before(head, Bias::Right, app).unwrap());
 600                selection.goal_column = goal_column;
 601            }
 602            self.changed_selections(ctx);
 603        }
 604    }
 605
 606    pub fn changed_selections(&mut self, ctx: &mut ViewContext<Self>) {
 607        self.merge_selections(ctx.app());
 608        self.pause_cursor_blinking(ctx);
 609        *self.autoscroll_requested.lock() = true;
 610        ctx.notify();
 611    }
 612
 613    fn merge_selections(&mut self, ctx: &AppContext) {
 614        let buffer = self.buffer.as_ref(ctx);
 615        let mut i = 1;
 616        while i < self.selections.len() {
 617            if self.selections[i - 1]
 618                .end
 619                .cmp(&self.selections[i].start, buffer)
 620                .unwrap()
 621                >= Ordering::Equal
 622            {
 623                let removed = self.selections.remove(i);
 624                if removed
 625                    .start
 626                    .cmp(&self.selections[i - 1].start, buffer)
 627                    .unwrap()
 628                    < Ordering::Equal
 629                {
 630                    self.selections[i - 1].start = removed.start;
 631                }
 632                if removed
 633                    .end
 634                    .cmp(&self.selections[i - 1].end, buffer)
 635                    .unwrap()
 636                    > Ordering::Equal
 637                {
 638                    self.selections[i - 1].end = removed.end;
 639                }
 640            } else {
 641                i += 1;
 642            }
 643        }
 644    }
 645
 646    pub fn first_selection(&self, app: &AppContext) -> Range<DisplayPoint> {
 647        self.selections
 648            .first()
 649            .unwrap()
 650            .display_range(self.display_map.as_ref(app), app)
 651    }
 652
 653    pub fn last_selection(&self, app: &AppContext) -> Range<DisplayPoint> {
 654        self.selections
 655            .last()
 656            .unwrap()
 657            .display_range(self.display_map.as_ref(app), app)
 658    }
 659
 660    pub fn selections_in_range<'a>(
 661        &'a self,
 662        range: Range<DisplayPoint>,
 663        app: &'a AppContext,
 664    ) -> impl 'a + Iterator<Item = Range<DisplayPoint>> {
 665        let map = self.display_map.as_ref(app);
 666
 667        let start = map.anchor_before(range.start, Bias::Left, app).unwrap();
 668        let start_index = self.selection_insertion_index(&start, app);
 669        let pending_selection = self.pending_selection.as_ref().and_then(|s| {
 670            let selection_range = s.display_range(map, app);
 671            if selection_range.start <= range.end || selection_range.end <= range.end {
 672                Some(selection_range)
 673            } else {
 674                None
 675            }
 676        });
 677        self.selections[start_index..]
 678            .iter()
 679            .map(move |s| s.display_range(map, app))
 680            .take_while(move |r| r.start <= range.end || r.end <= range.end)
 681            .chain(pending_selection)
 682    }
 683
 684    fn selection_insertion_index(&self, start: &Anchor, app: &AppContext) -> usize {
 685        let buffer = self.buffer.as_ref(app);
 686
 687        match self
 688            .selections
 689            .binary_search_by(|probe| probe.start.cmp(&start, buffer).unwrap())
 690        {
 691            Ok(index) => index,
 692            Err(index) => {
 693                if index > 0
 694                    && self.selections[index - 1].end.cmp(&start, buffer).unwrap()
 695                        == Ordering::Greater
 696                {
 697                    index - 1
 698                } else {
 699                    index
 700                }
 701            }
 702        }
 703    }
 704
 705    pub fn page_up(&mut self, _: &(), _: &mut ViewContext<Self>) {
 706        log::info!("BufferView::page_up");
 707    }
 708
 709    pub fn page_down(&mut self, _: &(), _: &mut ViewContext<Self>) {
 710        log::info!("BufferView::page_down");
 711    }
 712
 713    pub fn fold(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 714        use super::RangeExt;
 715
 716        let mut fold_ranges = Vec::new();
 717
 718        let app = ctx.app();
 719        let map = self.display_map.as_ref(app);
 720        for selection in &self.selections {
 721            let (start, end) = selection.display_range(map, app).sorted();
 722            let buffer_start_row = start.to_buffer_point(map, Bias::Left, app).unwrap().row;
 723
 724            for row in (0..=end.row()).rev() {
 725                if self.is_line_foldable(row, app) && !map.is_line_folded(row) {
 726                    let fold_range = self.foldable_range_for_line(row, app).unwrap();
 727                    if fold_range.end.row >= buffer_start_row {
 728                        fold_ranges.push(fold_range);
 729                        if row <= start.row() {
 730                            break;
 731                        }
 732                    }
 733                }
 734            }
 735        }
 736
 737        if !fold_ranges.is_empty() {
 738            self.display_map.update(ctx, |map, ctx| {
 739                map.fold(fold_ranges, ctx).unwrap();
 740            });
 741            *self.autoscroll_requested.lock() = true;
 742        }
 743    }
 744
 745    pub fn unfold(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 746        use super::RangeExt;
 747
 748        let app = ctx.app();
 749        let map = self.display_map.as_ref(app);
 750        let buffer = self.buffer.as_ref(app);
 751        let ranges = self
 752            .selections
 753            .iter()
 754            .map(|s| {
 755                let (start, end) = s.display_range(map, app).sorted();
 756                let mut start = start.to_buffer_point(map, Bias::Left, app).unwrap();
 757                let mut end = end.to_buffer_point(map, Bias::Left, app).unwrap();
 758                start.column = 0;
 759                end.column = buffer.line_len(end.row).unwrap();
 760                start..end
 761            })
 762            .collect::<Vec<_>>();
 763
 764        self.display_map.update(ctx, |map, ctx| {
 765            map.unfold(ranges, ctx).unwrap();
 766        });
 767        *self.autoscroll_requested.lock() = true;
 768    }
 769
 770    fn is_line_foldable(&self, display_row: u32, app: &AppContext) -> bool {
 771        let max_point = self.max_point(app);
 772        if display_row >= max_point.row() {
 773            false
 774        } else {
 775            let (start_indent, is_blank) = self.line_indent(display_row, app).unwrap();
 776            if is_blank {
 777                false
 778            } else {
 779                for display_row in display_row + 1..=max_point.row() {
 780                    let (indent, is_blank) = self.line_indent(display_row, app).unwrap();
 781                    if !is_blank {
 782                        return indent > start_indent;
 783                    }
 784                }
 785                false
 786            }
 787        }
 788    }
 789
 790    fn line_indent(&self, display_row: u32, app: &AppContext) -> Result<(usize, bool)> {
 791        let mut indent = 0;
 792        let mut is_blank = true;
 793        for c in self
 794            .display_map
 795            .as_ref(app)
 796            .chars_at(DisplayPoint::new(display_row, 0), app)?
 797        {
 798            if c == ' ' {
 799                indent += 1;
 800            } else {
 801                is_blank = c == '\n';
 802                break;
 803            }
 804        }
 805        Ok((indent, is_blank))
 806    }
 807
 808    fn foldable_range_for_line(&self, start_row: u32, app: &AppContext) -> Result<Range<Point>> {
 809        let map = self.display_map.as_ref(app);
 810        let max_point = self.max_point(app);
 811
 812        let (start_indent, _) = self.line_indent(start_row, app)?;
 813        let start = DisplayPoint::new(start_row, self.line_len(start_row, app)?);
 814        let mut end = None;
 815        for row in start_row + 1..=max_point.row() {
 816            let (indent, is_blank) = self.line_indent(row, app)?;
 817            if !is_blank && indent <= start_indent {
 818                end = Some(DisplayPoint::new(row - 1, self.line_len(row - 1, app)?));
 819                break;
 820            }
 821        }
 822
 823        let end = end.unwrap_or(max_point);
 824        return Ok(start.to_buffer_point(map, Bias::Left, app)?
 825            ..end.to_buffer_point(map, Bias::Left, app)?);
 826    }
 827
 828    pub fn fold_selected_ranges(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 829        self.display_map.update(ctx, |map, ctx| {
 830            let buffer = self.buffer.as_ref(ctx);
 831            let ranges = self
 832                .selections
 833                .iter()
 834                .map(|s| s.range(buffer))
 835                .collect::<Vec<_>>();
 836            map.fold(ranges, ctx).unwrap();
 837        });
 838    }
 839
 840    pub fn line(&self, display_row: u32, app: &AppContext) -> Result<String> {
 841        self.display_map.as_ref(app).line(display_row, app)
 842    }
 843
 844    pub fn line_len(&self, display_row: u32, app: &AppContext) -> Result<u32> {
 845        self.display_map.as_ref(app).line_len(display_row, app)
 846    }
 847
 848    pub fn rightmost_point(&self, app: &AppContext) -> DisplayPoint {
 849        self.display_map.as_ref(app).rightmost_point()
 850    }
 851
 852    pub fn max_point(&self, app: &AppContext) -> DisplayPoint {
 853        self.display_map.as_ref(app).max_point(app)
 854    }
 855
 856    pub fn text(&self, app: &AppContext) -> String {
 857        self.display_map.as_ref(app).text(app)
 858    }
 859
 860    pub fn font_size(&self) -> f32 {
 861        smol::block_on(self.settings.read()).buffer_font_size
 862    }
 863
 864    pub fn font_ascent(&self, font_cache: &FontCache) -> f32 {
 865        let settings = smol::block_on(self.settings.read());
 866        let font_id = font_cache.default_font(settings.buffer_font_family);
 867        let ascent = font_cache.metric(font_id, |m| m.ascent);
 868        font_cache.scale_metric(ascent, font_id, settings.buffer_font_size)
 869    }
 870
 871    pub fn font_descent(&self, font_cache: &FontCache) -> f32 {
 872        let settings = smol::block_on(self.settings.read());
 873        let font_id = font_cache.default_font(settings.buffer_font_family);
 874        let ascent = font_cache.metric(font_id, |m| m.descent);
 875        font_cache.scale_metric(ascent, font_id, settings.buffer_font_size)
 876    }
 877
 878    pub fn line_height(&self, font_cache: &FontCache) -> f32 {
 879        let settings = smol::block_on(self.settings.read());
 880        let font_id = font_cache.default_font(settings.buffer_font_family);
 881        font_cache
 882            .bounding_box(font_id, settings.buffer_font_size)
 883            .y()
 884    }
 885
 886    pub fn em_width(&self, font_cache: &FontCache) -> f32 {
 887        let settings = smol::block_on(self.settings.read());
 888        let font_id = font_cache.default_font(settings.buffer_font_family);
 889        let font = font_cache.font(font_id);
 890        let glyph_id = font.glyph_for_char('m').unwrap();
 891        let bounds = font.typographic_bounds(glyph_id).unwrap();
 892        font_cache.scale_metric(bounds.width(), font_id, settings.buffer_font_size)
 893    }
 894
 895    pub fn max_line_number_width(
 896        &self,
 897        font_cache: &FontCache,
 898        layout_cache: &TextLayoutCache,
 899        app: &AppContext,
 900    ) -> Result<f32> {
 901        let settings = smol::block_on(self.settings.read());
 902        let font_size = settings.buffer_font_size;
 903        let font_id =
 904            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
 905        let digit_count = ((self.buffer.as_ref(app).max_point().row + 1) as f32)
 906            .log10()
 907            .floor() as usize
 908            + 1;
 909
 910        Ok(layout_cache
 911            .layout_str(
 912                "1".repeat(digit_count).as_str(),
 913                font_size,
 914                &[(0..digit_count, font_id)],
 915                font_cache,
 916            )
 917            .width)
 918    }
 919
 920    pub fn layout_line_numbers(
 921        &self,
 922        viewport_height: f32,
 923        font_cache: &FontCache,
 924        layout_cache: &TextLayoutCache,
 925        app: &AppContext,
 926    ) -> Result<Vec<Arc<text_layout::Line>>> {
 927        let display_map = self.display_map.as_ref(app);
 928
 929        let settings = smol::block_on(self.settings.read());
 930        let font_size = settings.buffer_font_size;
 931        let font_id =
 932            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
 933
 934        let start_row = self.scroll_position().y() as usize;
 935        let end_row = cmp::min(
 936            self.max_point(app).row() as usize,
 937            start_row + (viewport_height / self.line_height(font_cache)).ceil() as usize,
 938        );
 939        let line_count = end_row - start_row + 1;
 940        let cpus = num_cpus::get();
 941        let chunk_size = (line_count + cpus - 1) / cpus;
 942
 943        let mut layouts = Vec::new();
 944        layouts.resize_with(line_count, Default::default);
 945
 946        Parallel::<Result<()>>::new()
 947            .each(
 948                layouts.chunks_mut(chunk_size).enumerate(),
 949                |(i, layouts)| {
 950                    let mut line_number = String::new();
 951                    let start = start_row + i * chunk_size;
 952                    let line_numbers = display_map.buffer_rows(start as u32)?.take(layouts.len());
 953                    for (j, buffer_row) in line_numbers.enumerate() {
 954                        line_number.clear();
 955                        write!(&mut line_number, "{}", buffer_row + 1).unwrap();
 956                        layouts[j] = layout_cache.layout_str(
 957                            &line_number,
 958                            font_size,
 959                            &[(0..line_number.len(), font_id)],
 960                            font_cache,
 961                        );
 962                    }
 963                    Ok(())
 964                },
 965            )
 966            .run()
 967            .into_iter()
 968            .collect::<Result<()>>()?;
 969
 970        Ok(layouts)
 971    }
 972
 973    pub fn layout_lines(
 974        &self,
 975        mut rows: Range<u32>,
 976        font_cache: &FontCache,
 977        layout_cache: &TextLayoutCache,
 978        app: &AppContext,
 979    ) -> Result<Vec<Arc<text_layout::Line>>> {
 980        let display_map = self.display_map.as_ref(app);
 981
 982        rows.end = cmp::min(rows.end, display_map.max_point(app).row() + 1);
 983        if rows.start >= rows.end {
 984            return Ok(Vec::new());
 985        }
 986
 987        let settings = smol::block_on(self.settings.read());
 988        let font_id =
 989            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
 990        let font_size = settings.buffer_font_size;
 991
 992        let cpus = num_cpus::get();
 993        let chunk_size = (rows.len() + cpus - 1) / cpus;
 994
 995        let mut layouts = Vec::new();
 996        layouts.resize_with(rows.len(), Default::default);
 997
 998        Parallel::new()
 999            .each(
1000                layouts.chunks_mut(chunk_size as usize).enumerate(),
1001                |(ix, chunk)| {
1002                    let font_cache = &font_cache;
1003                    let chunk_start = rows.start as usize + ix * chunk_size;
1004                    let chunk_end = cmp::min(chunk_start + chunk_size, rows.end as usize);
1005
1006                    let mut row = chunk_start;
1007                    let mut line = String::new();
1008                    let mut line_len = 0;
1009                    let chars = display_map
1010                        .chars_at(DisplayPoint::new(chunk_start as u32, 0), app)
1011                        .unwrap();
1012                    for char in chars.chain(Some('\n')) {
1013                        if char == '\n' {
1014                            chunk[(row - chunk_start) as usize] = layout_cache.layout_str(
1015                                &line,
1016                                font_size,
1017                                &[(0..line_len, font_id)],
1018                                font_cache,
1019                            );
1020                            line.clear();
1021                            line_len = 0;
1022                            row += 1;
1023                            if row == chunk_end {
1024                                break;
1025                            }
1026                        } else {
1027                            line_len += 1;
1028                            line.push(char);
1029                        }
1030                    }
1031                },
1032            )
1033            .run();
1034
1035        Ok(layouts)
1036    }
1037
1038    pub fn layout_line(
1039        &self,
1040        row: u32,
1041        font_cache: &FontCache,
1042        layout_cache: &TextLayoutCache,
1043        app: &AppContext,
1044    ) -> Result<Arc<text_layout::Line>> {
1045        let settings = smol::block_on(self.settings.read());
1046        let font_id =
1047            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
1048
1049        let line = self.line(row, app)?;
1050
1051        Ok(layout_cache.layout_str(
1052            &line,
1053            settings.buffer_font_size,
1054            &[(0..self.line_len(row, app)? as usize, font_id)],
1055            font_cache,
1056        ))
1057    }
1058
1059    fn next_blink_epoch(&mut self) -> usize {
1060        self.blink_epoch += 1;
1061        self.blink_epoch
1062    }
1063
1064    fn pause_cursor_blinking(&mut self, ctx: &mut ViewContext<Self>) {
1065        self.cursors_visible = true;
1066        ctx.notify();
1067
1068        let epoch = self.next_blink_epoch();
1069        let _ = ctx.spawn(
1070            async move {
1071                Timer::after(CURSOR_BLINK_INTERVAL).await;
1072                epoch
1073            },
1074            Self::resume_cursor_blinking,
1075        );
1076    }
1077
1078    fn resume_cursor_blinking(&mut self, epoch: usize, ctx: &mut ViewContext<Self>) {
1079        if epoch == self.blink_epoch {
1080            self.blinking_paused = false;
1081            self.blink_cursors(epoch, ctx);
1082        }
1083    }
1084
1085    fn blink_cursors(&mut self, epoch: usize, ctx: &mut ViewContext<Self>) {
1086        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
1087            self.cursors_visible = !self.cursors_visible;
1088            ctx.notify();
1089
1090            let epoch = self.next_blink_epoch();
1091            let _ = ctx.spawn(
1092                async move {
1093                    Timer::after(CURSOR_BLINK_INTERVAL).await;
1094                    epoch
1095                },
1096                Self::blink_cursors,
1097            );
1098        }
1099    }
1100
1101    pub fn cursors_visible(&self) -> bool {
1102        self.cursors_visible
1103    }
1104
1105    fn on_buffer_changed(&mut self, _: ModelHandle<Buffer>, ctx: &mut ViewContext<Self>) {
1106        ctx.notify();
1107    }
1108
1109    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, ctx: &mut ViewContext<Self>) {
1110        ctx.notify();
1111    }
1112
1113    fn on_buffer_event(
1114        &mut self,
1115        _: ModelHandle<Buffer>,
1116        event: &buffer::Event,
1117        ctx: &mut ViewContext<Self>,
1118    ) {
1119        match event {
1120            buffer::Event::Edited(_) => ctx.emit(Event::Edited),
1121        }
1122    }
1123}
1124
1125struct Selection {
1126    start: Anchor,
1127    end: Anchor,
1128    reversed: bool,
1129    goal_column: Option<u32>,
1130}
1131
1132pub enum Event {
1133    Activate,
1134    Edited,
1135    Blurred,
1136}
1137
1138impl Entity for BufferView {
1139    type Event = Event;
1140}
1141
1142impl View for BufferView {
1143    fn render<'a>(&self, app: &AppContext) -> Box<dyn Element> {
1144        BufferElement::new(self.handle.upgrade(app).unwrap()).boxed()
1145    }
1146
1147    fn ui_name() -> &'static str {
1148        "BufferView"
1149    }
1150
1151    fn on_focus(&mut self, ctx: &mut ViewContext<Self>) {
1152        self.focused = true;
1153        self.blink_cursors(self.blink_epoch, ctx);
1154    }
1155
1156    fn on_blur(&mut self, ctx: &mut ViewContext<Self>) {
1157        self.focused = false;
1158        self.cursors_visible = false;
1159        ctx.emit(Event::Blurred);
1160        ctx.notify();
1161    }
1162}
1163
1164impl workspace::Item for Buffer {
1165    type View = BufferView;
1166
1167    fn build_view(
1168        buffer: ModelHandle<Self>,
1169        settings: watch::Receiver<Settings>,
1170        ctx: &mut ViewContext<Self::View>,
1171    ) -> Self::View {
1172        BufferView::for_buffer(buffer, settings, ctx)
1173    }
1174}
1175
1176impl workspace::ItemView for BufferView {
1177    fn is_activate_event(event: &Self::Event) -> bool {
1178        match event {
1179            Event::Activate => true,
1180            _ => false,
1181        }
1182    }
1183
1184    fn title(&self, app: &AppContext) -> std::string::String {
1185        if let Some(path) = self.buffer.as_ref(app).path(app) {
1186            path.file_name()
1187                .expect("buffer's path is always to a file")
1188                .to_string_lossy()
1189                .into()
1190        } else {
1191            "untitled".into()
1192        }
1193    }
1194
1195    fn entry_id(&self, app: &AppContext) -> Option<(usize, usize)> {
1196        self.buffer.as_ref(app).entry_id()
1197    }
1198
1199    fn clone_on_split(&self, ctx: &mut ViewContext<Self>) -> Option<Self>
1200    where
1201        Self: Sized,
1202    {
1203        let clone = BufferView::for_buffer(self.buffer.clone(), self.settings.clone(), ctx);
1204        *clone.scroll_position.lock() = *self.scroll_position.lock();
1205        Some(clone)
1206    }
1207}
1208
1209impl Selection {
1210    fn head(&self) -> &Anchor {
1211        if self.reversed {
1212            &self.start
1213        } else {
1214            &self.end
1215        }
1216    }
1217
1218    fn set_head(&mut self, buffer: &Buffer, cursor: Anchor) {
1219        if cursor.cmp(self.tail(), buffer).unwrap() < Ordering::Equal {
1220            if !self.reversed {
1221                mem::swap(&mut self.start, &mut self.end);
1222                self.reversed = true;
1223            }
1224            self.start = cursor;
1225        } else {
1226            if self.reversed {
1227                mem::swap(&mut self.start, &mut self.end);
1228                self.reversed = false;
1229            }
1230            self.end = cursor;
1231        }
1232    }
1233
1234    fn tail(&self) -> &Anchor {
1235        if self.reversed {
1236            &self.end
1237        } else {
1238            &self.start
1239        }
1240    }
1241
1242    fn range(&self, buffer: &Buffer) -> Range<Point> {
1243        let start = self.start.to_point(buffer).unwrap();
1244        let end = self.end.to_point(buffer).unwrap();
1245        if self.reversed {
1246            end..start
1247        } else {
1248            start..end
1249        }
1250    }
1251
1252    fn display_range(&self, map: &DisplayMap, app: &AppContext) -> Range<DisplayPoint> {
1253        let start = self.start.to_display_point(map, app).unwrap();
1254        let end = self.end.to_display_point(map, app).unwrap();
1255        if self.reversed {
1256            end..start
1257        } else {
1258            start..end
1259        }
1260    }
1261}
1262
1263#[cfg(test)]
1264mod tests {
1265    use super::*;
1266    use crate::{editor::Point, settings, test::sample_text};
1267    use anyhow::Error;
1268    use unindent::Unindent;
1269
1270    #[test]
1271    fn test_selection_with_mouse() {
1272        App::test((), |mut app| async move {
1273            let buffer = app.add_model(|_| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n"));
1274            let settings = settings::channel(&FontCache::new()).unwrap().1;
1275            let (_, buffer_view) =
1276                app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
1277
1278            buffer_view.update(&mut app, |view, ctx| {
1279                view.begin_selection(DisplayPoint::new(2, 2), false, ctx);
1280            });
1281
1282            buffer_view.read(&app, |view, app| {
1283                let selections = view
1284                    .selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
1285                    .collect::<Vec<_>>();
1286                assert_eq!(
1287                    selections,
1288                    [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
1289                );
1290            });
1291
1292            buffer_view.update(&mut app, |view, ctx| {
1293                view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), ctx);
1294            });
1295
1296            buffer_view.read(&app, |view, app| {
1297                let selections = view
1298                    .selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
1299                    .collect::<Vec<_>>();
1300                assert_eq!(
1301                    selections,
1302                    [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
1303                );
1304            });
1305
1306            buffer_view.update(&mut app, |view, ctx| {
1307                view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), ctx);
1308            });
1309
1310            buffer_view.read(&app, |view, app| {
1311                let selections = view
1312                    .selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
1313                    .collect::<Vec<_>>();
1314                assert_eq!(
1315                    selections,
1316                    [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
1317                );
1318            });
1319
1320            buffer_view.update(&mut app, |view, ctx| {
1321                view.end_selection(ctx);
1322                view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), ctx);
1323            });
1324
1325            buffer_view.read(&app, |view, app| {
1326                let selections = view
1327                    .selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
1328                    .collect::<Vec<_>>();
1329                assert_eq!(
1330                    selections,
1331                    [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
1332                );
1333            });
1334
1335            buffer_view.update(&mut app, |view, ctx| {
1336                view.begin_selection(DisplayPoint::new(3, 3), true, ctx);
1337                view.update_selection(DisplayPoint::new(0, 0), Vector2F::zero(), ctx);
1338            });
1339
1340            buffer_view.read(&app, |view, app| {
1341                let selections = view
1342                    .selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
1343                    .collect::<Vec<_>>();
1344                assert_eq!(
1345                    selections,
1346                    [
1347                        DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
1348                        DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
1349                    ]
1350                );
1351            });
1352
1353            buffer_view.update(&mut app, |view, ctx| {
1354                view.end_selection(ctx);
1355            });
1356
1357            buffer_view.read(&app, |view, app| {
1358                let selections = view
1359                    .selections_in_range(DisplayPoint::zero()..view.max_point(app), app)
1360                    .collect::<Vec<_>>();
1361                assert_eq!(
1362                    selections,
1363                    [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
1364                );
1365            });
1366        });
1367    }
1368
1369    #[test]
1370    fn test_layout_line_numbers() -> Result<()> {
1371        use gpui::{fonts::FontCache, text_layout::TextLayoutCache};
1372
1373        let font_cache = FontCache::new();
1374        let layout_cache = TextLayoutCache::new();
1375
1376        App::test((), |mut app| async move {
1377            let buffer = app.add_model(|_| Buffer::new(0, sample_text(6, 6)));
1378
1379            let settings = settings::channel(&font_cache).unwrap().1;
1380            let (_, view) =
1381                app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
1382
1383            view.read(&app, |view, app| {
1384                let layouts = view.layout_line_numbers(1000.0, &font_cache, &layout_cache, app)?;
1385                assert_eq!(layouts.len(), 6);
1386                Result::<()>::Ok(())
1387            })?;
1388
1389            Ok(())
1390        })
1391    }
1392
1393    #[test]
1394    fn test_fold() -> Result<()> {
1395        App::test((), |mut app| async move {
1396            let buffer = app.add_model(|_| {
1397                Buffer::new(
1398                    0,
1399                    "
1400                    impl Foo {
1401                        // Hello!
1402
1403                        fn a() {
1404                            1
1405                        }
1406
1407                        fn b() {
1408                            2
1409                        }
1410                            3
1411                        }
1412                    }
1413                "
1414                    .unindent(),
1415                )
1416            });
1417            let settings = settings::channel(&FontCache::new()).unwrap().1;
1418            let (_, view) =
1419                app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
1420
1421            view.update(&mut app, |view, ctx| {
1422                view.select_ranges(Some(DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)), ctx)?;
1423                view.fold(&(), ctx);
1424                assert_eq!(
1425                    view.text(ctx.app()),
1426                    "
1427                    impl Foo {
1428                        // Hello!
1429
1430                        fn a() {
1431                            1
1432                        }
1433
1434                        fn b() {…
1435                        }
1436
1437                        fn c() {…
1438                        }
1439                    }
1440                "
1441                    .unindent(),
1442                );
1443
1444                view.fold(&(), ctx);
1445                assert_eq!(
1446                    view.text(ctx.app()),
1447                    "
1448                    impl Foo {…
1449                    }
1450                "
1451                    .unindent(),
1452                );
1453
1454                view.unfold(&(), ctx);
1455                assert_eq!(
1456                    view.text(ctx.app()),
1457                    "
1458                    impl Foo {
1459                        // Hello!
1460
1461                        fn a() {
1462                            1
1463                        }
1464
1465                        fn b() {…
1466                        }
1467
1468                        fn c() {…
1469                        }
1470                    }
1471                "
1472                    .unindent(),
1473                );
1474
1475                view.unfold(&(), ctx);
1476                assert_eq!(view.text(ctx.app()), buffer.as_ref(ctx).text());
1477
1478                Ok::<(), Error>(())
1479            })?;
1480
1481            Ok(())
1482        })
1483    }
1484
1485    #[test]
1486    fn test_move_cursor() -> Result<()> {
1487        App::test((), |mut app| async move {
1488            let buffer = app.add_model(|_| Buffer::new(0, sample_text(6, 6)));
1489            let settings = settings::channel(&FontCache::new()).unwrap().1;
1490            let (_, view) =
1491                app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
1492
1493            buffer.update(&mut app, |buffer, ctx| {
1494                buffer.edit(
1495                    vec![
1496                        Point::new(1, 0)..Point::new(1, 0),
1497                        Point::new(1, 1)..Point::new(1, 1),
1498                    ],
1499                    "\t",
1500                    Some(ctx),
1501                )
1502            })?;
1503
1504            view.update(&mut app, |view, ctx| {
1505                view.move_down(&(), ctx);
1506                assert_eq!(
1507                    view.selections(ctx.app()),
1508                    &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
1509                );
1510                view.move_right(&(), ctx);
1511                assert_eq!(
1512                    view.selections(ctx.app()),
1513                    &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
1514                );
1515                Ok::<(), Error>(())
1516            })?;
1517
1518            Ok(())
1519        })
1520    }
1521
1522    impl BufferView {
1523        fn selections(&self, app: &AppContext) -> Vec<Range<DisplayPoint>> {
1524            self.selections_in_range(DisplayPoint::zero()..self.max_point(app), app)
1525                .collect::<Vec<_>>()
1526        }
1527    }
1528}