buffer_view.rs

   1use super::{
   2    buffer, movement, Anchor, Bias, Buffer, BufferElement, DisplayMap, DisplayPoint, Point,
   3    Selection, SelectionGoal, SelectionSetId, ToOffset, ToPoint,
   4};
   5use crate::{settings::Settings, util::post_inc, workspace, worktree::FileHandle};
   6use anyhow::Result;
   7use gpui::{
   8    fonts::Properties as FontProperties, geometry::vector::Vector2F, keymap::Binding, text_layout,
   9    AppContext, ClipboardItem, Element, ElementBox, Entity, FontCache, ModelHandle,
  10    MutableAppContext, Task, TextLayoutCache, View, ViewContext, WeakViewHandle,
  11};
  12use parking_lot::Mutex;
  13use postage::watch;
  14use serde::{Deserialize, Serialize};
  15use smallvec::SmallVec;
  16use smol::Timer;
  17use std::{
  18    cmp::{self, Ordering},
  19    fmt::Write,
  20    iter::FromIterator,
  21    mem,
  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("escape", "buffer:cancel", Some("BufferView")),
  33        Binding::new("backspace", "buffer:backspace", Some("BufferView")),
  34        Binding::new("ctrl-h", "buffer:backspace", Some("BufferView")),
  35        Binding::new("delete", "buffer:delete", Some("BufferView")),
  36        Binding::new("ctrl-d", "buffer:delete", Some("BufferView")),
  37        Binding::new("enter", "buffer:newline", Some("BufferView")),
  38        Binding::new("tab", "buffer:insert", Some("BufferView")).with_arg("\t".to_string()),
  39        Binding::new("ctrl-shift-K", "buffer:delete_line", Some("BufferView")),
  40        Binding::new(
  41            "alt-backspace",
  42            "buffer:delete_to_previous_word_boundary",
  43            Some("BufferView"),
  44        ),
  45        Binding::new(
  46            "alt-delete",
  47            "buffer:delete_to_next_word_boundary",
  48            Some("BufferView"),
  49        ),
  50        Binding::new(
  51            "cmd-backspace",
  52            "buffer:delete_to_beginning_of_line",
  53            Some("BufferView"),
  54        ),
  55        Binding::new(
  56            "cmd-delete",
  57            "buffer:delete_to_end_of_line",
  58            Some("BufferView"),
  59        ),
  60        Binding::new("cmd-shift-D", "buffer:duplicate_line", Some("BufferView")),
  61        Binding::new("ctrl-cmd-up", "buffer:move_line_up", Some("BufferView")),
  62        Binding::new("ctrl-cmd-down", "buffer:move_line_down", Some("BufferView")),
  63        Binding::new("cmd-x", "buffer:cut", Some("BufferView")),
  64        Binding::new("cmd-c", "buffer:copy", Some("BufferView")),
  65        Binding::new("cmd-v", "buffer:paste", Some("BufferView")),
  66        Binding::new("cmd-z", "buffer:undo", Some("BufferView")),
  67        Binding::new("cmd-shift-Z", "buffer:redo", Some("BufferView")),
  68        Binding::new("up", "buffer:move_up", Some("BufferView")),
  69        Binding::new("down", "buffer:move_down", Some("BufferView")),
  70        Binding::new("left", "buffer:move_left", Some("BufferView")),
  71        Binding::new("right", "buffer:move_right", Some("BufferView")),
  72        Binding::new("ctrl-p", "buffer:move_up", Some("BufferView")),
  73        Binding::new("ctrl-n", "buffer:move_down", Some("BufferView")),
  74        Binding::new("ctrl-b", "buffer:move_left", Some("BufferView")),
  75        Binding::new("ctrl-f", "buffer:move_right", Some("BufferView")),
  76        Binding::new(
  77            "alt-left",
  78            "buffer:move_to_previous_word_boundary",
  79            Some("BufferView"),
  80        ),
  81        Binding::new(
  82            "alt-right",
  83            "buffer:move_to_next_word_boundary",
  84            Some("BufferView"),
  85        ),
  86        Binding::new(
  87            "cmd-left",
  88            "buffer:move_to_beginning_of_line",
  89            Some("BufferView"),
  90        ),
  91        Binding::new(
  92            "ctrl-a",
  93            "buffer:move_to_beginning_of_line",
  94            Some("BufferView"),
  95        ),
  96        Binding::new(
  97            "cmd-right",
  98            "buffer:move_to_end_of_line",
  99            Some("BufferView"),
 100        ),
 101        Binding::new("ctrl-e", "buffer:move_to_end_of_line", Some("BufferView")),
 102        Binding::new("cmd-up", "buffer:move_to_beginning", Some("BufferView")),
 103        Binding::new("cmd-down", "buffer:move_to_end", Some("BufferView")),
 104        Binding::new("shift-up", "buffer:select_up", Some("BufferView")),
 105        Binding::new("shift-down", "buffer:select_down", Some("BufferView")),
 106        Binding::new("shift-left", "buffer:select_left", Some("BufferView")),
 107        Binding::new("shift-right", "buffer:select_right", Some("BufferView")),
 108        Binding::new(
 109            "alt-shift-left",
 110            "buffer:select_to_previous_word_boundary",
 111            Some("BufferView"),
 112        ),
 113        Binding::new(
 114            "alt-shift-right",
 115            "buffer:select_to_next_word_boundary",
 116            Some("BufferView"),
 117        ),
 118        Binding::new(
 119            "cmd-shift-left",
 120            "buffer:select_to_beginning_of_line",
 121            Some("BufferView"),
 122        )
 123        .with_arg(true),
 124        Binding::new(
 125            "ctrl-shift-A",
 126            "buffer:select_to_beginning_of_line",
 127            Some("BufferView"),
 128        )
 129        .with_arg(true),
 130        Binding::new(
 131            "cmd-shift-right",
 132            "buffer:select_to_end_of_line",
 133            Some("BufferView"),
 134        ),
 135        Binding::new(
 136            "ctrl-shift-E",
 137            "buffer:select_to_end_of_line",
 138            Some("BufferView"),
 139        ),
 140        Binding::new(
 141            "cmd-shift-up",
 142            "buffer:select_to_beginning",
 143            Some("BufferView"),
 144        ),
 145        Binding::new("cmd-shift-down", "buffer:select_to_end", Some("BufferView")),
 146        Binding::new("cmd-a", "buffer:select_all", Some("BufferView")),
 147        Binding::new("cmd-l", "buffer:select_line", Some("BufferView")),
 148        Binding::new(
 149            "cmd-shift-L",
 150            "buffer:split_selection_into_lines",
 151            Some("BufferView"),
 152        ),
 153        Binding::new(
 154            "cmd-alt-up",
 155            "buffer:add_selection_above",
 156            Some("BufferView"),
 157        ),
 158        Binding::new(
 159            "cmd-alt-down",
 160            "buffer:add_selection_below",
 161            Some("BufferView"),
 162        ),
 163        Binding::new("pageup", "buffer:page_up", Some("BufferView")),
 164        Binding::new("pagedown", "buffer:page_down", Some("BufferView")),
 165        Binding::new("alt-cmd-[", "buffer:fold", Some("BufferView")),
 166        Binding::new("alt-cmd-]", "buffer:unfold", Some("BufferView")),
 167        Binding::new(
 168            "alt-cmd-f",
 169            "buffer:fold_selected_ranges",
 170            Some("BufferView"),
 171        ),
 172    ]);
 173
 174    app.add_action("buffer:scroll", BufferView::scroll);
 175    app.add_action("buffer:select", BufferView::select);
 176    app.add_action("buffer:cancel", BufferView::cancel);
 177    app.add_action("buffer:insert", BufferView::insert);
 178    app.add_action("buffer:newline", BufferView::newline);
 179    app.add_action("buffer:backspace", BufferView::backspace);
 180    app.add_action("buffer:delete", BufferView::delete);
 181    app.add_action("buffer:delete_line", BufferView::delete_line);
 182    app.add_action(
 183        "buffer:delete_to_previous_word_boundary",
 184        BufferView::delete_to_previous_word_boundary,
 185    );
 186    app.add_action(
 187        "buffer:delete_to_next_word_boundary",
 188        BufferView::delete_to_next_word_boundary,
 189    );
 190    app.add_action(
 191        "buffer:delete_to_beginning_of_line",
 192        BufferView::delete_to_beginning_of_line,
 193    );
 194    app.add_action(
 195        "buffer:delete_to_end_of_line",
 196        BufferView::delete_to_end_of_line,
 197    );
 198    app.add_action("buffer:duplicate_line", BufferView::duplicate_line);
 199    app.add_action("buffer:move_line_up", BufferView::move_line_up);
 200    app.add_action("buffer:move_line_down", BufferView::move_line_down);
 201    app.add_action("buffer:cut", BufferView::cut);
 202    app.add_action("buffer:copy", BufferView::copy);
 203    app.add_action("buffer:paste", BufferView::paste);
 204    app.add_action("buffer:undo", BufferView::undo);
 205    app.add_action("buffer:redo", BufferView::redo);
 206    app.add_action("buffer:move_up", BufferView::move_up);
 207    app.add_action("buffer:move_down", BufferView::move_down);
 208    app.add_action("buffer:move_left", BufferView::move_left);
 209    app.add_action("buffer:move_right", BufferView::move_right);
 210    app.add_action(
 211        "buffer:move_to_previous_word_boundary",
 212        BufferView::move_to_previous_word_boundary,
 213    );
 214    app.add_action(
 215        "buffer:move_to_next_word_boundary",
 216        BufferView::move_to_next_word_boundary,
 217    );
 218    app.add_action(
 219        "buffer:move_to_beginning_of_line",
 220        BufferView::move_to_beginning_of_line,
 221    );
 222    app.add_action(
 223        "buffer:move_to_end_of_line",
 224        BufferView::move_to_end_of_line,
 225    );
 226    app.add_action("buffer:move_to_beginning", BufferView::move_to_beginning);
 227    app.add_action("buffer:move_to_end", BufferView::move_to_end);
 228    app.add_action("buffer:select_up", BufferView::select_up);
 229    app.add_action("buffer:select_down", BufferView::select_down);
 230    app.add_action("buffer:select_left", BufferView::select_left);
 231    app.add_action("buffer:select_right", BufferView::select_right);
 232    app.add_action(
 233        "buffer:select_to_previous_word_boundary",
 234        BufferView::select_to_previous_word_boundary,
 235    );
 236    app.add_action(
 237        "buffer:select_to_next_word_boundary",
 238        BufferView::select_to_next_word_boundary,
 239    );
 240    app.add_action(
 241        "buffer:select_to_beginning_of_line",
 242        BufferView::select_to_beginning_of_line,
 243    );
 244    app.add_action(
 245        "buffer:select_to_end_of_line",
 246        BufferView::select_to_end_of_line,
 247    );
 248    app.add_action(
 249        "buffer:select_to_beginning",
 250        BufferView::select_to_beginning,
 251    );
 252    app.add_action("buffer:select_to_end", BufferView::select_to_end);
 253    app.add_action("buffer:select_all", BufferView::select_all);
 254    app.add_action("buffer:select_line", BufferView::select_line);
 255    app.add_action(
 256        "buffer:split_selection_into_lines",
 257        BufferView::split_selection_into_lines,
 258    );
 259    app.add_action(
 260        "buffer:add_selection_above",
 261        BufferView::add_selection_above,
 262    );
 263    app.add_action(
 264        "buffer:add_selection_below",
 265        BufferView::add_selection_below,
 266    );
 267    app.add_action("buffer:page_up", BufferView::page_up);
 268    app.add_action("buffer:page_down", BufferView::page_down);
 269    app.add_action("buffer:fold", BufferView::fold);
 270    app.add_action("buffer:unfold", BufferView::unfold);
 271    app.add_action(
 272        "buffer:fold_selected_ranges",
 273        BufferView::fold_selected_ranges,
 274    );
 275}
 276
 277pub enum SelectAction {
 278    Begin {
 279        position: DisplayPoint,
 280        add: bool,
 281    },
 282    Update {
 283        position: DisplayPoint,
 284        scroll_position: Vector2F,
 285    },
 286    End,
 287}
 288
 289pub struct BufferView {
 290    handle: WeakViewHandle<Self>,
 291    buffer: ModelHandle<Buffer>,
 292    display_map: DisplayMap,
 293    selection_set_id: SelectionSetId,
 294    pending_selection: Option<Selection>,
 295    next_selection_id: usize,
 296    add_selections_state: Option<AddSelectionsState>,
 297    scroll_position: Mutex<Vector2F>,
 298    autoscroll_requested: Mutex<bool>,
 299    settings: watch::Receiver<Settings>,
 300    focused: bool,
 301    cursors_visible: bool,
 302    blink_epoch: usize,
 303    blinking_paused: bool,
 304    single_line: bool,
 305}
 306
 307struct AddSelectionsState {
 308    above: bool,
 309    stack: Vec<usize>,
 310}
 311
 312#[derive(Serialize, Deserialize)]
 313struct ClipboardSelection {
 314    len: usize,
 315    is_entire_line: bool,
 316}
 317
 318impl BufferView {
 319    pub fn single_line(settings: watch::Receiver<Settings>, ctx: &mut ViewContext<Self>) -> Self {
 320        let buffer = ctx.add_model(|ctx| Buffer::new(0, String::new(), ctx));
 321        let mut view = Self::for_buffer(buffer, settings, ctx);
 322        view.single_line = true;
 323        view
 324    }
 325
 326    pub fn for_buffer(
 327        buffer: ModelHandle<Buffer>,
 328        settings: watch::Receiver<Settings>,
 329        ctx: &mut ViewContext<Self>,
 330    ) -> Self {
 331        ctx.observe_model(&buffer, Self::on_buffer_changed);
 332        ctx.subscribe_to_model(&buffer, Self::on_buffer_event);
 333        let display_map = DisplayMap::new(buffer.clone(), settings.borrow().tab_size, ctx.as_ref());
 334
 335        let mut next_selection_id = 0;
 336        let (selection_set_id, _) = buffer.update(ctx, |buffer, ctx| {
 337            buffer.add_selection_set(
 338                vec![Selection {
 339                    id: post_inc(&mut next_selection_id),
 340                    start: buffer.anchor_before(0),
 341                    end: buffer.anchor_before(0),
 342                    reversed: false,
 343                    goal: SelectionGoal::None,
 344                }],
 345                Some(ctx),
 346            )
 347        });
 348        Self {
 349            handle: ctx.handle().downgrade(),
 350            buffer,
 351            display_map,
 352            selection_set_id,
 353            pending_selection: None,
 354            next_selection_id,
 355            add_selections_state: None,
 356            scroll_position: Mutex::new(Vector2F::zero()),
 357            autoscroll_requested: Mutex::new(false),
 358            settings,
 359            focused: false,
 360            cursors_visible: false,
 361            blink_epoch: 0,
 362            blinking_paused: false,
 363            single_line: false,
 364        }
 365    }
 366
 367    pub fn buffer(&self) -> &ModelHandle<Buffer> {
 368        &self.buffer
 369    }
 370
 371    pub fn is_gutter_visible(&self) -> bool {
 372        !self.single_line
 373    }
 374
 375    fn scroll(&mut self, scroll_position: &Vector2F, ctx: &mut ViewContext<Self>) {
 376        *self.scroll_position.lock() = *scroll_position;
 377        ctx.notify();
 378    }
 379
 380    pub fn scroll_position(&self) -> Vector2F {
 381        *self.scroll_position.lock()
 382    }
 383
 384    pub fn clamp_scroll_left(&self, max: f32) {
 385        let mut scroll_position = self.scroll_position.lock();
 386        let scroll_left = scroll_position.x();
 387        scroll_position.set_x(scroll_left.min(max));
 388    }
 389
 390    pub fn autoscroll_vertically(
 391        &self,
 392        viewport_height: f32,
 393        line_height: f32,
 394        app: &AppContext,
 395    ) -> bool {
 396        let mut scroll_position = self.scroll_position.lock();
 397        let scroll_top = scroll_position.y();
 398        scroll_position.set_y(scroll_top.min(self.max_point(app).row().saturating_sub(1) as f32));
 399
 400        let mut autoscroll_requested = self.autoscroll_requested.lock();
 401        if *autoscroll_requested {
 402            *autoscroll_requested = false;
 403        } else {
 404            return false;
 405        }
 406
 407        let visible_lines = viewport_height / line_height;
 408        let first_cursor_top = self
 409            .selections(app)
 410            .first()
 411            .unwrap()
 412            .head()
 413            .to_display_point(&self.display_map, app)
 414            .row() as f32;
 415        let last_cursor_bottom = self
 416            .selections(app)
 417            .last()
 418            .unwrap()
 419            .head()
 420            .to_display_point(&self.display_map, app)
 421            .row() as f32
 422            + 1.0;
 423
 424        let margin = ((visible_lines - (last_cursor_bottom - first_cursor_top)) / 2.0)
 425            .floor()
 426            .min(3.0);
 427        if margin < 0.0 {
 428            return false;
 429        }
 430
 431        let target_top = (first_cursor_top - margin).max(0.0);
 432        let target_bottom = last_cursor_bottom + margin;
 433        let start_row = scroll_position.y();
 434        let end_row = start_row + visible_lines;
 435
 436        if target_top < start_row {
 437            scroll_position.set_y(target_top);
 438        } else if target_bottom >= end_row {
 439            scroll_position.set_y(target_bottom - visible_lines);
 440        }
 441
 442        true
 443    }
 444
 445    pub fn autoscroll_horizontally(
 446        &self,
 447        start_row: u32,
 448        viewport_width: f32,
 449        scroll_width: f32,
 450        max_glyph_width: f32,
 451        layouts: &[Arc<text_layout::Line>],
 452        ctx: &AppContext,
 453    ) {
 454        let mut target_left = std::f32::INFINITY;
 455        let mut target_right = 0.0_f32;
 456        for selection in self.selections(ctx) {
 457            let head = selection.head().to_display_point(&self.display_map, ctx);
 458            let start_column = head.column().saturating_sub(3);
 459            let end_column = cmp::min(
 460                self.display_map.line_len(head.row(), ctx),
 461                head.column() + 3,
 462            );
 463            target_left = target_left
 464                .min(layouts[(head.row() - start_row) as usize].x_for_index(start_column as usize));
 465            target_right = target_right.max(
 466                layouts[(head.row() - start_row) as usize].x_for_index(end_column as usize)
 467                    + max_glyph_width,
 468            );
 469        }
 470        target_right = target_right.min(scroll_width);
 471
 472        if target_right - target_left > viewport_width {
 473            return;
 474        }
 475
 476        let mut scroll_position = self.scroll_position.lock();
 477        let scroll_left = scroll_position.x() * max_glyph_width;
 478        let scroll_right = scroll_left + viewport_width;
 479
 480        if target_left < scroll_left {
 481            scroll_position.set_x(target_left / max_glyph_width);
 482        } else if target_right > scroll_right {
 483            scroll_position.set_x((target_right - viewport_width) / max_glyph_width);
 484        }
 485    }
 486
 487    fn select(&mut self, arg: &SelectAction, ctx: &mut ViewContext<Self>) {
 488        match arg {
 489            SelectAction::Begin { position, add } => self.begin_selection(*position, *add, ctx),
 490            SelectAction::Update {
 491                position,
 492                scroll_position,
 493            } => self.update_selection(*position, *scroll_position, ctx),
 494            SelectAction::End => self.end_selection(ctx),
 495        }
 496    }
 497
 498    fn begin_selection(&mut self, position: DisplayPoint, add: bool, ctx: &mut ViewContext<Self>) {
 499        if !self.focused {
 500            ctx.focus_self();
 501            ctx.emit(Event::Activate);
 502        }
 503
 504        let cursor = self
 505            .display_map
 506            .anchor_before(position, Bias::Left, ctx.as_ref());
 507        let selection = Selection {
 508            id: post_inc(&mut self.next_selection_id),
 509            start: cursor.clone(),
 510            end: cursor,
 511            reversed: false,
 512            goal: SelectionGoal::None,
 513        };
 514
 515        if !add {
 516            self.update_selections(Vec::new(), false, ctx);
 517        }
 518        self.pending_selection = Some(selection);
 519
 520        ctx.notify();
 521    }
 522
 523    fn update_selection(
 524        &mut self,
 525        position: DisplayPoint,
 526        scroll_position: Vector2F,
 527        ctx: &mut ViewContext<Self>,
 528    ) {
 529        let buffer = self.buffer.read(ctx);
 530        let cursor = self
 531            .display_map
 532            .anchor_before(position, Bias::Left, ctx.as_ref());
 533        if let Some(selection) = self.pending_selection.as_mut() {
 534            selection.set_head(buffer, cursor);
 535        } else {
 536            log::error!("update_selection dispatched with no pending selection");
 537            return;
 538        }
 539
 540        *self.scroll_position.lock() = scroll_position;
 541
 542        ctx.notify();
 543    }
 544
 545    fn end_selection(&mut self, ctx: &mut ViewContext<Self>) {
 546        if let Some(selection) = self.pending_selection.take() {
 547            let ix = self.selection_insertion_index(&selection.start, ctx.as_ref());
 548            let mut selections = self.selections(ctx.as_ref()).to_vec();
 549            selections.insert(ix, selection);
 550            self.update_selections(selections, false, ctx);
 551        } else {
 552            log::error!("end_selection dispatched with no pending selection");
 553        }
 554    }
 555
 556    pub fn is_selecting(&self) -> bool {
 557        self.pending_selection.is_some()
 558    }
 559
 560    pub fn cancel(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 561        let selections = self.selections(ctx.as_ref());
 562        if let Some(pending_selection) = self.pending_selection.take() {
 563            if selections.is_empty() {
 564                self.update_selections(vec![pending_selection], true, ctx);
 565            }
 566        } else {
 567            let mut oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 568            if selections.len() == 1 {
 569                oldest_selection.start = oldest_selection.head().clone();
 570                oldest_selection.end = oldest_selection.head().clone();
 571            }
 572            self.update_selections(vec![oldest_selection], true, ctx);
 573        }
 574    }
 575
 576    fn select_ranges<I, T>(&mut self, ranges: I, autoscroll: bool, ctx: &mut ViewContext<Self>)
 577    where
 578        I: IntoIterator<Item = Range<T>>,
 579        T: ToOffset,
 580    {
 581        let buffer = self.buffer.read(ctx);
 582        let mut selections = Vec::new();
 583        for range in ranges {
 584            let mut start = range.start.to_offset(buffer);
 585            let mut end = range.end.to_offset(buffer);
 586            let reversed = if start > end {
 587                mem::swap(&mut start, &mut end);
 588                true
 589            } else {
 590                false
 591            };
 592            selections.push(Selection {
 593                id: post_inc(&mut self.next_selection_id),
 594                start: buffer.anchor_before(start),
 595                end: buffer.anchor_before(end),
 596                reversed,
 597                goal: SelectionGoal::None,
 598            });
 599        }
 600        self.update_selections(selections, autoscroll, ctx);
 601    }
 602
 603    #[cfg(test)]
 604    fn select_display_ranges<'a, T>(&mut self, ranges: T, ctx: &mut ViewContext<Self>) -> Result<()>
 605    where
 606        T: IntoIterator<Item = &'a Range<DisplayPoint>>,
 607    {
 608        let mut selections = Vec::new();
 609        for range in ranges {
 610            let mut start = range.start;
 611            let mut end = range.end;
 612            let reversed = if start > end {
 613                mem::swap(&mut start, &mut end);
 614                true
 615            } else {
 616                false
 617            };
 618
 619            selections.push(Selection {
 620                id: post_inc(&mut self.next_selection_id),
 621                start: self
 622                    .display_map
 623                    .anchor_before(start, Bias::Left, ctx.as_ref()),
 624                end: self
 625                    .display_map
 626                    .anchor_before(end, Bias::Left, ctx.as_ref()),
 627                reversed,
 628                goal: SelectionGoal::None,
 629            });
 630        }
 631        self.update_selections(selections, false, ctx);
 632        Ok(())
 633    }
 634
 635    pub fn insert(&mut self, text: &String, ctx: &mut ViewContext<Self>) {
 636        let mut old_selections = SmallVec::<[_; 32]>::new();
 637        {
 638            let buffer = self.buffer.read(ctx);
 639            for selection in self.selections(ctx.as_ref()) {
 640                let start = selection.start.to_offset(buffer);
 641                let end = selection.end.to_offset(buffer);
 642                old_selections.push((selection.id, start..end));
 643            }
 644        }
 645
 646        self.start_transaction(ctx);
 647        let mut new_selections = Vec::new();
 648        self.buffer.update(ctx, |buffer, ctx| {
 649            let edit_ranges = old_selections.iter().map(|(_, range)| range.clone());
 650            if let Err(error) = buffer.edit(edit_ranges, text.as_str(), Some(ctx)) {
 651                log::error!("error inserting text: {}", error);
 652            };
 653            let text_len = text.len() as isize;
 654            let mut delta = 0_isize;
 655            new_selections = old_selections
 656                .into_iter()
 657                .map(|(id, range)| {
 658                    let start = range.start as isize;
 659                    let end = range.end as isize;
 660                    let anchor = buffer.anchor_before((start + delta + text_len) as usize);
 661                    let deleted_count = end - start;
 662                    delta += text_len - deleted_count;
 663                    Selection {
 664                        id,
 665                        start: anchor.clone(),
 666                        end: anchor,
 667                        reversed: false,
 668                        goal: SelectionGoal::None,
 669                    }
 670                })
 671                .collect();
 672        });
 673
 674        self.update_selections(new_selections, true, ctx);
 675        self.end_transaction(ctx);
 676    }
 677
 678    fn newline(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 679        if self.single_line {
 680            ctx.propagate_action();
 681        } else {
 682            self.insert(&"\n".into(), ctx);
 683        }
 684    }
 685
 686    pub fn backspace(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 687        self.start_transaction(ctx);
 688        let mut selections = self.selections(ctx.as_ref()).to_vec();
 689        {
 690            let buffer = self.buffer.read(ctx);
 691            for selection in &mut selections {
 692                let range = selection.range(buffer);
 693                if range.start == range.end {
 694                    let head = selection
 695                        .head()
 696                        .to_display_point(&self.display_map, ctx.as_ref());
 697                    let cursor = self.display_map.anchor_before(
 698                        movement::left(&self.display_map, head, ctx.as_ref()).unwrap(),
 699                        Bias::Left,
 700                        ctx.as_ref(),
 701                    );
 702                    selection.set_head(&buffer, cursor);
 703                    selection.goal = SelectionGoal::None;
 704                }
 705            }
 706        }
 707
 708        self.update_selections(selections, true, ctx);
 709        self.insert(&String::new(), ctx);
 710        self.end_transaction(ctx);
 711    }
 712
 713    pub fn delete(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 714        self.start_transaction(ctx);
 715        let mut selections = self.selections(ctx.as_ref()).to_vec();
 716        {
 717            let buffer = self.buffer.read(ctx);
 718            for selection in &mut selections {
 719                let range = selection.range(buffer);
 720                if range.start == range.end {
 721                    let head = selection
 722                        .head()
 723                        .to_display_point(&self.display_map, ctx.as_ref());
 724                    let cursor = self.display_map.anchor_before(
 725                        movement::right(&self.display_map, head, ctx.as_ref()).unwrap(),
 726                        Bias::Right,
 727                        ctx.as_ref(),
 728                    );
 729                    selection.set_head(&buffer, cursor);
 730                    selection.goal = SelectionGoal::None;
 731                }
 732            }
 733        }
 734
 735        self.update_selections(selections, true, ctx);
 736        self.insert(&String::new(), ctx);
 737        self.end_transaction(ctx);
 738    }
 739
 740    pub fn delete_line(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 741        self.start_transaction(ctx);
 742
 743        let app = ctx.as_ref();
 744        let buffer = self.buffer.read(app);
 745
 746        let mut new_cursors = Vec::new();
 747        let mut edit_ranges = Vec::new();
 748
 749        let mut selections = self.selections(app).iter().peekable();
 750        while let Some(selection) = selections.next() {
 751            let (mut rows, _) =
 752                selection.buffer_rows_for_display_rows(false, &self.display_map, app);
 753            let goal_display_column = selection
 754                .head()
 755                .to_display_point(&self.display_map, app)
 756                .column();
 757
 758            // Accumulate contiguous regions of rows that we want to delete.
 759            while let Some(next_selection) = selections.peek() {
 760                let (next_rows, _) =
 761                    next_selection.buffer_rows_for_display_rows(false, &self.display_map, app);
 762                if next_rows.start <= rows.end {
 763                    rows.end = next_rows.end;
 764                    selections.next().unwrap();
 765                } else {
 766                    break;
 767                }
 768            }
 769
 770            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
 771            let edit_end;
 772            let cursor_buffer_row;
 773            if buffer.max_point().row >= rows.end {
 774                // If there's a line after the range, delete the \n from the end of the row range
 775                // and position the cursor on the next line.
 776                edit_end = Point::new(rows.end, 0).to_offset(buffer);
 777                cursor_buffer_row = rows.end;
 778            } else {
 779                // If there isn't a line after the range, delete the \n from the line before the
 780                // start of the row range and position the cursor there.
 781                edit_start = edit_start.saturating_sub(1);
 782                edit_end = buffer.len();
 783                cursor_buffer_row = rows.start.saturating_sub(1);
 784            }
 785
 786            let mut cursor =
 787                Point::new(cursor_buffer_row, 0).to_display_point(&self.display_map, app);
 788            *cursor.column_mut() = cmp::min(
 789                goal_display_column,
 790                self.display_map.line_len(cursor.row(), app),
 791            );
 792
 793            new_cursors.push((
 794                selection.id,
 795                cursor.to_buffer_point(&self.display_map, Bias::Left, app),
 796            ));
 797            edit_ranges.push(edit_start..edit_end);
 798        }
 799
 800        new_cursors.sort_unstable_by_key(|(_, range)| range.clone());
 801        let new_selections = new_cursors
 802            .into_iter()
 803            .map(|(id, cursor)| {
 804                let anchor = buffer.anchor_before(cursor);
 805                Selection {
 806                    id,
 807                    start: anchor.clone(),
 808                    end: anchor,
 809                    reversed: false,
 810                    goal: SelectionGoal::None,
 811                }
 812            })
 813            .collect();
 814        self.buffer
 815            .update(ctx, |buffer, ctx| buffer.edit(edit_ranges, "", Some(ctx)))
 816            .unwrap();
 817        self.update_selections(new_selections, true, ctx);
 818        self.end_transaction(ctx);
 819    }
 820
 821    pub fn duplicate_line(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 822        self.start_transaction(ctx);
 823
 824        let mut selections = self.selections(ctx.as_ref()).to_vec();
 825        {
 826            // Temporarily bias selections right to allow newly duplicate lines to push them down
 827            // when the selections are at the beginning of a line.
 828            let buffer = self.buffer.read(ctx);
 829            for selection in &mut selections {
 830                selection.start = selection.start.bias_right(buffer);
 831                selection.end = selection.end.bias_right(buffer);
 832            }
 833        }
 834        self.update_selections(selections.clone(), false, ctx);
 835
 836        let app = ctx.as_ref();
 837        let buffer = self.buffer.read(ctx);
 838
 839        let mut edits = Vec::new();
 840        let mut selections_iter = selections.iter_mut().peekable();
 841        while let Some(selection) = selections_iter.next() {
 842            // Avoid duplicating the same lines twice.
 843            let (mut rows, _) =
 844                selection.buffer_rows_for_display_rows(false, &self.display_map, app);
 845            while let Some(next_selection) = selections_iter.peek() {
 846                let (next_rows, _) =
 847                    next_selection.buffer_rows_for_display_rows(false, &self.display_map, app);
 848                if next_rows.start <= rows.end - 1 {
 849                    rows.end = next_rows.end;
 850                    selections_iter.next().unwrap();
 851                } else {
 852                    break;
 853                }
 854            }
 855
 856            // Copy the text from the selected row region and splice it at the start of the region.
 857            let start = Point::new(rows.start, 0);
 858            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
 859            let text = buffer
 860                .text_for_range(start..end)
 861                .chain(Some("\n"))
 862                .collect::<String>();
 863            edits.push((start, text));
 864        }
 865
 866        self.buffer.update(ctx, |buffer, ctx| {
 867            for (offset, text) in edits.into_iter().rev() {
 868                buffer.edit(Some(offset..offset), text, Some(ctx)).unwrap();
 869            }
 870        });
 871
 872        // Restore bias on selections.
 873        let buffer = self.buffer.read(ctx);
 874        for selection in &mut selections {
 875            selection.start = selection.start.bias_left(buffer);
 876            selection.end = selection.end.bias_left(buffer);
 877        }
 878        self.update_selections(selections, true, ctx);
 879
 880        self.end_transaction(ctx);
 881    }
 882
 883    pub fn move_line_up(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 884        self.start_transaction(ctx);
 885
 886        let app = ctx.as_ref();
 887        let buffer = self.buffer.read(ctx);
 888
 889        let mut edits = Vec::new();
 890        let mut new_selection_ranges = Vec::new();
 891        let mut old_folds = Vec::new();
 892        let mut new_folds = Vec::new();
 893
 894        let mut selections = self.selections(app).iter().peekable();
 895        let mut contiguous_selections = Vec::new();
 896        while let Some(selection) = selections.next() {
 897            // Accumulate contiguous regions of rows that we want to move.
 898            contiguous_selections.push(selection.range(buffer));
 899            let (mut buffer_rows, mut display_rows) =
 900                selection.buffer_rows_for_display_rows(false, &self.display_map, app);
 901            while let Some(next_selection) = selections.peek() {
 902                let (next_buffer_rows, next_display_rows) =
 903                    next_selection.buffer_rows_for_display_rows(false, &self.display_map, app);
 904                if next_buffer_rows.start <= buffer_rows.end {
 905                    buffer_rows.end = next_buffer_rows.end;
 906                    display_rows.end = next_display_rows.end;
 907                    contiguous_selections.push(next_selection.range(buffer));
 908                    selections.next().unwrap();
 909                } else {
 910                    break;
 911                }
 912            }
 913
 914            // Cut the text from the selected rows and paste it at the start of the previous line.
 915            if display_rows.start != 0 {
 916                let start = Point::new(buffer_rows.start, 0).to_offset(buffer);
 917                let end = Point::new(buffer_rows.end - 1, buffer.line_len(buffer_rows.end - 1))
 918                    .to_offset(buffer);
 919
 920                let prev_row_display_start = DisplayPoint::new(display_rows.start - 1, 0);
 921                let prev_row_start =
 922                    prev_row_display_start.to_buffer_offset(&self.display_map, Bias::Left, app);
 923
 924                let mut text = String::new();
 925                text.extend(buffer.text_for_range(start..end));
 926                text.push('\n');
 927                edits.push((prev_row_start..prev_row_start, text));
 928                edits.push((start - 1..end, String::new()));
 929
 930                let row_delta = buffer_rows.start
 931                    - prev_row_display_start
 932                        .to_buffer_point(&self.display_map, Bias::Left, app)
 933                        .row;
 934
 935                // Move selections up.
 936                for range in &mut contiguous_selections {
 937                    range.start.row -= row_delta;
 938                    range.end.row -= row_delta;
 939                }
 940
 941                // Move folds up.
 942                old_folds.push(start..end);
 943                for fold in self.display_map.folds_in_range(start..end, app) {
 944                    let mut start = fold.start.to_point(buffer);
 945                    let mut end = fold.end.to_point(buffer);
 946                    start.row -= row_delta;
 947                    end.row -= row_delta;
 948                    new_folds.push(start..end);
 949                }
 950            }
 951
 952            new_selection_ranges.extend(contiguous_selections.drain(..));
 953        }
 954
 955        self.unfold_ranges(old_folds, ctx);
 956        self.buffer.update(ctx, |buffer, ctx| {
 957            for (range, text) in edits.into_iter().rev() {
 958                buffer.edit(Some(range), text, Some(ctx)).unwrap();
 959            }
 960        });
 961        self.fold_ranges(new_folds, ctx);
 962        self.select_ranges(new_selection_ranges, true, ctx);
 963
 964        self.end_transaction(ctx);
 965    }
 966
 967    pub fn move_line_down(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
 968        self.start_transaction(ctx);
 969
 970        let app = ctx.as_ref();
 971        let buffer = self.buffer.read(ctx);
 972
 973        let mut edits = Vec::new();
 974        let mut new_selection_ranges = Vec::new();
 975        let mut old_folds = Vec::new();
 976        let mut new_folds = Vec::new();
 977
 978        let mut selections = self.selections(app).iter().peekable();
 979        let mut contiguous_selections = Vec::new();
 980        while let Some(selection) = selections.next() {
 981            // Accumulate contiguous regions of rows that we want to move.
 982            contiguous_selections.push(selection.range(buffer));
 983            let (mut buffer_rows, mut display_rows) =
 984                selection.buffer_rows_for_display_rows(false, &self.display_map, app);
 985            while let Some(next_selection) = selections.peek() {
 986                let (next_buffer_rows, next_display_rows) =
 987                    next_selection.buffer_rows_for_display_rows(false, &self.display_map, app);
 988                if next_buffer_rows.start <= buffer_rows.end {
 989                    buffer_rows.end = next_buffer_rows.end;
 990                    display_rows.end = next_display_rows.end;
 991                    contiguous_selections.push(next_selection.range(buffer));
 992                    selections.next().unwrap();
 993                } else {
 994                    break;
 995                }
 996            }
 997
 998            // Cut the text from the selected rows and paste it at the end of the next line.
 999            if display_rows.end <= self.display_map.max_point(app).row() {
1000                let start = Point::new(buffer_rows.start, 0).to_offset(buffer);
1001                let end = Point::new(buffer_rows.end - 1, buffer.line_len(buffer_rows.end - 1))
1002                    .to_offset(buffer);
1003
1004                let next_row_display_end = DisplayPoint::new(
1005                    display_rows.end,
1006                    self.display_map.line_len(display_rows.end, app),
1007                );
1008                let next_row_end =
1009                    next_row_display_end.to_buffer_offset(&self.display_map, Bias::Right, app);
1010
1011                let mut text = String::new();
1012                text.push('\n');
1013                text.extend(buffer.text_for_range(start..end));
1014                edits.push((start..end + 1, String::new()));
1015                edits.push((next_row_end..next_row_end, text));
1016
1017                let row_delta = next_row_display_end
1018                    .to_buffer_point(&self.display_map, Bias::Right, app)
1019                    .row
1020                    - buffer_rows.end
1021                    + 1;
1022
1023                // Move selections down.
1024                for range in &mut contiguous_selections {
1025                    range.start.row += row_delta;
1026                    range.end.row += row_delta;
1027                }
1028
1029                // Move folds down.
1030                old_folds.push(start..end);
1031                for fold in self.display_map.folds_in_range(start..end, app) {
1032                    let mut start = fold.start.to_point(buffer);
1033                    let mut end = fold.end.to_point(buffer);
1034                    start.row += row_delta;
1035                    end.row += row_delta;
1036                    new_folds.push(start..end);
1037                }
1038            }
1039
1040            new_selection_ranges.extend(contiguous_selections.drain(..));
1041        }
1042
1043        self.unfold_ranges(old_folds, ctx);
1044        self.buffer.update(ctx, |buffer, ctx| {
1045            for (range, text) in edits.into_iter().rev() {
1046                buffer.edit(Some(range), text, Some(ctx)).unwrap();
1047            }
1048        });
1049        self.fold_ranges(new_folds, ctx);
1050        self.select_ranges(new_selection_ranges, true, ctx);
1051
1052        self.end_transaction(ctx);
1053    }
1054
1055    pub fn cut(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1056        self.start_transaction(ctx);
1057        let mut text = String::new();
1058        let mut selections = self.selections(ctx.as_ref()).to_vec();
1059        let mut clipboard_selections = Vec::with_capacity(selections.len());
1060        {
1061            let buffer = self.buffer.read(ctx);
1062            let max_point = buffer.max_point();
1063            for selection in &mut selections {
1064                let mut start = selection.start.to_point(buffer);
1065                let mut end = selection.end.to_point(buffer);
1066                let is_entire_line = start == end;
1067                if is_entire_line {
1068                    start = Point::new(start.row, 0);
1069                    end = cmp::min(max_point, Point::new(start.row + 1, 0));
1070                    selection.start = buffer.anchor_before(start);
1071                    selection.end = buffer.anchor_before(end);
1072                }
1073                let mut len = 0;
1074                for chunk in buffer.text_for_range(start..end) {
1075                    text.push_str(chunk);
1076                    len += chunk.len();
1077                }
1078                clipboard_selections.push(ClipboardSelection {
1079                    len,
1080                    is_entire_line,
1081                });
1082            }
1083        }
1084        self.update_selections(selections, true, ctx);
1085        self.insert(&String::new(), ctx);
1086        self.end_transaction(ctx);
1087
1088        ctx.as_mut()
1089            .write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
1090    }
1091
1092    pub fn copy(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1093        let buffer = self.buffer.read(ctx);
1094        let max_point = buffer.max_point();
1095        let mut text = String::new();
1096        let selections = self.selections(ctx.as_ref());
1097        let mut clipboard_selections = Vec::with_capacity(selections.len());
1098        for selection in selections {
1099            let mut start = selection.start.to_point(buffer);
1100            let mut end = selection.end.to_point(buffer);
1101            let is_entire_line = start == end;
1102            if is_entire_line {
1103                start = Point::new(start.row, 0);
1104                end = cmp::min(max_point, Point::new(start.row + 1, 0));
1105            }
1106            let mut len = 0;
1107            for chunk in buffer.text_for_range(start..end) {
1108                text.push_str(chunk);
1109                len += chunk.len();
1110            }
1111            clipboard_selections.push(ClipboardSelection {
1112                len,
1113                is_entire_line,
1114            });
1115        }
1116
1117        ctx.as_mut()
1118            .write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
1119    }
1120
1121    pub fn paste(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1122        if let Some(item) = ctx.as_mut().read_from_clipboard() {
1123            let clipboard_text = item.text();
1124            if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
1125                let selections = self.selections(ctx.as_ref()).to_vec();
1126                if clipboard_selections.len() != selections.len() {
1127                    let merged_selection = ClipboardSelection {
1128                        len: clipboard_selections.iter().map(|s| s.len).sum(),
1129                        is_entire_line: clipboard_selections.iter().all(|s| s.is_entire_line),
1130                    };
1131                    clipboard_selections.clear();
1132                    clipboard_selections.push(merged_selection);
1133                }
1134
1135                self.start_transaction(ctx);
1136                let mut new_selections = Vec::with_capacity(selections.len());
1137                let mut clipboard_chars = clipboard_text.chars().cycle();
1138                for (selection, clipboard_selection) in
1139                    selections.iter().zip(clipboard_selections.iter().cycle())
1140                {
1141                    let to_insert =
1142                        String::from_iter(clipboard_chars.by_ref().take(clipboard_selection.len));
1143
1144                    self.buffer.update(ctx, |buffer, ctx| {
1145                        let selection_start = selection.start.to_point(buffer);
1146                        let selection_end = selection.end.to_point(buffer);
1147
1148                        // If the corresponding selection was empty when this slice of the
1149                        // clipboard text was written, then the entire line containing the
1150                        // selection was copied. If this selection is also currently empty,
1151                        // then paste the line before the current line of the buffer.
1152                        let new_selection_start = selection.end.bias_right(buffer);
1153                        if selection_start == selection_end && clipboard_selection.is_entire_line {
1154                            let line_start = Point::new(selection_start.row, 0);
1155                            buffer
1156                                .edit(Some(line_start..line_start), to_insert, Some(ctx))
1157                                .unwrap();
1158                        } else {
1159                            buffer
1160                                .edit(Some(&selection.start..&selection.end), to_insert, Some(ctx))
1161                                .unwrap();
1162                        };
1163
1164                        let new_selection_start = new_selection_start.bias_left(buffer);
1165                        new_selections.push(Selection {
1166                            id: selection.id,
1167                            start: new_selection_start.clone(),
1168                            end: new_selection_start,
1169                            reversed: false,
1170                            goal: SelectionGoal::None,
1171                        });
1172                    });
1173                }
1174                self.update_selections(new_selections, true, ctx);
1175                self.end_transaction(ctx);
1176            } else {
1177                self.insert(clipboard_text, ctx);
1178            }
1179        }
1180    }
1181
1182    pub fn undo(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1183        self.buffer
1184            .update(ctx, |buffer, ctx| buffer.undo(Some(ctx)));
1185    }
1186
1187    pub fn redo(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1188        self.buffer
1189            .update(ctx, |buffer, ctx| buffer.redo(Some(ctx)));
1190    }
1191
1192    pub fn move_left(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1193        let app = ctx.as_ref();
1194        let mut selections = self.selections(app).to_vec();
1195        {
1196            for selection in &mut selections {
1197                let start = selection.start.to_display_point(&self.display_map, app);
1198                let end = selection.end.to_display_point(&self.display_map, app);
1199
1200                if start != end {
1201                    selection.end = selection.start.clone();
1202                } else {
1203                    let cursor = self.display_map.anchor_before(
1204                        movement::left(&self.display_map, start, app).unwrap(),
1205                        Bias::Left,
1206                        app,
1207                    );
1208                    selection.start = cursor.clone();
1209                    selection.end = cursor;
1210                }
1211                selection.reversed = false;
1212                selection.goal = SelectionGoal::None;
1213            }
1214        }
1215        self.update_selections(selections, true, ctx);
1216    }
1217
1218    pub fn select_left(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1219        let mut selections = self.selections(ctx.as_ref()).to_vec();
1220        {
1221            let buffer = self.buffer.read(ctx);
1222            for selection in &mut selections {
1223                let head = selection
1224                    .head()
1225                    .to_display_point(&self.display_map, ctx.as_ref());
1226                let cursor = self.display_map.anchor_before(
1227                    movement::left(&self.display_map, head, ctx.as_ref()).unwrap(),
1228                    Bias::Left,
1229                    ctx.as_ref(),
1230                );
1231                selection.set_head(&buffer, cursor);
1232                selection.goal = SelectionGoal::None;
1233            }
1234        }
1235        self.update_selections(selections, true, ctx);
1236    }
1237
1238    pub fn move_right(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1239        let mut selections = self.selections(ctx.as_ref()).to_vec();
1240        {
1241            let app = ctx.as_ref();
1242            for selection in &mut selections {
1243                let start = selection.start.to_display_point(&self.display_map, app);
1244                let end = selection.end.to_display_point(&self.display_map, app);
1245
1246                if start != end {
1247                    selection.start = selection.end.clone();
1248                } else {
1249                    let cursor = self.display_map.anchor_before(
1250                        movement::right(&self.display_map, end, app).unwrap(),
1251                        Bias::Right,
1252                        app,
1253                    );
1254                    selection.start = cursor.clone();
1255                    selection.end = cursor;
1256                }
1257                selection.reversed = false;
1258                selection.goal = SelectionGoal::None;
1259            }
1260        }
1261        self.update_selections(selections, true, ctx);
1262    }
1263
1264    pub fn select_right(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1265        let mut selections = self.selections(ctx.as_ref()).to_vec();
1266        {
1267            let app = ctx.as_ref();
1268            let buffer = self.buffer.read(app);
1269            for selection in &mut selections {
1270                let head = selection
1271                    .head()
1272                    .to_display_point(&self.display_map, ctx.as_ref());
1273                let cursor = self.display_map.anchor_before(
1274                    movement::right(&self.display_map, head, app).unwrap(),
1275                    Bias::Right,
1276                    app,
1277                );
1278                selection.set_head(&buffer, cursor);
1279                selection.goal = SelectionGoal::None;
1280            }
1281        }
1282        self.update_selections(selections, true, ctx);
1283    }
1284
1285    pub fn move_up(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1286        if self.single_line {
1287            ctx.propagate_action();
1288        } else {
1289            let mut selections = self.selections(ctx.as_ref()).to_vec();
1290            {
1291                let app = ctx.as_ref();
1292                for selection in &mut selections {
1293                    let start = selection.start.to_display_point(&self.display_map, app);
1294                    let end = selection.end.to_display_point(&self.display_map, app);
1295                    if start != end {
1296                        selection.goal = SelectionGoal::None;
1297                    }
1298
1299                    let (start, goal) =
1300                        movement::up(&self.display_map, start, selection.goal, app).unwrap();
1301                    let cursor = self.display_map.anchor_before(start, Bias::Left, app);
1302                    selection.start = cursor.clone();
1303                    selection.end = cursor;
1304                    selection.goal = goal;
1305                    selection.reversed = false;
1306                }
1307            }
1308            self.update_selections(selections, true, ctx);
1309        }
1310    }
1311
1312    pub fn select_up(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1313        let mut selections = self.selections(ctx.as_ref()).to_vec();
1314        {
1315            let app = ctx.as_ref();
1316            let buffer = self.buffer.read(app);
1317            for selection in &mut selections {
1318                let head = selection.head().to_display_point(&self.display_map, app);
1319                let (head, goal) =
1320                    movement::up(&self.display_map, head, selection.goal, app).unwrap();
1321                selection.set_head(
1322                    &buffer,
1323                    self.display_map.anchor_before(head, Bias::Left, app),
1324                );
1325                selection.goal = goal;
1326            }
1327        }
1328        self.update_selections(selections, true, ctx);
1329    }
1330
1331    pub fn move_down(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1332        if self.single_line {
1333            ctx.propagate_action();
1334        } else {
1335            let mut selections = self.selections(ctx.as_ref()).to_vec();
1336            {
1337                let app = ctx.as_ref();
1338                for selection in &mut selections {
1339                    let start = selection.start.to_display_point(&self.display_map, app);
1340                    let end = selection.end.to_display_point(&self.display_map, app);
1341                    if start != end {
1342                        selection.goal = SelectionGoal::None;
1343                    }
1344
1345                    let (start, goal) =
1346                        movement::down(&self.display_map, end, selection.goal, app).unwrap();
1347                    let cursor = self.display_map.anchor_before(start, Bias::Right, app);
1348                    selection.start = cursor.clone();
1349                    selection.end = cursor;
1350                    selection.goal = goal;
1351                    selection.reversed = false;
1352                }
1353            }
1354            self.update_selections(selections, true, ctx);
1355        }
1356    }
1357
1358    pub fn select_down(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1359        let mut selections = self.selections(ctx.as_ref()).to_vec();
1360        {
1361            let app = ctx.as_ref();
1362            let buffer = self.buffer.read(app);
1363            for selection in &mut selections {
1364                let head = selection.head().to_display_point(&self.display_map, app);
1365                let (head, goal) =
1366                    movement::down(&self.display_map, head, selection.goal, app).unwrap();
1367                selection.set_head(
1368                    &buffer,
1369                    self.display_map.anchor_before(head, Bias::Right, app),
1370                );
1371                selection.goal = goal;
1372            }
1373        }
1374        self.update_selections(selections, true, ctx);
1375    }
1376
1377    pub fn move_to_previous_word_boundary(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1378        let app = ctx.as_ref();
1379        let mut selections = self.selections(app).to_vec();
1380        {
1381            for selection in &mut selections {
1382                let head = selection.head().to_display_point(&self.display_map, app);
1383                let new_head = movement::prev_word_boundary(&self.display_map, head, app).unwrap();
1384                let anchor = self.display_map.anchor_before(new_head, Bias::Left, app);
1385                selection.start = anchor.clone();
1386                selection.end = anchor;
1387                selection.reversed = false;
1388                selection.goal = SelectionGoal::None;
1389            }
1390        }
1391        self.update_selections(selections, true, ctx);
1392    }
1393
1394    pub fn select_to_previous_word_boundary(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1395        let app = ctx.as_ref();
1396        let mut selections = self.selections(app).to_vec();
1397        {
1398            let buffer = self.buffer.read(ctx);
1399            for selection in &mut selections {
1400                let head = selection.head().to_display_point(&self.display_map, app);
1401                let new_head = movement::prev_word_boundary(&self.display_map, head, app).unwrap();
1402                let anchor = self.display_map.anchor_before(new_head, Bias::Left, app);
1403                selection.set_head(buffer, anchor);
1404                selection.goal = SelectionGoal::None;
1405            }
1406        }
1407        self.update_selections(selections, true, ctx);
1408    }
1409
1410    pub fn delete_to_previous_word_boundary(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1411        self.start_transaction(ctx);
1412        self.select_to_previous_word_boundary(&(), ctx);
1413        self.backspace(&(), ctx);
1414        self.end_transaction(ctx);
1415    }
1416
1417    pub fn move_to_next_word_boundary(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1418        let app = ctx.as_ref();
1419        let mut selections = self.selections(app).to_vec();
1420        {
1421            for selection in &mut selections {
1422                let head = selection.head().to_display_point(&self.display_map, app);
1423                let new_head = movement::next_word_boundary(&self.display_map, head, app).unwrap();
1424                let anchor = self.display_map.anchor_before(new_head, Bias::Left, app);
1425                selection.start = anchor.clone();
1426                selection.end = anchor;
1427                selection.reversed = false;
1428                selection.goal = SelectionGoal::None;
1429            }
1430        }
1431        self.update_selections(selections, true, ctx);
1432    }
1433
1434    pub fn select_to_next_word_boundary(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1435        let app = ctx.as_ref();
1436        let mut selections = self.selections(app).to_vec();
1437        {
1438            let buffer = self.buffer.read(ctx);
1439            for selection in &mut selections {
1440                let head = selection.head().to_display_point(&self.display_map, app);
1441                let new_head = movement::next_word_boundary(&self.display_map, head, app).unwrap();
1442                let anchor = self.display_map.anchor_before(new_head, Bias::Left, app);
1443                selection.set_head(buffer, anchor);
1444                selection.goal = SelectionGoal::None;
1445            }
1446        }
1447        self.update_selections(selections, true, ctx);
1448    }
1449
1450    pub fn delete_to_next_word_boundary(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1451        self.start_transaction(ctx);
1452        self.select_to_next_word_boundary(&(), ctx);
1453        self.delete(&(), ctx);
1454        self.end_transaction(ctx);
1455    }
1456
1457    pub fn move_to_beginning_of_line(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1458        let app = ctx.as_ref();
1459        let mut selections = self.selections(app).to_vec();
1460        {
1461            for selection in &mut selections {
1462                let head = selection.head().to_display_point(&self.display_map, app);
1463                let new_head =
1464                    movement::line_beginning(&self.display_map, head, true, app).unwrap();
1465                let anchor = self.display_map.anchor_before(new_head, Bias::Left, app);
1466                selection.start = anchor.clone();
1467                selection.end = anchor;
1468                selection.reversed = false;
1469                selection.goal = SelectionGoal::None;
1470            }
1471        }
1472        self.update_selections(selections, true, ctx);
1473    }
1474
1475    pub fn select_to_beginning_of_line(
1476        &mut self,
1477        toggle_indent: &bool,
1478        ctx: &mut ViewContext<Self>,
1479    ) {
1480        let app = ctx.as_ref();
1481        let mut selections = self.selections(app).to_vec();
1482        {
1483            let buffer = self.buffer.read(ctx);
1484            for selection in &mut selections {
1485                let head = selection.head().to_display_point(&self.display_map, app);
1486                let new_head =
1487                    movement::line_beginning(&self.display_map, head, *toggle_indent, app).unwrap();
1488                let anchor = self.display_map.anchor_before(new_head, Bias::Left, app);
1489                selection.set_head(buffer, anchor);
1490                selection.goal = SelectionGoal::None;
1491            }
1492        }
1493        self.update_selections(selections, true, ctx);
1494    }
1495
1496    pub fn delete_to_beginning_of_line(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1497        self.start_transaction(ctx);
1498        self.select_to_beginning_of_line(&false, ctx);
1499        self.backspace(&(), ctx);
1500        self.end_transaction(ctx);
1501    }
1502
1503    pub fn move_to_end_of_line(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1504        let app = ctx.as_ref();
1505        let mut selections = self.selections(app).to_vec();
1506        {
1507            for selection in &mut selections {
1508                let head = selection.head().to_display_point(&self.display_map, app);
1509                let new_head = movement::line_end(&self.display_map, head, app).unwrap();
1510                let anchor = self.display_map.anchor_before(new_head, Bias::Left, app);
1511                selection.start = anchor.clone();
1512                selection.end = anchor;
1513                selection.reversed = false;
1514                selection.goal = SelectionGoal::None;
1515            }
1516        }
1517        self.update_selections(selections, true, ctx);
1518    }
1519
1520    pub fn select_to_end_of_line(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1521        let app = ctx.as_ref();
1522        let mut selections = self.selections(app).to_vec();
1523        {
1524            let buffer = self.buffer.read(ctx);
1525            for selection in &mut selections {
1526                let head = selection.head().to_display_point(&self.display_map, app);
1527                let new_head = movement::line_end(&self.display_map, head, app).unwrap();
1528                let anchor = self.display_map.anchor_before(new_head, Bias::Left, app);
1529                selection.set_head(buffer, anchor);
1530                selection.goal = SelectionGoal::None;
1531            }
1532        }
1533        self.update_selections(selections, true, ctx);
1534    }
1535
1536    pub fn delete_to_end_of_line(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1537        self.start_transaction(ctx);
1538        self.select_to_end_of_line(&(), ctx);
1539        self.delete(&(), ctx);
1540        self.end_transaction(ctx);
1541    }
1542
1543    pub fn move_to_beginning(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1544        let buffer = self.buffer.read(ctx);
1545        let cursor = buffer.anchor_before(Point::new(0, 0));
1546        let selection = Selection {
1547            id: post_inc(&mut self.next_selection_id),
1548            start: cursor.clone(),
1549            end: cursor,
1550            reversed: false,
1551            goal: SelectionGoal::None,
1552        };
1553        self.update_selections(vec![selection], true, ctx);
1554    }
1555
1556    pub fn select_to_beginning(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1557        let mut selection = self.selections(ctx.as_ref()).last().unwrap().clone();
1558        selection.set_head(self.buffer.read(ctx), Anchor::Start);
1559        self.update_selections(vec![selection], true, ctx);
1560    }
1561
1562    pub fn move_to_end(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1563        let buffer = self.buffer.read(ctx);
1564        let cursor = buffer.anchor_before(buffer.max_point());
1565        let selection = Selection {
1566            id: post_inc(&mut self.next_selection_id),
1567            start: cursor.clone(),
1568            end: cursor,
1569            reversed: false,
1570            goal: SelectionGoal::None,
1571        };
1572        self.update_selections(vec![selection], true, ctx);
1573    }
1574
1575    pub fn select_to_end(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1576        let mut selection = self.selections(ctx.as_ref()).last().unwrap().clone();
1577        selection.set_head(self.buffer.read(ctx), Anchor::End);
1578        self.update_selections(vec![selection], true, ctx);
1579    }
1580
1581    pub fn select_all(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1582        let selection = Selection {
1583            id: post_inc(&mut self.next_selection_id),
1584            start: Anchor::Start,
1585            end: Anchor::End,
1586            reversed: false,
1587            goal: SelectionGoal::None,
1588        };
1589        self.update_selections(vec![selection], false, ctx);
1590    }
1591
1592    pub fn select_line(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1593        let app = ctx.as_ref();
1594        let buffer = self.buffer.read(app);
1595        let mut selections = self.selections(app).to_vec();
1596        let max_point = buffer.max_point();
1597        for selection in &mut selections {
1598            let (rows, _) = selection.buffer_rows_for_display_rows(true, &self.display_map, app);
1599            selection.start = buffer.anchor_before(Point::new(rows.start, 0));
1600            selection.end = buffer.anchor_before(cmp::min(max_point, Point::new(rows.end, 0)));
1601            selection.reversed = false;
1602        }
1603        self.update_selections(selections, true, ctx);
1604    }
1605
1606    pub fn split_selection_into_lines(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1607        use super::RangeExt;
1608
1609        let app = ctx.as_ref();
1610        let buffer = self.buffer.read(app);
1611
1612        let mut to_unfold = Vec::new();
1613        let mut new_selections = Vec::new();
1614        for selection in self.selections(app) {
1615            let range = selection.range(buffer).sorted();
1616            if range.start.row != range.end.row {
1617                new_selections.push(Selection {
1618                    id: post_inc(&mut self.next_selection_id),
1619                    start: selection.start.clone(),
1620                    end: selection.start.clone(),
1621                    reversed: false,
1622                    goal: SelectionGoal::None,
1623                });
1624            }
1625            for row in range.start.row + 1..range.end.row {
1626                let cursor = buffer.anchor_before(Point::new(row, buffer.line_len(row)));
1627                new_selections.push(Selection {
1628                    id: post_inc(&mut self.next_selection_id),
1629                    start: cursor.clone(),
1630                    end: cursor,
1631                    reversed: false,
1632                    goal: SelectionGoal::None,
1633                });
1634            }
1635            new_selections.push(Selection {
1636                id: selection.id,
1637                start: selection.end.clone(),
1638                end: selection.end.clone(),
1639                reversed: false,
1640                goal: SelectionGoal::None,
1641            });
1642            to_unfold.push(range);
1643        }
1644        self.unfold_ranges(to_unfold, ctx);
1645        self.update_selections(new_selections, true, ctx);
1646    }
1647
1648    pub fn add_selection_above(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1649        self.add_selection(true, ctx);
1650    }
1651
1652    pub fn add_selection_below(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1653        self.add_selection(false, ctx);
1654    }
1655
1656    pub fn add_selection(&mut self, above: bool, ctx: &mut ViewContext<Self>) {
1657        use super::RangeExt;
1658
1659        let app = ctx.as_ref();
1660
1661        let mut selections = self.selections(app).to_vec();
1662        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
1663            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
1664            let range = oldest_selection
1665                .display_range(&self.display_map, app)
1666                .sorted();
1667            let columns = cmp::min(range.start.column(), range.end.column())
1668                ..cmp::max(range.start.column(), range.end.column());
1669
1670            selections.clear();
1671            let mut stack = Vec::new();
1672            for row in range.start.row()..=range.end.row() {
1673                if let Some(selection) =
1674                    self.build_columnar_selection(row, &columns, oldest_selection.reversed, app)
1675                {
1676                    stack.push(selection.id);
1677                    selections.push(selection);
1678                }
1679            }
1680
1681            if above {
1682                stack.reverse();
1683            }
1684
1685            AddSelectionsState { above, stack }
1686        });
1687
1688        let last_added_selection = *state.stack.last().unwrap();
1689        let mut new_selections = Vec::new();
1690        if above == state.above {
1691            let end_row = if above {
1692                0
1693            } else {
1694                self.display_map.max_point(app).row()
1695            };
1696
1697            'outer: for selection in selections {
1698                if selection.id == last_added_selection {
1699                    let range = selection.display_range(&self.display_map, app).sorted();
1700                    debug_assert_eq!(range.start.row(), range.end.row());
1701                    let mut row = range.start.row();
1702                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
1703                    {
1704                        start..end
1705                    } else {
1706                        cmp::min(range.start.column(), range.end.column())
1707                            ..cmp::max(range.start.column(), range.end.column())
1708                    };
1709
1710                    while row != end_row {
1711                        if above {
1712                            row -= 1;
1713                        } else {
1714                            row += 1;
1715                        }
1716
1717                        if let Some(new_selection) =
1718                            self.build_columnar_selection(row, &columns, selection.reversed, app)
1719                        {
1720                            state.stack.push(new_selection.id);
1721                            if above {
1722                                new_selections.push(new_selection);
1723                                new_selections.push(selection);
1724                            } else {
1725                                new_selections.push(selection);
1726                                new_selections.push(new_selection);
1727                            }
1728
1729                            continue 'outer;
1730                        }
1731                    }
1732                }
1733
1734                new_selections.push(selection);
1735            }
1736        } else {
1737            new_selections = selections;
1738            new_selections.retain(|s| s.id != last_added_selection);
1739            state.stack.pop();
1740        }
1741
1742        self.update_selections(new_selections, true, ctx);
1743        if state.stack.len() > 1 {
1744            self.add_selections_state = Some(state);
1745        }
1746    }
1747
1748    fn build_columnar_selection(
1749        &mut self,
1750        row: u32,
1751        columns: &Range<u32>,
1752        reversed: bool,
1753        ctx: &AppContext,
1754    ) -> Option<Selection> {
1755        let is_empty = columns.start == columns.end;
1756        let line_len = self.display_map.line_len(row, ctx);
1757        if columns.start < line_len || (is_empty && columns.start == line_len) {
1758            let start = DisplayPoint::new(row, columns.start);
1759            let end = DisplayPoint::new(row, cmp::min(columns.end, line_len));
1760            Some(Selection {
1761                id: post_inc(&mut self.next_selection_id),
1762                start: self.display_map.anchor_before(start, Bias::Left, ctx),
1763                end: self.display_map.anchor_before(end, Bias::Left, ctx),
1764                reversed,
1765                goal: SelectionGoal::ColumnRange {
1766                    start: columns.start,
1767                    end: columns.end,
1768                },
1769            })
1770        } else {
1771            None
1772        }
1773    }
1774
1775    pub fn selections_in_range<'a>(
1776        &'a self,
1777        range: Range<DisplayPoint>,
1778        app: &'a AppContext,
1779    ) -> impl 'a + Iterator<Item = Range<DisplayPoint>> {
1780        let start = self.display_map.anchor_before(range.start, Bias::Left, app);
1781        let start_index = self.selection_insertion_index(&start, app);
1782        let pending_selection = self.pending_selection.as_ref().and_then(|s| {
1783            let selection_range = s.display_range(&self.display_map, app);
1784            if selection_range.start <= range.end || selection_range.end <= range.end {
1785                Some(selection_range)
1786            } else {
1787                None
1788            }
1789        });
1790        self.selections(app)[start_index..]
1791            .iter()
1792            .map(move |s| s.display_range(&self.display_map, app))
1793            .take_while(move |r| r.start <= range.end || r.end <= range.end)
1794            .chain(pending_selection)
1795    }
1796
1797    fn selection_insertion_index(&self, start: &Anchor, app: &AppContext) -> usize {
1798        let buffer = self.buffer.read(app);
1799        let selections = self.selections(app);
1800        match selections.binary_search_by(|probe| probe.start.cmp(&start, buffer).unwrap()) {
1801            Ok(index) => index,
1802            Err(index) => {
1803                if index > 0
1804                    && selections[index - 1].end.cmp(&start, buffer).unwrap() == Ordering::Greater
1805                {
1806                    index - 1
1807                } else {
1808                    index
1809                }
1810            }
1811        }
1812    }
1813
1814    fn selections<'a>(&self, app: &'a AppContext) -> &'a [Selection] {
1815        self.buffer
1816            .read(app)
1817            .selections(self.selection_set_id)
1818            .unwrap()
1819    }
1820
1821    fn update_selections(
1822        &mut self,
1823        mut selections: Vec<Selection>,
1824        autoscroll: bool,
1825        ctx: &mut ViewContext<Self>,
1826    ) {
1827        // Merge overlapping selections.
1828        let buffer = self.buffer.read(ctx);
1829        let mut i = 1;
1830        while i < selections.len() {
1831            if selections[i - 1]
1832                .end
1833                .cmp(&selections[i].start, buffer)
1834                .unwrap()
1835                >= Ordering::Equal
1836            {
1837                let removed = selections.remove(i);
1838                if removed.start.cmp(&selections[i - 1].start, buffer).unwrap() < Ordering::Equal {
1839                    selections[i - 1].start = removed.start;
1840                }
1841                if removed.end.cmp(&selections[i - 1].end, buffer).unwrap() > Ordering::Equal {
1842                    selections[i - 1].end = removed.end;
1843                }
1844            } else {
1845                i += 1;
1846            }
1847        }
1848
1849        self.buffer.update(ctx, |buffer, ctx| {
1850            buffer
1851                .update_selection_set(self.selection_set_id, selections, Some(ctx))
1852                .unwrap()
1853        });
1854        self.pause_cursor_blinking(ctx);
1855
1856        if autoscroll {
1857            *self.autoscroll_requested.lock() = true;
1858            ctx.notify();
1859        }
1860
1861        self.add_selections_state = None;
1862    }
1863
1864    fn start_transaction(&self, ctx: &mut ViewContext<Self>) {
1865        self.buffer.update(ctx, |buffer, _| {
1866            buffer
1867                .start_transaction(Some(self.selection_set_id))
1868                .unwrap()
1869        });
1870    }
1871
1872    fn end_transaction(&self, ctx: &mut ViewContext<Self>) {
1873        self.buffer.update(ctx, |buffer, ctx| {
1874            buffer
1875                .end_transaction(Some(self.selection_set_id), Some(ctx))
1876                .unwrap()
1877        });
1878    }
1879
1880    pub fn page_up(&mut self, _: &(), _: &mut ViewContext<Self>) {
1881        log::info!("BufferView::page_up");
1882    }
1883
1884    pub fn page_down(&mut self, _: &(), _: &mut ViewContext<Self>) {
1885        log::info!("BufferView::page_down");
1886    }
1887
1888    pub fn fold(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1889        use super::RangeExt;
1890
1891        let mut fold_ranges = Vec::new();
1892
1893        let app = ctx.as_ref();
1894        for selection in self.selections(app) {
1895            let range = selection.display_range(&self.display_map, app).sorted();
1896            let buffer_start_row = range
1897                .start
1898                .to_buffer_point(&self.display_map, Bias::Left, app)
1899                .row;
1900
1901            for row in (0..=range.end.row()).rev() {
1902                if self.is_line_foldable(row, app)
1903                    && !self.display_map.is_line_folded(row, ctx.as_ref())
1904                {
1905                    let fold_range = self.foldable_range_for_line(row, app);
1906                    if fold_range.end.row >= buffer_start_row {
1907                        fold_ranges.push(fold_range);
1908                        if row <= range.start.row() {
1909                            break;
1910                        }
1911                    }
1912                }
1913            }
1914        }
1915
1916        self.fold_ranges(fold_ranges, ctx);
1917    }
1918
1919    pub fn unfold(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1920        use super::RangeExt;
1921
1922        let app = ctx.as_ref();
1923        let buffer = self.buffer.read(app);
1924        let ranges = self
1925            .selections(app)
1926            .iter()
1927            .map(|s| {
1928                let range = s.display_range(&self.display_map, app).sorted();
1929                let mut start = range
1930                    .start
1931                    .to_buffer_point(&self.display_map, Bias::Left, app);
1932                let mut end = range
1933                    .end
1934                    .to_buffer_point(&self.display_map, Bias::Left, app);
1935                start.column = 0;
1936                end.column = buffer.line_len(end.row);
1937                start..end
1938            })
1939            .collect::<Vec<_>>();
1940        self.unfold_ranges(ranges, ctx);
1941    }
1942
1943    fn is_line_foldable(&self, display_row: u32, app: &AppContext) -> bool {
1944        let max_point = self.max_point(app);
1945        if display_row >= max_point.row() {
1946            false
1947        } else {
1948            let (start_indent, is_blank) = self.display_map.line_indent(display_row, app);
1949            if is_blank {
1950                false
1951            } else {
1952                for display_row in display_row + 1..=max_point.row() {
1953                    let (indent, is_blank) = self.display_map.line_indent(display_row, app);
1954                    if !is_blank {
1955                        return indent > start_indent;
1956                    }
1957                }
1958                false
1959            }
1960        }
1961    }
1962
1963    fn foldable_range_for_line(&self, start_row: u32, app: &AppContext) -> Range<Point> {
1964        let max_point = self.max_point(app);
1965
1966        let (start_indent, _) = self.display_map.line_indent(start_row, app);
1967        let start = DisplayPoint::new(start_row, self.line_len(start_row, app));
1968        let mut end = None;
1969        for row in start_row + 1..=max_point.row() {
1970            let (indent, is_blank) = self.display_map.line_indent(row, app);
1971            if !is_blank && indent <= start_indent {
1972                end = Some(DisplayPoint::new(row - 1, self.line_len(row - 1, app)));
1973                break;
1974            }
1975        }
1976
1977        let end = end.unwrap_or(max_point);
1978        return start.to_buffer_point(&self.display_map, Bias::Left, app)
1979            ..end.to_buffer_point(&self.display_map, Bias::Left, app);
1980    }
1981
1982    pub fn fold_selected_ranges(&mut self, _: &(), ctx: &mut ViewContext<Self>) {
1983        use super::RangeExt;
1984
1985        let buffer = self.buffer.read(ctx);
1986        let ranges = self
1987            .selections(ctx.as_ref())
1988            .iter()
1989            .map(|s| s.range(buffer).sorted())
1990            .collect();
1991        self.fold_ranges(ranges, ctx);
1992    }
1993
1994    fn fold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, ctx: &mut ViewContext<Self>) {
1995        if !ranges.is_empty() {
1996            self.display_map.fold(ranges, ctx.as_ref());
1997            *self.autoscroll_requested.lock() = true;
1998            ctx.notify();
1999        }
2000    }
2001
2002    fn unfold_ranges<T: ToOffset>(&mut self, ranges: Vec<Range<T>>, ctx: &mut ViewContext<Self>) {
2003        if !ranges.is_empty() {
2004            self.display_map.unfold(ranges, ctx.as_ref());
2005            *self.autoscroll_requested.lock() = true;
2006            ctx.notify();
2007        }
2008    }
2009
2010    pub fn line(&self, display_row: u32, ctx: &AppContext) -> String {
2011        self.display_map.line(display_row, ctx)
2012    }
2013
2014    pub fn line_len(&self, display_row: u32, ctx: &AppContext) -> u32 {
2015        self.display_map.line_len(display_row, ctx)
2016    }
2017
2018    pub fn rightmost_point(&self, ctx: &AppContext) -> DisplayPoint {
2019        self.display_map.rightmost_point(ctx)
2020    }
2021
2022    pub fn max_point(&self, ctx: &AppContext) -> DisplayPoint {
2023        self.display_map.max_point(ctx)
2024    }
2025
2026    pub fn text(&self, ctx: &AppContext) -> String {
2027        self.display_map.text(ctx)
2028    }
2029
2030    pub fn font_size(&self) -> f32 {
2031        self.settings.borrow().buffer_font_size
2032    }
2033
2034    pub fn font_ascent(&self, font_cache: &FontCache) -> f32 {
2035        let settings = self.settings.borrow();
2036        let font_id = font_cache.default_font(settings.buffer_font_family);
2037        let ascent = font_cache.metric(font_id, |m| m.ascent);
2038        font_cache.scale_metric(ascent, font_id, settings.buffer_font_size)
2039    }
2040
2041    pub fn font_descent(&self, font_cache: &FontCache) -> f32 {
2042        let settings = self.settings.borrow();
2043        let font_id = font_cache.default_font(settings.buffer_font_family);
2044        let ascent = font_cache.metric(font_id, |m| m.descent);
2045        font_cache.scale_metric(ascent, font_id, settings.buffer_font_size)
2046    }
2047
2048    pub fn line_height(&self, font_cache: &FontCache) -> f32 {
2049        let settings = self.settings.borrow();
2050        let font_id = font_cache.default_font(settings.buffer_font_family);
2051        font_cache.line_height(font_id, settings.buffer_font_size)
2052    }
2053
2054    pub fn em_width(&self, font_cache: &FontCache) -> f32 {
2055        let settings = self.settings.borrow();
2056        let font_id = font_cache.default_font(settings.buffer_font_family);
2057        font_cache.em_width(font_id, settings.buffer_font_size)
2058    }
2059
2060    // TODO: Can we make this not return a result?
2061    pub fn max_line_number_width(
2062        &self,
2063        font_cache: &FontCache,
2064        layout_cache: &TextLayoutCache,
2065        app: &AppContext,
2066    ) -> Result<f32> {
2067        let settings = self.settings.borrow();
2068        let font_size = settings.buffer_font_size;
2069        let font_id =
2070            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
2071        let digit_count = ((self.buffer.read(app).max_point().row + 1) as f32)
2072            .log10()
2073            .floor() as usize
2074            + 1;
2075
2076        Ok(layout_cache
2077            .layout_str(
2078                "1".repeat(digit_count).as_str(),
2079                font_size,
2080                &[(0..digit_count, font_id)],
2081            )
2082            .width)
2083    }
2084
2085    pub fn layout_line_numbers(
2086        &self,
2087        viewport_height: f32,
2088        font_cache: &FontCache,
2089        layout_cache: &TextLayoutCache,
2090        ctx: &AppContext,
2091    ) -> Result<Vec<Arc<text_layout::Line>>> {
2092        let settings = self.settings.borrow();
2093        let font_size = settings.buffer_font_size;
2094        let font_id =
2095            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
2096
2097        let start_row = self.scroll_position().y() as usize;
2098        let end_row = cmp::min(
2099            self.max_point(ctx).row() as usize,
2100            start_row + (viewport_height / self.line_height(font_cache)).ceil() as usize,
2101        );
2102        let line_count = end_row - start_row + 1;
2103
2104        let mut layouts = Vec::with_capacity(line_count);
2105        let mut line_number = String::new();
2106        for buffer_row in self
2107            .display_map
2108            .snapshot(ctx)
2109            .buffer_rows(start_row as u32)
2110            .take(line_count)
2111        {
2112            line_number.clear();
2113            write!(&mut line_number, "{}", buffer_row + 1).unwrap();
2114            layouts.push(layout_cache.layout_str(
2115                &line_number,
2116                font_size,
2117                &[(0..line_number.len(), font_id)],
2118            ));
2119        }
2120
2121        Ok(layouts)
2122    }
2123
2124    pub fn layout_lines(
2125        &self,
2126        mut rows: Range<u32>,
2127        font_cache: &FontCache,
2128        layout_cache: &TextLayoutCache,
2129        ctx: &AppContext,
2130    ) -> Result<Vec<Arc<text_layout::Line>>> {
2131        rows.end = cmp::min(rows.end, self.display_map.max_point(ctx).row() + 1);
2132        if rows.start >= rows.end {
2133            return Ok(Vec::new());
2134        }
2135
2136        let settings = self.settings.borrow();
2137        let font_id =
2138            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
2139        let font_size = settings.buffer_font_size;
2140
2141        let mut layouts = Vec::with_capacity(rows.len());
2142        let mut line = String::new();
2143        let mut row = rows.start;
2144        let snapshot = self.display_map.snapshot(ctx);
2145        let chunks = snapshot.chunks_at(DisplayPoint::new(rows.start, 0), ctx);
2146        for (chunk_row, chunk_line) in chunks
2147            .chain(Some("\n"))
2148            .flat_map(|chunk| chunk.split("\n").enumerate())
2149        {
2150            if chunk_row > 0 {
2151                layouts.push(layout_cache.layout_str(
2152                    &line,
2153                    font_size,
2154                    &[(0..line.len(), font_id)],
2155                ));
2156                line.clear();
2157                row += 1;
2158                if row == rows.end {
2159                    break;
2160                }
2161            }
2162            line.push_str(chunk_line);
2163        }
2164
2165        Ok(layouts)
2166    }
2167
2168    pub fn layout_line(
2169        &self,
2170        row: u32,
2171        font_cache: &FontCache,
2172        layout_cache: &TextLayoutCache,
2173        app: &AppContext,
2174    ) -> Result<Arc<text_layout::Line>> {
2175        let settings = self.settings.borrow();
2176        let font_id =
2177            font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?;
2178
2179        let line = self.line(row, app);
2180
2181        Ok(layout_cache.layout_str(
2182            &line,
2183            settings.buffer_font_size,
2184            &[(0..self.line_len(row, app) as usize, font_id)],
2185        ))
2186    }
2187
2188    fn next_blink_epoch(&mut self) -> usize {
2189        self.blink_epoch += 1;
2190        self.blink_epoch
2191    }
2192
2193    fn pause_cursor_blinking(&mut self, ctx: &mut ViewContext<Self>) {
2194        self.cursors_visible = true;
2195        ctx.notify();
2196
2197        let epoch = self.next_blink_epoch();
2198        ctx.spawn(|this, mut ctx| async move {
2199            Timer::after(CURSOR_BLINK_INTERVAL).await;
2200            this.update(&mut ctx, |this, ctx| {
2201                this.resume_cursor_blinking(epoch, ctx);
2202            })
2203        })
2204        .detach();
2205    }
2206
2207    fn resume_cursor_blinking(&mut self, epoch: usize, ctx: &mut ViewContext<Self>) {
2208        if epoch == self.blink_epoch {
2209            self.blinking_paused = false;
2210            self.blink_cursors(epoch, ctx);
2211        }
2212    }
2213
2214    fn blink_cursors(&mut self, epoch: usize, ctx: &mut ViewContext<Self>) {
2215        if epoch == self.blink_epoch && self.focused && !self.blinking_paused {
2216            self.cursors_visible = !self.cursors_visible;
2217            ctx.notify();
2218
2219            let epoch = self.next_blink_epoch();
2220            ctx.spawn(|this, mut ctx| async move {
2221                Timer::after(CURSOR_BLINK_INTERVAL).await;
2222                this.update(&mut ctx, |this, ctx| this.blink_cursors(epoch, ctx));
2223            })
2224            .detach();
2225        }
2226    }
2227
2228    pub fn cursors_visible(&self) -> bool {
2229        self.cursors_visible
2230    }
2231
2232    fn on_buffer_changed(&mut self, _: ModelHandle<Buffer>, ctx: &mut ViewContext<Self>) {
2233        ctx.notify();
2234    }
2235
2236    fn on_buffer_event(
2237        &mut self,
2238        _: ModelHandle<Buffer>,
2239        event: &buffer::Event,
2240        ctx: &mut ViewContext<Self>,
2241    ) {
2242        match event {
2243            buffer::Event::Edited => ctx.emit(Event::Edited),
2244            buffer::Event::Dirtied => ctx.emit(Event::Dirtied),
2245            buffer::Event::Saved => ctx.emit(Event::Saved),
2246            buffer::Event::FileHandleChanged => ctx.emit(Event::FileHandleChanged),
2247            buffer::Event::Reloaded => ctx.emit(Event::FileHandleChanged),
2248        }
2249    }
2250}
2251
2252pub enum Event {
2253    Activate,
2254    Edited,
2255    Blurred,
2256    Dirtied,
2257    Saved,
2258    FileHandleChanged,
2259}
2260
2261impl Entity for BufferView {
2262    type Event = Event;
2263}
2264
2265impl View for BufferView {
2266    fn render<'a>(&self, _: &AppContext) -> ElementBox {
2267        BufferElement::new(self.handle.clone()).boxed()
2268    }
2269
2270    fn ui_name() -> &'static str {
2271        "BufferView"
2272    }
2273
2274    fn on_focus(&mut self, ctx: &mut ViewContext<Self>) {
2275        self.focused = true;
2276        self.blink_cursors(self.blink_epoch, ctx);
2277    }
2278
2279    fn on_blur(&mut self, ctx: &mut ViewContext<Self>) {
2280        self.focused = false;
2281        self.cursors_visible = false;
2282        ctx.emit(Event::Blurred);
2283        ctx.notify();
2284    }
2285}
2286
2287impl workspace::Item for Buffer {
2288    type View = BufferView;
2289
2290    fn file(&self) -> Option<&FileHandle> {
2291        self.file()
2292    }
2293
2294    fn build_view(
2295        handle: ModelHandle<Self>,
2296        settings: watch::Receiver<Settings>,
2297        ctx: &mut ViewContext<Self::View>,
2298    ) -> Self::View {
2299        BufferView::for_buffer(handle, settings, ctx)
2300    }
2301}
2302
2303impl workspace::ItemView for BufferView {
2304    fn should_activate_item_on_event(event: &Self::Event) -> bool {
2305        matches!(event, Event::Activate)
2306    }
2307
2308    fn should_update_tab_on_event(event: &Self::Event) -> bool {
2309        matches!(
2310            event,
2311            Event::Saved | Event::Dirtied | Event::FileHandleChanged
2312        )
2313    }
2314
2315    fn title(&self, app: &AppContext) -> std::string::String {
2316        let filename = self
2317            .buffer
2318            .read(app)
2319            .file()
2320            .and_then(|file| file.file_name(app));
2321        if let Some(name) = filename {
2322            name.to_string_lossy().into()
2323        } else {
2324            "untitled".into()
2325        }
2326    }
2327
2328    fn entry_id(&self, ctx: &AppContext) -> Option<(usize, Arc<Path>)> {
2329        self.buffer.read(ctx).file().map(|file| file.entry_id())
2330    }
2331
2332    fn clone_on_split(&self, ctx: &mut ViewContext<Self>) -> Option<Self>
2333    where
2334        Self: Sized,
2335    {
2336        let clone = BufferView::for_buffer(self.buffer.clone(), self.settings.clone(), ctx);
2337        *clone.scroll_position.lock() = *self.scroll_position.lock();
2338        Some(clone)
2339    }
2340
2341    fn save(
2342        &mut self,
2343        new_file: Option<FileHandle>,
2344        ctx: &mut ViewContext<Self>,
2345    ) -> Task<Result<()>> {
2346        self.buffer.update(ctx, |b, ctx| b.save(new_file, ctx))
2347    }
2348
2349    fn is_dirty(&self, ctx: &AppContext) -> bool {
2350        self.buffer.read(ctx).is_dirty()
2351    }
2352
2353    fn has_conflict(&self, ctx: &AppContext) -> bool {
2354        self.buffer.read(ctx).has_conflict()
2355    }
2356}
2357
2358#[cfg(test)]
2359mod tests {
2360    use super::*;
2361    use crate::{editor::Point, settings, test::sample_text};
2362    use unindent::Unindent;
2363
2364    #[gpui::test]
2365    fn test_selection_with_mouse(app: &mut gpui::MutableAppContext) {
2366        let buffer = app.add_model(|ctx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", ctx));
2367        let settings = settings::channel(&app.font_cache()).unwrap().1;
2368        let (_, buffer_view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
2369
2370        buffer_view.update(app, |view, ctx| {
2371            view.begin_selection(DisplayPoint::new(2, 2), false, ctx);
2372        });
2373
2374        let view = buffer_view.read(app);
2375        let selections = view
2376            .selections_in_range(
2377                DisplayPoint::zero()..view.max_point(app.as_ref()),
2378                app.as_ref(),
2379            )
2380            .collect::<Vec<_>>();
2381        assert_eq!(
2382            selections,
2383            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
2384        );
2385
2386        buffer_view.update(app, |view, ctx| {
2387            view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), ctx);
2388        });
2389
2390        let view = buffer_view.read(app);
2391        let selections = view
2392            .selections_in_range(
2393                DisplayPoint::zero()..view.max_point(app.as_ref()),
2394                app.as_ref(),
2395            )
2396            .collect::<Vec<_>>();
2397        assert_eq!(
2398            selections,
2399            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
2400        );
2401
2402        buffer_view.update(app, |view, ctx| {
2403            view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), ctx);
2404        });
2405
2406        let view = buffer_view.read(app);
2407        let selections = view
2408            .selections_in_range(
2409                DisplayPoint::zero()..view.max_point(app.as_ref()),
2410                app.as_ref(),
2411            )
2412            .collect::<Vec<_>>();
2413        assert_eq!(
2414            selections,
2415            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
2416        );
2417
2418        buffer_view.update(app, |view, ctx| {
2419            view.end_selection(ctx);
2420            view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), ctx);
2421        });
2422
2423        let view = buffer_view.read(app);
2424        let selections = view
2425            .selections_in_range(
2426                DisplayPoint::zero()..view.max_point(app.as_ref()),
2427                app.as_ref(),
2428            )
2429            .collect::<Vec<_>>();
2430        assert_eq!(
2431            selections,
2432            [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)]
2433        );
2434
2435        buffer_view.update(app, |view, ctx| {
2436            view.begin_selection(DisplayPoint::new(3, 3), true, ctx);
2437            view.update_selection(DisplayPoint::new(0, 0), Vector2F::zero(), ctx);
2438        });
2439
2440        let view = buffer_view.read(app);
2441        let selections = view
2442            .selections_in_range(
2443                DisplayPoint::zero()..view.max_point(app.as_ref()),
2444                app.as_ref(),
2445            )
2446            .collect::<Vec<_>>();
2447        assert_eq!(
2448            selections,
2449            [
2450                DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1),
2451                DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)
2452            ]
2453        );
2454
2455        buffer_view.update(app, |view, ctx| {
2456            view.end_selection(ctx);
2457        });
2458
2459        let view = buffer_view.read(app);
2460        let selections = view
2461            .selections_in_range(
2462                DisplayPoint::zero()..view.max_point(app.as_ref()),
2463                app.as_ref(),
2464            )
2465            .collect::<Vec<_>>();
2466        assert_eq!(
2467            selections,
2468            [DisplayPoint::new(3, 3)..DisplayPoint::new(0, 0)]
2469        );
2470    }
2471
2472    #[gpui::test]
2473    fn test_canceling_pending_selection(app: &mut gpui::MutableAppContext) {
2474        let buffer = app.add_model(|ctx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", ctx));
2475        let settings = settings::channel(&app.font_cache()).unwrap().1;
2476        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
2477
2478        view.update(app, |view, ctx| {
2479            view.begin_selection(DisplayPoint::new(2, 2), false, ctx);
2480        });
2481        assert_eq!(
2482            view.read(app).selection_ranges(app.as_ref()),
2483            [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
2484        );
2485
2486        view.update(app, |view, ctx| {
2487            view.update_selection(DisplayPoint::new(3, 3), Vector2F::zero(), ctx);
2488        });
2489        assert_eq!(
2490            view.read(app).selection_ranges(app.as_ref()),
2491            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
2492        );
2493
2494        view.update(app, |view, ctx| {
2495            view.cancel(&(), ctx);
2496            view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), ctx);
2497        });
2498        assert_eq!(
2499            view.read(app).selection_ranges(app.as_ref()),
2500            [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
2501        );
2502    }
2503
2504    #[gpui::test]
2505    fn test_cancel(app: &mut gpui::MutableAppContext) {
2506        let buffer = app.add_model(|ctx| Buffer::new(0, "aaaaaa\nbbbbbb\ncccccc\ndddddd\n", ctx));
2507        let settings = settings::channel(&app.font_cache()).unwrap().1;
2508        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
2509
2510        view.update(app, |view, ctx| {
2511            view.begin_selection(DisplayPoint::new(3, 4), false, ctx);
2512            view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), ctx);
2513            view.end_selection(ctx);
2514
2515            view.begin_selection(DisplayPoint::new(0, 1), true, ctx);
2516            view.update_selection(DisplayPoint::new(0, 3), Vector2F::zero(), ctx);
2517            view.end_selection(ctx);
2518        });
2519        assert_eq!(
2520            view.read(app).selection_ranges(app.as_ref()),
2521            [
2522                DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
2523                DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1),
2524            ]
2525        );
2526
2527        view.update(app, |view, ctx| view.cancel(&(), ctx));
2528        assert_eq!(
2529            view.read(app).selection_ranges(app.as_ref()),
2530            [DisplayPoint::new(3, 4)..DisplayPoint::new(1, 1)]
2531        );
2532
2533        view.update(app, |view, ctx| view.cancel(&(), ctx));
2534        assert_eq!(
2535            view.read(app).selection_ranges(app.as_ref()),
2536            [DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1)]
2537        );
2538    }
2539
2540    #[gpui::test]
2541    fn test_layout_line_numbers(app: &mut gpui::MutableAppContext) {
2542        let layout_cache = TextLayoutCache::new(app.platform().fonts());
2543        let font_cache = app.font_cache().clone();
2544
2545        let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(6, 6), ctx));
2546
2547        let settings = settings::channel(&font_cache).unwrap().1;
2548        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
2549
2550        let layouts = view
2551            .read(app)
2552            .layout_line_numbers(1000.0, &font_cache, &layout_cache, app.as_ref())
2553            .unwrap();
2554        assert_eq!(layouts.len(), 6);
2555    }
2556
2557    #[gpui::test]
2558    fn test_fold(app: &mut gpui::MutableAppContext) {
2559        let buffer = app.add_model(|ctx| {
2560            Buffer::new(
2561                0,
2562                "
2563                    impl Foo {
2564                        // Hello!
2565
2566                        fn a() {
2567                            1
2568                        }
2569
2570                        fn b() {
2571                            2
2572                        }
2573
2574                        fn c() {
2575                            3
2576                        }
2577                    }
2578                "
2579                .unindent(),
2580                ctx,
2581            )
2582        });
2583        let settings = settings::channel(&app.font_cache()).unwrap().1;
2584        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
2585
2586        view.update(app, |view, ctx| {
2587            view.select_display_ranges(&[DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)], ctx)
2588                .unwrap();
2589            view.fold(&(), ctx);
2590            assert_eq!(
2591                view.text(ctx.as_ref()),
2592                "
2593                    impl Foo {
2594                        // Hello!
2595
2596                        fn a() {
2597                            1
2598                        }
2599
2600                        fn b() {…
2601                        }
2602
2603                        fn c() {…
2604                        }
2605                    }
2606                "
2607                .unindent(),
2608            );
2609
2610            view.fold(&(), ctx);
2611            assert_eq!(
2612                view.text(ctx.as_ref()),
2613                "
2614                    impl Foo {…
2615                    }
2616                "
2617                .unindent(),
2618            );
2619
2620            view.unfold(&(), ctx);
2621            assert_eq!(
2622                view.text(ctx.as_ref()),
2623                "
2624                    impl Foo {
2625                        // Hello!
2626
2627                        fn a() {
2628                            1
2629                        }
2630
2631                        fn b() {…
2632                        }
2633
2634                        fn c() {…
2635                        }
2636                    }
2637                "
2638                .unindent(),
2639            );
2640
2641            view.unfold(&(), ctx);
2642            assert_eq!(view.text(ctx.as_ref()), buffer.read(ctx).text());
2643        });
2644    }
2645
2646    #[gpui::test]
2647    fn test_move_cursor(app: &mut gpui::MutableAppContext) {
2648        let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(6, 6), ctx));
2649        let settings = settings::channel(&app.font_cache()).unwrap().1;
2650        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
2651
2652        buffer.update(app, |buffer, ctx| {
2653            buffer
2654                .edit(
2655                    vec![
2656                        Point::new(1, 0)..Point::new(1, 0),
2657                        Point::new(1, 1)..Point::new(1, 1),
2658                    ],
2659                    "\t",
2660                    Some(ctx),
2661                )
2662                .unwrap();
2663        });
2664
2665        view.update(app, |view, ctx| {
2666            assert_eq!(
2667                view.selection_ranges(ctx.as_ref()),
2668                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
2669            );
2670
2671            view.move_down(&(), ctx);
2672            assert_eq!(
2673                view.selection_ranges(ctx.as_ref()),
2674                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
2675            );
2676
2677            view.move_right(&(), ctx);
2678            assert_eq!(
2679                view.selection_ranges(ctx.as_ref()),
2680                &[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4)]
2681            );
2682
2683            view.move_left(&(), ctx);
2684            assert_eq!(
2685                view.selection_ranges(ctx.as_ref()),
2686                &[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)]
2687            );
2688
2689            view.move_up(&(), ctx);
2690            assert_eq!(
2691                view.selection_ranges(ctx.as_ref()),
2692                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
2693            );
2694
2695            view.move_to_end(&(), ctx);
2696            assert_eq!(
2697                view.selection_ranges(ctx.as_ref()),
2698                &[DisplayPoint::new(5, 6)..DisplayPoint::new(5, 6)]
2699            );
2700
2701            view.move_to_beginning(&(), ctx);
2702            assert_eq!(
2703                view.selection_ranges(ctx.as_ref()),
2704                &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)]
2705            );
2706
2707            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2)], ctx)
2708                .unwrap();
2709            view.select_to_beginning(&(), ctx);
2710            assert_eq!(
2711                view.selection_ranges(ctx.as_ref()),
2712                &[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 0)]
2713            );
2714
2715            view.select_to_end(&(), ctx);
2716            assert_eq!(
2717                view.selection_ranges(ctx.as_ref()),
2718                &[DisplayPoint::new(0, 1)..DisplayPoint::new(5, 6)]
2719            );
2720        });
2721    }
2722
2723    #[gpui::test]
2724    fn test_move_cursor_multibyte(app: &mut gpui::MutableAppContext) {
2725        let buffer = app.add_model(|ctx| Buffer::new(0, "ⓐⓑⓒⓓⓔ\nabcde\nαβγδε\n", ctx));
2726        let settings = settings::channel(&app.font_cache()).unwrap().1;
2727        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
2728
2729        assert_eq!('ⓐ'.len_utf8(), 3);
2730        assert_eq!('α'.len_utf8(), 2);
2731
2732        view.update(app, |view, ctx| {
2733            view.fold_ranges(
2734                vec![
2735                    Point::new(0, 6)..Point::new(0, 12),
2736                    Point::new(1, 2)..Point::new(1, 4),
2737                    Point::new(2, 4)..Point::new(2, 8),
2738                ],
2739                ctx,
2740            );
2741            assert_eq!(view.text(ctx.as_ref()), "ⓐⓑ…ⓔ\nab…e\nαβ…ε\n");
2742
2743            view.move_right(&(), ctx);
2744            assert_eq!(
2745                view.selection_ranges(ctx.as_ref()),
2746                &[empty_range(0, "".len())]
2747            );
2748            view.move_right(&(), ctx);
2749            assert_eq!(
2750                view.selection_ranges(ctx.as_ref()),
2751                &[empty_range(0, "ⓐⓑ".len())]
2752            );
2753            view.move_right(&(), ctx);
2754            assert_eq!(
2755                view.selection_ranges(ctx.as_ref()),
2756                &[empty_range(0, "ⓐⓑ…".len())]
2757            );
2758
2759            view.move_down(&(), ctx);
2760            assert_eq!(
2761                view.selection_ranges(ctx.as_ref()),
2762                &[empty_range(1, "ab…".len())]
2763            );
2764            view.move_left(&(), ctx);
2765            assert_eq!(
2766                view.selection_ranges(ctx.as_ref()),
2767                &[empty_range(1, "ab".len())]
2768            );
2769            view.move_left(&(), ctx);
2770            assert_eq!(
2771                view.selection_ranges(ctx.as_ref()),
2772                &[empty_range(1, "a".len())]
2773            );
2774
2775            view.move_down(&(), ctx);
2776            assert_eq!(
2777                view.selection_ranges(ctx.as_ref()),
2778                &[empty_range(2, "α".len())]
2779            );
2780            view.move_right(&(), ctx);
2781            assert_eq!(
2782                view.selection_ranges(ctx.as_ref()),
2783                &[empty_range(2, "αβ".len())]
2784            );
2785            view.move_right(&(), ctx);
2786            assert_eq!(
2787                view.selection_ranges(ctx.as_ref()),
2788                &[empty_range(2, "αβ…".len())]
2789            );
2790            view.move_right(&(), ctx);
2791            assert_eq!(
2792                view.selection_ranges(ctx.as_ref()),
2793                &[empty_range(2, "αβ…ε".len())]
2794            );
2795
2796            view.move_up(&(), ctx);
2797            assert_eq!(
2798                view.selection_ranges(ctx.as_ref()),
2799                &[empty_range(1, "ab…e".len())]
2800            );
2801            view.move_up(&(), ctx);
2802            assert_eq!(
2803                view.selection_ranges(ctx.as_ref()),
2804                &[empty_range(0, "ⓐⓑ…ⓔ".len())]
2805            );
2806            view.move_left(&(), ctx);
2807            assert_eq!(
2808                view.selection_ranges(ctx.as_ref()),
2809                &[empty_range(0, "ⓐⓑ…".len())]
2810            );
2811            view.move_left(&(), ctx);
2812            assert_eq!(
2813                view.selection_ranges(ctx.as_ref()),
2814                &[empty_range(0, "ⓐⓑ".len())]
2815            );
2816            view.move_left(&(), ctx);
2817            assert_eq!(
2818                view.selection_ranges(ctx.as_ref()),
2819                &[empty_range(0, "".len())]
2820            );
2821        });
2822    }
2823
2824    #[gpui::test]
2825    fn test_move_cursor_different_line_lengths(app: &mut gpui::MutableAppContext) {
2826        let buffer = app.add_model(|ctx| Buffer::new(0, "ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", ctx));
2827        let settings = settings::channel(&app.font_cache()).unwrap().1;
2828        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
2829        view.update(app, |view, ctx| {
2830            view.select_display_ranges(&[empty_range(0, "ⓐⓑⓒⓓⓔ".len())], ctx)
2831                .unwrap();
2832
2833            view.move_down(&(), ctx);
2834            assert_eq!(
2835                view.selection_ranges(ctx.as_ref()),
2836                &[empty_range(1, "abcd".len())]
2837            );
2838
2839            view.move_down(&(), ctx);
2840            assert_eq!(
2841                view.selection_ranges(ctx.as_ref()),
2842                &[empty_range(2, "αβγ".len())]
2843            );
2844
2845            view.move_down(&(), ctx);
2846            assert_eq!(
2847                view.selection_ranges(ctx.as_ref()),
2848                &[empty_range(3, "abcd".len())]
2849            );
2850
2851            view.move_down(&(), ctx);
2852            assert_eq!(
2853                view.selection_ranges(ctx.as_ref()),
2854                &[empty_range(4, "ⓐⓑⓒⓓⓔ".len())]
2855            );
2856
2857            view.move_up(&(), ctx);
2858            assert_eq!(
2859                view.selection_ranges(ctx.as_ref()),
2860                &[empty_range(3, "abcd".len())]
2861            );
2862
2863            view.move_up(&(), ctx);
2864            assert_eq!(
2865                view.selection_ranges(ctx.as_ref()),
2866                &[empty_range(2, "αβγ".len())]
2867            );
2868        });
2869    }
2870
2871    #[gpui::test]
2872    fn test_beginning_end_of_line(app: &mut gpui::MutableAppContext) {
2873        let buffer = app.add_model(|ctx| Buffer::new(0, "abc\n  def", ctx));
2874        let settings = settings::channel(&app.font_cache()).unwrap().1;
2875        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
2876        view.update(app, |view, ctx| {
2877            view.select_display_ranges(
2878                &[
2879                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
2880                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
2881                ],
2882                ctx,
2883            )
2884            .unwrap();
2885        });
2886
2887        view.update(app, |view, ctx| view.move_to_beginning_of_line(&(), ctx));
2888        assert_eq!(
2889            view.read(app).selection_ranges(app.as_ref()),
2890            &[
2891                DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
2892                DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
2893            ]
2894        );
2895
2896        view.update(app, |view, ctx| view.move_to_beginning_of_line(&(), ctx));
2897        assert_eq!(
2898            view.read(app).selection_ranges(app.as_ref()),
2899            &[
2900                DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
2901                DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
2902            ]
2903        );
2904
2905        view.update(app, |view, ctx| view.move_to_beginning_of_line(&(), ctx));
2906        assert_eq!(
2907            view.read(app).selection_ranges(app.as_ref()),
2908            &[
2909                DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
2910                DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
2911            ]
2912        );
2913
2914        view.update(app, |view, ctx| view.move_to_end_of_line(&(), ctx));
2915        assert_eq!(
2916            view.read(app).selection_ranges(app.as_ref()),
2917            &[
2918                DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
2919                DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
2920            ]
2921        );
2922
2923        // Moving to the end of line again is a no-op.
2924        view.update(app, |view, ctx| view.move_to_end_of_line(&(), ctx));
2925        assert_eq!(
2926            view.read(app).selection_ranges(app.as_ref()),
2927            &[
2928                DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
2929                DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
2930            ]
2931        );
2932
2933        view.update(app, |view, ctx| {
2934            view.move_left(&(), ctx);
2935            view.select_to_beginning_of_line(&true, ctx);
2936        });
2937        assert_eq!(
2938            view.read(app).selection_ranges(app.as_ref()),
2939            &[
2940                DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
2941                DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
2942            ]
2943        );
2944
2945        view.update(app, |view, ctx| {
2946            view.select_to_beginning_of_line(&true, ctx)
2947        });
2948        assert_eq!(
2949            view.read(app).selection_ranges(app.as_ref()),
2950            &[
2951                DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
2952                DisplayPoint::new(1, 4)..DisplayPoint::new(1, 0),
2953            ]
2954        );
2955
2956        view.update(app, |view, ctx| {
2957            view.select_to_beginning_of_line(&true, ctx)
2958        });
2959        assert_eq!(
2960            view.read(app).selection_ranges(app.as_ref()),
2961            &[
2962                DisplayPoint::new(0, 2)..DisplayPoint::new(0, 0),
2963                DisplayPoint::new(1, 4)..DisplayPoint::new(1, 2),
2964            ]
2965        );
2966
2967        view.update(app, |view, ctx| view.select_to_end_of_line(&(), ctx));
2968        assert_eq!(
2969            view.read(app).selection_ranges(app.as_ref()),
2970            &[
2971                DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3),
2972                DisplayPoint::new(1, 4)..DisplayPoint::new(1, 5),
2973            ]
2974        );
2975
2976        view.update(app, |view, ctx| view.delete_to_end_of_line(&(), ctx));
2977        assert_eq!(view.read(app).text(app.as_ref()), "ab\n  de");
2978        assert_eq!(
2979            view.read(app).selection_ranges(app.as_ref()),
2980            &[
2981                DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
2982                DisplayPoint::new(1, 4)..DisplayPoint::new(1, 4),
2983            ]
2984        );
2985
2986        view.update(app, |view, ctx| view.delete_to_beginning_of_line(&(), ctx));
2987        assert_eq!(view.read(app).text(app.as_ref()), "\n");
2988        assert_eq!(
2989            view.read(app).selection_ranges(app.as_ref()),
2990            &[
2991                DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
2992                DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
2993            ]
2994        );
2995    }
2996
2997    #[gpui::test]
2998    fn test_prev_next_word_boundary(app: &mut gpui::MutableAppContext) {
2999        let buffer =
3000            app.add_model(|ctx| Buffer::new(0, "use std::str::{foo, bar}\n\n  {baz.qux()}", ctx));
3001        let settings = settings::channel(&app.font_cache()).unwrap().1;
3002        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
3003        view.update(app, |view, ctx| {
3004            view.select_display_ranges(
3005                &[
3006                    DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11),
3007                    DisplayPoint::new(2, 4)..DisplayPoint::new(2, 4),
3008                ],
3009                ctx,
3010            )
3011            .unwrap();
3012        });
3013
3014        view.update(app, |view, ctx| {
3015            view.move_to_previous_word_boundary(&(), ctx)
3016        });
3017        assert_eq!(
3018            view.read(app).selection_ranges(app.as_ref()),
3019            &[
3020                DisplayPoint::new(0, 9)..DisplayPoint::new(0, 9),
3021                DisplayPoint::new(2, 3)..DisplayPoint::new(2, 3),
3022            ]
3023        );
3024
3025        view.update(app, |view, ctx| {
3026            view.move_to_previous_word_boundary(&(), ctx)
3027        });
3028        assert_eq!(
3029            view.read(app).selection_ranges(app.as_ref()),
3030            &[
3031                DisplayPoint::new(0, 7)..DisplayPoint::new(0, 7),
3032                DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2),
3033            ]
3034        );
3035
3036        view.update(app, |view, ctx| {
3037            view.move_to_previous_word_boundary(&(), ctx)
3038        });
3039        assert_eq!(
3040            view.read(app).selection_ranges(app.as_ref()),
3041            &[
3042                DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
3043                DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
3044            ]
3045        );
3046
3047        view.update(app, |view, ctx| {
3048            view.move_to_previous_word_boundary(&(), ctx)
3049        });
3050        assert_eq!(
3051            view.read(app).selection_ranges(app.as_ref()),
3052            &[
3053                DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3054                DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3055            ]
3056        );
3057
3058        view.update(app, |view, ctx| {
3059            view.move_to_previous_word_boundary(&(), ctx)
3060        });
3061        assert_eq!(
3062            view.read(app).selection_ranges(app.as_ref()),
3063            &[
3064                DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3065                DisplayPoint::new(0, 24)..DisplayPoint::new(0, 24),
3066            ]
3067        );
3068
3069        view.update(app, |view, ctx| {
3070            view.move_to_previous_word_boundary(&(), ctx)
3071        });
3072        assert_eq!(
3073            view.read(app).selection_ranges(app.as_ref()),
3074            &[
3075                DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3076                DisplayPoint::new(0, 23)..DisplayPoint::new(0, 23),
3077            ]
3078        );
3079
3080        view.update(app, |view, ctx| view.move_to_next_word_boundary(&(), ctx));
3081        assert_eq!(
3082            view.read(app).selection_ranges(app.as_ref()),
3083            &[
3084                DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3085                DisplayPoint::new(0, 24)..DisplayPoint::new(0, 24),
3086            ]
3087        );
3088
3089        view.update(app, |view, ctx| view.move_to_next_word_boundary(&(), ctx));
3090        assert_eq!(
3091            view.read(app).selection_ranges(app.as_ref()),
3092            &[
3093                DisplayPoint::new(0, 4)..DisplayPoint::new(0, 4),
3094                DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3095            ]
3096        );
3097
3098        view.update(app, |view, ctx| view.move_to_next_word_boundary(&(), ctx));
3099        assert_eq!(
3100            view.read(app).selection_ranges(app.as_ref()),
3101            &[
3102                DisplayPoint::new(0, 7)..DisplayPoint::new(0, 7),
3103                DisplayPoint::new(2, 0)..DisplayPoint::new(2, 0),
3104            ]
3105        );
3106
3107        view.update(app, |view, ctx| view.move_to_next_word_boundary(&(), ctx));
3108        assert_eq!(
3109            view.read(app).selection_ranges(app.as_ref()),
3110            &[
3111                DisplayPoint::new(0, 9)..DisplayPoint::new(0, 9),
3112                DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2),
3113            ]
3114        );
3115
3116        view.update(app, |view, ctx| {
3117            view.move_right(&(), ctx);
3118            view.select_to_previous_word_boundary(&(), ctx);
3119        });
3120        assert_eq!(
3121            view.read(app).selection_ranges(app.as_ref()),
3122            &[
3123                DisplayPoint::new(0, 10)..DisplayPoint::new(0, 9),
3124                DisplayPoint::new(2, 3)..DisplayPoint::new(2, 2),
3125            ]
3126        );
3127
3128        view.update(app, |view, ctx| {
3129            view.select_to_previous_word_boundary(&(), ctx)
3130        });
3131        assert_eq!(
3132            view.read(app).selection_ranges(app.as_ref()),
3133            &[
3134                DisplayPoint::new(0, 10)..DisplayPoint::new(0, 7),
3135                DisplayPoint::new(2, 3)..DisplayPoint::new(2, 0),
3136            ]
3137        );
3138
3139        view.update(app, |view, ctx| view.select_to_next_word_boundary(&(), ctx));
3140        assert_eq!(
3141            view.read(app).selection_ranges(app.as_ref()),
3142            &[
3143                DisplayPoint::new(0, 10)..DisplayPoint::new(0, 9),
3144                DisplayPoint::new(2, 3)..DisplayPoint::new(2, 2),
3145            ]
3146        );
3147
3148        view.update(app, |view, ctx| view.delete_to_next_word_boundary(&(), ctx));
3149        assert_eq!(
3150            view.read(app).text(app.as_ref()),
3151            "use std::s::{foo, bar}\n\n  {az.qux()}"
3152        );
3153        assert_eq!(
3154            view.read(app).selection_ranges(app.as_ref()),
3155            &[
3156                DisplayPoint::new(0, 10)..DisplayPoint::new(0, 10),
3157                DisplayPoint::new(2, 3)..DisplayPoint::new(2, 3),
3158            ]
3159        );
3160
3161        view.update(app, |view, ctx| {
3162            view.delete_to_previous_word_boundary(&(), ctx)
3163        });
3164        assert_eq!(
3165            view.read(app).text(app.as_ref()),
3166            "use std::::{foo, bar}\n\n  az.qux()}"
3167        );
3168        assert_eq!(
3169            view.read(app).selection_ranges(app.as_ref()),
3170            &[
3171                DisplayPoint::new(0, 9)..DisplayPoint::new(0, 9),
3172                DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2),
3173            ]
3174        );
3175    }
3176
3177    #[gpui::test]
3178    fn test_backspace(app: &mut gpui::MutableAppContext) {
3179        let buffer = app.add_model(|ctx| {
3180            Buffer::new(
3181                0,
3182                "one two three\nfour five six\nseven eight nine\nten\n",
3183                ctx,
3184            )
3185        });
3186        let settings = settings::channel(&app.font_cache()).unwrap().1;
3187        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
3188
3189        view.update(app, |view, ctx| {
3190            view.select_display_ranges(
3191                &[
3192                    // an empty selection - the preceding character is deleted
3193                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3194                    // one character selected - it is deleted
3195                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
3196                    // a line suffix selected - it is deleted
3197                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
3198                ],
3199                ctx,
3200            )
3201            .unwrap();
3202            view.backspace(&(), ctx);
3203        });
3204
3205        assert_eq!(
3206            buffer.read(app).text(),
3207            "oe two three\nfou five six\nseven ten\n"
3208        );
3209    }
3210
3211    #[gpui::test]
3212    fn test_delete(app: &mut gpui::MutableAppContext) {
3213        let buffer = app.add_model(|ctx| {
3214            Buffer::new(
3215                0,
3216                "one two three\nfour five six\nseven eight nine\nten\n",
3217                ctx,
3218            )
3219        });
3220        let settings = settings::channel(&app.font_cache()).unwrap().1;
3221        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx));
3222
3223        view.update(app, |view, ctx| {
3224            view.select_display_ranges(
3225                &[
3226                    // an empty selection - the following character is deleted
3227                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3228                    // one character selected - it is deleted
3229                    DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
3230                    // a line suffix selected - it is deleted
3231                    DisplayPoint::new(2, 6)..DisplayPoint::new(3, 0),
3232                ],
3233                ctx,
3234            )
3235            .unwrap();
3236            view.delete(&(), ctx);
3237        });
3238
3239        assert_eq!(
3240            buffer.read(app).text(),
3241            "on two three\nfou five six\nseven ten\n"
3242        );
3243    }
3244
3245    #[gpui::test]
3246    fn test_delete_line(app: &mut gpui::MutableAppContext) {
3247        let settings = settings::channel(&app.font_cache()).unwrap().1;
3248        let buffer = app.add_model(|ctx| Buffer::new(0, "abc\ndef\nghi\n", ctx));
3249        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
3250        view.update(app, |view, ctx| {
3251            view.select_display_ranges(
3252                &[
3253                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3254                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
3255                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
3256                ],
3257                ctx,
3258            )
3259            .unwrap();
3260            view.delete_line(&(), ctx);
3261        });
3262        assert_eq!(view.read(app).text(app.as_ref()), "ghi");
3263        assert_eq!(
3264            view.read(app).selection_ranges(app.as_ref()),
3265            vec![
3266                DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0),
3267                DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)
3268            ]
3269        );
3270
3271        let settings = settings::channel(&app.font_cache()).unwrap().1;
3272        let buffer = app.add_model(|ctx| Buffer::new(0, "abc\ndef\nghi\n", ctx));
3273        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
3274        view.update(app, |view, ctx| {
3275            view.select_display_ranges(&[DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)], ctx)
3276                .unwrap();
3277            view.delete_line(&(), ctx);
3278        });
3279        assert_eq!(view.read(app).text(app.as_ref()), "ghi\n");
3280        assert_eq!(
3281            view.read(app).selection_ranges(app.as_ref()),
3282            vec![DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)]
3283        );
3284    }
3285
3286    #[gpui::test]
3287    fn test_duplicate_line(app: &mut gpui::MutableAppContext) {
3288        let settings = settings::channel(&app.font_cache()).unwrap().1;
3289        let buffer = app.add_model(|ctx| Buffer::new(0, "abc\ndef\nghi\n", ctx));
3290        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
3291        view.update(app, |view, ctx| {
3292            view.select_display_ranges(
3293                &[
3294                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
3295                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3296                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3297                    DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
3298                ],
3299                ctx,
3300            )
3301            .unwrap();
3302            view.duplicate_line(&(), ctx);
3303        });
3304        assert_eq!(
3305            view.read(app).text(app.as_ref()),
3306            "abc\nabc\ndef\ndef\nghi\n\n"
3307        );
3308        assert_eq!(
3309            view.read(app).selection_ranges(app.as_ref()),
3310            vec![
3311                DisplayPoint::new(1, 0)..DisplayPoint::new(1, 1),
3312                DisplayPoint::new(1, 2)..DisplayPoint::new(1, 2),
3313                DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
3314                DisplayPoint::new(6, 0)..DisplayPoint::new(6, 0),
3315            ]
3316        );
3317
3318        let settings = settings::channel(&app.font_cache()).unwrap().1;
3319        let buffer = app.add_model(|ctx| Buffer::new(0, "abc\ndef\nghi\n", ctx));
3320        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
3321        view.update(app, |view, ctx| {
3322            view.select_display_ranges(
3323                &[
3324                    DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1),
3325                    DisplayPoint::new(1, 2)..DisplayPoint::new(2, 1),
3326                ],
3327                ctx,
3328            )
3329            .unwrap();
3330            view.duplicate_line(&(), ctx);
3331        });
3332        assert_eq!(
3333            view.read(app).text(app.as_ref()),
3334            "abc\ndef\nghi\nabc\ndef\nghi\n"
3335        );
3336        assert_eq!(
3337            view.read(app).selection_ranges(app.as_ref()),
3338            vec![
3339                DisplayPoint::new(3, 1)..DisplayPoint::new(4, 1),
3340                DisplayPoint::new(4, 2)..DisplayPoint::new(5, 1),
3341            ]
3342        );
3343    }
3344
3345    #[gpui::test]
3346    fn test_move_line_up_down(app: &mut gpui::MutableAppContext) {
3347        let settings = settings::channel(&app.font_cache()).unwrap().1;
3348        let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(10, 5), ctx));
3349        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
3350        view.update(app, |view, ctx| {
3351            view.fold_ranges(
3352                vec![
3353                    Point::new(0, 2)..Point::new(1, 2),
3354                    Point::new(2, 3)..Point::new(4, 1),
3355                    Point::new(7, 0)..Point::new(8, 4),
3356                ],
3357                ctx,
3358            );
3359            view.select_display_ranges(
3360                &[
3361                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3362                    DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
3363                    DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
3364                    DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2),
3365                ],
3366                ctx,
3367            )
3368            .unwrap();
3369        });
3370        assert_eq!(
3371            view.read(app).text(app.as_ref()),
3372            "aa…bbb\nccc…eeee\nfffff\nggggg\n…i\njjjjj"
3373        );
3374
3375        view.update(app, |view, ctx| view.move_line_up(&(), ctx));
3376        assert_eq!(
3377            view.read(app).text(app.as_ref()),
3378            "aa…bbb\nccc…eeee\nggggg\n…i\njjjjj\nfffff"
3379        );
3380        assert_eq!(
3381            view.read(app).selection_ranges(app.as_ref()),
3382            vec![
3383                DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3384                DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3385                DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
3386                DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
3387            ]
3388        );
3389
3390        view.update(app, |view, ctx| view.move_line_down(&(), ctx));
3391        assert_eq!(
3392            view.read(app).text(app.as_ref()),
3393            "ccc…eeee\naa…bbb\nfffff\nggggg\n…i\njjjjj"
3394        );
3395        assert_eq!(
3396            view.read(app).selection_ranges(app.as_ref()),
3397            vec![
3398                DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
3399                DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
3400                DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
3401                DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
3402            ]
3403        );
3404
3405        view.update(app, |view, ctx| view.move_line_down(&(), ctx));
3406        assert_eq!(
3407            view.read(app).text(app.as_ref()),
3408            "ccc…eeee\nfffff\naa…bbb\nggggg\n…i\njjjjj"
3409        );
3410        assert_eq!(
3411            view.read(app).selection_ranges(app.as_ref()),
3412            vec![
3413                DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3414                DisplayPoint::new(3, 1)..DisplayPoint::new(3, 1),
3415                DisplayPoint::new(3, 2)..DisplayPoint::new(4, 3),
3416                DisplayPoint::new(5, 0)..DisplayPoint::new(5, 2)
3417            ]
3418        );
3419
3420        view.update(app, |view, ctx| view.move_line_up(&(), ctx));
3421        assert_eq!(
3422            view.read(app).text(app.as_ref()),
3423            "ccc…eeee\naa…bbb\nggggg\n…i\njjjjj\nfffff"
3424        );
3425        assert_eq!(
3426            view.read(app).selection_ranges(app.as_ref()),
3427            vec![
3428                DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
3429                DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3430                DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3),
3431                DisplayPoint::new(4, 0)..DisplayPoint::new(4, 2)
3432            ]
3433        );
3434    }
3435
3436    #[gpui::test]
3437    fn test_clipboard(app: &mut gpui::MutableAppContext) {
3438        let buffer = app.add_model(|ctx| Buffer::new(0, "one two three four five six ", ctx));
3439        let settings = settings::channel(&app.font_cache()).unwrap().1;
3440        let view = app
3441            .add_window(|ctx| BufferView::for_buffer(buffer.clone(), settings, ctx))
3442            .1;
3443
3444        // Cut with three selections. Clipboard text is divided into three slices.
3445        view.update(app, |view, ctx| {
3446            view.select_ranges(vec![0..4, 8..14, 19..24], false, ctx);
3447            view.cut(&(), ctx);
3448        });
3449        assert_eq!(view.read(app).text(app.as_ref()), "two four six ");
3450
3451        // Paste with three cursors. Each cursor pastes one slice of the clipboard text.
3452        view.update(app, |view, ctx| {
3453            view.select_ranges(vec![4..4, 9..9, 13..13], false, ctx);
3454            view.paste(&(), ctx);
3455        });
3456        assert_eq!(
3457            view.read(app).text(app.as_ref()),
3458            "two one four three six five "
3459        );
3460        assert_eq!(
3461            view.read(app).selection_ranges(app.as_ref()),
3462            &[
3463                DisplayPoint::new(0, 8)..DisplayPoint::new(0, 8),
3464                DisplayPoint::new(0, 19)..DisplayPoint::new(0, 19),
3465                DisplayPoint::new(0, 28)..DisplayPoint::new(0, 28)
3466            ]
3467        );
3468
3469        // Paste again but with only two cursors. Since the number of cursors doesn't
3470        // match the number of slices in the clipboard, the entire clipboard text
3471        // is pasted at each cursor.
3472        view.update(app, |view, ctx| {
3473            view.select_ranges(vec![0..0, 28..28], false, ctx);
3474            view.insert(&"( ".to_string(), ctx);
3475            view.paste(&(), ctx);
3476            view.insert(&") ".to_string(), ctx);
3477        });
3478        assert_eq!(
3479            view.read(app).text(app.as_ref()),
3480            "( one three five ) two one four three six five ( one three five ) "
3481        );
3482
3483        view.update(app, |view, ctx| {
3484            view.select_ranges(vec![0..0], false, ctx);
3485            view.insert(&"123\n4567\n89\n".to_string(), ctx);
3486        });
3487        assert_eq!(
3488            view.read(app).text(app.as_ref()),
3489            "123\n4567\n89\n( one three five ) two one four three six five ( one three five ) "
3490        );
3491
3492        // Cut with three selections, one of which is full-line.
3493        view.update(app, |view, ctx| {
3494            view.select_display_ranges(
3495                &[
3496                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 2),
3497                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
3498                    DisplayPoint::new(2, 0)..DisplayPoint::new(2, 1),
3499                ],
3500                ctx,
3501            )
3502            .unwrap();
3503            view.cut(&(), ctx);
3504        });
3505        assert_eq!(
3506            view.read(app).text(app.as_ref()),
3507            "13\n9\n( one three five ) two one four three six five ( one three five ) "
3508        );
3509
3510        // Paste with three selections, noticing how the copied selection that was full-line
3511        // gets inserted before the second cursor.
3512        view.update(app, |view, ctx| {
3513            view.select_display_ranges(
3514                &[
3515                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3516                    DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
3517                    DisplayPoint::new(2, 2)..DisplayPoint::new(2, 3),
3518                ],
3519                ctx,
3520            )
3521            .unwrap();
3522            view.paste(&(), ctx);
3523        });
3524        assert_eq!(
3525            view.read(app).text(app.as_ref()),
3526            "123\n4567\n9\n( 8ne three five ) two one four three six five ( one three five ) "
3527        );
3528        assert_eq!(
3529            view.read(app).selection_ranges(app.as_ref()),
3530            &[
3531                DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3532                DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3533                DisplayPoint::new(3, 3)..DisplayPoint::new(3, 3),
3534            ]
3535        );
3536
3537        // Copy with a single cursor only, which writes the whole line into the clipboard.
3538        view.update(app, |view, ctx| {
3539            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1)], ctx)
3540                .unwrap();
3541            view.copy(&(), ctx);
3542        });
3543
3544        // Paste with three selections, noticing how the copied full-line selection is inserted
3545        // before the empty selections but replaces the selection that is non-empty.
3546        view.update(app, |view, ctx| {
3547            view.select_display_ranges(
3548                &[
3549                    DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3550                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 2),
3551                    DisplayPoint::new(2, 1)..DisplayPoint::new(2, 1),
3552                ],
3553                ctx,
3554            )
3555            .unwrap();
3556            view.paste(&(), ctx);
3557        });
3558        assert_eq!(
3559                view.read(app).text(app.as_ref()),
3560                "123\n123\n123\n67\n123\n9\n( 8ne three five ) two one four three six five ( one three five ) "
3561            );
3562        assert_eq!(
3563            view.read(app).selection_ranges(app.as_ref()),
3564            &[
3565                DisplayPoint::new(1, 1)..DisplayPoint::new(1, 1),
3566                DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0),
3567                DisplayPoint::new(5, 1)..DisplayPoint::new(5, 1),
3568            ]
3569        );
3570    }
3571
3572    #[gpui::test]
3573    fn test_select_all(app: &mut gpui::MutableAppContext) {
3574        let buffer = app.add_model(|ctx| Buffer::new(0, "abc\nde\nfgh", ctx));
3575        let settings = settings::channel(&app.font_cache()).unwrap().1;
3576        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
3577        view.update(app, |b, ctx| b.select_all(&(), ctx));
3578        assert_eq!(
3579            view.read(app).selection_ranges(app.as_ref()),
3580            &[DisplayPoint::new(0, 0)..DisplayPoint::new(2, 3)]
3581        );
3582    }
3583
3584    #[gpui::test]
3585    fn test_select_line(app: &mut gpui::MutableAppContext) {
3586        let settings = settings::channel(&app.font_cache()).unwrap().1;
3587        let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(6, 5), ctx));
3588        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
3589        view.update(app, |view, ctx| {
3590            view.select_display_ranges(
3591                &[
3592                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
3593                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3594                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3595                    DisplayPoint::new(4, 2)..DisplayPoint::new(4, 2),
3596                ],
3597                ctx,
3598            )
3599            .unwrap();
3600            view.select_line(&(), ctx);
3601        });
3602        assert_eq!(
3603            view.read(app).selection_ranges(app.as_ref()),
3604            vec![
3605                DisplayPoint::new(0, 0)..DisplayPoint::new(2, 0),
3606                DisplayPoint::new(4, 0)..DisplayPoint::new(5, 0),
3607            ]
3608        );
3609
3610        view.update(app, |view, ctx| view.select_line(&(), ctx));
3611        assert_eq!(
3612            view.read(app).selection_ranges(app.as_ref()),
3613            vec![
3614                DisplayPoint::new(0, 0)..DisplayPoint::new(3, 0),
3615                DisplayPoint::new(4, 0)..DisplayPoint::new(5, 5),
3616            ]
3617        );
3618
3619        view.update(app, |view, ctx| view.select_line(&(), ctx));
3620        assert_eq!(
3621            view.read(app).selection_ranges(app.as_ref()),
3622            vec![DisplayPoint::new(0, 0)..DisplayPoint::new(5, 5)]
3623        );
3624    }
3625
3626    #[gpui::test]
3627    fn test_split_selection_into_lines(app: &mut gpui::MutableAppContext) {
3628        let settings = settings::channel(&app.font_cache()).unwrap().1;
3629        let buffer = app.add_model(|ctx| Buffer::new(0, sample_text(9, 5), ctx));
3630        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
3631        view.update(app, |view, ctx| {
3632            view.fold_ranges(
3633                vec![
3634                    Point::new(0, 2)..Point::new(1, 2),
3635                    Point::new(2, 3)..Point::new(4, 1),
3636                    Point::new(7, 0)..Point::new(8, 4),
3637                ],
3638                ctx,
3639            );
3640            view.select_display_ranges(
3641                &[
3642                    DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1),
3643                    DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3644                    DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3645                    DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4),
3646                ],
3647                ctx,
3648            )
3649            .unwrap();
3650        });
3651        assert_eq!(
3652            view.read(app).text(app.as_ref()),
3653            "aa…bbb\nccc…eeee\nfffff\nggggg\n…i"
3654        );
3655
3656        view.update(app, |view, ctx| view.split_selection_into_lines(&(), ctx));
3657        assert_eq!(
3658            view.read(app).text(app.as_ref()),
3659            "aa…bbb\nccc…eeee\nfffff\nggggg\n…i"
3660        );
3661        assert_eq!(
3662            view.read(app).selection_ranges(app.as_ref()),
3663            [
3664                DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3665                DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2),
3666                DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0),
3667                DisplayPoint::new(4, 4)..DisplayPoint::new(4, 4)
3668            ]
3669        );
3670
3671        view.update(app, |view, ctx| {
3672            view.select_display_ranges(&[DisplayPoint::new(4, 0)..DisplayPoint::new(0, 1)], ctx)
3673                .unwrap();
3674            view.split_selection_into_lines(&(), ctx);
3675        });
3676        assert_eq!(
3677            view.read(app).text(app.as_ref()),
3678            "aaaaa\nbbbbb\nccccc\nddddd\neeeee\nfffff\nggggg\n…i"
3679        );
3680        assert_eq!(
3681            view.read(app).selection_ranges(app.as_ref()),
3682            [
3683                DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1),
3684                DisplayPoint::new(1, 5)..DisplayPoint::new(1, 5),
3685                DisplayPoint::new(2, 5)..DisplayPoint::new(2, 5),
3686                DisplayPoint::new(3, 5)..DisplayPoint::new(3, 5),
3687                DisplayPoint::new(4, 5)..DisplayPoint::new(4, 5),
3688                DisplayPoint::new(5, 5)..DisplayPoint::new(5, 5),
3689                DisplayPoint::new(6, 5)..DisplayPoint::new(6, 5),
3690                DisplayPoint::new(7, 0)..DisplayPoint::new(7, 0)
3691            ]
3692        );
3693    }
3694
3695    #[gpui::test]
3696    fn test_add_selection_above_below(app: &mut gpui::MutableAppContext) {
3697        let settings = settings::channel(&app.font_cache()).unwrap().1;
3698        let buffer = app.add_model(|ctx| Buffer::new(0, "abc\ndefghi\n\njk\nlmno\n", ctx));
3699        let (_, view) = app.add_window(|ctx| BufferView::for_buffer(buffer, settings, ctx));
3700
3701        view.update(app, |view, ctx| {
3702            view.select_display_ranges(&[DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)], ctx)
3703                .unwrap();
3704        });
3705        view.update(app, |view, ctx| view.add_selection_above(&(), ctx));
3706        assert_eq!(
3707            view.read(app).selection_ranges(app.as_ref()),
3708            vec![
3709                DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3710                DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
3711            ]
3712        );
3713
3714        view.update(app, |view, ctx| view.add_selection_above(&(), ctx));
3715        assert_eq!(
3716            view.read(app).selection_ranges(app.as_ref()),
3717            vec![
3718                DisplayPoint::new(0, 3)..DisplayPoint::new(0, 3),
3719                DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)
3720            ]
3721        );
3722
3723        view.update(app, |view, ctx| view.add_selection_below(&(), ctx));
3724        assert_eq!(
3725            view.read(app).selection_ranges(app.as_ref()),
3726            vec![DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3)]
3727        );
3728
3729        view.update(app, |view, ctx| view.add_selection_below(&(), ctx));
3730        assert_eq!(
3731            view.read(app).selection_ranges(app.as_ref()),
3732            vec![
3733                DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
3734                DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
3735            ]
3736        );
3737
3738        view.update(app, |view, ctx| view.add_selection_below(&(), ctx));
3739        assert_eq!(
3740            view.read(app).selection_ranges(app.as_ref()),
3741            vec![
3742                DisplayPoint::new(1, 3)..DisplayPoint::new(1, 3),
3743                DisplayPoint::new(4, 3)..DisplayPoint::new(4, 3)
3744            ]
3745        );
3746
3747        view.update(app, |view, ctx| {
3748            view.select_display_ranges(&[DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)], ctx)
3749                .unwrap();
3750        });
3751        view.update(app, |view, ctx| view.add_selection_below(&(), ctx));
3752        assert_eq!(
3753            view.read(app).selection_ranges(app.as_ref()),
3754            vec![
3755                DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
3756                DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
3757            ]
3758        );
3759
3760        view.update(app, |view, ctx| view.add_selection_below(&(), ctx));
3761        assert_eq!(
3762            view.read(app).selection_ranges(app.as_ref()),
3763            vec![
3764                DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3),
3765                DisplayPoint::new(4, 4)..DisplayPoint::new(4, 3)
3766            ]
3767        );
3768
3769        view.update(app, |view, ctx| view.add_selection_above(&(), ctx));
3770        assert_eq!(
3771            view.read(app).selection_ranges(app.as_ref()),
3772            vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
3773        );
3774
3775        view.update(app, |view, ctx| view.add_selection_above(&(), ctx));
3776        assert_eq!(
3777            view.read(app).selection_ranges(app.as_ref()),
3778            vec![DisplayPoint::new(1, 4)..DisplayPoint::new(1, 3)]
3779        );
3780
3781        view.update(app, |view, ctx| {
3782            view.select_display_ranges(&[DisplayPoint::new(0, 1)..DisplayPoint::new(1, 4)], ctx)
3783                .unwrap();
3784        });
3785        view.update(app, |view, ctx| view.add_selection_below(&(), ctx));
3786        assert_eq!(
3787            view.read(app).selection_ranges(app.as_ref()),
3788            vec![
3789                DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
3790                DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
3791                DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
3792            ]
3793        );
3794
3795        view.update(app, |view, ctx| view.add_selection_below(&(), ctx));
3796        assert_eq!(
3797            view.read(app).selection_ranges(app.as_ref()),
3798            vec![
3799                DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
3800                DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
3801                DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
3802                DisplayPoint::new(4, 1)..DisplayPoint::new(4, 4),
3803            ]
3804        );
3805
3806        view.update(app, |view, ctx| view.add_selection_above(&(), ctx));
3807        assert_eq!(
3808            view.read(app).selection_ranges(app.as_ref()),
3809            vec![
3810                DisplayPoint::new(0, 1)..DisplayPoint::new(0, 3),
3811                DisplayPoint::new(1, 1)..DisplayPoint::new(1, 4),
3812                DisplayPoint::new(3, 1)..DisplayPoint::new(3, 2),
3813            ]
3814        );
3815
3816        view.update(app, |view, ctx| {
3817            view.select_display_ranges(&[DisplayPoint::new(4, 3)..DisplayPoint::new(1, 1)], ctx)
3818                .unwrap();
3819        });
3820        view.update(app, |view, ctx| view.add_selection_above(&(), ctx));
3821        assert_eq!(
3822            view.read(app).selection_ranges(app.as_ref()),
3823            vec![
3824                DisplayPoint::new(0, 3)..DisplayPoint::new(0, 1),
3825                DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
3826                DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
3827                DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
3828            ]
3829        );
3830
3831        view.update(app, |view, ctx| view.add_selection_below(&(), ctx));
3832        assert_eq!(
3833            view.read(app).selection_ranges(app.as_ref()),
3834            vec![
3835                DisplayPoint::new(1, 3)..DisplayPoint::new(1, 1),
3836                DisplayPoint::new(3, 2)..DisplayPoint::new(3, 1),
3837                DisplayPoint::new(4, 3)..DisplayPoint::new(4, 1),
3838            ]
3839        );
3840    }
3841
3842    impl BufferView {
3843        fn selection_ranges(&self, app: &AppContext) -> Vec<Range<DisplayPoint>> {
3844            self.selections_in_range(DisplayPoint::zero()..self.max_point(app), app)
3845                .collect::<Vec<_>>()
3846        }
3847    }
3848
3849    fn empty_range(row: usize, column: usize) -> Range<DisplayPoint> {
3850        let point = DisplayPoint::new(row as u32, column as u32);
3851        point..point
3852    }
3853}