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