This commit is contained in:
ef3d0c3e 2024-12-01 08:42:22 +01:00
parent ac8862e459
commit 347fd6ce59
8 changed files with 65 additions and 27 deletions

4
src/cache/cache.rs vendored
View file

@ -33,9 +33,9 @@ pub trait Cached {
/// # Error
///
/// Will return an error if the database connection(s) fail,
/// or if not cached, an error from the generator [`f`]
/// or if not cached, an error from the generator `f`
///
/// Note that on error, [`f`] may still have been called
/// Note that on error, `f` may still have been called
fn cached<E, F>(
&self,
con: &Connection,

View file

@ -300,7 +300,7 @@ pub struct CompiledDocument {
pub variables: HashMap<String, String>,
/// All the referenceable elements in the document
/// with values mapped by [`ReferenceableElement::refid()`]
/// with values mapped by [`crate::document::element::ReferenceableElement::refid()`]
pub references: HashMap<String, String>,
/// Compiled document's header

View file

@ -177,11 +177,11 @@ pub trait Document<'a>: core::fmt::Debug {
}
}
/// Merges [`other`] into [`self`]
/// Merges another [`Document`]'s scope into [`self`]
///
/// # Parameters
///
/// If [`merge_as`] is None, references and variables from the other document are not merged into self
/// If `merge_as` is None, references and variables from the other document are not merged into self
fn merge(
&self,
content: &RefCell<Vec<Box<dyn Element>>>,

View file

@ -180,7 +180,7 @@ impl<'a, 'b> ParserState<'a, 'b> {
/// 2. (Optional) The winning match with it's match data
/// If the winning match is None, it means that the document has no more
/// rule to match. I.e The rest of the content should be added as a
/// [`Text`] element.
/// [`crate::elements::text::Text`] element.
/// The match data should be passed to the [`Rule::on_match`] method.
///
/// # Strategy
@ -298,13 +298,13 @@ impl<'a, 'b> ParserState<'a, 'b> {
}
/// Resets the position and the match_data for a given rule. This is used
/// in order to have 'dynamic' rules that may not match at first, but their
/// matching rule is modified through the parsing process.
/// in order to have 'dynamic' rules that may not match at first, but may match
/// in the future when modified.
///
/// This function also recursively calls itself on it's `parent`, in order
/// to fully reset the match.
///
/// See [`CustomStyleRule`] for an example of how this is used.
/// See [`crate::elements::customstyle::CustomStyleRule`] for an example of how this is used.
///
/// # Error
///

View file

@ -70,7 +70,7 @@ pub trait Rule: Downcast {
/// The name of the rule that should come before this one
fn previous(&self) -> Option<&'static str>;
/// Finds the next match starting from [`cursor`]
/// Finds the next match starting from `cursor`
fn next_match(
&self,
mode: &ParseMode,
@ -137,7 +137,7 @@ impl<T: RegexRule + 'static> Rule for T {
fn previous(&self) -> Option<&'static str> { RegexRule::previous(self) }
/// Finds the next match starting from [`cursor`]
/// Finds the next match starting from [`Cursor`]
fn next_match(
&self,
mode: &ParseMode,

View file

@ -10,8 +10,13 @@ use unicode_segmentation::UnicodeSegmentation;
/// Trait for source content
pub trait Source: Downcast + Debug {
/// Gets the source's location
///
/// This usually means the parent source.
/// If the source is a [`SourceFile`], this generally means the [`SourceFile`] that included it.
fn location(&self) -> Option<&Token>;
/// Gets the source's name
///
/// For [`SourceFile`] this means the path of the source. Note that some [`VirtualSource`] are prefixed with a special identifier such as `:LUA:`.
fn name(&self) -> &String;
/// Gets the source's content
fn content(&self) -> &String;
@ -37,13 +42,19 @@ impl std::hash::Hash for dyn Source {
/// [`SourceFile`] is a type of [`Source`] that represents a real file.
#[derive(Debug)]
pub struct SourceFile {
/// The token that created this [`SourceFile`], empty if file comes from the executable's
/// options.
location: Option<Token>,
/// Path to the file, used for the [`Self::name()`] method
path: String,
/// Content of the file
content: String,
}
impl SourceFile {
// TODO: Create a SourceFileRegistry holding already loaded files to avoid reloading them
/// Creates a [`SourceFile`] from a `path`. This will read the content of the file at that
/// `path`. In case the file is not accessible or reading fails, an error is returned.
pub fn new(path: String, location: Option<Token>) -> Result<Self, String> {
match fs::read_to_string(&path) {
Err(_) => Err(format!("Unable to read file content: `{}`", path)),
@ -55,6 +66,7 @@ impl SourceFile {
}
}
/// Creates a [`SourceFile`] from a `String`
pub fn with_content(path: String, content: String, location: Option<Token>) -> Self {
Self {
location,
@ -63,6 +75,7 @@ impl SourceFile {
}
}
/// Gets the path of this [`SourceFile`]
pub fn path(&self) -> &String { &self.path }
}
@ -79,8 +92,8 @@ impl Source for SourceFile {
///
/// # Example
///
/// Let's say you make a virtual source from the following: "Con\]tent" -> "Con]tent"
/// Then at position 3, an offset of 1 will be created to account for the removed '\'
/// Let's say you make a virtual source from the following: "Con\\]tent" -> "Con]tent"
/// Then at position 3, an offset of 1 will be created to account for the removed '\\'
#[derive(Debug)]
struct SourceOffset {
/// Stores the total offsets
@ -105,16 +118,25 @@ impl SourceOffset {
/// [`VirtualSource`] is a type of [`Source`] that represents a virtual file. [`VirtualSource`]s
/// can be created from other [`VirtualSource`]s but it must always come from a [`SourceFile`].
///
/// # Offsets
///
/// [`VirtualSource`] will keep a list of offsets that were applied from the their parent source (available via [`Self::location`]).
/// For instance, if you consider the [`VirtualSource`] created by removing the '\\' from the following string: "He\\llo", then an offset is stored to account for the missing '\\'. This is required in order to keep diagnostics accurate.
#[derive(Debug)]
pub struct VirtualSource {
/// Token that createrd this [`VirtualSource`]
location: Token,
/// Name of the [`VirtualSource`]
name: String,
/// Content of the [`VirtualSource`]
content: String,
/// Offset relative to the [`location`]'s source
/// Offsets relative to the [`Self::location`]'s source
offsets: Option<SourceOffset>,
}
impl VirtualSource {
/// Creates a new [`VirtualSource`] from a `location`, `name` and `content`.
pub fn new(location: Token, name: String, content: String) -> Self {
Self {
location,
@ -124,6 +146,11 @@ impl VirtualSource {
}
}
/// Creates a new [`VirtualSource`] from a `location`, `name`, `content` and `offsets`.
///
/// # Notes
///
/// This should be called by [`crate::parser::util::escape_source`]
pub fn new_offsets(
location: Token,
name: String,
@ -233,7 +260,7 @@ pub struct Cursor {
impl Cursor {
pub fn new(pos: usize, source: Rc<dyn Source>) -> Self { Self { pos, source } }
/// Creates [`cursor`] at [`new_pos`] in the same [`file`]
/// Creates [`Cursor`] at `new_pos` in the same [`Source`]
pub fn at(&self, new_pos: usize) -> Self {
Self {
pos: new_pos,
@ -246,7 +273,7 @@ impl Cursor {
///
/// # Notes
///
/// Because the LSP uses UTF-16 encoded positions, field [`line_pos`] corresponds to the UTF-16
/// Because the LSP uses UTF-16 encoded positions, field [`Self::line_pos`] corresponds to the UTF-16
/// distance between the first character (position = 0 or after '\n') and the character at the
/// current position.
#[derive(Debug, Clone)]
@ -273,10 +300,11 @@ impl LineCursor {
}
/// Moves [`LineCursor`] to an absolute byte position
/// This function may only advance the position, as is required for the LSP semantics.
///
/// # Error
///
/// This function will panic if [`pos`] is not utf8 aligned
/// This function will panic if [`Self::pos`] is not UTF-88 aligned, or if trying to go to a previous position.
pub fn move_to(&mut self, pos: usize) {
if self.pos < pos {
let start = self.pos;

View file

@ -5,18 +5,20 @@ use downcast_rs::impl_downcast;
use downcast_rs::Downcast;
/// Styling for an element
///
/// Some elements have support for styling.
pub trait ElementStyle: Downcast + core::fmt::Debug {
/// The style key
fn key(&self) -> &'static str;
/// Attempts to create a new style from a [`json`] string
/// Attempts to create a new style from a `json` string
///
/// # Errors
///
/// Will fail if deserialization fails
fn from_json(&self, json: &str) -> Result<Rc<dyn ElementStyle>, String>;
/// Attempts to deserialize lua table into a new style
/// Attempts to deserialize a `lua table` into a new style
fn from_lua(
&self,
lua: &mlua::Lua,
@ -25,6 +27,7 @@ pub trait ElementStyle: Downcast + core::fmt::Debug {
}
impl_downcast!(ElementStyle);
/// A structure that holds registered [`ElementStyle`]
#[derive(Default)]
pub struct StyleHolder {
styles: HashMap<String, Rc<dyn ElementStyle>>,
@ -35,13 +38,17 @@ impl StyleHolder {
pub fn is_registered(&self, style_key: &str) -> bool { self.styles.contains_key(style_key) }
/// Gets the current active style for an element
/// NOTE: Will panic if a style is not defined for a given element
/// If you need to process user input, use [`is_registered`]
/// If you need to process user input, use [`Self::is_registered`]
///
/// # Notes
///
/// Will panic if a style is not defined for a given element.
/// Elements should have their styles (when they support it) registered when the parser starts.
pub fn current(&self, style_key: &str) -> Rc<dyn ElementStyle> {
self.styles.get(style_key).cloned().unwrap()
}
/// Sets the [`style`]
/// Sets the style
pub fn set_current(&mut self, style: Rc<dyn ElementStyle>) {
self.styles.insert(style.key().to_string(), style);
}

View file

@ -90,12 +90,15 @@ pub fn process_text(document: &dyn Document, content: &str) -> String {
processed
}
/// Transforms source into a new [`VirtualSource`]. Transforms range from source by
/// detecting escaped tokens.
/// Transforms source into a new [`VirtualSource`] using a `range`.
///
/// This function will extract the sub-source using the specified `range`, then escape `token` using the specified `escape` character.
/// It will also keep a list of removed/added characters and build an offset list that will be passed to the newly created source, via [`VirtualSource::new_offsets`].
///
///
/// # Notes
///
/// If you only need to escape content that won't be parsed, use [`process_escaped`] instead.
/// If you only need to escape content that won't be parsed, use [`escape_text`] instead.
pub fn escape_source(
source: Rc<dyn Source>,
range: Range<usize>,
@ -147,11 +150,11 @@ pub fn escape_source(
}
/// Processed a string and escapes a single token out of it
/// Escaped characters other than the [`token`] will be not be treated as escaped
/// Escaped characters other than the [`Token`] will be not be treated as escaped
///
/// # Example
/// ```
/// assert_eq!(process_escaped('\\', "%", "escaped: \\%, also escaped: \\\\\\%, untouched: \\a"),
/// assert_eq!(scape_text('\\', "%", "escaped: \\%, also escaped: \\\\\\%, untouched: \\a"),
/// "escaped: %, also escaped: \\%, untouched: \\a");
/// ```
///