Repository: helix-editor/helix
File: helix-core/src/transaction.rs (Rust)

Code before:
                    // pos += n;
                }
                Insert(s) => {
                    text.insert(pos, s);
                    pos += s.chars().count();
                }
            }
        }
        true
    }

    /// `true` when the set is empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.changes.is_empty() || self.changes == [Operation::Retain(self.len)]
    }

    /// Map a position through the changes.
    ///
    /// `assoc` indicates which size to associate the position with. `Before` will keep the
    /// position close to the character before, and will place it before insertions over that
    /// range, or at that point. `After` will move it forward, placing it at the end of such
    /// insertions.
    ///
    /// The stick variants of these two indicate that `pos` should remain unchaged for exact replacements. This is
    //// desirable for cursors but undesirable for other things like diagnostics
    pub fn map_pos(&self, pos: usize, assoc: Assoc) -> usize {
        use Operation::*;
        let mut old_pos = 0;
        let mut new_pos = 0;

        let mut iter = self.changes.iter().peekable();

        while let Some(change) = iter.next() {
            let len = match change {
                Delete(i) | Retain(i) => *i,
                Insert(_) => 0,
            };
            let mut old_end = old_pos + len;

            match change {
                Retain(_) => {
                    if old_end > pos {
                        return new_pos + (pos - old_pos);
                    }
                    new_pos += len;
                }
                Delete(_) => {
                    // in range
                    if old_end > pos {
                        return new_pos;

Review comment (suggestion):
```suggestion
    /// The "sticky" variants of these two indicate that `pos` should remain unchanged for exact replacements. This is
    /// desirable for cursors but undesirable for other things like diagnostics
```

Code after:
            }
        }

        changes
    }

    /// Returns true if applied successfully.
    pub fn apply(&self, text: &mut Rope) -> bool {
        if text.len_chars() != self.len {
            return false;
        }

        let mut pos = 0;

        for change in &self.changes {
            use Operation::*;
            match change {
                Retain(n) => {
                    pos += n;
                }
                Delete(n) => {
                    text.remove(pos..pos + *n);
                    // pos += n;
                }
                Insert(s) => {
                    text.insert(pos, s);
                    pos += s.chars().count();
                }
            }
        }
        true
    }

    /// `true` when the set is empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.changes.is_empty() || self.changes == [Operation::Retain(self.len)]
    }

    /// Map a (mostly) *sorted* list of positions through the changes.
    ///
    /// This is equivalent to updating each position with `map_pos`:
    ///
    /// ``` no-compile
    /// for (pos, assoc) in positions {
    ///     *pos = changes.map_pos(*pos, assoc);
    /// }
    /// ```
    /// However this function is significantly faster for sorted lists running
    /// in `O(N+M)` instead of `O(NM)`. This function also handles unsorted/
    /// partially sorted lists. However, in that case worst case complexity is