buffer_view.rs

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