diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 14 | ||||
-rw-r--r-- | src/suggestion.rs | 81 |
2 files changed, 95 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs index 2900669..d8c7582 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,18 @@ +// Copyright (c) 2021 Soni L. + +//! Iosonism is a command parsing library. It parses commands from strings, in +//! contrast with an argument parsing library, which parses arrays of strings. +//! +//! Iosonism is based on [Brigadier](https://github.com/Mojang/brigadier). + +// quick overview of brigadier vs iosonism: +// +// - brigadier.StringReader -> iosonism::strcursor::StringReader + Cursor<&str> +// - brigadier.context.StringRange -> Range<usize> +// - brigadier.suggestion.Suggestion -> iosonism::suggestion::Suggestion; + pub mod strcursor; +pub mod suggestion; #[cfg(test)] mod tests { diff --git a/src/suggestion.rs b/src/suggestion.rs new file mode 100644 index 0000000..bad9793 --- /dev/null +++ b/src/suggestion.rs @@ -0,0 +1,81 @@ +// Copyright (c) 2021 Soni L. +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. + +//! A Suggestion. + +use ::std::ops::Range; + +/// A suggested editing operation. +/// +/// # Examples +/// +/// ```rust +/// use iosonism::suggestion::Suggestion; +/// +/// let s = Suggestion::new(3..3, "home".into()); +/// assert_eq!(s.apply("Go ".into()), "Go home"); +/// ``` +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct Suggestion { + range: Range<usize>, + text: String, +} + +impl Suggestion { + /// Creates a new `Suggestion` for `text` for the given `range`. + pub fn new(range: Range<usize>, text: String) -> Self { + Self { + range: range, + text: text, + } + } + + /// Returns the range associated with this suggestion. + pub fn get_range(&self) -> Range<usize> { + self.range.clone() + } + + /// Returns the replacement text associated with this suggestion. + pub fn get_text(&self) -> &str { + &self.text + } + + /// Applies this suggestion on the `input`. + /// + /// # Panics + /// + /// Panics if the range is outside the `input`'s bounds, or not on an UTF-8 + /// boundary. + pub fn apply(&self, mut input: String) -> String { + // the use of String here actually has a performance reason: + // either you already have a String, in which case this is fast, + // or you need a String anyway, in which case it's your responsibility + // to make your &str into one. + input.replace_range(self.range.clone(), &self.text); + input + } + + /// Creates a new `Suggestion` by applying this `Suggestion` on the + /// `range` part of the given `input`. + /// + /// # Panics + /// + /// May panic if this suggestion's range is outside the bounds given by + /// `range`. Panics if the given `range` is outside `input`'s bounds, or any + /// range is not on an UTF-8 boundary. + // FIXME: This function could really use a better description. + pub fn expand(&self, mut input: String, range: Range<usize>) -> Self { + // It is our understanding that both ranges must be within input. + // It's also our understanding that self.range must be within the passed + // range. + // So we just do our best to enforce those. + input.truncate(range.end); + input.drain(..range.start); + input.replace_range( + (self.range.start-range.start)..(self.range.end-range.start), + &self.text, + ); + Self::new(range, input) + } +} |