@@ -1,665 +1,665 @@
1−use bitflags::bitflags;
1+use bitflags::bitflags;
2−use serde::{Deserialize, Serialize};
2+use serde::{Deserialize, Serialize};
4− cmp::{max, min},
4+ cmp::{max, min},
5− str::FromStr,
5+ str::FromStr,
8−#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
8+#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
9−#[serde(rename_all = "lowercase")]
9+#[serde(rename_all = "lowercase")]
10−/// UNSTABLE
10+/// UNSTABLE
11−pub enum CursorKind {
11+pub enum CursorKind {
17− Underline,
17+ Underline,
18− /// Hidden cursor, can set cursor position with this to let IME have correct cursor position.
18+ /// Hidden cursor, can set cursor position with this to let IME have correct cursor position.
22−impl Default for CursorKind {
22+impl Default for CursorKind {
23− fn default() -> Self {
23+ fn default() -> Self {
24− Self::Block
24+ Self::Block
28−#[derive(Debug, Clone, PartialEq, Eq, Hash)]
28+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
29−pub struct Margin {
29+pub struct Margin {
30− pub left: u16,
30+ pub left: u16,
31− pub right: u16,
31+ pub right: u16,
32− pub top: u16,
32+ pub top: u16,
33− pub bottom: u16,
33+ pub bottom: u16,
36−impl Margin {
36+impl Margin {
37− pub fn none() -> Self {
37+ pub fn none() -> Self {
40− right: 0,
40+ right: 0,
42− bottom: 0,
42+ bottom: 0,
46− /// Set uniform margin for all sides.
46+ /// Set uniform margin for all sides.
47− pub fn all(value: u16) -> Self {
47+ pub fn all(value: u16) -> Self {
49− left: value,
49+ left: value,
50− right: value,
50+ right: value,
51− top: value,
51+ top: value,
52− bottom: value,
52+ bottom: value,
56− /// Set the margin of left and right sides to specified value.
56+ /// Set the margin of left and right sides to specified value.
57− pub fn horizontal(value: u16) -> Self {
57+ pub fn horizontal(value: u16) -> Self {
59− left: value,
59+ left: value,
60− right: value,
60+ right: value,
62− bottom: 0,
62+ bottom: 0,
66− /// Set the margin of top and bottom sides to specified value.
66+ /// Set the margin of top and bottom sides to specified value.
67− pub fn vertical(value: u16) -> Self {
67+ pub fn vertical(value: u16) -> Self {
70− right: 0,
70+ right: 0,
71− top: value,
71+ top: value,
72− bottom: value,
72+ bottom: value,
76− /// Get the total width of the margin (left + right)
76+ /// Get the total width of the margin (left + right)
77− pub fn width(&self) -> u16 {
77+ pub fn width(&self) -> u16 {
78− self.left + self.right
78+ self.left + self.right
81− /// Get the total height of the margin (top + bottom)
81+ /// Get the total height of the margin (top + bottom)
82− pub fn height(&self) -> u16 {
82+ pub fn height(&self) -> u16 {
83− self.top + self.bottom
83+ self.top + self.bottom
87−/// A simple rectangle used in the computation of the layout and to give widgets an hint about the
87+/// A simple rectangle used in the computation of the layout and to give widgets an hint about the
88−/// area they are supposed to render to. (x, y) = (0, 0) is at the top left corner of the screen.
88+/// area they are supposed to render to. (x, y) = (0, 0) is at the top left corner of the screen.
89−#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)]
89+#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)]
90−pub struct Rect {
90+pub struct Rect {
91− pub x: u16,
91+ pub x: u16,
92− pub y: u16,
92+ pub y: u16,
93− pub width: u16,
93+ pub width: u16,
94− pub height: u16,
94+ pub height: u16,
97−impl Rect {
97+impl Rect {
98− /// Creates a new rect, with width and height limited to keep the area under max u16.
98+ /// Creates a new rect, with width and height limited to keep the area under max u16.
99− /// If clipped, aspect ratio will be preserved.
99+ /// If clipped, aspect ratio will be preserved.
100− pub fn new(x: u16, y: u16, width: u16, height: u16) -> Rect {
100+ pub fn new(x: u16, y: u16, width: u16, height: u16) -> Rect {
101− let max_area = u16::max_value();
101+ let max_area = u16::max_value();
102− let (clipped_width, clipped_height) =
102+ let (clipped_width, clipped_height) =
103− if u32::from(width) * u32::from(height) > u32::from(max_area) {
103+ if u32::from(width) * u32::from(height) > u32::from(max_area) {
104− let aspect_ratio = f64::from(width) / f64::from(height);
104+ let aspect_ratio = f64::from(width) / f64::from(height);
105− let max_area_f = f64::from(max_area);
105+ let max_area_f = f64::from(max_area);
106− let height_f = (max_area_f / aspect_ratio).sqrt();
106+ let height_f = (max_area_f / aspect_ratio).sqrt();
107− let width_f = height_f * aspect_ratio;
107+ let width_f = height_f * aspect_ratio;
108− (width_f as u16, height_f as u16)
108+ (width_f as u16, height_f as u16)
109− } else {
109+ } else {
110− (width, height)
110+ (width, height)
115− width: clipped_width,
115+ width: clipped_width,
116− height: clipped_height,
116+ height: clipped_height,
120− #[inline]
120+ #[inline]
121− pub fn area(self) -> u16 {
121+ pub fn area(self) -> u16 {
122− self.width * self.height
122+ self.width * self.height
125− #[inline]
125+ #[inline]
126− pub fn left(self) -> u16 {
126+ pub fn left(self) -> u16 {
130− #[inline]
130+ #[inline]
131− pub fn right(self) -> u16 {
131+ pub fn right(self) -> u16 {
132− self.x.saturating_add(self.width)
132+ self.x.saturating_add(self.width)
135− #[inline]
135+ #[inline]
136− pub fn top(self) -> u16 {
136+ pub fn top(self) -> u16 {
140− #[inline]
140+ #[inline]
141− pub fn bottom(self) -> u16 {
141+ pub fn bottom(self) -> u16 {
142− self.y.saturating_add(self.height)
142+ self.y.saturating_add(self.height)
145− // Returns a new Rect with width reduced from the left side.
145+ // Returns a new Rect with width reduced from the left side.
146− // This changes the `x` coordinate and clamps it to the right
146+ // This changes the `x` coordinate and clamps it to the right
147− // edge of the original Rect.
147+ // edge of the original Rect.
148− pub fn clip_left(self, width: u16) -> Rect {
148+ pub fn clip_left(self, width: u16) -> Rect {
149− let width = std::cmp::min(width, self.width);
149+ let width = std::cmp::min(width, self.width);
151− x: self.x.saturating_add(width),
151+ x: self.x.saturating_add(width),
152− width: self.width.saturating_sub(width),
152+ width: self.width.saturating_sub(width),
157− // Returns a new Rect with width reduced from the right side.
157+ // Returns a new Rect with width reduced from the right side.
158− // This does _not_ change the `x` coordinate.
158+ // This does _not_ change the `x` coordinate.
159− pub fn clip_right(self, width: u16) -> Rect {
159+ pub fn clip_right(self, width: u16) -> Rect {
161− width: self.width.saturating_sub(width),
161+ width: self.width.saturating_sub(width),
166− // Returns a new Rect with height reduced from the top.
166+ // Returns a new Rect with height reduced from the top.
167− // This changes the `y` coordinate and clamps it to the bottom
167+ // This changes the `y` coordinate and clamps it to the bottom
168− // edge of the original Rect.
168+ // edge of the original Rect.
169− pub fn clip_top(self, height: u16) -> Rect {
169+ pub fn clip_top(self, height: u16) -> Rect {
170− let height = std::cmp::min(height, self.height);
170+ let height = std::cmp::min(height, self.height);
172− y: self.y.saturating_add(height),
172+ y: self.y.saturating_add(height),
173− height: self.height.saturating_sub(height),
173+ height: self.height.saturating_sub(height),
178− // Returns a new Rect with height reduced from the bottom.
178+ // Returns a new Rect with height reduced from the bottom.
179− // This does _not_ change the `y` coordinate.
179+ // This does _not_ change the `y` coordinate.
180− pub fn clip_bottom(self, height: u16) -> Rect {
180+ pub fn clip_bottom(self, height: u16) -> Rect {
182− height: self.height.saturating_sub(height),
182+ height: self.height.saturating_sub(height),
187− pub fn with_height(self, height: u16) -> Rect {
187+ pub fn with_height(self, height: u16) -> Rect {
188− // new height may make area > u16::max_value, so use new()
188+ // new height may make area > u16::max_value, so use new()
189− Self::new(self.x, self.y, self.width, height)
189+ Self::new(self.x, self.y, self.width, height)
192− pub fn with_width(self, width: u16) -> Rect {
192+ pub fn with_width(self, width: u16) -> Rect {
193− Self::new(self.x, self.y, width, self.height)
193+ Self::new(self.x, self.y, width, self.height)
196− pub fn inner(self, margin: &Margin) -> Rect {
196+ pub fn inner(self, margin: &Margin) -> Rect {
197− if self.width < margin.width() || self.height < margin.height() {
197+ if self.width < margin.width() || self.height < margin.height() {
198− Rect::default()
198+ Rect::default()
199− } else {
199+ } else {
201− x: self.x + margin.left,
201+ x: self.x + margin.left,
202− y: self.y + margin.top,
202+ y: self.y + margin.top,
203− width: self.width - margin.width(),
203+ width: self.width - margin.width(),
204− height: self.height - margin.height(),
204+ height: self.height - margin.height(),
209− /// Calculate the union between two [`Rect`]s.
209+ /// Calculate the union between two [`Rect`]s.
210− pub fn union(self, other: Rect) -> Rect {
210+ pub fn union(self, other: Rect) -> Rect {
211− // Example:
211+ // Example:
213− // If `Rect` A is positioned at `(0, 0)` with a width and height of `5`,
213+ // If `Rect` A is positioned at `(0, 0)` with a width and height of `5`,
214− // and `Rect` B is positioned at `(5, 0)` with a width and height of `2`,
214+ // and `Rect` B is positioned at `(5, 0)` with a width and height of `2`,
215− // then this is the resulting union:
215+ // then this is the resulting union:
217− // x1 = min(0, 5) => x1 = 0
217+ // x1 = min(0, 5) => x1 = 0
218− // y1 = min(0, 0) => y1 = 0
218+ // y1 = min(0, 0) => y1 = 0
219− // x2 = max(0 + 5, 5 + 2) => x2 = 7
219+ // x2 = max(0 + 5, 5 + 2) => x2 = 7
220− // y2 = max(0 + 5, 0 + 2) => y2 = 5
220+ // y2 = max(0 + 5, 0 + 2) => y2 = 5
221− let x1 = min(self.x, other.x);
221+ let x1 = min(self.x, other.x);
222− let y1 = min(self.y, other.y);
222+ let y1 = min(self.y, other.y);
223− let x2 = max(self.x + self.width, other.x + other.width);
223+ let x2 = max(self.x + self.width, other.x + other.width);
224− let y2 = max(self.y + self.height, other.y + other.height);
224+ let y2 = max(self.y + self.height, other.y + other.height);
228− width: x2 - x1,
228+ width: x2 - x1,
229− height: y2 - y1,
229+ height: y2 - y1,
233− /// Calculate the intersection between two [`Rect`]s.
233+ /// Calculate the intersection between two [`Rect`]s.
234− pub fn intersection(self, other: Rect) -> Rect {
234+ pub fn intersection(self, other: Rect) -> Rect {
235− // Example:
235+ // Example:
237− // If `Rect` A is positioned at `(0, 0)` with a width and height of `5`,
237+ // If `Rect` A is positioned at `(0, 0)` with a width and height of `5`,
238− // and `Rect` B is positioned at `(5, 0)` with a width and height of `2`,
238+ // and `Rect` B is positioned at `(5, 0)` with a width and height of `2`,
239− // then this is the resulting intersection:
239+ // then this is the resulting intersection:
241− // x1 = max(0, 5) => x1 = 5
241+ // x1 = max(0, 5) => x1 = 5
242− // y1 = max(0, 0) => y1 = 0
242+ // y1 = max(0, 0) => y1 = 0
243− // x2 = min(0 + 5, 5 + 2) => x2 = 5
243+ // x2 = min(0 + 5, 5 + 2) => x2 = 5
244− // y2 = min(0 + 5, 0 + 2) => y2 = 2
244+ // y2 = min(0 + 5, 0 + 2) => y2 = 2
245− let x1 = max(self.x, other.x);
245+ let x1 = max(self.x, other.x);
246− let y1 = max(self.y, other.y);
246+ let y1 = max(self.y, other.y);
247− let x2 = min(self.x + self.width, other.x + other.width);
247+ let x2 = min(self.x + self.width, other.x + other.width);
248− let y2 = min(self.y + self.height, other.y + other.height);
248+ let y2 = min(self.y + self.height, other.y + other.height);
252− width: x2 - x1,
252+ width: x2 - x1,
253− height: y2 - y1,
253+ height: y2 - y1,
257− pub fn intersects(self, other: Rect) -> bool {
257+ pub fn intersects(self, other: Rect) -> bool {
258− self.x < other.x + other.width
258+ self.x < other.x + other.width
259− && self.x + self.width > other.x
259+ && self.x + self.width > other.x
260− && self.y < other.y + other.height
260+ && self.y < other.y + other.height
261− && self.y + self.height > other.y
261+ && self.y + self.height > other.y
265−#[derive(Debug, Clone, Copy, PartialEq)]
265+#[derive(Debug, Clone, Copy, PartialEq)]
266−#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
266+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
267−pub enum Color {
267+pub enum Color {
274− Magenta,
274+ Magenta,
277− LightRed,
277+ LightRed,
278− LightGreen,
278+ LightGreen,
279− LightYellow,
279+ LightYellow,
280− LightBlue,
280+ LightBlue,
281− LightMagenta,
281+ LightMagenta,
282− LightCyan,
282+ LightCyan,
283− LightGray,
283+ LightGray,
285− Rgb(u8, u8, u8),
285+ Rgb(u8, u8, u8),
286− Indexed(u8),
286+ Indexed(u8),
289−#[cfg(feature = "term")]
289+#[cfg(feature = "term")]
290−impl From<Color> for crossterm::style::Color {
290+impl From<Color> for crossterm::style::Color {
291− fn from(color: Color) -> Self {
291+ fn from(color: Color) -> Self {
292− use crossterm::style::Color as CColor;
292+ use crossterm::style::Color as CColor;
294− match color {
294+ match color {
295− Color::Reset => CColor::Reset,
295+ Color::Reset => CColor::Reset,
296− Color::Black => CColor::Black,
296+ Color::Black => CColor::Black,
297− Color::Red => CColor::DarkRed,
297+ Color::Red => CColor::DarkRed,
298− Color::Green => CColor::DarkGreen,
298+ Color::Green => CColor::DarkGreen,
299− Color::Yellow => CColor::DarkYellow,
299+ Color::Yellow => CColor::DarkYellow,
300− Color::Blue => CColor::DarkBlue,
300+ Color::Blue => CColor::DarkBlue,
301− Color::Magenta => CColor::DarkMagenta,
301+ Color::Magenta => CColor::DarkMagenta,
302− Color::Cyan => CColor::DarkCyan,
302+ Color::Cyan => CColor::DarkCyan,
303− Color::Gray => CColor::DarkGrey,
303+ Color::Gray => CColor::DarkGrey,
304− Color::LightRed => CColor::Red,
304+ Color::LightRed => CColor::Red,
305− Color::LightGreen => CColor::Green,
305+ Color::LightGreen => CColor::Green,
306− Color::LightBlue => CColor::Blue,
306+ Color::LightBlue => CColor::Blue,
307− Color::LightYellow => CColor::Yellow,
307+ Color::LightYellow => CColor::Yellow,
308− Color::LightMagenta => CColor::Magenta,
308+ Color::LightMagenta => CColor::Magenta,
309− Color::LightCyan => CColor::Cyan,
309+ Color::LightCyan => CColor::Cyan,
310− Color::LightGray => CColor::Grey,
310+ Color::LightGray => CColor::Grey,
311− Color::White => CColor::White,
311+ Color::White => CColor::White,
312− Color::Indexed(i) => CColor::AnsiValue(i),
312+ Color::Indexed(i) => CColor::AnsiValue(i),
313− Color::Rgb(r, g, b) => CColor::Rgb { r, g, b },
313+ Color::Rgb(r, g, b) => CColor::Rgb { r, g, b },
318−bitflags! {
318+bitflags! {
319− /// Modifier changes the way a piece of text is displayed.
319+ /// Modifier changes the way a piece of text is displayed.
321− /// They are bitflags so they can easily be composed.
321+ /// They are bitflags so they can easily be composed.
323− /// ## Examples
323+ /// ## Examples
325− /// ```rust
325+ /// ```rust
326− /// # use helix_view::graphics::Modifier;
326+ /// # use helix_view::graphics::Modifier;
328− /// let m = Modifier::BOLD | Modifier::ITALIC;
328+ /// let m = Modifier::BOLD | Modifier::ITALIC;
330− #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
330+ #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
331− pub struct Modifier: u16 {
331+ pub struct Modifier: u16 {
332− const BOLD = 0b0000_0000_0001;
332+ const BOLD = 0b0000_0000_0001;
333− const DIM = 0b0000_0000_0010;
333+ const DIM = 0b0000_0000_0010;
334− const ITALIC = 0b0000_0000_0100;
334+ const ITALIC = 0b0000_0000_0100;
335− const UNDERLINED = 0b0000_0000_1000;
335+ const UNDERLINED = 0b0000_0000_1000;
336− const SLOW_BLINK = 0b0000_0001_0000;
336+ const SLOW_BLINK = 0b0000_0001_0000;
337− const RAPID_BLINK = 0b0000_0010_0000;
337+ const RAPID_BLINK = 0b0000_0010_0000;
338− const REVERSED = 0b0000_0100_0000;
338+ const REVERSED = 0b0000_0100_0000;
339− const HIDDEN = 0b0000_1000_0000;
339+ const HIDDEN = 0b0000_1000_0000;
340− const CROSSED_OUT = 0b0001_0000_0000;
340+ const CROSSED_OUT = 0b0001_0000_0000;
344−impl FromStr for Modifier {
344+impl FromStr for Modifier {
345− type Err = &'static str;
345+ type Err = &'static str;
347− fn from_str(modifier: &str) -> Result<Self, Self::Err> {
347+ fn from_str(modifier: &str) -> Result<Self, Self::Err> {
348− match modifier {
348+ match modifier {
349− "bold" => Ok(Self::BOLD),
349+ "bold" => Ok(Self::BOLD),
350− "dim" => Ok(Self::DIM),
350+ "dim" => Ok(Self::DIM),
351− "italic" => Ok(Self::ITALIC),
351+ "italic" => Ok(Self::ITALIC),
352− "underlined" => Ok(Self::UNDERLINED),
352+ "underlined" => Ok(Self::UNDERLINED),
353− "slow_blink" => Ok(Self::SLOW_BLINK),
353+ "slow_blink" => Ok(Self::SLOW_BLINK),
354− "rapid_blink" => Ok(Self::RAPID_BLINK),
354+ "rapid_blink" => Ok(Self::RAPID_BLINK),
355− "reversed" => Ok(Self::REVERSED),
355+ "reversed" => Ok(Self::REVERSED),
356− "hidden" => Ok(Self::HIDDEN),
356+ "hidden" => Ok(Self::HIDDEN),
357− "crossed_out" => Ok(Self::CROSSED_OUT),
357+ "crossed_out" => Ok(Self::CROSSED_OUT),
358− _ => Err("Invalid modifier"),
358+ _ => Err("Invalid modifier"),
363−/// Style let you control the main characteristics of the displayed elements.
363+/// Style let you control the main characteristics of the displayed elements.
365−/// ```rust
365+/// ```rust
366−/// # use helix_view::graphics::{Color, Modifier, Style};
366+/// # use helix_view::graphics::{Color, Modifier, Style};
367−/// Style::default()
367+/// Style::default()
368−/// .fg(Color::Black)
368+/// .fg(Color::Black)
369−/// .bg(Color::Green)
369+/// .bg(Color::Green)
370−/// .add_modifier(Modifier::ITALIC | Modifier::BOLD);
370+/// .add_modifier(Modifier::ITALIC | Modifier::BOLD);
373−/// It represents an incremental change. If you apply the styles S1, S2, S3 to a cell of the
373+/// It represents an incremental change. If you apply the styles S1, S2, S3 to a cell of the
374−/// terminal buffer, the style of this cell will be the result of the merge of S1, S2 and S3, not
374+/// terminal buffer, the style of this cell will be the result of the merge of S1, S2 and S3, not
375−/// just S3.
375+/// just S3.
377−/// ```rust
377+/// ```rust
378−/// # use helix_view::graphics::{Rect, Color, Modifier, Style};
378+/// # use helix_view::graphics::{Rect, Color, Modifier, Style};
379−/// # use helix_tui::buffer::Buffer;
379+/// # use helix_tui::buffer::Buffer;
380−/// let styles = [
380+/// let styles = [
381−/// Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD | Modifier::ITALIC),
381+/// Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD | Modifier::ITALIC),
382−/// Style::default().bg(Color::Red),
382+/// Style::default().bg(Color::Red),
383−/// Style::default().fg(Color::Yellow).remove_modifier(Modifier::ITALIC),
383+/// Style::default().fg(Color::Yellow).remove_modifier(Modifier::ITALIC),
385−/// let mut buffer = Buffer::empty(Rect::new(0, 0, 1, 1));
385+/// let mut buffer = Buffer::empty(Rect::new(0, 0, 1, 1));
386−/// for style in &styles {
386+/// for style in &styles {
387−/// buffer[(0, 0)].set_style(*style);
387+/// buffer[(0, 0)].set_style(*style);
389−/// assert_eq!(
389+/// assert_eq!(
390−/// Style {
390+/// Style {
391−/// fg: Some(Color::Yellow),
391+/// fg: Some(Color::Yellow),
392−/// bg: Some(Color::Red),
392+/// bg: Some(Color::Red),
393−/// add_modifier: Modifier::BOLD,
393+/// add_modifier: Modifier::BOLD,
394−/// sub_modifier: Modifier::empty(),
394+/// sub_modifier: Modifier::empty(),
396−/// buffer[(0, 0)].style(),
396+/// buffer[(0, 0)].style(),
400−/// The default implementation returns a `Style` that does not modify anything. If you wish to
400+/// The default implementation returns a `Style` that does not modify anything. If you wish to
401−/// reset all properties until that point use [`Style::reset`].
401+/// reset all properties until that point use [`Style::reset`].
404−/// # use helix_view::graphics::{Rect, Color, Modifier, Style};
404+/// # use helix_view::graphics::{Rect, Color, Modifier, Style};
405−/// # use helix_tui::buffer::Buffer;
405+/// # use helix_tui::buffer::Buffer;
406−/// let styles = [
406+/// let styles = [
407−/// Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD | Modifier::ITALIC),
407+/// Style::default().fg(Color::Blue).add_modifier(Modifier::BOLD | Modifier::ITALIC),
408−/// Style::reset().fg(Color::Yellow),
408+/// Style::reset().fg(Color::Yellow),
410−/// let mut buffer = Buffer::empty(Rect::new(0, 0, 1, 1));
410+/// let mut buffer = Buffer::empty(Rect::new(0, 0, 1, 1));
411−/// for style in &styles {
411+/// for style in &styles {
412−/// buffer[(0, 0)].set_style(*style);
412+/// buffer[(0, 0)].set_style(*style);
414−/// assert_eq!(
414+/// assert_eq!(
415−/// Style {
415+/// Style {
416−/// fg: Some(Color::Yellow),
416+/// fg: Some(Color::Yellow),
417−/// bg: Some(Color::Reset),
417+/// bg: Some(Color::Reset),
418−/// add_modifier: Modifier::empty(),
418+/// add_modifier: Modifier::empty(),
419−/// sub_modifier: Modifier::empty(),
419+/// sub_modifier: Modifier::empty(),
421−/// buffer[(0, 0)].style(),
421+/// buffer[(0, 0)].style(),
424−#[derive(Debug, Clone, Copy, PartialEq)]
424+#[derive(Debug, Clone, Copy, PartialEq)]
425−#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
425+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
426−pub struct Style {
426+pub struct Style {
427− pub fg: Option<Color>,
427+ pub fg: Option<Color>,
428− pub bg: Option<Color>,
428+ pub bg: Option<Color>,
429− pub add_modifier: Modifier,
429+ pub add_modifier: Modifier,
430− pub sub_modifier: Modifier,
430+ pub sub_modifier: Modifier,
433−impl Default for Style {
433+impl Default for Style {
434− fn default() -> Style {
434+ fn default() -> Style {
436− fg: None,
436+ fg: None,
437− bg: None,
437+ bg: None,
438− add_modifier: Modifier::empty(),
438+ add_modifier: Modifier::empty(),
439− sub_modifier: Modifier::empty(),
439+ sub_modifier: Modifier::empty(),
444−impl Style {
444+impl Style {
445− /// Returns a `Style` resetting all properties.
445+ /// Returns a `Style` resetting all properties.
446− pub fn reset() -> Style {
446+ pub fn reset() -> Style {
448− fg: Some(Color::Reset),
448+ fg: Some(Color::Reset),
449− bg: Some(Color::Reset),
449+ bg: Some(Color::Reset),
450− add_modifier: Modifier::empty(),
450+ add_modifier: Modifier::empty(),
451− sub_modifier: Modifier::all(),
451+ sub_modifier: Modifier::all(),
455− /// Changes the foreground color.
455+ /// Changes the foreground color.
457− /// ## Examples
457+ /// ## Examples
459− /// ```rust
459+ /// ```rust
460− /// # use helix_view::graphics::{Color, Style};
460+ /// # use helix_view::graphics::{Color, Style};
461− /// let style = Style::default().fg(Color::Blue);
461+ /// let style = Style::default().fg(Color::Blue);
462− /// let diff = Style::default().fg(Color::Red);
462+ /// let diff = Style::default().fg(Color::Red);
463− /// assert_eq!(style.patch(diff), Style::default().fg(Color::Red));
463+ /// assert_eq!(style.patch(diff), Style::default().fg(Color::Red));
465− pub fn fg(mut self, color: Color) -> Style {
465+ pub fn fg(mut self, color: Color) -> Style {
466− self.fg = Some(color);
466+ self.fg = Some(color);
470− /// Changes the background color.
470+ /// Changes the background color.
472− /// ## Examples
472+ /// ## Examples
474− /// ```rust
474+ /// ```rust
475− /// # use helix_view::graphics::{Color, Style};
475+ /// # use helix_view::graphics::{Color, Style};
476− /// let style = Style::default().bg(Color::Blue);
476+ /// let style = Style::default().bg(Color::Blue);
477− /// let diff = Style::default().bg(Color::Red);
477+ /// let diff = Style::default().bg(Color::Red);
478− /// assert_eq!(style.patch(diff), Style::default().bg(Color::Red));
478+ /// assert_eq!(style.patch(diff), Style::default().bg(Color::Red));
480− pub fn bg(mut self, color: Color) -> Style {
480+ pub fn bg(mut self, color: Color) -> Style {
481− self.bg = Some(color);
481+ self.bg = Some(color);
485− /// Changes the text emphasis.
485+ /// Changes the text emphasis.
487− /// When applied, it adds the given modifier to the `Style` modifiers.
487+ /// When applied, it adds the given modifier to the `Style` modifiers.
489− /// ## Examples
489+ /// ## Examples
491− /// ```rust
491+ /// ```rust
492− /// # use helix_view::graphics::{Color, Modifier, Style};
492+ /// # use helix_view::graphics::{Color, Modifier, Style};
493− /// let style = Style::default().add_modifier(Modifier::BOLD);
493+ /// let style = Style::default().add_modifier(Modifier::BOLD);
494− /// let diff = Style::default().add_modifier(Modifier::ITALIC);
494+ /// let diff = Style::default().add_modifier(Modifier::ITALIC);
495− /// let patched = style.patch(diff);
495+ /// let patched = style.patch(diff);
496− /// assert_eq!(patched.add_modifier, Modifier::BOLD | Modifier::ITALIC);
496+ /// assert_eq!(patched.add_modifier, Modifier::BOLD | Modifier::ITALIC);
497− /// assert_eq!(patched.sub_modifier, Modifier::empty());
497+ /// assert_eq!(patched.sub_modifier, Modifier::empty());
499− pub fn add_modifier(mut self, modifier: Modifier) -> Style {
499+ pub fn add_modifier(mut self, modifier: Modifier) -> Style {
500− self.sub_modifier.remove(modifier);
500+ self.sub_modifier.remove(modifier);
501− self.add_modifier.insert(modifier);
501+ self.add_modifier.insert(modifier);
505− /// Changes the text emphasis.
505+ /// Changes the text emphasis.
507− /// When applied, it removes the given modifier from the `Style` modifiers.
507+ /// When applied, it removes the given modifier from the `Style` modifiers.
509− /// ## Examples
509+ /// ## Examples
511− /// ```rust
511+ /// ```rust
512− /// # use helix_view::graphics::{Color, Modifier, Style};
512+ /// # use helix_view::graphics::{Color, Modifier, Style};
513− /// let style = Style::default().add_modifier(Modifier::BOLD | Modifier::ITALIC);
513+ /// let style = Style::default().add_modifier(Modifier::BOLD | Modifier::ITALIC);
514− /// let diff = Style::default().remove_modifier(Modifier::ITALIC);
514+ /// let diff = Style::default().remove_modifier(Modifier::ITALIC);
515− /// let patched = style.patch(diff);
515+ /// let patched = style.patch(diff);
516− /// assert_eq!(patched.add_modifier, Modifier::BOLD);
516+ /// assert_eq!(patched.add_modifier, Modifier::BOLD);
517− /// assert_eq!(patched.sub_modifier, Modifier::ITALIC);
517+ /// assert_eq!(patched.sub_modifier, Modifier::ITALIC);
519− pub fn remove_modifier(mut self, modifier: Modifier) -> Style {
519+ pub fn remove_modifier(mut self, modifier: Modifier) -> Style {
520− self.add_modifier.remove(modifier);
520+ self.add_modifier.remove(modifier);
521− self.sub_modifier.insert(modifier);
521+ self.sub_modifier.insert(modifier);
525− /// Results in a combined style that is equivalent to applying the two individual styles to
525+ /// Results in a combined style that is equivalent to applying the two individual styles to
526− /// a style one after the other.
526+ /// a style one after the other.
528− /// ## Examples
528+ /// ## Examples
530− /// # use helix_view::graphics::{Color, Modifier, Style};
530+ /// # use helix_view::graphics::{Color, Modifier, Style};
531− /// let style_1 = Style::default().fg(Color::Yellow);
531+ /// let style_1 = Style::default().fg(Color::Yellow);
532− /// let style_2 = Style::default().bg(Color::Red);
532+ /// let style_2 = Style::default().bg(Color::Red);
533− /// let combined = style_1.patch(style_2);
533+ /// let combined = style_1.patch(style_2);
534− /// assert_eq!(
534+ /// assert_eq!(
535− /// Style::default().patch(style_1).patch(style_2),
535+ /// Style::default().patch(style_1).patch(style_2),
536− /// Style::default().patch(combined));
536+ /// Style::default().patch(combined));
538− pub fn patch(mut self, other: Style) -> Style {
538+ pub fn patch(mut self, other: Style) -> Style {
539− self.fg = other.fg.or(self.fg);
539+ self.fg = other.fg.or(self.fg);
540− self.bg = other.bg.or(self.bg);
540+ self.bg = other.bg.or(self.bg);
542− self.add_modifier.remove(other.sub_modifier);
542+ self.add_modifier.remove(other.sub_modifier);
543− self.add_modifier.insert(other.add_modifier);
543+ self.add_modifier.insert(other.add_modifier);
544− self.sub_modifier.remove(other.add_modifier);
544+ self.sub_modifier.remove(other.add_modifier);
545− self.sub_modifier.insert(other.sub_modifier);
545+ self.sub_modifier.insert(other.sub_modifier);
551−#[cfg(test)]
551+#[cfg(test)]
552−mod tests {
552+mod tests {
553− use super::*;
553+ use super::*;
556− fn test_rect_size_truncation() {
556+ fn test_rect_size_truncation() {
557− for width in 256u16..300u16 {
557+ for width in 256u16..300u16 {
558− for height in 256u16..300u16 {
558+ for height in 256u16..300u16 {
559− let rect = Rect::new(0, 0, width, height);
559+ let rect = Rect::new(0, 0, width, height);
560− rect.area(); // Should not panic.
560+ rect.area(); // Should not panic.
561− assert!(rect.width < width || rect.height < height);
561+ assert!(rect.width < width || rect.height < height);
562− // The target dimensions are rounded down so the math will not be too precise
562+ // The target dimensions are rounded down so the math will not be too precise
563− // but let's make sure the ratios don't diverge crazily.
563+ // but let's make sure the ratios don't diverge crazily.
564− assert!(
564+ assert!(
565− (f64::from(rect.width) / f64::from(rect.height)
565+ (f64::from(rect.width) / f64::from(rect.height)
566− - f64::from(width) / f64::from(height))
566+ - f64::from(width) / f64::from(height))
573− // One dimension below 255, one above. Area above max u16.
573+ // One dimension below 255, one above. Area above max u16.
574− let width = 900;
574+ let width = 900;
575− let height = 100;
575+ let height = 100;
576− let rect = Rect::new(0, 0, width, height);
576+ let rect = Rect::new(0, 0, width, height);
577− assert_ne!(rect.width, 900);
577+ assert_ne!(rect.width, 900);
578− assert_ne!(rect.height, 100);
578+ assert_ne!(rect.height, 100);
579− assert!(rect.width < width || rect.height < height);
579+ assert!(rect.width < width || rect.height < height);
583− fn test_rect_size_preservation() {
583+ fn test_rect_size_preservation() {
584− for width in 0..256u16 {
584+ for width in 0..256u16 {
585− for height in 0..256u16 {
585+ for height in 0..256u16 {
586− let rect = Rect::new(0, 0, width, height);
586+ let rect = Rect::new(0, 0, width, height);
587− rect.area(); // Should not panic.
587+ rect.area(); // Should not panic.
588− assert_eq!(rect.width, width);
588+ assert_eq!(rect.width, width);
589− assert_eq!(rect.height, height);
589+ assert_eq!(rect.height, height);
593− // One dimension below 255, one above. Area below max u16.
593+ // One dimension below 255, one above. Area below max u16.
594− let rect = Rect::new(0, 0, 300, 100);
594+ let rect = Rect::new(0, 0, 300, 100);
595− assert_eq!(rect.width, 300);
595+ assert_eq!(rect.width, 300);
596− assert_eq!(rect.height, 100);
596+ assert_eq!(rect.height, 100);
600− fn test_rect_chop_from_left() {
600+ fn test_rect_chop_from_left() {
601− let rect = Rect::new(0, 0, 20, 30);
601+ let rect = Rect::new(0, 0, 20, 30);
602− assert_eq!(Rect::new(10, 0, 10, 30), rect.clip_left(10));
602+ assert_eq!(Rect::new(10, 0, 10, 30), rect.clip_left(10));
603− assert_eq!(
603+ assert_eq!(
604− Rect::new(20, 0, 0, 30),
604+ Rect::new(20, 0, 0, 30),
605− rect.clip_left(40),
605+ rect.clip_left(40),
606− "x should be clamped to original width if new width is bigger"
606+ "x should be clamped to original width if new width is bigger"
611− fn test_rect_chop_from_right() {
611+ fn test_rect_chop_from_right() {
612− let rect = Rect::new(0, 0, 20, 30);
612+ let rect = Rect::new(0, 0, 20, 30);
613− assert_eq!(Rect::new(0, 0, 10, 30), rect.clip_right(10));
613+ assert_eq!(Rect::new(0, 0, 10, 30), rect.clip_right(10));
617− fn test_rect_chop_from_top() {
617+ fn test_rect_chop_from_top() {
618− let rect = Rect::new(0, 0, 20, 30);
618+ let rect = Rect::new(0, 0, 20, 30);
619− assert_eq!(Rect::new(0, 10, 20, 20), rect.clip_top(10));
619+ assert_eq!(Rect::new(0, 10, 20, 20), rect.clip_top(10));
620− assert_eq!(
620+ assert_eq!(
621− Rect::new(0, 30, 20, 0),
621+ Rect::new(0, 30, 20, 0),
622− rect.clip_top(50),
622+ rect.clip_top(50),
623− "y should be clamped to original height if new height is bigger"
623+ "y should be clamped to original height if new height is bigger"
628− fn test_rect_chop_from_bottom() {
628+ fn test_rect_chop_from_bottom() {
629− let rect = Rect::new(0, 0, 20, 30);
629+ let rect = Rect::new(0, 0, 20, 30);
630− assert_eq!(Rect::new(0, 0, 20, 20), rect.clip_bottom(10));
630+ assert_eq!(Rect::new(0, 0, 20, 20), rect.clip_bottom(10));
633− fn styles() -> Vec<Style> {
633+ fn styles() -> Vec<Style> {
635− Style::default(),
635+ Style::default(),
636− Style::default().fg(Color::Yellow),
636+ Style::default().fg(Color::Yellow),
637− Style::default().bg(Color::Yellow),
637+ Style::default().bg(Color::Yellow),
638− Style::default().add_modifier(Modifier::BOLD),
638+ Style::default().add_modifier(Modifier::BOLD),
639− Style::default().remove_modifier(Modifier::BOLD),
639+ Style::default().remove_modifier(Modifier::BOLD),
640− Style::default().add_modifier(Modifier::ITALIC),
640+ Style::default().add_modifier(Modifier::ITALIC),
641− Style::default().remove_modifier(Modifier::ITALIC),
641+ Style::default().remove_modifier(Modifier::ITALIC),
642− Style::default().add_modifier(Modifier::ITALIC | Modifier::BOLD),
642+ Style::default().add_modifier(Modifier::ITALIC | Modifier::BOLD),
643− Style::default().remove_modifier(Modifier::ITALIC | Modifier::BOLD),
643+ Style::default().remove_modifier(Modifier::ITALIC | Modifier::BOLD),
648− fn combined_patch_gives_same_result_as_individual_patch() {
648+ fn combined_patch_gives_same_result_as_individual_patch() {
649− let styles = styles();
649+ let styles = styles();
650− for &a in &styles {
650+ for &a in &styles {
651− for &b in &styles {
651+ for &b in &styles {
652− for &c in &styles {
652+ for &c in &styles {
653− for &d in &styles {
653+ for &d in &styles {
654− let combined = a.patch(b.patch(c.patch(d)));
654+ let combined = a.patch(b.patch(c.patch(d)));
656− assert_eq!(
656+ assert_eq!(
657− Style::default().patch(a).patch(b).patch(c).patch(d),
657+ Style::default().patch(a).patch(b).patch(c).patch(d),
658− Style::default().patch(combined)
658+ Style::default().patch(combined)