buffer_view.rs

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