lib.rs

   1mod highlight_map;
   2mod language;
   3#[cfg(test)]
   4mod tests;
   5
   6pub use self::{
   7    highlight_map::{HighlightId, HighlightMap},
   8    language::{BracketPair, Language, LanguageConfig, LanguageRegistry},
   9};
  10use anyhow::{anyhow, Result};
  11pub use buffer::*;
  12use clock::ReplicaId;
  13use gpui::{AppContext, Entity, ModelContext, MutableAppContext, Task};
  14use lazy_static::lazy_static;
  15use parking_lot::Mutex;
  16use rpc::proto;
  17use similar::{ChangeTag, TextDiff};
  18use smol::future::yield_now;
  19use std::{
  20    any::Any,
  21    cell::RefCell,
  22    cmp,
  23    collections::{BTreeMap, HashMap, HashSet},
  24    ffi::OsString,
  25    future::Future,
  26    iter::Iterator,
  27    ops::{Deref, DerefMut, Range},
  28    path::{Path, PathBuf},
  29    str,
  30    sync::Arc,
  31    time::{Duration, Instant, SystemTime, UNIX_EPOCH},
  32};
  33use sum_tree::Bias;
  34use tree_sitter::{InputEdit, Parser, QueryCursor, Tree};
  35
  36thread_local! {
  37    static PARSER: RefCell<Parser> = RefCell::new(Parser::new());
  38}
  39
  40lazy_static! {
  41    static ref QUERY_CURSORS: Mutex<Vec<QueryCursor>> = Default::default();
  42}
  43
  44// TODO - Make this configurable
  45const INDENT_SIZE: u32 = 4;
  46
  47pub struct Buffer {
  48    buffer: TextBuffer,
  49    file: Option<Box<dyn File>>,
  50    saved_version: clock::Global,
  51    saved_mtime: SystemTime,
  52    language: Option<Arc<Language>>,
  53    autoindent_requests: Vec<Arc<AutoindentRequest>>,
  54    pending_autoindent: Option<Task<()>>,
  55    sync_parse_timeout: Duration,
  56    syntax_tree: Mutex<Option<SyntaxTree>>,
  57    parsing_in_background: bool,
  58    parse_count: usize,
  59    #[cfg(test)]
  60    operations: Vec<Operation>,
  61}
  62
  63pub struct Snapshot {
  64    text: buffer::Snapshot,
  65    tree: Option<Tree>,
  66    is_parsing: bool,
  67    language: Option<Arc<Language>>,
  68    query_cursor: QueryCursorHandle,
  69}
  70
  71#[derive(Clone, Debug, Eq, PartialEq)]
  72pub enum Event {
  73    Edited,
  74    Dirtied,
  75    Saved,
  76    FileHandleChanged,
  77    Reloaded,
  78    Reparsed,
  79    Closed,
  80}
  81
  82pub trait File {
  83    fn worktree_id(&self) -> usize;
  84
  85    fn entry_id(&self) -> Option<usize>;
  86
  87    fn set_entry_id(&mut self, entry_id: Option<usize>);
  88
  89    fn mtime(&self) -> SystemTime;
  90
  91    fn set_mtime(&mut self, mtime: SystemTime);
  92
  93    fn path(&self) -> &Arc<Path>;
  94
  95    fn set_path(&mut self, path: Arc<Path>);
  96
  97    fn full_path(&self, cx: &AppContext) -> PathBuf;
  98
  99    /// Returns the last component of this handle's absolute path. If this handle refers to the root
 100    /// of its worktree, then this method will return the name of the worktree itself.
 101    fn file_name<'a>(&'a self, cx: &'a AppContext) -> Option<OsString>;
 102
 103    fn is_deleted(&self) -> bool;
 104
 105    fn save(
 106        &self,
 107        buffer_id: u64,
 108        text: Rope,
 109        version: clock::Global,
 110        cx: &mut MutableAppContext,
 111    ) -> Task<Result<(clock::Global, SystemTime)>>;
 112
 113    fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext);
 114
 115    fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext);
 116
 117    fn boxed_clone(&self) -> Box<dyn File>;
 118
 119    fn as_any(&self) -> &dyn Any;
 120}
 121
 122struct QueryCursorHandle(Option<QueryCursor>);
 123
 124#[derive(Clone)]
 125struct SyntaxTree {
 126    tree: Tree,
 127    version: clock::Global,
 128}
 129
 130#[derive(Clone)]
 131struct AutoindentRequest {
 132    selection_set_ids: HashSet<SelectionSetId>,
 133    before_edit: Snapshot,
 134    edited: AnchorSet,
 135    inserted: Option<AnchorRangeSet>,
 136}
 137
 138#[derive(Debug)]
 139struct IndentSuggestion {
 140    basis_row: u32,
 141    indent: bool,
 142}
 143
 144struct TextProvider<'a>(&'a Rope);
 145
 146struct Highlights<'a> {
 147    captures: tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>,
 148    next_capture: Option<(tree_sitter::QueryMatch<'a, 'a>, usize)>,
 149    stack: Vec<(usize, HighlightId)>,
 150    highlight_map: HighlightMap,
 151}
 152
 153pub struct HighlightedChunks<'a> {
 154    range: Range<usize>,
 155    chunks: Chunks<'a>,
 156    highlights: Option<Highlights<'a>>,
 157}
 158
 159struct Diff {
 160    base_version: clock::Global,
 161    new_text: Arc<str>,
 162    changes: Vec<(ChangeTag, usize)>,
 163}
 164
 165impl Buffer {
 166    pub fn new<T: Into<Arc<str>>>(
 167        replica_id: ReplicaId,
 168        base_text: T,
 169        cx: &mut ModelContext<Self>,
 170    ) -> Self {
 171        Self::build(
 172            TextBuffer::new(
 173                replica_id,
 174                cx.model_id() as u64,
 175                History::new(base_text.into()),
 176            ),
 177            None,
 178            None,
 179            cx,
 180        )
 181    }
 182
 183    pub fn from_history(
 184        replica_id: ReplicaId,
 185        history: History,
 186        file: Option<Box<dyn File>>,
 187        language: Option<Arc<Language>>,
 188        cx: &mut ModelContext<Self>,
 189    ) -> Self {
 190        Self::build(
 191            TextBuffer::new(replica_id, cx.model_id() as u64, history),
 192            file,
 193            language,
 194            cx,
 195        )
 196    }
 197
 198    pub fn from_proto(
 199        replica_id: ReplicaId,
 200        message: proto::Buffer,
 201        file: Option<Box<dyn File>>,
 202        language: Option<Arc<Language>>,
 203        cx: &mut ModelContext<Self>,
 204    ) -> Result<Self> {
 205        Ok(Self::build(
 206            TextBuffer::from_proto(replica_id, message)?,
 207            file,
 208            language,
 209            cx,
 210        ))
 211    }
 212
 213    fn build(
 214        buffer: TextBuffer,
 215        file: Option<Box<dyn File>>,
 216        language: Option<Arc<Language>>,
 217        cx: &mut ModelContext<Self>,
 218    ) -> Self {
 219        let saved_mtime;
 220        if let Some(file) = file.as_ref() {
 221            saved_mtime = file.mtime();
 222        } else {
 223            saved_mtime = UNIX_EPOCH;
 224        }
 225
 226        let mut result = Self {
 227            buffer,
 228            saved_mtime,
 229            saved_version: clock::Global::new(),
 230            file,
 231            syntax_tree: Mutex::new(None),
 232            parsing_in_background: false,
 233            parse_count: 0,
 234            sync_parse_timeout: Duration::from_millis(1),
 235            autoindent_requests: Default::default(),
 236            pending_autoindent: Default::default(),
 237            language,
 238
 239            #[cfg(test)]
 240            operations: Default::default(),
 241        };
 242        result.reparse(cx);
 243        result
 244    }
 245
 246    pub fn snapshot(&self) -> Snapshot {
 247        Snapshot {
 248            text: self.buffer.snapshot(),
 249            tree: self.syntax_tree(),
 250            is_parsing: self.parsing_in_background,
 251            language: self.language.clone(),
 252            query_cursor: QueryCursorHandle::new(),
 253        }
 254    }
 255
 256    pub fn file(&self) -> Option<&dyn File> {
 257        self.file.as_deref()
 258    }
 259
 260    pub fn file_mut(&mut self) -> Option<&mut dyn File> {
 261        self.file.as_mut().map(|f| f.deref_mut() as &mut dyn File)
 262    }
 263
 264    pub fn save(
 265        &mut self,
 266        cx: &mut ModelContext<Self>,
 267    ) -> Result<Task<Result<(clock::Global, SystemTime)>>> {
 268        let file = self
 269            .file
 270            .as_ref()
 271            .ok_or_else(|| anyhow!("buffer has no file"))?;
 272        let text = self.as_rope().clone();
 273        let version = self.version.clone();
 274        let save = file.save(self.remote_id(), text, version, cx.as_mut());
 275        Ok(cx.spawn(|this, mut cx| async move {
 276            let (version, mtime) = save.await?;
 277            this.update(&mut cx, |this, cx| {
 278                this.did_save(version.clone(), mtime, None, cx);
 279            });
 280            Ok((version, mtime))
 281        }))
 282    }
 283
 284    pub fn set_language(&mut self, language: Option<Arc<Language>>, cx: &mut ModelContext<Self>) {
 285        self.language = language;
 286        self.reparse(cx);
 287    }
 288
 289    pub fn did_save(
 290        &mut self,
 291        version: clock::Global,
 292        mtime: SystemTime,
 293        new_file: Option<Box<dyn File>>,
 294        cx: &mut ModelContext<Self>,
 295    ) {
 296        self.saved_mtime = mtime;
 297        self.saved_version = version;
 298        if let Some(new_file) = new_file {
 299            self.file = Some(new_file);
 300        }
 301        cx.emit(Event::Saved);
 302    }
 303
 304    pub fn file_updated(
 305        &mut self,
 306        path: Arc<Path>,
 307        mtime: SystemTime,
 308        new_text: Option<String>,
 309        cx: &mut ModelContext<Self>,
 310    ) {
 311        let file = self.file.as_mut().unwrap();
 312        let mut changed = false;
 313        if path != *file.path() {
 314            file.set_path(path);
 315            changed = true;
 316        }
 317
 318        if mtime != file.mtime() {
 319            file.set_mtime(mtime);
 320            changed = true;
 321            if let Some(new_text) = new_text {
 322                if self.version == self.saved_version {
 323                    cx.spawn(|this, mut cx| async move {
 324                        let diff = this
 325                            .read_with(&cx, |this, cx| this.diff(new_text.into(), cx))
 326                            .await;
 327                        this.update(&mut cx, |this, cx| {
 328                            if this.apply_diff(diff, cx) {
 329                                this.saved_version = this.version.clone();
 330                                this.saved_mtime = mtime;
 331                                cx.emit(Event::Reloaded);
 332                            }
 333                        });
 334                    })
 335                    .detach();
 336                }
 337            }
 338        }
 339
 340        if changed {
 341            cx.emit(Event::FileHandleChanged);
 342        }
 343    }
 344
 345    pub fn file_deleted(&mut self, cx: &mut ModelContext<Self>) {
 346        if self.version == self.saved_version {
 347            cx.emit(Event::Dirtied);
 348        }
 349        cx.emit(Event::FileHandleChanged);
 350    }
 351
 352    pub fn close(&mut self, cx: &mut ModelContext<Self>) {
 353        cx.emit(Event::Closed);
 354    }
 355
 356    pub fn language(&self) -> Option<&Arc<Language>> {
 357        self.language.as_ref()
 358    }
 359
 360    pub fn parse_count(&self) -> usize {
 361        self.parse_count
 362    }
 363
 364    fn syntax_tree(&self) -> Option<Tree> {
 365        if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() {
 366            self.interpolate_tree(syntax_tree);
 367            Some(syntax_tree.tree.clone())
 368        } else {
 369            None
 370        }
 371    }
 372
 373    #[cfg(any(test, feature = "test-support"))]
 374    pub fn is_parsing(&self) -> bool {
 375        self.parsing_in_background
 376    }
 377
 378    #[cfg(test)]
 379    pub fn set_sync_parse_timeout(&mut self, timeout: Duration) {
 380        self.sync_parse_timeout = timeout;
 381    }
 382
 383    fn reparse(&mut self, cx: &mut ModelContext<Self>) -> bool {
 384        if self.parsing_in_background {
 385            return false;
 386        }
 387
 388        if let Some(language) = self.language.clone() {
 389            let old_tree = self.syntax_tree();
 390            let text = self.as_rope().clone();
 391            let parsed_version = self.version();
 392            let parse_task = cx.background().spawn({
 393                let language = language.clone();
 394                async move { Self::parse_text(&text, old_tree, &language) }
 395            });
 396
 397            match cx
 398                .background()
 399                .block_with_timeout(self.sync_parse_timeout, parse_task)
 400            {
 401                Ok(new_tree) => {
 402                    self.did_finish_parsing(new_tree, parsed_version, cx);
 403                    return true;
 404                }
 405                Err(parse_task) => {
 406                    self.parsing_in_background = true;
 407                    cx.spawn(move |this, mut cx| async move {
 408                        let new_tree = parse_task.await;
 409                        this.update(&mut cx, move |this, cx| {
 410                            let language_changed =
 411                                this.language.as_ref().map_or(true, |curr_language| {
 412                                    !Arc::ptr_eq(curr_language, &language)
 413                                });
 414                            let parse_again = this.version > parsed_version || language_changed;
 415                            this.parsing_in_background = false;
 416                            this.did_finish_parsing(new_tree, parsed_version, cx);
 417
 418                            if parse_again && this.reparse(cx) {
 419                                return;
 420                            }
 421                        });
 422                    })
 423                    .detach();
 424                }
 425            }
 426        }
 427        false
 428    }
 429
 430    fn parse_text(text: &Rope, old_tree: Option<Tree>, language: &Language) -> Tree {
 431        PARSER.with(|parser| {
 432            let mut parser = parser.borrow_mut();
 433            parser
 434                .set_language(language.grammar)
 435                .expect("incompatible grammar");
 436            let mut chunks = text.chunks_in_range(0..text.len());
 437            let tree = parser
 438                .parse_with(
 439                    &mut move |offset, _| {
 440                        chunks.seek(offset);
 441                        chunks.next().unwrap_or("").as_bytes()
 442                    },
 443                    old_tree.as_ref(),
 444                )
 445                .unwrap();
 446            tree
 447        })
 448    }
 449
 450    fn interpolate_tree(&self, tree: &mut SyntaxTree) {
 451        let mut delta = 0_isize;
 452        for edit in self.edits_since(tree.version.clone()) {
 453            let start_offset = (edit.old_bytes.start as isize + delta) as usize;
 454            let start_point = self.as_rope().to_point(start_offset);
 455            tree.tree.edit(&InputEdit {
 456                start_byte: start_offset,
 457                old_end_byte: start_offset + edit.deleted_bytes(),
 458                new_end_byte: start_offset + edit.inserted_bytes(),
 459                start_position: start_point.into(),
 460                old_end_position: (start_point + edit.deleted_lines()).into(),
 461                new_end_position: self
 462                    .as_rope()
 463                    .to_point(start_offset + edit.inserted_bytes())
 464                    .into(),
 465            });
 466            delta += edit.inserted_bytes() as isize - edit.deleted_bytes() as isize;
 467        }
 468        tree.version = self.version();
 469    }
 470
 471    fn did_finish_parsing(
 472        &mut self,
 473        tree: Tree,
 474        version: clock::Global,
 475        cx: &mut ModelContext<Self>,
 476    ) {
 477        self.parse_count += 1;
 478        *self.syntax_tree.lock() = Some(SyntaxTree { tree, version });
 479        self.request_autoindent(cx);
 480        cx.emit(Event::Reparsed);
 481        cx.notify();
 482    }
 483
 484    fn request_autoindent(&mut self, cx: &mut ModelContext<Self>) {
 485        if let Some(indent_columns) = self.compute_autoindents() {
 486            let indent_columns = cx.background().spawn(indent_columns);
 487            match cx
 488                .background()
 489                .block_with_timeout(Duration::from_micros(500), indent_columns)
 490            {
 491                Ok(indent_columns) => self.apply_autoindents(indent_columns, cx),
 492                Err(indent_columns) => {
 493                    self.pending_autoindent = Some(cx.spawn(|this, mut cx| async move {
 494                        let indent_columns = indent_columns.await;
 495                        this.update(&mut cx, |this, cx| {
 496                            this.apply_autoindents(indent_columns, cx);
 497                        });
 498                    }));
 499                }
 500            }
 501        }
 502    }
 503
 504    fn compute_autoindents(&self) -> Option<impl Future<Output = BTreeMap<u32, u32>>> {
 505        let max_rows_between_yields = 100;
 506        let snapshot = self.snapshot();
 507        if snapshot.language.is_none()
 508            || snapshot.tree.is_none()
 509            || self.autoindent_requests.is_empty()
 510        {
 511            return None;
 512        }
 513
 514        let autoindent_requests = self.autoindent_requests.clone();
 515        Some(async move {
 516            let mut indent_columns = BTreeMap::new();
 517            for request in autoindent_requests {
 518                let old_to_new_rows = request
 519                    .edited
 520                    .to_points(&request.before_edit)
 521                    .map(|point| point.row)
 522                    .zip(request.edited.to_points(&snapshot).map(|point| point.row))
 523                    .collect::<BTreeMap<u32, u32>>();
 524
 525                let mut old_suggestions = HashMap::<u32, u32>::default();
 526                let old_edited_ranges =
 527                    contiguous_ranges(old_to_new_rows.keys().copied(), max_rows_between_yields);
 528                for old_edited_range in old_edited_ranges {
 529                    let suggestions = request
 530                        .before_edit
 531                        .suggest_autoindents(old_edited_range.clone())
 532                        .into_iter()
 533                        .flatten();
 534                    for (old_row, suggestion) in old_edited_range.zip(suggestions) {
 535                        let indentation_basis = old_to_new_rows
 536                            .get(&suggestion.basis_row)
 537                            .and_then(|from_row| old_suggestions.get(from_row).copied())
 538                            .unwrap_or_else(|| {
 539                                request
 540                                    .before_edit
 541                                    .indent_column_for_line(suggestion.basis_row)
 542                            });
 543                        let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
 544                        old_suggestions.insert(
 545                            *old_to_new_rows.get(&old_row).unwrap(),
 546                            indentation_basis + delta,
 547                        );
 548                    }
 549                    yield_now().await;
 550                }
 551
 552                // At this point, old_suggestions contains the suggested indentation for all edited lines with respect to the state of the
 553                // buffer before the edit, but keyed by the row for these lines after the edits were applied.
 554                let new_edited_row_ranges =
 555                    contiguous_ranges(old_to_new_rows.values().copied(), max_rows_between_yields);
 556                for new_edited_row_range in new_edited_row_ranges {
 557                    let suggestions = snapshot
 558                        .suggest_autoindents(new_edited_row_range.clone())
 559                        .into_iter()
 560                        .flatten();
 561                    for (new_row, suggestion) in new_edited_row_range.zip(suggestions) {
 562                        let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
 563                        let new_indentation = indent_columns
 564                            .get(&suggestion.basis_row)
 565                            .copied()
 566                            .unwrap_or_else(|| {
 567                                snapshot.indent_column_for_line(suggestion.basis_row)
 568                            })
 569                            + delta;
 570                        if old_suggestions
 571                            .get(&new_row)
 572                            .map_or(true, |old_indentation| new_indentation != *old_indentation)
 573                        {
 574                            indent_columns.insert(new_row, new_indentation);
 575                        }
 576                    }
 577                    yield_now().await;
 578                }
 579
 580                if let Some(inserted) = request.inserted.as_ref() {
 581                    let inserted_row_ranges = contiguous_ranges(
 582                        inserted
 583                            .to_point_ranges(&snapshot)
 584                            .flat_map(|range| range.start.row..range.end.row + 1),
 585                        max_rows_between_yields,
 586                    );
 587                    for inserted_row_range in inserted_row_ranges {
 588                        let suggestions = snapshot
 589                            .suggest_autoindents(inserted_row_range.clone())
 590                            .into_iter()
 591                            .flatten();
 592                        for (row, suggestion) in inserted_row_range.zip(suggestions) {
 593                            let delta = if suggestion.indent { INDENT_SIZE } else { 0 };
 594                            let new_indentation = indent_columns
 595                                .get(&suggestion.basis_row)
 596                                .copied()
 597                                .unwrap_or_else(|| {
 598                                    snapshot.indent_column_for_line(suggestion.basis_row)
 599                                })
 600                                + delta;
 601                            indent_columns.insert(row, new_indentation);
 602                        }
 603                        yield_now().await;
 604                    }
 605                }
 606            }
 607            indent_columns
 608        })
 609    }
 610
 611    fn apply_autoindents(
 612        &mut self,
 613        indent_columns: BTreeMap<u32, u32>,
 614        cx: &mut ModelContext<Self>,
 615    ) {
 616        let selection_set_ids = self
 617            .autoindent_requests
 618            .drain(..)
 619            .flat_map(|req| req.selection_set_ids.clone())
 620            .collect::<HashSet<_>>();
 621
 622        self.start_transaction(selection_set_ids.iter().copied())
 623            .unwrap();
 624        for (row, indent_column) in &indent_columns {
 625            self.set_indent_column_for_line(*row, *indent_column, cx);
 626        }
 627
 628        for selection_set_id in &selection_set_ids {
 629            if let Ok(set) = self.selection_set(*selection_set_id) {
 630                let new_selections = set
 631                    .selections
 632                    .iter()
 633                    .map(|selection| {
 634                        let start_point = selection.start.to_point(&self.buffer);
 635                        if start_point.column == 0 {
 636                            let end_point = selection.end.to_point(&self.buffer);
 637                            let delta = Point::new(
 638                                0,
 639                                indent_columns.get(&start_point.row).copied().unwrap_or(0),
 640                            );
 641                            if delta.column > 0 {
 642                                return Selection {
 643                                    id: selection.id,
 644                                    goal: selection.goal,
 645                                    reversed: selection.reversed,
 646                                    start: self
 647                                        .anchor_at(start_point + delta, selection.start.bias),
 648                                    end: self.anchor_at(end_point + delta, selection.end.bias),
 649                                };
 650                            }
 651                        }
 652                        selection.clone()
 653                    })
 654                    .collect::<Arc<[_]>>();
 655                self.update_selection_set(*selection_set_id, new_selections, cx)
 656                    .unwrap();
 657            }
 658        }
 659
 660        self.end_transaction(selection_set_ids.iter().copied(), cx)
 661            .unwrap();
 662    }
 663
 664    pub fn indent_column_for_line(&self, row: u32) -> u32 {
 665        self.content().indent_column_for_line(row)
 666    }
 667
 668    fn set_indent_column_for_line(&mut self, row: u32, column: u32, cx: &mut ModelContext<Self>) {
 669        let current_column = self.indent_column_for_line(row);
 670        if column > current_column {
 671            let offset = Point::new(row, 0).to_offset(&*self);
 672            self.edit(
 673                [offset..offset],
 674                " ".repeat((column - current_column) as usize),
 675                cx,
 676            );
 677        } else if column < current_column {
 678            self.edit(
 679                [Point::new(row, 0)..Point::new(row, current_column - column)],
 680                "",
 681                cx,
 682            );
 683        }
 684    }
 685
 686    pub fn range_for_syntax_ancestor<T: ToOffset>(&self, range: Range<T>) -> Option<Range<usize>> {
 687        if let Some(tree) = self.syntax_tree() {
 688            let root = tree.root_node();
 689            let range = range.start.to_offset(self)..range.end.to_offset(self);
 690            let mut node = root.descendant_for_byte_range(range.start, range.end);
 691            while node.map_or(false, |n| n.byte_range() == range) {
 692                node = node.unwrap().parent();
 693            }
 694            node.map(|n| n.byte_range())
 695        } else {
 696            None
 697        }
 698    }
 699
 700    pub fn enclosing_bracket_ranges<T: ToOffset>(
 701        &self,
 702        range: Range<T>,
 703    ) -> Option<(Range<usize>, Range<usize>)> {
 704        let (lang, tree) = self.language.as_ref().zip(self.syntax_tree())?;
 705        let open_capture_ix = lang.brackets_query.capture_index_for_name("open")?;
 706        let close_capture_ix = lang.brackets_query.capture_index_for_name("close")?;
 707
 708        // Find bracket pairs that *inclusively* contain the given range.
 709        let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1;
 710        let mut cursor = QueryCursorHandle::new();
 711        let matches = cursor.set_byte_range(range).matches(
 712            &lang.brackets_query,
 713            tree.root_node(),
 714            TextProvider(self.as_rope()),
 715        );
 716
 717        // Get the ranges of the innermost pair of brackets.
 718        matches
 719            .filter_map(|mat| {
 720                let open = mat.nodes_for_capture_index(open_capture_ix).next()?;
 721                let close = mat.nodes_for_capture_index(close_capture_ix).next()?;
 722                Some((open.byte_range(), close.byte_range()))
 723            })
 724            .min_by_key(|(open_range, close_range)| close_range.end - open_range.start)
 725    }
 726
 727    fn diff(&self, new_text: Arc<str>, cx: &AppContext) -> Task<Diff> {
 728        // TODO: it would be nice to not allocate here.
 729        let old_text = self.text();
 730        let base_version = self.version();
 731        cx.background().spawn(async move {
 732            let changes = TextDiff::from_lines(old_text.as_str(), new_text.as_ref())
 733                .iter_all_changes()
 734                .map(|c| (c.tag(), c.value().len()))
 735                .collect::<Vec<_>>();
 736            Diff {
 737                base_version,
 738                new_text,
 739                changes,
 740            }
 741        })
 742    }
 743
 744    pub fn set_text_from_disk(&self, new_text: Arc<str>, cx: &mut ModelContext<Self>) -> Task<()> {
 745        cx.spawn(|this, mut cx| async move {
 746            let diff = this
 747                .read_with(&cx, |this, cx| this.diff(new_text, cx))
 748                .await;
 749
 750            this.update(&mut cx, |this, cx| {
 751                if this.apply_diff(diff, cx) {
 752                    this.saved_version = this.version.clone();
 753                }
 754            });
 755        })
 756    }
 757
 758    fn apply_diff(&mut self, diff: Diff, cx: &mut ModelContext<Self>) -> bool {
 759        if self.version == diff.base_version {
 760            self.start_transaction(None).unwrap();
 761            let mut offset = 0;
 762            for (tag, len) in diff.changes {
 763                let range = offset..(offset + len);
 764                match tag {
 765                    ChangeTag::Equal => offset += len,
 766                    ChangeTag::Delete => self.edit(Some(range), "", cx),
 767                    ChangeTag::Insert => {
 768                        self.edit(Some(offset..offset), &diff.new_text[range], cx);
 769                        offset += len;
 770                    }
 771                }
 772            }
 773            self.end_transaction(None, cx).unwrap();
 774            true
 775        } else {
 776            false
 777        }
 778    }
 779
 780    pub fn is_dirty(&self) -> bool {
 781        self.version > self.saved_version
 782            || self.file.as_ref().map_or(false, |file| file.is_deleted())
 783    }
 784
 785    pub fn has_conflict(&self) -> bool {
 786        self.version > self.saved_version
 787            && self
 788                .file
 789                .as_ref()
 790                .map_or(false, |file| file.mtime() > self.saved_mtime)
 791    }
 792
 793    pub fn start_transaction(
 794        &mut self,
 795        selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
 796    ) -> Result<()> {
 797        self.start_transaction_at(selection_set_ids, Instant::now())
 798    }
 799
 800    fn start_transaction_at(
 801        &mut self,
 802        selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
 803        now: Instant,
 804    ) -> Result<()> {
 805        self.buffer.start_transaction_at(selection_set_ids, now)
 806    }
 807
 808    pub fn end_transaction(
 809        &mut self,
 810        selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
 811        cx: &mut ModelContext<Self>,
 812    ) -> Result<()> {
 813        self.end_transaction_at(selection_set_ids, Instant::now(), cx)
 814    }
 815
 816    fn end_transaction_at(
 817        &mut self,
 818        selection_set_ids: impl IntoIterator<Item = SelectionSetId>,
 819        now: Instant,
 820        cx: &mut ModelContext<Self>,
 821    ) -> Result<()> {
 822        if let Some(start_version) = self.buffer.end_transaction_at(selection_set_ids, now) {
 823            cx.notify();
 824            let was_dirty = start_version != self.saved_version;
 825            let edited = self.edits_since(start_version).next().is_some();
 826            if edited {
 827                self.did_edit(was_dirty, cx);
 828                self.reparse(cx);
 829            }
 830        }
 831        Ok(())
 832    }
 833
 834    pub fn edit<I, S, T>(&mut self, ranges_iter: I, new_text: T, cx: &mut ModelContext<Self>)
 835    where
 836        I: IntoIterator<Item = Range<S>>,
 837        S: ToOffset,
 838        T: Into<String>,
 839    {
 840        self.edit_internal(ranges_iter, new_text, false, cx)
 841    }
 842
 843    pub fn edit_with_autoindent<I, S, T>(
 844        &mut self,
 845        ranges_iter: I,
 846        new_text: T,
 847        cx: &mut ModelContext<Self>,
 848    ) where
 849        I: IntoIterator<Item = Range<S>>,
 850        S: ToOffset,
 851        T: Into<String>,
 852    {
 853        self.edit_internal(ranges_iter, new_text, true, cx)
 854    }
 855
 856    pub fn edit_internal<I, S, T>(
 857        &mut self,
 858        ranges_iter: I,
 859        new_text: T,
 860        autoindent: bool,
 861        cx: &mut ModelContext<Self>,
 862    ) where
 863        I: IntoIterator<Item = Range<S>>,
 864        S: ToOffset,
 865        T: Into<String>,
 866    {
 867        let new_text = new_text.into();
 868
 869        // Skip invalid ranges and coalesce contiguous ones.
 870        let mut ranges: Vec<Range<usize>> = Vec::new();
 871        for range in ranges_iter {
 872            let range = range.start.to_offset(&*self)..range.end.to_offset(&*self);
 873            if !new_text.is_empty() || !range.is_empty() {
 874                if let Some(prev_range) = ranges.last_mut() {
 875                    if prev_range.end >= range.start {
 876                        prev_range.end = cmp::max(prev_range.end, range.end);
 877                    } else {
 878                        ranges.push(range);
 879                    }
 880                } else {
 881                    ranges.push(range);
 882                }
 883            }
 884        }
 885        if ranges.is_empty() {
 886            return;
 887        }
 888
 889        self.start_transaction(None).unwrap();
 890        self.pending_autoindent.take();
 891        let autoindent_request = if autoindent && self.language.is_some() {
 892            let before_edit = self.snapshot();
 893            let edited = self.content().anchor_set(ranges.iter().filter_map(|range| {
 894                let start = range.start.to_point(&*self);
 895                if new_text.starts_with('\n') && start.column == self.line_len(start.row) {
 896                    None
 897                } else {
 898                    Some((range.start, Bias::Left))
 899                }
 900            }));
 901            Some((before_edit, edited))
 902        } else {
 903            None
 904        };
 905
 906        let first_newline_ix = new_text.find('\n');
 907        let new_text_len = new_text.len();
 908
 909        let edit = self.buffer.edit(ranges.iter().cloned(), new_text);
 910
 911        if let Some((before_edit, edited)) = autoindent_request {
 912            let mut inserted = None;
 913            if let Some(first_newline_ix) = first_newline_ix {
 914                let mut delta = 0isize;
 915                inserted = Some(self.content().anchor_range_set(ranges.iter().map(|range| {
 916                    let start = (delta + range.start as isize) as usize + first_newline_ix + 1;
 917                    let end = (delta + range.start as isize) as usize + new_text_len;
 918                    delta += (range.end as isize - range.start as isize) + new_text_len as isize;
 919                    (start, Bias::Left)..(end, Bias::Right)
 920                })));
 921            }
 922
 923            let selection_set_ids = self
 924                .buffer
 925                .peek_undo_stack()
 926                .unwrap()
 927                .starting_selection_set_ids()
 928                .collect();
 929            self.autoindent_requests.push(Arc::new(AutoindentRequest {
 930                selection_set_ids,
 931                before_edit,
 932                edited,
 933                inserted,
 934            }));
 935        }
 936
 937        self.end_transaction(None, cx).unwrap();
 938        self.send_operation(Operation::Edit(edit), cx);
 939    }
 940
 941    fn did_edit(&self, was_dirty: bool, cx: &mut ModelContext<Self>) {
 942        cx.emit(Event::Edited);
 943        if !was_dirty {
 944            cx.emit(Event::Dirtied);
 945        }
 946    }
 947
 948    pub fn add_selection_set(
 949        &mut self,
 950        selections: impl Into<Arc<[Selection]>>,
 951        cx: &mut ModelContext<Self>,
 952    ) -> SelectionSetId {
 953        let operation = self.buffer.add_selection_set(selections);
 954        if let Operation::UpdateSelections { set_id, .. } = &operation {
 955            let set_id = *set_id;
 956            cx.notify();
 957            self.send_operation(operation, cx);
 958            set_id
 959        } else {
 960            unreachable!()
 961        }
 962    }
 963
 964    pub fn update_selection_set(
 965        &mut self,
 966        set_id: SelectionSetId,
 967        selections: impl Into<Arc<[Selection]>>,
 968        cx: &mut ModelContext<Self>,
 969    ) -> Result<()> {
 970        let operation = self.buffer.update_selection_set(set_id, selections)?;
 971        cx.notify();
 972        self.send_operation(operation, cx);
 973        Ok(())
 974    }
 975
 976    pub fn set_active_selection_set(
 977        &mut self,
 978        set_id: Option<SelectionSetId>,
 979        cx: &mut ModelContext<Self>,
 980    ) -> Result<()> {
 981        let operation = self.buffer.set_active_selection_set(set_id)?;
 982        self.send_operation(operation, cx);
 983        Ok(())
 984    }
 985
 986    pub fn remove_selection_set(
 987        &mut self,
 988        set_id: SelectionSetId,
 989        cx: &mut ModelContext<Self>,
 990    ) -> Result<()> {
 991        let operation = self.buffer.remove_selection_set(set_id)?;
 992        cx.notify();
 993        self.send_operation(operation, cx);
 994        Ok(())
 995    }
 996
 997    pub fn apply_ops<I: IntoIterator<Item = Operation>>(
 998        &mut self,
 999        ops: I,
1000        cx: &mut ModelContext<Self>,
1001    ) -> Result<()> {
1002        self.pending_autoindent.take();
1003
1004        let was_dirty = self.is_dirty();
1005        let old_version = self.version.clone();
1006
1007        self.buffer.apply_ops(ops)?;
1008
1009        cx.notify();
1010        if self.edits_since(old_version).next().is_some() {
1011            self.did_edit(was_dirty, cx);
1012            self.reparse(cx);
1013        }
1014
1015        Ok(())
1016    }
1017
1018    #[cfg(not(test))]
1019    pub fn send_operation(&mut self, operation: Operation, cx: &mut ModelContext<Self>) {
1020        if let Some(file) = &self.file {
1021            file.buffer_updated(self.remote_id(), operation, cx.as_mut());
1022        }
1023    }
1024
1025    #[cfg(test)]
1026    pub fn send_operation(&mut self, operation: Operation, _: &mut ModelContext<Self>) {
1027        self.operations.push(operation);
1028    }
1029
1030    pub fn remove_peer(&mut self, replica_id: ReplicaId, cx: &mut ModelContext<Self>) {
1031        self.buffer.remove_peer(replica_id);
1032        cx.notify();
1033    }
1034
1035    pub fn undo(&mut self, cx: &mut ModelContext<Self>) {
1036        let was_dirty = self.is_dirty();
1037        let old_version = self.version.clone();
1038
1039        for operation in self.buffer.undo() {
1040            self.send_operation(operation, cx);
1041        }
1042
1043        cx.notify();
1044        if self.edits_since(old_version).next().is_some() {
1045            self.did_edit(was_dirty, cx);
1046            self.reparse(cx);
1047        }
1048    }
1049
1050    pub fn redo(&mut self, cx: &mut ModelContext<Self>) {
1051        let was_dirty = self.is_dirty();
1052        let old_version = self.version.clone();
1053
1054        for operation in self.buffer.redo() {
1055            self.send_operation(operation, cx);
1056        }
1057
1058        cx.notify();
1059        if self.edits_since(old_version).next().is_some() {
1060            self.did_edit(was_dirty, cx);
1061            self.reparse(cx);
1062        }
1063    }
1064}
1065
1066#[cfg(any(test, feature = "test-support"))]
1067impl Buffer {
1068    pub fn randomly_edit<T>(&mut self, rng: &mut T, old_range_count: usize)
1069    where
1070        T: rand::Rng,
1071    {
1072        self.buffer.randomly_edit(rng, old_range_count);
1073    }
1074
1075    pub fn randomly_mutate<T>(&mut self, rng: &mut T)
1076    where
1077        T: rand::Rng,
1078    {
1079        self.buffer.randomly_mutate(rng);
1080    }
1081}
1082
1083impl Entity for Buffer {
1084    type Event = Event;
1085
1086    fn release(&mut self, cx: &mut gpui::MutableAppContext) {
1087        if let Some(file) = self.file.as_ref() {
1088            file.buffer_removed(self.remote_id(), cx);
1089        }
1090    }
1091}
1092
1093impl Clone for Buffer {
1094    fn clone(&self) -> Self {
1095        Self {
1096            buffer: self.buffer.clone(),
1097            saved_version: self.saved_version.clone(),
1098            saved_mtime: self.saved_mtime,
1099            file: self.file.as_ref().map(|f| f.boxed_clone()),
1100            language: self.language.clone(),
1101            syntax_tree: Mutex::new(self.syntax_tree.lock().clone()),
1102            parsing_in_background: false,
1103            sync_parse_timeout: self.sync_parse_timeout,
1104            parse_count: self.parse_count,
1105            autoindent_requests: Default::default(),
1106            pending_autoindent: Default::default(),
1107
1108            #[cfg(test)]
1109            operations: self.operations.clone(),
1110        }
1111    }
1112}
1113
1114impl Deref for Buffer {
1115    type Target = TextBuffer;
1116
1117    fn deref(&self) -> &Self::Target {
1118        &self.buffer
1119    }
1120}
1121
1122impl<'a> From<&'a Buffer> for Content<'a> {
1123    fn from(buffer: &'a Buffer) -> Self {
1124        Self::from(&buffer.buffer)
1125    }
1126}
1127
1128impl<'a> From<&'a mut Buffer> for Content<'a> {
1129    fn from(buffer: &'a mut Buffer) -> Self {
1130        Self::from(&buffer.buffer)
1131    }
1132}
1133
1134impl<'a> From<&'a Snapshot> for Content<'a> {
1135    fn from(snapshot: &'a Snapshot) -> Self {
1136        Self::from(&snapshot.text)
1137    }
1138}
1139
1140impl Snapshot {
1141    fn suggest_autoindents<'a>(
1142        &'a self,
1143        row_range: Range<u32>,
1144    ) -> Option<impl Iterator<Item = IndentSuggestion> + 'a> {
1145        let mut query_cursor = QueryCursorHandle::new();
1146        if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) {
1147            let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
1148
1149            // Get the "indentation ranges" that intersect this row range.
1150            let indent_capture_ix = language.indents_query.capture_index_for_name("indent");
1151            let end_capture_ix = language.indents_query.capture_index_for_name("end");
1152            query_cursor.set_point_range(
1153                Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0).into()
1154                    ..Point::new(row_range.end, 0).into(),
1155            );
1156            let mut indentation_ranges = Vec::<(Range<Point>, &'static str)>::new();
1157            for mat in query_cursor.matches(
1158                &language.indents_query,
1159                tree.root_node(),
1160                TextProvider(self.as_rope()),
1161            ) {
1162                let mut node_kind = "";
1163                let mut start: Option<Point> = None;
1164                let mut end: Option<Point> = None;
1165                for capture in mat.captures {
1166                    if Some(capture.index) == indent_capture_ix {
1167                        node_kind = capture.node.kind();
1168                        start.get_or_insert(capture.node.start_position().into());
1169                        end.get_or_insert(capture.node.end_position().into());
1170                    } else if Some(capture.index) == end_capture_ix {
1171                        end = Some(capture.node.start_position().into());
1172                    }
1173                }
1174
1175                if let Some((start, end)) = start.zip(end) {
1176                    if start.row == end.row {
1177                        continue;
1178                    }
1179
1180                    let range = start..end;
1181                    match indentation_ranges.binary_search_by_key(&range.start, |r| r.0.start) {
1182                        Err(ix) => indentation_ranges.insert(ix, (range, node_kind)),
1183                        Ok(ix) => {
1184                            let prev_range = &mut indentation_ranges[ix];
1185                            prev_range.0.end = prev_range.0.end.max(range.end);
1186                        }
1187                    }
1188                }
1189            }
1190
1191            let mut prev_row = prev_non_blank_row.unwrap_or(0);
1192            Some(row_range.map(move |row| {
1193                let row_start = Point::new(row, self.indent_column_for_line(row));
1194
1195                let mut indent_from_prev_row = false;
1196                let mut outdent_to_row = u32::MAX;
1197                for (range, _node_kind) in &indentation_ranges {
1198                    if range.start.row >= row {
1199                        break;
1200                    }
1201
1202                    if range.start.row == prev_row && range.end > row_start {
1203                        indent_from_prev_row = true;
1204                    }
1205                    if range.end.row >= prev_row && range.end <= row_start {
1206                        outdent_to_row = outdent_to_row.min(range.start.row);
1207                    }
1208                }
1209
1210                let suggestion = if outdent_to_row == prev_row {
1211                    IndentSuggestion {
1212                        basis_row: prev_row,
1213                        indent: false,
1214                    }
1215                } else if indent_from_prev_row {
1216                    IndentSuggestion {
1217                        basis_row: prev_row,
1218                        indent: true,
1219                    }
1220                } else if outdent_to_row < prev_row {
1221                    IndentSuggestion {
1222                        basis_row: outdent_to_row,
1223                        indent: false,
1224                    }
1225                } else {
1226                    IndentSuggestion {
1227                        basis_row: prev_row,
1228                        indent: false,
1229                    }
1230                };
1231
1232                prev_row = row;
1233                suggestion
1234            }))
1235        } else {
1236            None
1237        }
1238    }
1239
1240    fn prev_non_blank_row(&self, mut row: u32) -> Option<u32> {
1241        while row > 0 {
1242            row -= 1;
1243            if !self.is_line_blank(row) {
1244                return Some(row);
1245            }
1246        }
1247        None
1248    }
1249
1250    fn is_line_blank(&self, row: u32) -> bool {
1251        self.text_for_range(Point::new(row, 0)..Point::new(row, self.line_len(row)))
1252            .all(|chunk| chunk.matches(|c: char| !c.is_whitespace()).next().is_none())
1253    }
1254
1255    pub fn highlighted_text_for_range<T: ToOffset>(
1256        &mut self,
1257        range: Range<T>,
1258    ) -> HighlightedChunks {
1259        let range = range.start.to_offset(&*self)..range.end.to_offset(&*self);
1260        let chunks = self.text.as_rope().chunks_in_range(range.clone());
1261        if let Some((language, tree)) = self.language.as_ref().zip(self.tree.as_ref()) {
1262            let captures = self.query_cursor.set_byte_range(range.clone()).captures(
1263                &language.highlights_query,
1264                tree.root_node(),
1265                TextProvider(self.text.as_rope()),
1266            );
1267
1268            HighlightedChunks {
1269                range,
1270                chunks,
1271                highlights: Some(Highlights {
1272                    captures,
1273                    next_capture: None,
1274                    stack: Default::default(),
1275                    highlight_map: language.highlight_map(),
1276                }),
1277            }
1278        } else {
1279            HighlightedChunks {
1280                range,
1281                chunks,
1282                highlights: None,
1283            }
1284        }
1285    }
1286}
1287
1288impl Clone for Snapshot {
1289    fn clone(&self) -> Self {
1290        Self {
1291            text: self.text.clone(),
1292            tree: self.tree.clone(),
1293            is_parsing: self.is_parsing,
1294            language: self.language.clone(),
1295            query_cursor: QueryCursorHandle::new(),
1296        }
1297    }
1298}
1299
1300impl Deref for Snapshot {
1301    type Target = buffer::Snapshot;
1302
1303    fn deref(&self) -> &Self::Target {
1304        &self.text
1305    }
1306}
1307
1308impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
1309    type I = ByteChunks<'a>;
1310
1311    fn text(&mut self, node: tree_sitter::Node) -> Self::I {
1312        ByteChunks(self.0.chunks_in_range(node.byte_range()))
1313    }
1314}
1315
1316struct ByteChunks<'a>(rope::Chunks<'a>);
1317
1318impl<'a> Iterator for ByteChunks<'a> {
1319    type Item = &'a [u8];
1320
1321    fn next(&mut self) -> Option<Self::Item> {
1322        self.0.next().map(str::as_bytes)
1323    }
1324}
1325
1326impl<'a> HighlightedChunks<'a> {
1327    pub fn seek(&mut self, offset: usize) {
1328        self.range.start = offset;
1329        self.chunks.seek(self.range.start);
1330        if let Some(highlights) = self.highlights.as_mut() {
1331            highlights
1332                .stack
1333                .retain(|(end_offset, _)| *end_offset > offset);
1334            if let Some((mat, capture_ix)) = &highlights.next_capture {
1335                let capture = mat.captures[*capture_ix as usize];
1336                if offset >= capture.node.start_byte() {
1337                    let next_capture_end = capture.node.end_byte();
1338                    if offset < next_capture_end {
1339                        highlights.stack.push((
1340                            next_capture_end,
1341                            highlights.highlight_map.get(capture.index),
1342                        ));
1343                    }
1344                    highlights.next_capture.take();
1345                }
1346            }
1347            highlights.captures.set_byte_range(self.range.clone());
1348        }
1349    }
1350
1351    pub fn offset(&self) -> usize {
1352        self.range.start
1353    }
1354}
1355
1356impl<'a> Iterator for HighlightedChunks<'a> {
1357    type Item = (&'a str, HighlightId);
1358
1359    fn next(&mut self) -> Option<Self::Item> {
1360        let mut next_capture_start = usize::MAX;
1361
1362        if let Some(highlights) = self.highlights.as_mut() {
1363            while let Some((parent_capture_end, _)) = highlights.stack.last() {
1364                if *parent_capture_end <= self.range.start {
1365                    highlights.stack.pop();
1366                } else {
1367                    break;
1368                }
1369            }
1370
1371            if highlights.next_capture.is_none() {
1372                highlights.next_capture = highlights.captures.next();
1373            }
1374
1375            while let Some((mat, capture_ix)) = highlights.next_capture.as_ref() {
1376                let capture = mat.captures[*capture_ix as usize];
1377                if self.range.start < capture.node.start_byte() {
1378                    next_capture_start = capture.node.start_byte();
1379                    break;
1380                } else {
1381                    let style_id = highlights.highlight_map.get(capture.index);
1382                    highlights.stack.push((capture.node.end_byte(), style_id));
1383                    highlights.next_capture = highlights.captures.next();
1384                }
1385            }
1386        }
1387
1388        if let Some(chunk) = self.chunks.peek() {
1389            let chunk_start = self.range.start;
1390            let mut chunk_end = (self.chunks.offset() + chunk.len()).min(next_capture_start);
1391            let mut style_id = HighlightId::default();
1392            if let Some((parent_capture_end, parent_style_id)) =
1393                self.highlights.as_ref().and_then(|h| h.stack.last())
1394            {
1395                chunk_end = chunk_end.min(*parent_capture_end);
1396                style_id = *parent_style_id;
1397            }
1398
1399            let slice =
1400                &chunk[chunk_start - self.chunks.offset()..chunk_end - self.chunks.offset()];
1401            self.range.start = chunk_end;
1402            if self.range.start == self.chunks.offset() + chunk.len() {
1403                self.chunks.next().unwrap();
1404            }
1405
1406            Some((slice, style_id))
1407        } else {
1408            None
1409        }
1410    }
1411}
1412
1413impl QueryCursorHandle {
1414    fn new() -> Self {
1415        QueryCursorHandle(Some(
1416            QUERY_CURSORS
1417                .lock()
1418                .pop()
1419                .unwrap_or_else(|| QueryCursor::new()),
1420        ))
1421    }
1422}
1423
1424impl Deref for QueryCursorHandle {
1425    type Target = QueryCursor;
1426
1427    fn deref(&self) -> &Self::Target {
1428        self.0.as_ref().unwrap()
1429    }
1430}
1431
1432impl DerefMut for QueryCursorHandle {
1433    fn deref_mut(&mut self) -> &mut Self::Target {
1434        self.0.as_mut().unwrap()
1435    }
1436}
1437
1438impl Drop for QueryCursorHandle {
1439    fn drop(&mut self) {
1440        let mut cursor = self.0.take().unwrap();
1441        cursor.set_byte_range(0..usize::MAX);
1442        cursor.set_point_range(Point::zero().into()..Point::MAX.into());
1443        QUERY_CURSORS.lock().push(cursor)
1444    }
1445}
1446
1447fn contiguous_ranges(
1448    values: impl IntoIterator<Item = u32>,
1449    max_len: usize,
1450) -> impl Iterator<Item = Range<u32>> {
1451    let mut values = values.into_iter();
1452    let mut current_range: Option<Range<u32>> = None;
1453    std::iter::from_fn(move || loop {
1454        if let Some(value) = values.next() {
1455            if let Some(range) = &mut current_range {
1456                if value == range.end && range.len() < max_len {
1457                    range.end += 1;
1458                    continue;
1459                }
1460            }
1461
1462            let prev_range = current_range.clone();
1463            current_range = Some(value..(value + 1));
1464            if prev_range.is_some() {
1465                return prev_range;
1466            }
1467        } else {
1468            return current_range.take();
1469        }
1470    })
1471}