Skip to content

Commit

Permalink
refactor: add ExtmarkVirtTextChunk
Browse files Browse the repository at this point in the history
  • Loading branch information
noib3 committed Dec 15, 2023
1 parent 8dfe19d commit 4eab70f
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 15 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

## [Unreleased]

### Added

- a new `ExtmarkVirtTextChunk` struct;

### Changed

- the type of `ExtmarkInfos`'s `virt_text` field from
`Option<Vec<(String, OneOrMore<String>)>>` to `Vec<ExtmarkVirtTextChunk>`;

## [0.4.0] - Dec 11 2023

[Unreleased]: https://github.com/noib3/nvim-oxi/compare/v0.4.0...HEAD
Expand Down
4 changes: 2 additions & 2 deletions crates/oxi-api/src/types/extmark_infos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use oxi_types::{
};
use serde::Deserialize;

use super::{ExtmarkHlMode, ExtmarkVirtTextPosition, OneOrMore};
use super::{ExtmarkHlMode, ExtmarkVirtTextChunk, ExtmarkVirtTextPosition};

/// Extmark infos returned by `Buffer::get_extmark_by_id`.
#[non_exhaustive]
Expand Down Expand Up @@ -47,7 +47,7 @@ pub struct ExtmarkInfos {
pub virt_lines_leftcol: Option<bool>,

#[serde(default)]
pub virt_text: Option<Vec<(String, OneOrMore<String>)>>,
pub virt_text: Vec<ExtmarkVirtTextChunk>,

#[serde(default)]
pub virt_text_hide: Option<bool>,
Expand Down
80 changes: 80 additions & 0 deletions crates/oxi-api/src/types/extmark_virt_text_chunk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use oxi_types::Integer;

use super::OneOrMore;

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ExtmarkVirtTextChunk {
pub text: String,
pub hl_groups: Vec<StringOrInt>,
}

impl<'de> serde::de::Deserialize<'de> for ExtmarkVirtTextChunk {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::de::Deserializer<'de>,
{
use serde::de::{self, Visitor};

struct ExtmarkVirtTextChunkVisitor;

impl<'de> Visitor<'de> for ExtmarkVirtTextChunkVisitor {
type Value = ExtmarkVirtTextChunk;

fn expecting(
&self,
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
f.write_str("a (text, hl_group) tuple")
}

fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: de::SeqAccess<'de>,
{
let text = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?;

let hl_groups = seq
.next_element::<OneOrMore<StringOrInt>>()?
.map(|groups| match groups {
OneOrMore::One(group) => vec![group],
OneOrMore::List(groups) => groups,
})
.unwrap_or_default();

Ok(ExtmarkVirtTextChunk { text, hl_groups })
}
}

deserializer.deserialize_seq(ExtmarkVirtTextChunkVisitor)
}
}

#[derive(Clone, Debug, Eq, PartialEq, Hash, serde::Deserialize)]
#[serde(untagged)]
pub enum StringOrInt {
String(String),
Int(Integer),
}

impl From<String> for StringOrInt {
#[inline]
fn from(s: String) -> Self {
Self::String(s)
}
}

impl From<&str> for StringOrInt {
#[inline]
fn from(s: &str) -> Self {
Self::String(s.to_owned())
}
}

impl From<Integer> for StringOrInt {
#[inline]
fn from(i: Integer) -> Self {
Self::Int(i)
}
}
2 changes: 2 additions & 0 deletions crates/oxi-api/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ mod editor_context;
mod extmark_hl_mode;
mod extmark_infos;
mod extmark_position;
mod extmark_virt_text_chunk;
mod extmark_virt_text_position;
mod got_mode;
mod highlight_infos;
Expand Down Expand Up @@ -66,6 +67,7 @@ pub use editor_context::*;
pub use extmark_hl_mode::*;
pub use extmark_infos::*;
pub use extmark_position::*;
pub use extmark_virt_text_chunk::*;
pub use extmark_virt_text_position::*;
pub use got_mode::*;
pub use highlight_infos::*;
Expand Down
49 changes: 36 additions & 13 deletions tests/src/api/extmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,24 @@ fn get_extmarks() {
assert_eq!(Some(ExtmarkHlMode::Combine), infos.hl_mode);

#[cfg(feature = "neovim-nightly")]
let virt_text = vec![(
"foo".to_owned(),
vec!["Foo".to_owned(), "Bar".to_owned()].into(),
)];
let virt_text = vec![ExtmarkVirtTextChunk {
text: "foo".to_owned(),
hl_groups: vec!["Foo".into(), "Bar".into()],
}];

#[cfg(not(feature = "neovim-nightly"))]
let virt_text =
vec![("".into(), "Foo".into()), ("foo".into(), "Bar".into())];
let virt_text = vec![
ExtmarkVirtTextChunk {
text: "".to_owned(),
hl_groups: vec!["Foo".into()],
},
ExtmarkVirtTextChunk {
text: "foo".to_owned(),
hl_groups: vec!["Bar".into()],
},
];

assert_eq!(Some(virt_text), infos.virt_text);
assert_eq!(infos.virt_text, virt_text);

assert_eq!(Some(ExtmarkVirtTextPosition::Overlay), infos.virt_text_pos);
}
Expand Down Expand Up @@ -167,18 +175,33 @@ fn set_get_del_extmark() {

#[cfg(feature = "neovim-nightly")]
let virt_text = vec![
("foo".to_owned(), "Foo".into()),
("bar".to_owned(), vec!["Bar".to_owned(), "Baz".to_owned()].into()),
ExtmarkVirtTextChunk {
text: "foo".to_owned(),
hl_groups: vec!["Foo".into()],
},
ExtmarkVirtTextChunk {
text: "bar".to_owned(),
hl_groups: vec!["Bar".into(), "Baz".into()],
},
];

#[cfg(not(feature = "neovim-nightly"))]
let virt_text = vec![
("foo".into(), "Foo".into()),
("".into(), "Bar".into()),
("bar".into(), "Baz".into()),
ExtmarkVirtTextChunk {
text: "foo".to_owned(),
hl_groups: vec!["Foo".into()],
},
ExtmarkVirtTextChunk {
text: "".to_owned(),
hl_groups: vec!["Bar".into()],
},
ExtmarkVirtTextChunk {
text: "bar".to_owned(),
hl_groups: vec!["Baz".into()],
},
];

assert_eq!(Some(virt_text), infos.virt_text);
assert_eq!(infos.virt_text, virt_text);

assert_eq!(Some(ExtmarkVirtTextPosition::Overlay), infos.virt_text_pos);

Expand Down

0 comments on commit 4eab70f

Please sign in to comment.