From 92c2d5d3bffb52a165fad75b6db2120de37b5ae4 Mon Sep 17 00:00:00 2001 From: Kirawi <67773714+kirawi@users.noreply.github.com> Date: Mon, 25 Oct 2021 12:02:16 -0400 Subject: [PATCH] Document more of helix-core (#904) --- helix-core/src/auto_pairs.rs | 3 + helix-core/src/chars.rs | 2 + helix-core/src/comment.rs | 3 + helix-core/src/diagnostic.rs | 5 ++ helix-core/src/graphemes.rs | 4 +- helix-core/src/history.rs | 105 ++++++++++++++++++++++------------- 6 files changed, 81 insertions(+), 41 deletions(-) diff --git a/helix-core/src/auto_pairs.rs b/helix-core/src/auto_pairs.rs index 9b901e9b..cc966852 100644 --- a/helix-core/src/auto_pairs.rs +++ b/helix-core/src/auto_pairs.rs @@ -1,3 +1,6 @@ +//! When typing the opening character of one of the possible pairs defined below, +//! this module provides the functionality to insert the paired closing character. + use crate::{Range, Rope, Selection, Tendril, Transaction}; use smallvec::SmallVec; diff --git a/helix-core/src/chars.rs b/helix-core/src/chars.rs index 24133dd3..c8e5efbd 100644 --- a/helix-core/src/chars.rs +++ b/helix-core/src/chars.rs @@ -1,3 +1,5 @@ +//! Utility functions to categorize a `char`. + use crate::LineEnding; #[derive(Debug, Eq, PartialEq)] diff --git a/helix-core/src/comment.rs b/helix-core/src/comment.rs index 3d8e1ce3..4072a532 100644 --- a/helix-core/src/comment.rs +++ b/helix-core/src/comment.rs @@ -1,3 +1,6 @@ +//! This module contains the functionality toggle comments on lines over the selection +//! using the comment character defined in the user's `languages.toml` + use crate::{ find_first_non_whitespace_char, Change, Rope, RopeSlice, Selection, Tendril, Transaction, }; diff --git a/helix-core/src/diagnostic.rs b/helix-core/src/diagnostic.rs index e08a71e7..ab47e075 100644 --- a/helix-core/src/diagnostic.rs +++ b/helix-core/src/diagnostic.rs @@ -1,3 +1,6 @@ +//! LSP diagnostic utility types. + +/// Describes the severity level of a [`Diagnostic`]. #[derive(Debug, Eq, PartialEq)] pub enum Severity { Error, @@ -6,12 +9,14 @@ pub enum Severity { Hint, } +/// A range of `char`s within the text. #[derive(Debug)] pub struct Range { pub start: usize, pub end: usize, } +/// Corresponds to [`lsp_types::Diagnostic`](https://docs.rs/lsp-types/0.91.0/lsp_types/struct.Diagnostic.html) #[derive(Debug)] pub struct Diagnostic { pub range: Range, diff --git a/helix-core/src/graphemes.rs b/helix-core/src/graphemes.rs index 0465fe51..56f5bacb 100644 --- a/helix-core/src/graphemes.rs +++ b/helix-core/src/graphemes.rs @@ -1,4 +1,6 @@ -// Based on https://github.com/cessen/led/blob/c4fa72405f510b7fd16052f90a598c429b3104a6/src/graphemes.rs +//! Utility functions to traverse the unicode graphemes of a `Rope`'s text contents. +//! +//! Based on https://github.com/cessen/led/blob/c4fa72405f510b7fd16052f90a598c429b3104a6/src/graphemes.rs use ropey::{iter::Chunks, str_utils::byte_to_char_idx, RopeSlice}; use unicode_segmentation::{GraphemeCursor, GraphemeIncomplete}; use unicode_width::UnicodeWidthStr; diff --git a/helix-core/src/history.rs b/helix-core/src/history.rs index 67ded166..cf62708a 100644 --- a/helix-core/src/history.rs +++ b/helix-core/src/history.rs @@ -4,48 +4,50 @@ use regex::Regex; use std::num::NonZeroUsize; use std::time::{Duration, Instant}; -// Stores the history of changes to a buffer. -// -// Currently the history is represented as a vector of revisions. The vector -// always has at least one element: the empty root revision. Each revision -// with the exception of the root has a parent revision, a [Transaction] -// that can be applied to its parent to transition from the parent to itself, -// and an inversion of that transaction to transition from the parent to its -// latest child. -// -// When using `u` to undo a change, an inverse of the stored transaction will -// be applied which will transition the buffer to the parent state. -// -// Each revision with the exception of the last in the vector also has a -// last child revision. When using `U` to redo a change, the last child transaction -// will be applied to the current state of the buffer. -// -// The current revision is the one currently displayed in the buffer. -// -// Commiting a new revision to the history will update the last child of the -// current revision, and push a new revision to the end of the vector. -// -// Revisions are commited with a timestamp. :earlier and :later can be used -// to jump to the closest revision to a moment in time relative to the timestamp -// of the current revision plus (:later) or minus (:earlier) the duration -// given to the command. If a single integer is given, the editor will instead -// jump the given number of revisions in the vector. -// -// Limitations: -// * Changes in selections currently don't commit history changes. The selection -// will only be updated to the state after a commited buffer change. -// * The vector of history revisions is currently unbounded. This might -// cause the memory consumption to grow significantly large during long -// editing sessions. -// * Because delete transactions currently don't store the text that they -// delete, we also store an inversion of the transaction. +/// Stores the history of changes to a buffer. +/// +/// Currently the history is represented as a vector of revisions. The vector +/// always has at least one element: the empty root revision. Each revision +/// with the exception of the root has a parent revision, a [Transaction] +/// that can be applied to its parent to transition from the parent to itself, +/// and an inversion of that transaction to transition from the parent to its +/// latest child. +/// +/// When using `u` to undo a change, an inverse of the stored transaction will +/// be applied which will transition the buffer to the parent state. +/// +/// Each revision with the exception of the last in the vector also has a +/// last child revision. When using `U` to redo a change, the last child transaction +/// will be applied to the current state of the buffer. +/// +/// The current revision is the one currently displayed in the buffer. +/// +/// Commiting a new revision to the history will update the last child of the +/// current revision, and push a new revision to the end of the vector. +/// +/// Revisions are commited with a timestamp. :earlier and :later can be used +/// to jump to the closest revision to a moment in time relative to the timestamp +/// of the current revision plus (:later) or minus (:earlier) the duration +/// given to the command. If a single integer is given, the editor will instead +/// jump the given number of revisions in the vector. +/// +/// Limitations: +/// * Changes in selections currently don't commit history changes. The selection +/// will only be updated to the state after a commited buffer change. +/// * The vector of history revisions is currently unbounded. This might +/// cause the memory consumption to grow significantly large during long +/// editing sessions. +/// * Because delete transactions currently don't store the text that they +/// delete, we also store an inversion of the transaction. +/// +/// Using time to navigate the history: https://github.com/helix-editor/helix/pull/194 #[derive(Debug)] pub struct History { revisions: Vec, current: usize, } -// A single point in history. See [History] for more information. +/// A single point in history. See [History] for more information. #[derive(Debug)] struct Revision { parent: usize, @@ -111,6 +113,7 @@ impl History { self.current == 0 } + /// Undo the last edit. pub fn undo(&mut self) -> Option<&Transaction> { if self.at_root() { return None; @@ -121,6 +124,7 @@ impl History { Some(¤t_revision.inversion) } + /// Redo the last edit. pub fn redo(&mut self) -> Option<&Transaction> { let current_revision = &self.revisions[self.current]; let last_child = current_revision.last_child?; @@ -147,8 +151,8 @@ impl History { } } - // List of nodes on the way from `n` to 'a`. Doesn`t include `a`. - // Includes `n` unless `a == n`. `a` must be an ancestor of `n`. + /// List of nodes on the way from `n` to 'a`. Doesn`t include `a`. + /// Includes `n` unless `a == n`. `a` must be an ancestor of `n`. fn path_up(&self, mut n: usize, a: usize) -> Vec { let mut path = Vec::new(); while n != a { @@ -158,6 +162,7 @@ impl History { path } + /// Create a [`Transaction`] that will jump to a specific revision in the history. fn jump_to(&mut self, to: usize) -> Vec { let lca = self.lowest_common_ancestor(self.current, to); let up = self.path_up(self.current, lca); @@ -171,10 +176,12 @@ impl History { up_txns.chain(down_txns).collect() } + /// Creates a [`Transaction`] that will undo `delta` revisions. fn jump_backward(&mut self, delta: usize) -> Vec { self.jump_to(self.current.saturating_sub(delta)) } + /// Creates a [`Transaction`] that will redo `delta` revisions. fn jump_forward(&mut self, delta: usize) -> Vec { self.jump_to( self.current @@ -183,7 +190,7 @@ impl History { ) } - // Helper for a binary search case below. + /// Helper for a binary search case below. fn revision_closer_to_instant(&self, i: usize, instant: Instant) -> usize { let dur_im1 = instant.duration_since(self.revisions[i - 1].timestamp); let dur_i = self.revisions[i].timestamp.duration_since(instant); @@ -194,6 +201,8 @@ impl History { } } + /// Creates a [`Transaction`] that will match a revision created at around + /// `instant`. fn jump_instant(&mut self, instant: Instant) -> Vec { let search_result = self .revisions @@ -209,6 +218,8 @@ impl History { self.jump_to(revision) } + /// Creates a [`Transaction`] that will match a revision created `duration` ago + /// from the timestamp of current revision. fn jump_duration_backward(&mut self, duration: Duration) -> Vec { match self.revisions[self.current].timestamp.checked_sub(duration) { Some(instant) => self.jump_instant(instant), @@ -216,6 +227,8 @@ impl History { } } + /// Creates a [`Transaction`] that will match a revision created `duration` in + /// the future from the timestamp of the current revision. fn jump_duration_forward(&mut self, duration: Duration) -> Vec { match self.revisions[self.current].timestamp.checked_add(duration) { Some(instant) => self.jump_instant(instant), @@ -223,6 +236,7 @@ impl History { } } + /// Creates an undo [`Transaction`]. pub fn earlier(&mut self, uk: UndoKind) -> Vec { use UndoKind::*; match uk { @@ -231,6 +245,7 @@ impl History { } } + /// Creates a redo [`Transaction`]. pub fn later(&mut self, uk: UndoKind) -> Vec { use UndoKind::*; match uk { @@ -240,13 +255,14 @@ impl History { } } +/// Whether to undo by a number of edits or a duration of time. #[derive(Debug, PartialEq)] pub enum UndoKind { Steps(usize), TimePeriod(std::time::Duration), } -// A subset of sytemd.time time span syntax units. +/// A subset of sytemd.time time span syntax units. const TIME_UNITS: &[(&[&str], &str, u64)] = &[ (&["seconds", "second", "sec", "s"], "seconds", 1), (&["minutes", "minute", "min", "m"], "minutes", 60), @@ -254,11 +270,20 @@ const TIME_UNITS: &[(&[&str], &str, u64)] = &[ (&["days", "day", "d"], "days", 24 * 60 * 60), ]; +/// Checks if the duration input can be turned into a valid duration. It must be a +/// positive integer and denote the [unit of time.](`TIME_UNITS`) +/// Examples of valid durations: +/// * `5 sec` +/// * `5 min` +/// * `5 hr` +/// * `5 days` static DURATION_VALIDATION_REGEX: Lazy = Lazy::new(|| Regex::new(r"^(?:\d+\s*[a-z]+\s*)+$").unwrap()); +/// Captures both the number and unit as separate capture groups. static NUMBER_UNIT_REGEX: Lazy = Lazy::new(|| Regex::new(r"(\d+)\s*([a-z]+)").unwrap()); +/// Parse a string (e.g. "5 sec") and try to convert it into a [`Duration`]. fn parse_human_duration(s: &str) -> Result { if !DURATION_VALIDATION_REGEX.is_match(s) { return Err("duration should be composed \