buffer_view.rs

   1use super::{
   2    buffer, movement, Anchor, Bias, Buffer, BufferElement, DisplayMap, DisplayPoint, Point,
   3    Selection, SelectionSetId, ToOffset, ToPoint,
   4};
   5use crate::{settings::Settings, watch, workspace};
   6use anyhow::Result;
   7use futures_core::future::LocalBoxFuture;
   8use gpui::{
   9    fonts::Properties as FontProperties, keymap::Binding, text_layout, AppContext, ClipboardItem,
  10    Element, ElementBox, Entity, FontCache, ModelHandle, MutableAppContext, View, ViewContext,
  11    WeakViewHandle,
  12};
  13use gpui::{geometry::vector::Vector2F, TextLayoutCache};
  14use parking_lot::Mutex;
  15use serde::{Deserialize, Serialize};
  16use smallvec::SmallVec;
  17use smol::Timer;
  18use std::{
  19    cmp::{self, Ordering},
  20    fmt::Write,
  21    iter::FromIterator,
  22    ops::Range,
  23    path::Path,
  24    sync::Arc,
  25    time::Duration,
  26};
  27
  28const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  29
  30pub fn init(app: &mut MutableAppContext) {
  31    app.add_bindings(vec![
  32        Binding::new("backspace", "buffer:backspace", Some("BufferView")),
  33        Binding::new("delete", "buffer:delete", Some("BufferView")),
  34        Binding::new("ctrl-d", "buffer:delete", Some("BufferView")),
  35        Binding::new("enter", "buffer:newline", Some("BufferView")),
  36        Binding::new("ctrl-shift-K", "buffer:delete_line", Some("BufferView")),
  37        Binding::new("cmd-x", "buffer:cut", Some("BufferView")),
  38        Binding::new("cmd-c", "buffer:copy", Some("BufferView")),
  39        Binding::new("cmd-v", "buffer:paste", Some("BufferView")),
  40        Binding::new("cmd-z", "buffer:undo", Some("BufferView")),
  41        Binding::new("cmd-shift-Z", "buffer:redo", Some("BufferView")),
  42        Binding::new("up", "buffer:move_up", Some("BufferView")),
  43        Binding::new("down", "buffer:move_down", Some("BufferView")),
  44        Binding::new("left", "buffer:move_left", Some("BufferView")),
  45        Binding::new("right", "buffer:move_right", Some("BufferView")),
  46        Binding::new("cmd-up", "buffer:move_to_beginning", Some("BufferView")),
  47        Binding::new("cmd-down", "buffer:move_to_end", Some("BufferView")),
  48        Binding::new("shift-up", "buffer:select_up", Some("BufferView")),
  49        Binding::new("shift-down", "buffer:select_down", Some("BufferView")),
  50        Binding::new("shift-left", "buffer:select_left", Some("BufferView")),
  51        Binding::new("shift-right", "buffer:select_right", Some("BufferView")),
  52        Binding::new(
  53            "cmd-shift-up",
  54            "buffer:select_to_beginning",
  55            Some("BufferView"),
  56        ),
  57        Binding::new("cmd-shift-down", "buffer:select_to_end", Some("BufferView")),
  58        Binding::new("cmd-a", "buffer:select_all", Some("BufferView")),
  59        Binding::new("pageup", "buffer:page_up", Some("BufferView")),
  60        Binding::new("pagedown", "buffer:page_down", Some("BufferView")),
  61        Binding::new("alt-cmd-[", "buffer:fold", Some("BufferView")),
  62        Binding::new("alt-cmd-]", "buffer:unfold", Some("BufferView")),
  63        Binding::new(
  64            "alt-cmd-f",
  65            "buffer:fold_selected_ranges",
  66            Some("BufferView"),
  67        ),
  68    ]);
  69
  70    app.add_action("buffer:scroll", BufferView::scroll);
  71    app.add_action("buffer:select", BufferView::select);
  72    app.add_action("buffer:insert", BufferView::insert);
  73    app.add_action("buffer:newline", BufferView::newline);
  74    app.add_action("buffer:backspace", BufferView::backspace);
  75    app.add_action("buffer:delete", BufferView::delete);
  76    app.add_action("buffer:delete_line", BufferView::delete_line);
  77    app.add_action("buffer:cut", BufferView::cut);
  78    app.add_action("buffer:copy", BufferView::copy);
  79    app.add_action("buffer:paste", BufferView::paste);
  80    app.add_action("buffer:undo", BufferView::undo);
  81    app.add_action("buffer:redo", BufferView::redo);
  82    app.add_action("buffer:move_up", BufferView::move_up);
  83    app.add_action("buffer:move_down", BufferView::move_down);
  84    app.add_action("buffer:move_left", BufferView::move_left);
  85    app.add_action("buffer:move_right", BufferView::move_right);
  86    app.add_action("buffer:move_to_beginning", BufferView::move_to_beginning);
  87    app.add_action("buffer:move_to_end", BufferView::move_to_end);
  88    app.add_action("buffer:select_up", BufferView::select_up);
  89    app.add_action("buffer:select_down", BufferView::select_down);
  90    app.add_action("buffer:select_left", BufferView::select_left);
  91    app.add_action("buffer:select_right", BufferView::select_right);
  92    app.add_action(
  93        "buffer:select_to_beginning",
  94        BufferView::select_to_beginning,
  95    );
  96    app.add_action("buffer:select_to_end", BufferView::select_to_end);
  97    app.add_action("buffer:select_all", BufferView::select_all);
  98    app.add_action("buffer:page_up", BufferView::page_up);
  99    app.add_action("buffer:page_down", BufferView::page_down);
 100    app.add_action("buffer:fold", BufferView::fold);
 101    app.add_action("buffer:unfold", BufferView::unfold);
 102    app.add_action(
 103        "buffer:fold_selected_ranges",
 104        BufferView::fold_selected_ranges,
 105    );
 106}
 107
 108pub enum SelectAction {
 109    Begin {
 110        position: DisplayPoint,
 111        add: bool,
 112    },
 113    Update {
 114        position: DisplayPoint,
 115        scroll_position: Vector2F,
 116    },
 117    End,
 118}
 119
 120pub struct BufferView {
 121    handle: WeakViewHandle<Self>,
 122    buffer: ModelHandle<Buffer>,
 123    display_map: ModelHandle<DisplayMap>,
 124    selection_set_id: SelectionSetId,
 125    pending_selection: Option<Selection>,
 126    scroll_position: Mutex<Vector2F>,
 127    autoscroll_requested: Mutex<bool>,
 128    settings: watch::Receiver<Settings>,
 129    focused: bool,
 130    cursors_visible: bool,
 131    blink_epoch: usize,
 132    blinking_paused: bool,
 133    single_line: bool,
 134}
 135
 136#[derive(Serialize, Deserialize)]
 137struct ClipboardSelection {
 138    len: usize,
 139    is_entire_line: bool,
 140}
 141
 142impl BufferView {
 143    pub fn single_line(settings: watch::Receiver<Settings>, ctx: &mut ViewContext<Self>) -> Self {
 144        let buffer = ctx.add_model(|ctx| Buffer::new(0, String::new(), ctx));
 145        let mut view = Self::for_buffer(buffer, settings, ctx);
 146        view.single_line = true;
 147        view
 148    }
 149
 150    pub fn for_buffer(
 151        buffer: ModelHandle<Buffer>,
 152        settings: watch::Receiver<Settings>,
 153        ctx: &mut ViewContext<Self>,
 154    ) -> Self {
 155        settings.notify_view_on_change(ctx);
 156
 157        ctx.observe(&buffer, Self::on_buffer_changed);
 158        ctx.subscribe_to_model(&buffer, Self::on_buffer_event);
 159        let display_map = ctx.add_model(|ctx| {
 160            DisplayMap::new(
 161                buffer.clone(),
 162                smol::block_on(settings.read()).tab_size,
 163                ctx,
 164            )
 165        });
 166        ctx.observe(&display_map, Self::on_display_map_changed);
 167
 168        let (selection_set_id, _) = buffer.update(ctx, |buffer, ctx| {
 169            buffer.add_selection_set(
 170                vec![Selection {
 171                    start: buffer.anchor_before(0).unwrap(),
 172                    end: buffer.anchor_before(0).unwrap(),
 173                    reversed: false,
 174                    goal_column: None,
 175                }],
 176                Some(ctx),
 177            )
 178        });
 179        Self {
 180            handle: ctx.handle().downgrade(),
 181            buffer,
 182            display_map,
 183            selection_set_id,
 184            pending_selection: None,
 185            scroll_position: Mutex::new(Vector2F::zero()),
 186            autoscroll_requested: Mutex::new(false),
 187            settings,
 188            focused: false,
 189            cursors_visible: false,
 190            blink_epoch: 0,
 191            blinking_paused: false,
 192            single_line: false,
 193        }
 194    }
 195
 196    pub fn buffer(&self) -> &ModelHandle<Buffer> {
 197        &self.buffer
 198    }
 199
 200    pub fn is_gutter_visible(&self) -> bool {
 201        !self.single_line
 202    }
 203
 204    fn scroll(&mut self, scroll_position: &Vector2F, ctx: &mut ViewContext<Self>) {
 205        *self.scroll_position.lock() = *scroll_position;
 206        ctx.notify();
 207    }
 208
 209    pub fn scroll_position(&self) -> Vector2F {
 210        *self.scroll_position.lock()
 211    }
 212
 213    pub fn clamp_scroll_left(&self, max: f32) {
 214        let mut scroll_position = self.scroll_position.lock();
 215        let scroll_left = scroll_position.x();
 216        scroll_position.set_x(scroll_left.min(max));
 217    }
 218
 219    pub fn autoscroll_vertically(
 220        &self,
 221        viewport_height: f32,
 222        line_height: f32,
 223        app: &AppContext,
 224    ) -> bool {
 225        let mut scroll_position = self.scroll_position.lock();
 226        let scroll_top = scroll_position.y();
 227        scroll_position.set_y(scroll_top.min(self.max_point(app).row().saturating_sub(1) as f32));
 228
 229        let mut autoscroll_requested = self.autoscroll_requested.lock();
 230        if *autoscroll_requested {
 231            *autoscroll_requested = false;
 232        } else {
 233            return false;
 234        }
 235
 236        let map = self.display_map.read(app);
 237        let visible_lines = viewport_height / line_height;
 238        let first_cursor_top = self
 239            .selections(app)
 240            .first()
 241            .unwrap()
 242            .head()
 243            .to_display_point(map, app)
 244            .unwrap()
 245            .row() as f32;
 246        let last_cursor_bottom = self
 247            .selections(app)
 248            .last()
 249            .unwrap()
 250            .head()
 251            .to_display_point(map, app)
 252            .unwrap()
 253            .row() as f32
 254            + 1.0;
 255
 256        let margin = ((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0)
 257            .floor()
 258            .min(3.0);
 259        if margin < 0.0 {
 260            return false;
 261        }
 262
 263        let target_top = (first_cursor_top - margin).max(0.0);
 264        let target_bottom = last_cursor_bottom + margin;
 265        let start_row = scroll_position.y();
 266        let end_row = start_row + visible_lines;
 267
 268        if target_top < start_row {
 269            scroll_position.set_y(target_top);
 270        } else if target_bottom >= end_row {
 271            scroll_position.set_y(target_bottom - visible_lines);
 272        }
 273
 274        true
 275    }
 276
 277    pub fn autoscroll_horizontally(
 278        &self,
 279        start_row: u32,
 280        viewport_width: f32,
 281        scroll_width: f32,
 282        max_glyph_width: f32,
 283        layouts: &[Arc<text_layout::Line>],
 284        app: &AppContext,
 285    ) {
 286        let map = self.display_map.read(app);
 287
 288        let mut target_left = std::f32::INFINITY;
 289        let mut target_right = 0.0_f32;
 290        for selection in self.selections(app) {
 291            let head = selection.head().to_display_point(map, app).unwrap();
 292            let start_column = head.column().saturating_sub(3);
 293            let end_column = cmp::min(map.line_len(head.row(), app).unwrap(), head.column() + 3);
 294            target_left = target_left
 295                .min(layouts[(head.row() - start_row) as usize].x_for_index(start_column as usize));
 296            target_right = target_right.max(
 297                layouts[(head.row() - start_row) as usize].x_for_index(end_column as usize)
 298                    + max_glyph_width,
 299            );
 300        }
 301        target_right = target_right.min(scroll_width);
 302
 303        if target_right - target_left > viewport_width {
 304            return;
 305        }
 306
 307        let mut scroll_position = self.scroll_position.lock();
 308        let scroll_left = scroll_position.x() * max_glyph_width;
 309        let scroll_right = scroll_left + viewport_width;
 310
 311        if target_left < scroll_left {
 312            scroll_position.set_x(target_left / max_glyph_width);
 313        } else if target_right > scroll_right {
 314            scroll_position.set_x((target_right - viewport_width) / max_glyph_width);
 315        }
 316    }
 317
 318    fn select(&mut self, arg: &SelectAction, ctx: &mut ViewContext<Self>) {
 319        match arg {
 320            SelectAction::Begin { position, add } => self.begin_selection(*position, *add, ctx),
 321            SelectAction::Update {
 322                position,
 323                scroll_position,
 324            } => self.update_selection(*position, *scroll_position, ctx),
 325            SelectAction::End => self.end_selection(ctx),
 326        }
 327    }
 328
 329    fn begin_selection(&mut self, position: DisplayPoint, add: bool, ctx: &mut ViewContext<Self>) {
 330        if !self.focused {
 331            ctx.focus_self();
 332            ctx.emit(Event::Activate);
 333        }
 334
 335        let display_map = self.display_map.read(ctx);
 336        let cursor = display_map
 337            .anchor_before(position, Bias::Left, ctx.as_ref())
 338            .unwrap();
 339        let selection = Selection {
 340            start: cursor.clone(),
 341            end: cursor,
 342            reversed: false,
 343            goal_column: None,
 344        };
 345
 346        if !add {
 347            self.update_selections(Vec::new(), false, ctx);
 348        }
 349        self.pending_selection = Some(selection);
 350
 351        ctx.notify();
 352    }
 353
 354    fn update_selection(
 355        &mut self,
 356        position: DisplayPoint,
 357        scroll_position: Vector2F,
 358        ctx: &mut ViewContext<Self>,
 359    ) {
 360        let buffer = self.buffer.read(ctx);
 361        let map = self.display_map.read(ctx);
 362        let cursor = map
 363            .anchor_before(position, Bias::Left, ctx.as_ref())
 364            .unwrap();
 365        if let Some(selection) = self.pending_selection.as_mut() {
 366            selection.set_head(buffer, cursor);
 367        } else {
 368            log::error!("update_selection dispatched with no pending selection");
 369            return;
 370        }
 371
 372        *self.scroll_position.lock() = scroll_position;
 373
 374        ctx.notify();
 375    }
 376
 377    fn end_selection(&mut self, ctx: &mut ViewContext<Self>) {
 378        if let Some(selection) = self.pending_selection.take() {
 379            let ix = self.selection_insertion_index(&selection.start, ctx.as_ref());
 380            let mut selections = self.selections(ctx.as_ref()).to_vec();
 381            selections.insert(ix, selection);
 382            self.update_selections(selections, false, ctx);
 383        } else {
 384            log::error!("end_selection dispatched with no pending selection");
 385        }
 386    }
 387
 388    pub fn is_selecting(&self) -> bool {
 389        self.pending_selection.is_some()
 390    }
 391
 392    #[cfg(test)]
 393    fn select_ranges<'a, T>(&mut self, ranges: T, ctx: &mut ViewContext<Self>) -> Result<()>
 394    where
 395        T: IntoIterator<Item = &'a Range<usize>>,
 396    {
 397        let buffer = self.buffer.read(ctx);
 398        let mut selections = Vec::new();
 399        for range in ranges {
 400            selections.push(Selection {
 401                start: buffer.anchor_before(range.start)?,
 402                end: buffer.anchor_before(range.end)?,
 403                reversed: false,
 404                goal_column: None,
 405            });
 406        }
 407        self.update_selections(selections, false, ctx);
 408        Ok(())
 409    }
 410
 411    #[cfg(test)]
 412    fn select_display_ranges<'a, T>(&mut self, ranges: T, ctx: &mut ViewContext<Self>) -> Result<()>
 413    where
 414        T: IntoIterator<Item = &'a Range<DisplayPoint>>,
 415    {
 416        use std::mem;
 417
 418        let map = self.display_map.read(ctx);
 419        let mut selections = Vec::new();
 420        for range in ranges {
 421            let mut start = range.start;
 422            let mut end = range.end;
 423            let reversed = if start > end {
 424                mem::swap(&mut start, &mut end);
 425                true
 426            } else {
 427                false
 428            };
 429
 430            selections.push(Selection {
 431                start: map.anchor_before(start, Bias::Left, ctx.as_ref())?,
 432                end: map.anchor_before(end, Bias::Left, ctx.as_ref())?,
 433                reversed,
 434                goal_column: None,
 435            });
 436        }
 437        self.update_selections(selections, false, ctx);
 438        Ok(())
 439    }
 440
 441    fn insert(&mut self, text: &String, ctx: &mut ViewContext<Self>) {
 442        let mut offset_ranges = SmallVec::<[Range<usize>; 32]>::new();
 443        {
 444            let buffer = self.buffer.read(ctx);
 445            for selection in self.selections(ctx.as_ref()) {
 446                let start = selection.start.to_offset(buffer).unwrap();
 447                let end = selection.end.to_offset(buffer).unwrap();
 448                offset_ranges.push(start..end);
 449            }
 450        }
 451
 452        self.start_transaction(ctx);
 453        let mut new_selections = Vec::new();
 454        self.buffer.update(ctx, |buffer, ctx| {
 455            if let Err(error) = buffer.edit(offset_ranges.iter().cloned(), text.as_str(), Some(ctx))
 456            {
 457                log::error!("error inserting text: {}", error);
 458            };
 459            let char_count = text.chars().count() as isize;
 460            let mut delta = 0_isize;
 461            new_selections = offset_ranges
 462                .into_iter()
 463                .map(|range| {
 464                    let start = range.start as isize;
 465                    let end = range.end as isize;
 466                    let anchor = buffer
 467                        .anchor_before((start + delta + char_count) as usize)
 468                        .unwrap();
 469                    let deleted_count = end - start;
 470                    delta += char_count - deleted_count;
 471                    Selection {
 472                        start: anchor.clone(),
 473                        end: anchor,
 474                        reversed: false,
 475                        goal_column: None,
 476                    }
 477                })
 478                .collect();
 479        });
 480
 481        self.update_selections(new_selections, true, ctx);
 482        self.end_transaction(ctx);
 483    }
 484
 485    fn newline(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 486        if self.single_line {
 487            ctx.propagate_action();
 488        } else {
 489            self.insert(&"\n".into(), ctx);
 490        }
 491    }
 492
 493    pub fn backspace(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 494        self.start_transaction(ctx);
 495        let mut selections = self.selections(ctx.as_ref()).to_vec();
 496        {
 497            let buffer = self.buffer.read(ctx);
 498            let map = self.display_map.read(ctx);
 499            for selection in &mut selections {
 500                if selection.range(buffer).is_empty() {
 501                    let head = selection
 502                        .head()
 503                        .to_display_point(map, ctx.as_ref())
 504                        .unwrap();
 505                    let cursor = map
 506                        .anchor_before(
 507                            movement::left(map, head, ctx.as_ref()).unwrap(),
 508                            Bias::Left,
 509                            ctx.as_ref(),
 510                        )
 511                        .unwrap();
 512                    selection.set_head(&buffer, cursor);
 513                    selection.goal_column = None;
 514                }
 515            }
 516        }
 517
 518        self.update_selections(selections, true, ctx);
 519        self.insert(&String::new(), ctx);
 520        self.end_transaction(ctx);
 521    }
 522
 523    pub fn delete(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 524        self.start_transaction(ctx);
 525        let mut selections = self.selections(ctx.as_ref()).to_vec();
 526        {
 527            let buffer = self.buffer.read(ctx);
 528            let map = self.display_map.read(ctx);
 529            for selection in &mut selections {
 530                if selection.range(buffer).is_empty() {
 531                    let head = selection
 532                        .head()
 533                        .to_display_point(map, ctx.as_ref())
 534                        .unwrap();
 535                    let cursor = map
 536                        .anchor_before(
 537                            movement::right(map, head, ctx.as_ref()).unwrap(),
 538                            Bias::Right,
 539                            ctx.as_ref(),
 540                        )
 541                        .unwrap();
 542                    selection.set_head(&buffer, cursor);
 543                    selection.goal_column = None;
 544                }
 545            }
 546        }
 547
 548        self.update_selections(selections, true, ctx);
 549        self.insert(&String::new(), ctx);
 550        self.end_transaction(ctx);
 551    }
 552
 553    pub fn delete_line(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 554        self.start_transaction(ctx);
 555
 556        let app = ctx.as_ref();
 557        let map = self.display_map.read(app);
 558        let buffer = self.buffer.read(app);
 559
 560        let mut new_cursors = Vec::new();
 561        let mut edit_ranges = Vec::new();
 562
 563        let mut selections = self.selections(app).iter().peekable();
 564        while let Some(selection) = selections.next() {
 565            let mut range = selection.buffer_row_range(map, app);
 566            let goal_display_column = selection
 567                .head()
 568                .to_display_point(map, app)
 569                .unwrap()
 570                .column();
 571
 572            // Accumulate contiguous regions of rows that we want to delete.
 573            while let Some(next_selection) = selections.peek() {
 574                let next_range = next_selection.buffer_row_range(map, app);
 575                if next_range.start <= range.end {
 576                    range.end = next_range.end;
 577                    selections.next().unwrap();
 578                } else {
 579                    break;
 580                }
 581            }
 582
 583            let mut edit_start = Point::new(range.start, 0).to_offset(buffer).unwrap();
 584            let edit_end;
 585            let cursor_buffer_row;
 586            if let Ok(end_offset) = Point::new(range.end, 0).to_offset(buffer) {
 587                // If there's a line after the range, delete the \n from the end of the row range
 588                // and position the cursor on the next line.
 589                edit_end = end_offset;
 590                cursor_buffer_row = range.end;
 591            } else {
 592                // If there isn't a line after the range, delete the \n from the line before the
 593                // start of the row range and position the cursor there.
 594                edit_start = edit_start.saturating_sub(1);
 595                edit_end = buffer.len();
 596                cursor_buffer_row = range.start.saturating_sub(1);
 597            }
 598
 599            let mut cursor = Point::new(cursor_buffer_row, 0)
 600                .to_display_point(map, app)
 601                .unwrap();
 602            *cursor.column_mut() = cmp::min(
 603                goal_display_column,
 604                map.line_len(cursor.row(), app).unwrap(),
 605            );
 606
 607            new_cursors.push(cursor.to_buffer_point(map, Bias::Left, app).unwrap());
 608            edit_ranges.push(edit_start..edit_end);
 609        }
 610
 611        new_cursors.sort_unstable();
 612        let new_selections = new_cursors
 613            .into_iter()
 614            .map(|cursor| buffer.anchor_before(cursor).unwrap())
 615            .map(|anchor| Selection {
 616                start: anchor.clone(),
 617                end: anchor,
 618                reversed: false,
 619                goal_column: None,
 620            })
 621            .collect();
 622        self.update_selections(new_selections, true, ctx);
 623        self.buffer
 624            .update(ctx, |buffer, ctx| buffer.edit(edit_ranges, "", Some(ctx)))
 625            .unwrap();
 626        self.end_transaction(ctx);
 627    }
 628
 629    pub fn cut(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 630        self.start_transaction(ctx);
 631        let mut text = String::new();
 632        let mut selections = self.selections(ctx.as_ref()).to_vec();
 633        let mut clipboard_selections = Vec::with_capacity(selections.len());
 634        {
 635            let buffer = self.buffer.read(ctx);
 636            let max_point = buffer.max_point();
 637            for selection in &mut selections {
 638                let mut start = selection.start.to_point(buffer).expect("invalid start");
 639                let mut end = selection.end.to_point(buffer).expect("invalid end");
 640                let is_entire_line = start == end;
 641                if is_entire_line {
 642                    start = Point::new(start.row, 0);
 643                    end = cmp::min(max_point, Point::new(start.row + 1, 0));
 644                    selection.start = buffer.anchor_before(start).unwrap();
 645                    selection.end = buffer.anchor_before(end).unwrap();
 646                }
 647                let mut len = 0;
 648                for ch in buffer.text_for_range(start..end).unwrap() {
 649                    text.push(ch);
 650                    len += 1;
 651                }
 652                clipboard_selections.push(ClipboardSelection {
 653                    len,
 654                    is_entire_line,
 655                });
 656            }
 657        }
 658        self.update_selections(selections, true, ctx);
 659        self.insert(&String::new(), ctx);
 660        self.end_transaction(ctx);
 661
 662        ctx.as_mut()
 663            .write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 664    }
 665
 666    pub fn copy(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 667        let buffer = self.buffer.read(ctx);
 668        let max_point = buffer.max_point();
 669        let mut text = String::new();
 670        let selections = self.selections(ctx.as_ref());
 671        let mut clipboard_selections = Vec::with_capacity(selections.len());
 672        for selection in selections {
 673            let mut start = selection.start.to_point(buffer).expect("invalid start");
 674            let mut end = selection.end.to_point(buffer).expect("invalid end");
 675            let is_entire_line = start == end;
 676            if is_entire_line {
 677                start = Point::new(start.row, 0);
 678                end = cmp::min(max_point, Point::new(start.row + 1, 0));
 679            }
 680            let mut len = 0;
 681            for ch in buffer.text_for_range(start..end).unwrap() {
 682                text.push(ch);
 683                len += 1;
 684            }
 685            clipboard_selections.push(ClipboardSelection {
 686                len,
 687                is_entire_line,
 688            });
 689        }
 690
 691        ctx.as_mut()
 692            .write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 693    }
 694
 695    pub fn paste(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 696        if let Some(item) = ctx.as_mut().read_from_clipboard() {
 697            let clipboard_text = item.text();
 698            if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
 699                let selections = self.selections(ctx.as_ref()).to_vec();
 700                if clipboard_selections.len() != selections.len() {
 701                    let merged_selection = ClipboardSelection {
 702                        len: clipboard_selections.iter().map(|s| s.len).sum(),
 703                        is_entire_line: clipboard_selections.iter().all(|s| s.is_entire_line),
 704                    };
 705                    clipboard_selections.clear();
 706                    clipboard_selections.push(merged_selection);
 707                }
 708
 709                self.start_transaction(ctx);
 710                let mut new_selections = Vec::with_capacity(selections.len());
 711                let mut clipboard_chars = clipboard_text.chars().cycle();
 712                for (selection, clipboard_selection) in
 713                    selections.iter().zip(clipboard_selections.iter().cycle())
 714                {
 715                    let to_insert =
 716                        String::from_iter(clipboard_chars.by_ref().take(clipboard_selection.len));
 717
 718                    self.buffer.update(ctx, |buffer, ctx| {
 719                        let selection_start = selection.start.to_point(buffer).unwrap();
 720                        let selection_end = selection.end.to_point(buffer).unwrap();
 721
 722                        // If the corresponding selection was empty when this slice of the
 723                        // clipboard text was written, then the entire line containing the
 724                        // selection was copied. If this selection is also currently empty,
 725                        // then paste the line before the current line of the buffer.
 726                        let new_selection_start = selection.end.bias_right(buffer).unwrap();
 727                        if selection_start == selection_end && clipboard_selection.is_entire_line {
 728                            let line_start = Point::new(selection_start.row, 0);
 729                            buffer
 730                                .edit(Some(line_start..line_start), to_insert, Some(ctx))
 731                                .unwrap();
 732                        } else {
 733                            buffer
 734                                .edit(Some(&selection.start..&selection.end), to_insert, Some(ctx))
 735                                .unwrap();
 736                        };
 737
 738                        let new_selection_start = new_selection_start.bias_left(buffer).unwrap();
 739                        new_selections.push(Selection {
 740                            start: new_selection_start.clone(),
 741                            end: new_selection_start,
 742                            reversed: false,
 743                            goal_column: None,
 744                        });
 745                    });
 746                }
 747                self.update_selections(new_selections, true, ctx);
 748                self.end_transaction(ctx);
 749            } else {
 750                self.insert(clipboard_text, ctx);
 751            }
 752        }
 753    }
 754
 755    pub fn undo(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 756        self.buffer
 757            .update(ctx, |buffer, ctx| buffer.undo(Some(ctx)));
 758    }
 759
 760    pub fn redo(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 761        self.buffer
 762            .update(ctx, |buffer, ctx| buffer.redo(Some(ctx)));
 763    }
 764
 765    pub fn move_left(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 766        let app = ctx.as_ref();
 767        let mut selections = self.selections(app).to_vec();
 768        {
 769            let map = self.display_map.read(app);
 770            for selection in &mut selections {
 771                let start = selection.start.to_display_point(map, app).unwrap();
 772                let end = selection.end.to_display_point(map, app).unwrap();
 773
 774                if start != end {
 775                    selection.end = selection.start.clone();
 776                } else {
 777                    let cursor = map
 778                        .anchor_before(movement::left(map, start, app).unwrap(), Bias::Left, app)
 779                        .unwrap();
 780                    selection.start = cursor.clone();
 781                    selection.end = cursor;
 782                }
 783                selection.reversed = false;
 784                selection.goal_column = None;
 785            }
 786        }
 787        self.update_selections(selections, true, ctx);
 788    }
 789
 790    pub fn select_left(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 791        let mut selections = self.selections(ctx.as_ref()).to_vec();
 792        {
 793            let buffer = self.buffer.read(ctx);
 794            let map = self.display_map.read(ctx);
 795            for selection in &mut selections {
 796                let head = selection
 797                    .head()
 798                    .to_display_point(map, ctx.as_ref())
 799                    .unwrap();
 800                let cursor = map
 801                    .anchor_before(
 802                        movement::left(map, head, ctx.as_ref()).unwrap(),
 803                        Bias::Left,
 804                        ctx.as_ref(),
 805                    )
 806                    .unwrap();
 807                selection.set_head(&buffer, cursor);
 808                selection.goal_column = None;
 809            }
 810        }
 811        self.update_selections(selections, true, ctx);
 812    }
 813
 814    pub fn move_right(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 815        let mut selections = self.selections(ctx.as_ref()).to_vec();
 816        {
 817            let app = ctx.as_ref();
 818            let map = self.display_map.read(app);
 819            for selection in &mut selections {
 820                let start = selection.start.to_display_point(map, app).unwrap();
 821                let end = selection.end.to_display_point(map, app).unwrap();
 822
 823                if start != end {
 824                    selection.start = selection.end.clone();
 825                } else {
 826                    let cursor = map
 827                        .anchor_before(movement::right(map, end, app).unwrap(), Bias::Right, app)
 828                        .unwrap();
 829                    selection.start = cursor.clone();
 830                    selection.end = cursor;
 831                }
 832                selection.reversed = false;
 833                selection.goal_column = None;
 834            }
 835        }
 836        self.update_selections(selections, true, ctx);
 837    }
 838
 839    pub fn select_right(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 840        let mut selections = self.selections(ctx.as_ref()).to_vec();
 841        {
 842            let app = ctx.as_ref();
 843            let buffer = self.buffer.read(app);
 844            let map = self.display_map.read(app);
 845            for selection in &mut selections {
 846                let head = selection
 847                    .head()
 848                    .to_display_point(map, ctx.as_ref())
 849                    .unwrap();
 850                let cursor = map
 851                    .anchor_before(movement::right(map, head, app).unwrap(), Bias::Right, app)
 852                    .unwrap();
 853                selection.set_head(&buffer, cursor);
 854                selection.goal_column = None;
 855            }
 856        }
 857        self.update_selections(selections, true, ctx);
 858    }
 859
 860    pub fn move_up(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 861        if self.single_line {
 862            ctx.propagate_action();
 863        } else {
 864            let mut selections = self.selections(ctx.as_ref()).to_vec();
 865            {
 866                let app = ctx.as_ref();
 867                let map = self.display_map.read(app);
 868                for selection in &mut selections {
 869                    let start = selection.start.to_display_point(map, app).unwrap();
 870                    let end = selection.end.to_display_point(map, app).unwrap();
 871                    if start != end {
 872                        selection.goal_column = None;
 873                    }
 874
 875                    let (start, goal_column) =
 876                        movement::up(map, start, selection.goal_column, app).unwrap();
 877                    let cursor = map.anchor_before(start, Bias::Left, app).unwrap();
 878                    selection.start = cursor.clone();
 879                    selection.end = cursor;
 880                    selection.goal_column = goal_column;
 881                    selection.reversed = false;
 882                }
 883            }
 884            self.update_selections(selections, true, ctx);
 885        }
 886    }
 887
 888    pub fn select_up(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 889        let mut selections = self.selections(ctx.as_ref()).to_vec();
 890        {
 891            let app = ctx.as_ref();
 892            let buffer = self.buffer.read(app);
 893            let map = self.display_map.read(app);
 894            for selection in &mut selections {
 895                let head = selection.head().to_display_point(map, app).unwrap();
 896                let (head, goal_column) =
 897                    movement::up(map, head, selection.goal_column, app).unwrap();
 898                selection.set_head(&buffer, map.anchor_before(head, Bias::Left, app).unwrap());
 899                selection.goal_column = goal_column;
 900            }
 901        }
 902        self.update_selections(selections, true, ctx);
 903    }
 904
 905    pub fn move_down(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 906        if self.single_line {
 907            ctx.propagate_action();
 908        } else {
 909            let mut selections = self.selections(ctx.as_ref()).to_vec();
 910            {
 911                let app = ctx.as_ref();
 912                let map = self.display_map.read(app);
 913                for selection in &mut selections {
 914                    let start = selection.start.to_display_point(map, app).unwrap();
 915                    let end = selection.end.to_display_point(map, app).unwrap();
 916                    if start != end {
 917                        selection.goal_column = None;
 918                    }
 919
 920                    let (start, goal_column) =
 921                        movement::down(map, end, selection.goal_column, app).unwrap();
 922                    let cursor = map.anchor_before(start, Bias::Right, app).unwrap();
 923                    selection.start = cursor.clone();
 924                    selection.end = cursor;
 925                    selection.goal_column = goal_column;
 926                    selection.reversed = false;
 927                }
 928            }
 929            self.update_selections(selections, true, ctx);
 930        }
 931    }
 932
 933    pub fn select_down(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 934        let mut selections = self.selections(ctx.as_ref()).to_vec();
 935        {
 936            let app = ctx.as_ref();
 937            let buffer = self.buffer.read(app);
 938            let map = self.display_map.read(app);
 939            for selection in &mut selections {
 940                let head = selection.head().to_display_point(map, app).unwrap();
 941                let (head, goal_column) =
 942                    movement::down(map, head, selection.goal_column, app).unwrap();
 943                selection.set_head(&buffer, map.anchor_before(head, Bias::Right, app).unwrap());
 944                selection.goal_column = goal_column;
 945            }
 946        }
 947        self.update_selections(selections, true, ctx);
 948    }
 949
 950    pub fn move_to_beginning(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 951        let selection = Selection {
 952            start: Anchor::Start,
 953            end: Anchor::Start,
 954            reversed: false,
 955            goal_column: None,
 956        };
 957        self.update_selections(vec![selection], true, ctx);
 958    }
 959
 960    pub fn select_to_beginning(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 961        let mut selection = self.selections(ctx.as_ref()).last().unwrap().clone();
 962        selection.set_head(self.buffer.read(ctx), Anchor::Start);
 963        self.update_selections(vec![selection], true, ctx);
 964    }
 965
 966    pub fn move_to_end(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 967        let selection = Selection {
 968            start: Anchor::End,
 969            end: Anchor::End,
 970            reversed: false,
 971            goal_column: None,
 972        };
 973        self.update_selections(vec![selection], true, ctx);
 974    }
 975
 976    pub fn select_to_end(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 977        let mut selection = self.selections(ctx.as_ref()).last().unwrap().clone();
 978        selection.set_head(self.buffer.read(ctx), Anchor::End);
 979        self.update_selections(vec![selection], true, ctx);
 980    }
 981
 982    pub fn select_all(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 983        let selection = Selection {
 984            start: Anchor::Start,
 985            end: Anchor::End,
 986            reversed: false,
 987            goal_column: None,
 988        };
 989        self.update_selections(vec![selection], false, ctx);
 990    }
 991
 992    pub fn selections_in_range<'a>(
 993        &'a self,
 994        range: Range<DisplayPoint>,
 995        app: &'a AppContext,
 996    ) -> impl 'a + Iterator<Item = Range<DisplayPoint>> {
 997        let map = self.display_map.read(app);
 998
 999        let start = map.anchor_before(range.start, Bias::Left, app).unwrap();
1000        let start_index = self.selection_insertion_index(&start, app);
1001        let pending_selection = self.pending_selection.as_ref().and_then(|s| {
1002            let selection_range = s.display_range(map, app);
1003            if selection_range.start <= range.end || selection_range.end <= range.end {
1004                Some(selection_range)
1005            } else {
1006                None
1007            }
1008        });
1009        self.selections(app)[start_index..]
1010            .iter()
1011            .map(move |s| s.display_range(map, app))
1012            .take_while(move |r| r.start <= range.end || r.end <= range.end)
1013            .chain(pending_selection)
1014    }
1015
1016    fn selection_insertion_index(&self, start: &Anchor, app: &AppContext) -> usize {
1017        let buffer = self.buffer.read(app);
1018        let selections = self.selections(app);
1019        match selections.binary_search_by(|probe| probe.start.cmp(&start, buffer).unwrap()) {
1020            Ok(index) => index,
1021            Err(index) => {
1022                if index > 0
1023                    && selections[index - 1].end.cmp(&start, buffer).unwrap() == Ordering::Greater
1024                {
1025                    index - 1
1026                } else {
1027                    index
1028                }
1029            }
1030        }
1031    }
1032
1033    fn selections<'a>(&self, app: &'a AppContext) -> &'a [Selection] {
1034        self.buffer
1035            .read(app)
1036            .selections(self.selection_set_id)
1037            .unwrap()
1038    }
1039
1040    fn update_selections(
1041        &mut self,
1042        mut selections: Vec<Selection>,
1043        autoscroll: bool,
1044        ctx: &mut ViewContext<Self>,
1045    ) {
1046        // Merge overlapping selections.
1047        let buffer = self.buffer.read(ctx);
1048        let mut i = 1;
1049        while i < selections.len() {
1050            if selections[i - 1]
1051                .end
1052                .cmp(&selections[i].start, buffer)
1053                .unwrap()
1054                >= Ordering::Equal
1055            {
1056                let removed = selections.remove(i);
1057                if removed.start.cmp(&selections[i - 1].start, buffer).unwrap() < Ordering::Equal {
1058                    selections[i - 1].start = removed.start;
1059                }
1060                if removed.end.cmp(&selections[i - 1].end, buffer).unwrap() > Ordering::Equal {
1061                    selections[i - 1].end = removed.end;
1062                }
1063            } else {
1064                i += 1;
1065            }
1066        }
1067
1068        self.buffer.update(ctx, |buffer, ctx| {
1069            buffer
1070                .update_selection_set(self.selection_set_id, selections, Some(ctx))
1071                .unwrap()
1072        });
1073        self.pause_cursor_blinking(ctx);
1074
1075        if autoscroll {
1076            *self.autoscroll_requested.lock() = true;
1077            ctx.notify();
1078        }
1079    }
1080
1081    fn start_transaction(&self, ctx: &mut ViewContext<Self>) {
1082        self.buffer.update(ctx, |buffer, _| {
1083            buffer
1084                .start_transaction(Some(self.selection_set_id))
1085                .unwrap()
1086        });
1087    }
1088
1089    fn end_transaction(&self, ctx: &mut ViewContext<Self>) {
1090        self.buffer.update(ctx, |buffer, ctx| {
1091            buffer
1092                .end_transaction(Some(self.selection_set_id), Some(ctx))
1093                .unwrap()
1094        });
1095    }
1096
1097    pub fn page_up(&mut self, _: &(), _: &mut ViewContext<Self>) {
1098        log::info!("BufferView::page_up");
1099    }
1100
1101    pub fn page_down(&mut self, _: &(), _: &mut ViewContext<Self>) {
1102        log::info!("BufferView::page_down");
1103    }
1104
1105    pub fn fold(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1106        use super::RangeExt;
1107
1108        let mut fold_ranges = Vec::new();
1109
1110        let app = ctx.as_ref();
1111        let map = self.display_map.read(app);
1112        for selection in self.selections(app) {
1113            let (start, end) = selection.display_range(map, app).sorted();
1114            let buffer_start_row = start.to_buffer_point(map, Bias::Left, app).unwrap().row;
1115
1116            for row in (0..=end.row()).rev() {
1117                if self.is_line_foldable(row, app) && !map.is_line_folded(row) {
1118                    let fold_range = self.foldable_range_for_line(row, app).unwrap();
1119                    if fold_range.end.row >= buffer_start_row {
1120                        fold_ranges.push(fold_range);
1121                        if row <= start.row() {
1122                            break;
1123                        }
1124                    }
1125                }
1126            }
1127        }
1128
1129        if !fold_ranges.is_empty() {
1130            self.display_map.update(ctx, |map, ctx| {
1131                map.fold(fold_ranges, ctx).unwrap();
1132            });
1133            *self.autoscroll_requested.lock() = true;
1134        }
1135    }
1136
1137    pub fn unfold(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1138        use super::RangeExt;
1139
1140        let app = ctx.as_ref();
1141        let map = self.display_map.read(app);
1142        let buffer = self.buffer.read(app);
1143        let ranges = self
1144            .selections(app)
1145            .iter()
1146            .map(|s| {
1147                let (start, end) = s.display_range(map, app).sorted();
1148                let mut start = start.to_buffer_point(map, Bias::Left, app).unwrap();
1149                let mut end = end.to_buffer_point(map, Bias::Left, app).unwrap();
1150                start.column = 0;
1151                end.column = buffer.line_len(end.row).unwrap();
1152                start..end
1153            })
1154            .collect::<Vec<_>>();
1155
1156        self.display_map.update(ctx, |map, ctx| {
1157            map.unfold(ranges, ctx).unwrap();
1158        });
1159        *self.autoscroll_requested.lock() = true;
1160    }
1161
1162    fn is_line_foldable(&self, display_row: u32, app: &AppContext) -> bool {
1163        let max_point = self.max_point(app);
1164        if display_row >= max_point.row() {
1165            false
1166        } else {
1167            let (start_indent, is_blank) = self.line_indent(display_row, app).unwrap();
1168            if is_blank {
1169                false
1170            } else {
1171                for display_row in display_row + 1..=max_point.row() {
1172                    let (indent, is_blank) = self.line_indent(display_row, app).unwrap();
1173                    if !is_blank {
1174                        return indent > start_indent;
1175                    }
1176                }
1177                false
1178            }
1179        }
1180    }
1181
1182    fn line_indent(&self, display_row: u32, app: &AppContext) -> Result<(usize, bool)> {
1183        let mut indent = 0;
1184        let mut is_blank = true;
1185        for c in self
1186            .display_map
1187            .read(app)
1188            .chars_at(DisplayPoint::new(display_row, 0), app)?
1189        {
1190            if c == ' ' {
1191                indent += 1;
1192            } else {
1193                is_blank = c == '\n';
1194                break;
1195            }
1196        }
1197        Ok((indent, is_blank))
1198    }
1199
1200    fn foldable_range_for_line(&self, start_row: u32, app: &AppContext) -> Result<Range<Point>> {
1201        let map = self.display_map.read(app);
1202        let max_point = self.max_point(app);
1203
1204        let (start_indent, _) = self.line_indent(start_row, app)?;
1205        let start = DisplayPoint::new(start_row, self.line_len(start_row, app)?);
1206        let mut end = None;
1207        for row in start_row + 1..=max_point.row() {
1208            let (indent, is_blank) = self.line_indent(row, app)?;
1209            if !is_blank && indent <= start_indent {
1210                end = Some(DisplayPoint::new(row - 1, self.line_len(row - 1, app)?));
1211                break;
1212            }
1213        }
1214
1215        let end = end.unwrap_or(max_point);
1216        return Ok(start.to_buffer_point(map, Bias::Left, app)?
1217            ..end.to_buffer_point(map, Bias::Left, app)?);
1218    }
1219
1220    pub fn fold_selected_ranges(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1221        self.display_map.update(ctx, |map, ctx| {
1222            let buffer = self.buffer.read(ctx);
1223            let ranges = self
1224                .selections(ctx.as_ref())
1225                .iter()
1226                .map(|s| s.range(buffer))
1227                .collect::<Vec<_>>();
1228            map.fold(ranges, ctx).unwrap();
1229        });
1230    }
1231
1232    pub fn line(&self, display_row: u32, app: &AppContext) -> Result<String> {
1233        self.display_map.read(app).line(display_row, app)
1234    }
1235
1236    pub fn line_len(&self, display_row: u32, app: &AppContext) -> Result<u32> {
1237        self.display_map.read(app).line_len(display_row, app)
1238    }
1239
1240    pub fn rightmost_point(&self, app: &AppContext) -> DisplayPoint {
1241        self.display_map.read(app).rightmost_point()
1242    }
1243
1244    pub fn max_point(&self, app: &AppContext) -> DisplayPoint {
1245        self.display_map.read(app).max_point(app)
1246    }
1247
1248    pub fn text(&self, app: &AppContext) -> String {
1249        self.display_map.read(app).text(app)
1250    }
1251
1252    pub fn font_size(&self) -> f32 {
1253        smol::block_on(self.settings.read()).buffer_font_size
1254    }
1255
1256    pub fn font_ascent(&self, font_cache: &FontCache) -> f32 {
1257        let settings = smol::block_on(self.settings.read());
1258        let font_id = font_cache.default_font(settings.buffer_font_family);
1259        let ascent = font_cache.metric(font_id, |m| m.ascent);
1260        font_cache.scale_metric(ascent, font_id, settings.buffer_font_size)
1261    }
1262
1263    pub fn font_descent(&self, font_cache: &FontCache) -> f32 {
1264        let settings = smol::block_on(self.settings.read());
1265        let font_id = font_cache.default_font(settings.buffer_font_family);
1266        let ascent = font_cache.metric(font_id, |m| m.descent);
1267        font_cache.scale_metric(ascent, font_id, settings.buffer_font_size)
1268    }
1269
1270    pub fn line_height(&self, font_cache: &FontCache) -> f32 {
1271        let settings = smol::block_on(self.settings.read());
1272        let font_id = font_cache.default_font(settings.buffer_font_family);
1273        font_cache.line_height(font_id, settings.buffer_font_size)
1274    }
1275
1276    pub fn em_width(&self, font_cache: &FontCache) -> f32 {
1277        let settings = smol::block_on(self.settings.read());
1278        let font_id = font_cache.default_font(settings.buffer_font_family);
1279        font_cache.em_width(font_id, settings.buffer_font_size)
1280    }
1281
1282    // TODO: Can we make this not return a result?
1283    pub fn max_line_number_width(
1284        &self,
1285        font_cache: &FontCache,
1286        layout_cache: &TextLayoutCache,
1287        app: &AppContext,
1288    ) -> Result<f32> {
1289        let settings = smol::block_on(self.settings.read());
1290        let font_size = settings.buffer_font_size;
1291        let font_id =
1292            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
1293        let digit_count = ((self.buffer.read(app).max_point().row + 1) as f32)
1294            .log10()
1295            .floor() as usize
1296            + 1;
1297
1298        Ok(layout_cache
1299            .layout_str(
1300                "1".repeat(digit_count).as_str(),
1301                font_size,
1302                &[(0..digit_count, font_id)],
1303            )
1304            .width)
1305    }
1306
1307    pub fn layout_line_numbers(
1308        &self,
1309        viewport_height: f32,
1310        font_cache: &FontCache,
1311        layout_cache: &TextLayoutCache,
1312        app: &AppContext,
1313    ) -> Result<Vec<Arc<text_layout::Line>>> {
1314        let display_map = self.display_map.read(app);
1315
1316        let settings = smol::block_on(self.settings.read());
1317        let font_size = settings.buffer_font_size;
1318        let font_id =
1319            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
1320
1321        let start_row = self.scroll_position().y() as usize;
1322        let end_row = cmp::min(
1323            self.max_point(app).row() as usize,
1324            start_row + (viewport_height / self.line_height(font_cache)).ceil() as usize,
1325        );
1326        let line_count = end_row - start_row + 1;
1327
1328        let mut layouts = Vec::with_capacity(line_count);
1329        let mut line_number = String::new();
1330        for buffer_row in display_map.buffer_rows(start_row as u32)?.take(line_count) {
1331            line_number.clear();
1332            write!(&mut line_number, "{}", buffer_row + 1).unwrap();
1333            layouts.push(layout_cache.layout_str(
1334                &line_number,
1335                font_size,
1336                &[(0..line_number.len(), font_id)],
1337            ));
1338        }
1339
1340        Ok(layouts)
1341    }
1342
1343    pub fn layout_lines(
1344        &self,
1345        mut rows: Range<u32>,
1346        font_cache: &FontCache,
1347        layout_cache: &TextLayoutCache,
1348        app: &AppContext,
1349    ) -> Result<Vec<Arc<text_layout::Line>>> {
1350        let display_map = self.display_map.read(app);
1351
1352        rows.end = cmp::min(rows.end, display_map.max_point(app).row() + 1);
1353        if rows.start >= rows.end {
1354            return Ok(Vec::new());
1355        }
1356
1357        let settings = smol::block_on(self.settings.read());
1358        let font_id =
1359            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
1360        let font_size = settings.buffer_font_size;
1361
1362        let mut layouts = Vec::with_capacity(rows.len());
1363        let mut line = String::new();
1364        let mut line_len = 0;
1365        let mut row = rows.start;
1366        let chars = display_map
1367            .chars_at(DisplayPoint::new(rows.start, 0), app)
1368            .unwrap();
1369        for char in chars.chain(Some('\n')) {
1370            if char == '\n' {
1371                layouts.push(layout_cache.layout_str(&line, font_size, &[(0..line_len, font_id)]));
1372                line.clear();
1373                line_len = 0;
1374                row += 1;
1375                if row == rows.end {
1376                    break;
1377                }
1378            } else {
1379                line_len += 1;
1380                line.push(char);
1381            }
1382        }
1383
1384        Ok(layouts)
1385    }
1386
1387    pub fn layout_line(
1388        &self,
1389        row: u32,
1390        font_cache: &FontCache,
1391        layout_cache: &TextLayoutCache,
1392        app: &AppContext,
1393    ) -> Result<Arc<text_layout::Line>> {
1394        let settings = smol::block_on(self.settings.read());
1395        let font_id =
1396            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
1397
1398        let line = self.line(row, app)?;
1399
1400        Ok(layout_cache.layout_str(
1401            &line,
1402            settings.buffer_font_size,
1403            &[(0..self.line_len(row, app)? as usize, font_id)],
1404        ))
1405    }
1406
1407    fn next_blink_epoch(&mut self) -> usize {
1408        self.blink_epoch += 1;
1409        self.blink_epoch
1410    }
1411
1412    fn pause_cursor_blinking(&mut self, ctx: &mut ViewContext<Self>) {
1413        self.cursors_visible = true;
1414        ctx.notify();
1415
1416        let epoch = self.next_blink_epoch();
1417        ctx.spawn(
1418            async move {
1419                Timer::after(CURSOR_BLINK_INTERVAL).await;
1420                epoch
1421            },
1422            Self::resume_cursor_blinking,
1423        )
1424        .detach();
1425    }
1426
1427    fn resume_cursor_blinking(&mut self, epoch: usize, ctx: &mut ViewContext<Self>) {
1428        if epoch == self.blink_epoch {
1429            self.blinking_paused = false;
1430            self.blink_cursors(epoch, ctx);
1431        }
1432    }
1433
1434    fn blink_cursors(&mut self, epoch: usize, ctx: &mut ViewContext<Self>) {
1435        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
1436            self.cursors_visible = !self.cursors_visible;
1437            ctx.notify();
1438
1439            let epoch = self.next_blink_epoch();
1440            ctx.spawn(
1441                async move {
1442                    Timer::after(CURSOR_BLINK_INTERVAL).await;
1443                    epoch
1444                },
1445                Self::blink_cursors,
1446            )
1447            .detach();
1448        }
1449    }
1450
1451    pub fn cursors_visible(&self) -> bool {
1452        self.cursors_visible
1453    }
1454
1455    fn on_buffer_changed(&mut self, _: ModelHandle<Buffer>, ctx: &mut ViewContext<Self>) {
1456        ctx.notify();
1457    }
1458
1459    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, ctx: &mut ViewContext<Self>) {
1460        ctx.notify();
1461    }
1462
1463    fn on_buffer_event(
1464        &mut self,
1465        _: ModelHandle<Buffer>,
1466        event: &buffer::Event,
1467        ctx: &mut ViewContext<Self>,
1468    ) {
1469        match event {
1470            buffer::Event::Edited(_) => ctx.emit(Event::Edited),
1471            buffer::Event::Dirtied => ctx.emit(Event::Dirtied),
1472            buffer::Event::Saved => ctx.emit(Event::Saved),
1473            buffer::Event::FileHandleChanged => ctx.emit(Event::FileHandleChanged),
1474        }
1475    }
1476}
1477
1478pub enum Event {
1479    Activate,
1480    Edited,
1481    Blurred,
1482    Dirtied,
1483    Saved,
1484    FileHandleChanged,
1485}
1486
1487impl Entity for BufferView {
1488    type Event = Event;
1489}
1490
1491impl View for BufferView {
1492    fn render<'a>(&self, app: &AppContext) -> ElementBox {
1493        BufferElement::new(self.handle.upgrade(app).unwrap()).boxed()
1494    }
1495
1496    fn ui_name() -> &'static str {
1497        "BufferView"
1498    }
1499
1500    fn on_focus(&mut self, ctx: &mut ViewContext<Self>) {
1501        self.focused = true;
1502        self.blink_cursors(self.blink_epoch, ctx);
1503    }
1504
1505    fn on_blur(&mut self, ctx: &mut ViewContext<Self>) {
1506        self.focused = false;
1507        self.cursors_visible = false;
1508        ctx.emit(Event::Blurred);
1509        ctx.notify();
1510    }
1511}
1512
1513impl workspace::Item for Buffer {
1514    type View = BufferView;
1515
1516    fn build_view(
1517        buffer: ModelHandle<Self>,
1518        settings: watch::Receiver<Settings>,
1519        ctx: &mut ViewContext<Self::View>,
1520    ) -> Self::View {
1521        BufferView::for_buffer(buffer, settings, ctx)
1522    }
1523}
1524
1525impl workspace::ItemView for BufferView {
1526    fn should_activate_item_on_event(event: &Self::Event) -> bool {
1527        matches!(event, Event::Activate)
1528    }
1529
1530    fn should_update_tab_on_event(event: &Self::Event) -> bool {
1531        matches!(
1532            event,
1533            Event::Saved | Event::Dirtied | Event::FileHandleChanged
1534        )
1535    }
1536
1537    fn title(&self, app: &AppContext) -> std::string::String {
1538        if let Some(path) = self.buffer.read(app).path() {
1539            path.file_name()
1540                .expect("buffer's path is always to a file")
1541                .to_string_lossy()
1542                .into()
1543        } else {
1544            "untitled".into()
1545        }
1546    }
1547
1548    fn entry_id(&self, app: &AppContext) -> Option<(usize, Arc<Path>)> {
1549        self.buffer.read(app).entry_id()
1550    }
1551
1552    fn clone_on_split(&self, ctx: &mut ViewContext<Self>) -> Option<Self>
1553    where
1554        Self: Sized,
1555    {
1556        let clone = BufferView::for_buffer(self.buffer.clone(), self.settings.clone(), ctx);
1557        *clone.scroll_position.lock() = *self.scroll_position.lock();
1558        Some(clone)
1559    }
1560
1561    fn save(&self, ctx: &mut ViewContext<Self>) -> LocalBoxFuture<'static, Result<()>> {
1562        self.buffer.update(ctx, |buffer, ctx| buffer.save(ctx))
1563    }
1564
1565    fn is_dirty(&self, ctx: &AppContext) -> bool {
1566        self.buffer.read(ctx).is_dirty()
1567    }
1568}
1569
1570#[cfg(test)]
1571mod tests {
1572    use super::*;
1573    use crate::{editor::Point, settings, test::sample_text};
1574    use gpui::App;
1575    use unindent::Unindent;
1576
1577    #[test]
1578    fn test_selection_with_mouse() {
1579        App::test((), |app| {
1580            let buffer =
1581                app.add_model(|ctx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", ctx));
1582            let settings = settings::channel(&app.font_cache()).unwrap().1;
1583            let (_, buffer_view) =
1584                app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
1585
1586            buffer_view.update(app, |view, ctx| {
1587                view.begin_selection(DisplayPoint::new(2, 2), false, ctx);
1588            });
1589
1590            let view = buffer_view.read(app);
1591            let selections = view
1592                .selections_in_range(
1593                    DisplayPoint::zero()..view.max_point(app.as_ref()),
1594                    app.as_ref(),
1595                )
1596                .collect::<Vec<_>>();
1597            assert_eq!(
1598                selections,
1599                [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
1600            );
1601
1602            buffer_view.update(app, |view, ctx| {
1603                view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), ctx);
1604            });
1605
1606            let view = buffer_view.read(app);
1607            let selections = view
1608                .selections_in_range(
1609                    DisplayPoint::zero()..view.max_point(app.as_ref()),
1610                    app.as_ref(),
1611                )
1612                .collect::<Vec<_>>();
1613            assert_eq!(
1614                selections,
1615                [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
1616            );
1617
1618            buffer_view.update(app, |view, ctx| {
1619                view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), ctx);
1620            });
1621
1622            let view = buffer_view.read(app);
1623            let selections = view
1624                .selections_in_range(
1625                    DisplayPoint::zero()..view.max_point(app.as_ref()),
1626                    app.as_ref(),
1627                )
1628                .collect::<Vec<_>>();
1629            assert_eq!(
1630                selections,
1631                [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
1632            );
1633
1634            buffer_view.update(app, |view, ctx| {
1635                view.end_selection(ctx);
1636                view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), ctx);
1637            });
1638
1639            let view = buffer_view.read(app);
1640            let selections = view
1641                .selections_in_range(
1642                    DisplayPoint::zero()..view.max_point(app.as_ref()),
1643                    app.as_ref(),
1644                )
1645                .collect::<Vec<_>>();
1646            assert_eq!(
1647                selections,
1648                [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
1649            );
1650
1651            buffer_view.update(app, |view, ctx| {
1652                view.begin_selection(DisplayPoint::new(3, 3), true, ctx);
1653                view.update_selection(DisplayPoint::new(0, 0), Vector2F::zero(), ctx);
1654            });
1655
1656            let view = buffer_view.read(app);
1657            let selections = view
1658                .selections_in_range(
1659                    DisplayPoint::zero()..view.max_point(app.as_ref()),
1660                    app.as_ref(),
1661                )
1662                .collect::<Vec<_>>();
1663            assert_eq!(
1664                selections,
1665                [
1666                    DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
1667                    DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
1668                ]
1669            );
1670
1671            buffer_view.update(app, |view, ctx| {
1672                view.end_selection(ctx);
1673            });
1674
1675            let view = buffer_view.read(app);
1676            let selections = view
1677                .selections_in_range(
1678                    DisplayPoint::zero()..view.max_point(app.as_ref()),
1679                    app.as_ref(),
1680                )
1681                .collect::<Vec<_>>();
1682            assert_eq!(
1683                selections,
1684                [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
1685            );
1686        });
1687    }
1688
1689    #[test]
1690    fn test_layout_line_numbers() {
1691        App::test((), |app| {
1692            let layout_cache = TextLayoutCache::new(app.platform().fonts());
1693            let font_cache = app.font_cache().clone();
1694
1695            let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(6, 6), ctx));
1696
1697            let settings = settings::channel(&font_cache).unwrap().1;
1698            let (_, view) =
1699                app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
1700
1701            let layouts = view
1702                .read(app)
1703                .layout_line_numbers(1000.0, &font_cache, &layout_cache, app.as_ref())
1704                .unwrap();
1705            assert_eq!(layouts.len(), 6);
1706        })
1707    }
1708
1709    #[test]
1710    fn test_fold() {
1711        App::test((), |app| {
1712            let buffer = app.add_model(|ctx| {
1713                Buffer::new(
1714                    0,
1715                    "
1716                    impl Foo {
1717                        // Hello!
1718
1719                        fn a() {
1720                            1
1721                        }
1722
1723                        fn b() {
1724                            2
1725                        }
1726
1727                        fn c() {
1728                            3
1729                        }
1730                    }
1731                "
1732                    .unindent(),
1733                    ctx,
1734                )
1735            });
1736            let settings = settings::channel(&app.font_cache()).unwrap().1;
1737            let (_, view) =
1738                app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
1739
1740            view.update(app, |view, ctx| {
1741                view.select_display_ranges(
1742                    &[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)],
1743                    ctx,
1744                )
1745                .unwrap();
1746                view.fold(&(), ctx);
1747                assert_eq!(
1748                    view.text(ctx.as_ref()),
1749                    "
1750                    impl Foo {
1751                        // Hello!
1752
1753                        fn a() {
1754                            1
1755                        }
1756
1757                        fn b() {…
1758                        }
1759
1760                        fn c() {…
1761                        }
1762                    }
1763                "
1764                    .unindent(),
1765                );
1766
1767                view.fold(&(), ctx);
1768                assert_eq!(
1769                    view.text(ctx.as_ref()),
1770                    "
1771                    impl Foo {…
1772                    }
1773                "
1774                    .unindent(),
1775                );
1776
1777                view.unfold(&(), ctx);
1778                assert_eq!(
1779                    view.text(ctx.as_ref()),
1780                    "
1781                    impl Foo {
1782                        // Hello!
1783
1784                        fn a() {
1785                            1
1786                        }
1787
1788                        fn b() {…
1789                        }
1790
1791                        fn c() {…
1792                        }
1793                    }
1794                "
1795                    .unindent(),
1796                );
1797
1798                view.unfold(&(), ctx);
1799                assert_eq!(view.text(ctx.as_ref()), buffer.read(ctx).text());
1800            });
1801        });
1802    }
1803
1804    #[test]
1805    fn test_move_cursor() {
1806        App::test((), |app| {
1807            let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(6, 6), ctx));
1808            let settings = settings::channel(&app.font_cache()).unwrap().1;
1809            let (_, view) =
1810                app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
1811
1812            buffer.update(app, |buffer, ctx| {
1813                buffer
1814                    .edit(
1815                        vec![
1816                            Point::new(1, 0)..Point::new(1, 0),
1817                            Point::new(1, 1)..Point::new(1, 1),
1818                        ],
1819                        "\t",
1820                        Some(ctx),
1821                    )
1822                    .unwrap();
1823            });
1824
1825            view.update(app, |view, ctx| {
1826                view.move_down(&(), ctx);
1827                assert_eq!(
1828                    view.selection_ranges(ctx.as_ref()),
1829                    &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
1830                );
1831
1832                view.move_right(&(), ctx);
1833                assert_eq!(
1834                    view.selection_ranges(ctx.as_ref()),
1835                    &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
1836                );
1837
1838                view.move_left(&(), ctx);
1839                assert_eq!(
1840                    view.selection_ranges(ctx.as_ref()),
1841                    &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
1842                );
1843
1844                view.move_up(&(), ctx);
1845                assert_eq!(
1846                    view.selection_ranges(ctx.as_ref()),
1847                    &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
1848                );
1849
1850                view.move_to_end(&(), ctx);
1851                assert_eq!(
1852                    view.selection_ranges(ctx.as_ref()),
1853                    &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
1854                );
1855
1856                view.move_to_beginning(&(), ctx);
1857                assert_eq!(
1858                    view.selection_ranges(ctx.as_ref()),
1859                    &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
1860                );
1861
1862                view.select_display_ranges(
1863                    &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)],
1864                    ctx,
1865                )
1866                .unwrap();
1867                view.select_to_beginning(&(), ctx);
1868                assert_eq!(
1869                    view.selection_ranges(ctx.as_ref()),
1870                    &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
1871                );
1872
1873                view.select_to_end(&(), ctx);
1874                assert_eq!(
1875                    view.selection_ranges(ctx.as_ref()),
1876                    &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
1877                );
1878            });
1879        });
1880    }
1881
1882    #[test]
1883    fn test_backspace() {
1884        App::test((), |app| {
1885            let buffer = app.add_model(|ctx| {
1886                Buffer::new(
1887                    0,
1888                    "one two three\nfour five six\nseven eight nine\nten\n",
1889                    ctx,
1890                )
1891            });
1892            let settings = settings::channel(&app.font_cache()).unwrap().1;
1893            let (_, view) =
1894                app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
1895
1896            view.update(app, |view, ctx| {
1897                view.select_display_ranges(
1898                    &[
1899                        // an empty selection - the preceding character is deleted
1900                        DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
1901                        // one character selected - it is deleted
1902                        DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
1903                        // a line suffix selected - it is deleted
1904                        DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
1905                    ],
1906                    ctx,
1907                )
1908                .unwrap();
1909                view.backspace(&(), ctx);
1910            });
1911
1912            assert_eq!(
1913                buffer.read(app).text(),
1914                "oe two three\nfou five six\nseven ten\n"
1915            );
1916        })
1917    }
1918
1919    #[test]
1920    fn test_delete() {
1921        App::test((), |app| {
1922            let buffer = app.add_model(|ctx| {
1923                Buffer::new(
1924                    0,
1925                    "one two three\nfour five six\nseven eight nine\nten\n",
1926                    ctx,
1927                )
1928            });
1929            let settings = settings::channel(&app.font_cache()).unwrap().1;
1930            let (_, view) =
1931                app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
1932
1933            view.update(app, |view, ctx| {
1934                view.select_display_ranges(
1935                    &[
1936                        // an empty selection - the following character is deleted
1937                        DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
1938                        // one character selected - it is deleted
1939                        DisplayPoint::new(1, 3)..DisplayPoint::new(1, 4),
1940                        // a line suffix selected - it is deleted
1941                        DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
1942                    ],
1943                    ctx,
1944                )
1945                .unwrap();
1946                view.delete(&(), ctx);
1947            });
1948
1949            assert_eq!(
1950                buffer.read(app).text(),
1951                "on two three\nfou five six\nseven ten\n"
1952            );
1953        })
1954    }
1955
1956    #[test]
1957    fn test_delete_line() {
1958        App::test((), |app| {
1959            let settings = settings::channel(&app.font_cache()).unwrap().1;
1960            let buffer = app.add_model(|ctx| Buffer::new(0, "abc\ndef\nghi\n", ctx));
1961            let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
1962            view.update(app, |view, ctx| {
1963                view.select_display_ranges(
1964                    &[
1965                        DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
1966                        DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
1967                        DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
1968                    ],
1969                    ctx,
1970                )
1971                .unwrap();
1972                view.delete_line(&(), ctx);
1973            });
1974            assert_eq!(view.read(app).text(app.as_ref()), "ghi");
1975            assert_eq!(
1976                view.read(app).selection_ranges(app.as_ref()),
1977                vec![
1978                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
1979                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
1980                ]
1981            );
1982
1983            let settings = settings::channel(&app.font_cache()).unwrap().1;
1984            let buffer = app.add_model(|ctx| Buffer::new(0, "abc\ndef\nghi\n", ctx));
1985            let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
1986            view.update(app, |view, ctx| {
1987                view.select_display_ranges(
1988                    &[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)],
1989                    ctx,
1990                )
1991                .unwrap();
1992                view.delete_line(&(), ctx);
1993            });
1994            assert_eq!(view.read(app).text(app.as_ref()), "ghi\n");
1995            assert_eq!(
1996                view.read(app).selection_ranges(app.as_ref()),
1997                vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
1998            );
1999        });
2000    }
2001
2002    #[test]
2003    fn test_clipboard() {
2004        App::test((), |app| {
2005            let buffer = app.add_model(|ctx| Buffer::new(0, "one two three four five six ", ctx));
2006            let settings = settings::channel(&app.font_cache()).unwrap().1;
2007            let view = app
2008                .add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx))
2009                .1;
2010
2011            // Cut with three selections. Clipboard text is divided into three slices.
2012            view.update(app, |view, ctx| {
2013                view.select_ranges(&[0..4, 8..14, 19..24], ctx).unwrap();
2014                view.cut(&(), ctx);
2015            });
2016            assert_eq!(view.read(app).text(app.as_ref()), "two four six ");
2017
2018            // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
2019            view.update(app, |view, ctx| {
2020                view.select_ranges(&[4..4, 9..9, 13..13], ctx).unwrap();
2021                view.paste(&(), ctx);
2022            });
2023            assert_eq!(
2024                view.read(app).text(app.as_ref()),
2025                "two one four three six five "
2026            );
2027            assert_eq!(
2028                view.read(app).selection_ranges(app.as_ref()),
2029                &[
2030                    DisplayPoint::new(0, 8)..DisplayPoint::new(0, 8),
2031                    DisplayPoint::new(0, 19)..DisplayPoint::new(0, 19),
2032                    DisplayPoint::new(0, 28)..DisplayPoint::new(0, 28)
2033                ]
2034            );
2035
2036            // Paste again but with only two cursors. Since the number of cursors doesn't
2037            // match the number of slices in the clipboard, the entire clipboard text
2038            // is pasted at each cursor.
2039            view.update(app, |view, ctx| {
2040                view.select_ranges(&[0..0, 28..28], ctx).unwrap();
2041                view.insert(&"( ".to_string(), ctx);
2042                view.paste(&(), ctx);
2043                view.insert(&") ".to_string(), ctx);
2044            });
2045            assert_eq!(
2046                view.read(app).text(app.as_ref()),
2047                "( one three five ) two one four three six five ( one three five ) "
2048            );
2049
2050            view.update(app, |view, ctx| {
2051                view.select_ranges(&[0..0], ctx).unwrap();
2052                view.insert(&"123\n4567\n89\n".to_string(), ctx);
2053            });
2054            assert_eq!(
2055                view.read(app).text(app.as_ref()),
2056                "123\n4567\n89\n( one three five ) two one four three six five ( one three five ) "
2057            );
2058
2059            // Cut with three selections, one of which is full-line.
2060            view.update(app, |view, ctx| {
2061                view.select_display_ranges(
2062                    &[
2063                        DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
2064                        DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
2065                        DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
2066                    ],
2067                    ctx,
2068                )
2069                .unwrap();
2070                view.cut(&(), ctx);
2071            });
2072            assert_eq!(
2073                view.read(app).text(app.as_ref()),
2074                "13\n9\n( one three five ) two one four three six five ( one three five ) "
2075            );
2076
2077            // Paste with three selections, noticing how the copied selection that was full-line
2078            // gets inserted before the second cursor.
2079            view.update(app, |view, ctx| {
2080                view.select_display_ranges(
2081                    &[
2082                        DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
2083                        DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
2084                        DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
2085                    ],
2086                    ctx,
2087                )
2088                .unwrap();
2089                view.paste(&(), ctx);
2090            });
2091            assert_eq!(
2092                view.read(app).text(app.as_ref()),
2093                "123\n4567\n9\n( 8ne three five ) two one four three six five ( one three five ) "
2094            );
2095            assert_eq!(
2096                view.read(app).selection_ranges(app.as_ref()),
2097                &[
2098                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
2099                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
2100                    DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
2101                ]
2102            );
2103
2104            // Copy with a single cursor only, which writes the whole line into the clipboard.
2105            view.update(app, |view, ctx| {
2106                view.select_display_ranges(
2107                    &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)],
2108                    ctx,
2109                )
2110                .unwrap();
2111                view.copy(&(), ctx);
2112            });
2113
2114            // Paste with three selections, noticing how the copied full-line selection is inserted
2115            // before the empty selections but replaces the selection that is non-empty.
2116            view.update(app, |view, ctx| {
2117                view.select_display_ranges(
2118                    &[
2119                        DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
2120                        DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
2121                        DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
2122                    ],
2123                    ctx,
2124                )
2125                .unwrap();
2126                view.paste(&(), ctx);
2127            });
2128            assert_eq!(
2129                view.read(app).text(app.as_ref()),
2130                "123\n123\n123\n67\n123\n9\n( 8ne three five ) two one four three six five ( one three five ) "
2131            );
2132            assert_eq!(
2133                view.read(app).selection_ranges(app.as_ref()),
2134                &[
2135                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
2136                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
2137                    DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
2138                ]
2139            );
2140        });
2141    }
2142
2143    #[test]
2144    fn test_select_all() {
2145        App::test((), |app| {
2146            let buffer = app.add_model(|ctx| Buffer::new(0, "abc\nde\nfgh", ctx));
2147            let settings = settings::channel(&app.font_cache()).unwrap().1;
2148            let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
2149            view.update(app, |b, ctx| b.select_all(&(), ctx));
2150            assert_eq!(
2151                view.read(app).selection_ranges(app.as_ref()),
2152                &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
2153            );
2154        });
2155    }
2156
2157    impl BufferView {
2158        fn selection_ranges(&self, app: &AppContext) -> Vec<Range<DisplayPoint>> {
2159            self.selections_in_range(DisplayPoint::zero()..self.max_point(app), app)
2160                .collect::<Vec<_>>()
2161        }
2162    }
2163}