Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow configuring alignment when max columns is hit #475

Merged
merged 1 commit into from
Mar 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions config-file-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@
"format": "uint16",
"minimum": 0.0
},
"max_columns_alignment": {
"description": "The alignment the presentation should have if `max_columns` is set and the terminal is larger than that.",
"allOf": [
{
"$ref": "#/definitions/MaxColumnsAlignment"
}
]
},
"terminal_font_size": {
"description": "Override the terminal font size when in windows or when using sixel.",
"default": 16,
Expand Down Expand Up @@ -267,6 +275,32 @@
}
}
},
"MaxColumnsAlignment": {
"description": "The alignment to use when `defaults.max_columns` is set.",
"oneOf": [
{
"description": "Align the presentation to the left.",
"type": "string",
"enum": [
"left"
]
},
{
"description": "Align the presentation on the center.",
"type": "string",
"enum": [
"center"
]
},
{
"description": "Align the presentation to the right.",
"type": "string",
"enum": [
"right"
]
}
]
},
"MermaidConfig": {
"type": "object",
"properties": {
Expand Down
27 changes: 24 additions & 3 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub struct DefaultsConfig {
pub theme: Option<String>,

/// Override the terminal font size when in windows or when using sixel.
#[serde(default = "default_font_size")]
#[serde(default = "default_terminal_font_size")]
#[validate(range(min = 1))]
pub terminal_font_size: u8,

Expand All @@ -89,24 +89,45 @@ pub struct DefaultsConfig {
/// A max width in columns that the presentation must always be capped to.
#[serde(default = "default_max_columns")]
pub max_columns: u16,

/// The alignment the presentation should have if `max_columns` is set and the terminal is
/// larger than that.
#[serde(default)]
pub max_columns_alignment: MaxColumnsAlignment,
}

impl Default for DefaultsConfig {
fn default() -> Self {
Self {
theme: Default::default(),
terminal_font_size: default_font_size(),
terminal_font_size: default_terminal_font_size(),
image_protocol: Default::default(),
validate_overflows: Default::default(),
max_columns: default_max_columns(),
max_columns_alignment: Default::default(),
}
}
}

fn default_font_size() -> u8 {
fn default_terminal_font_size() -> u8 {
16
}

/// The alignment to use when `defaults.max_columns` is set.
#[derive(Clone, Copy, Debug, Default, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum MaxColumnsAlignment {
/// Align the presentation to the left.
Left,

/// Align the presentation on the center.
#[default]
Center,

/// Align the presentation to the right.
Right,
}

#[derive(Clone, Debug, Default, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ValidateOverflows {
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ fn run(cli: Cli) -> Result<(), Box<dyn std::error::Error>> {
bindings: config.bindings,
validate_overflows,
max_columns: config.defaults.max_columns,
max_columns_alignment: config.defaults.max_columns_alignment,
};
let presenter = Presenter::new(
&default_theme,
Expand Down
4 changes: 3 additions & 1 deletion src/presenter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::{
listener::{Command, CommandListener},
speaker_notes::{SpeakerNotesEvent, SpeakerNotesEventPublisher},
},
config::KeyBindingsConfig,
config::{KeyBindingsConfig, MaxColumnsAlignment},
export::ImageReplacer,
markdown::parse::{MarkdownParser, ParseError},
presentation::{
Expand Down Expand Up @@ -43,6 +43,7 @@ pub struct PresenterOptions {
pub bindings: KeyBindingsConfig,
pub validate_overflows: bool,
pub max_columns: u16,
pub max_columns_alignment: MaxColumnsAlignment,
}

/// A slideshow presenter.
Expand Down Expand Up @@ -105,6 +106,7 @@ impl<'a> Presenter<'a> {
let drawer_options = TerminalDrawerOptions {
font_size_fallback: self.options.font_size_fallback,
max_columns: self.options.max_columns,
max_columns_alignment: self.options.max_columns_alignment,
};
let mut drawer = TerminalDrawer::new(self.image_printer.clone(), drawer_options)?;
loop {
Expand Down
23 changes: 20 additions & 3 deletions src/render/engine.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{RenderError, RenderResult, layout::Layout, properties::CursorPosition, text::TextDrawer};
use crate::{
config::MaxColumnsAlignment,
markdown::{text::WeightedLine, text_style::Colors},
render::{
layout::Positioning,
Expand Down Expand Up @@ -27,12 +28,18 @@ const MINIMUM_LINE_LENGTH: u16 = 10;
pub(crate) struct RenderEngineOptions {
pub(crate) validate_overflows: bool,
pub(crate) max_columns: u16,
pub(crate) max_columns_alignment: MaxColumnsAlignment,
pub(crate) column_layout_margin: u16,
}

impl Default for RenderEngineOptions {
fn default() -> Self {
Self { validate_overflows: false, max_columns: u16::MAX, column_layout_margin: 4 }
Self {
validate_overflows: false,
max_columns: u16::MAX,
max_columns_alignment: Default::default(),
column_layout_margin: 4,
}
}
}

Expand Down Expand Up @@ -71,7 +78,12 @@ where
if window_dimensions.columns > options.max_columns {
let extra_width = window_dimensions.columns - options.max_columns;
let dimensions = window_dimensions.shrink_columns(extra_width);
WindowRect { dimensions, start_column: extra_width / 2, start_row }
let start_column = match options.max_columns_alignment {
MaxColumnsAlignment::Left => 0,
MaxColumnsAlignment::Center => extra_width / 2,
MaxColumnsAlignment::Right => extra_width,
};
WindowRect { dimensions, start_column, start_row }
} else {
WindowRect { dimensions: window_dimensions, start_column: 0, start_row }
}
Expand Down Expand Up @@ -549,7 +561,12 @@ mod tests {
fn render(operations: &[RenderOperation]) -> Vec<Instruction> {
let mut buf = TerminalBuf::default();
let dimensions = WindowSize { rows: 100, columns: 100, height: 200, width: 200 };
let options = RenderEngineOptions { validate_overflows: false, max_columns: u16::MAX, column_layout_margin: 0 };
let options = RenderEngineOptions {
validate_overflows: false,
max_columns: u16::MAX,
max_columns_alignment: Default::default(),
column_layout_margin: 0,
};
let engine = RenderEngine::new(&mut buf, dimensions, options);
engine.render(operations.iter()).expect("render failed");
buf.instructions
Expand Down
13 changes: 8 additions & 5 deletions src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub(crate) mod text;
pub(crate) mod validate;

use crate::{
config::MaxColumnsAlignment,
markdown::{
elements::Text,
text::WeightedLine,
Expand All @@ -28,16 +29,14 @@ use std::{
pub(crate) type RenderResult = Result<(), RenderError>;

pub(crate) struct TerminalDrawerOptions {
/// The font size to fall back to if we can't find the window size in pixels.
pub(crate) font_size_fallback: u8,

/// The max width in columns that the presentation should be capped to.
pub(crate) max_columns: u16,
pub(crate) max_columns_alignment: MaxColumnsAlignment,
}

impl Default for TerminalDrawerOptions {
fn default() -> Self {
Self { font_size_fallback: 1, max_columns: u16::MAX }
Self { font_size_fallback: 1, max_columns: u16::MAX, max_columns_alignment: Default::default() }
}
}

Expand Down Expand Up @@ -98,7 +97,11 @@ impl TerminalDrawer {
}

fn create_engine(&mut self, dimensions: WindowSize) -> RenderEngine<Terminal<Stdout>> {
let options = RenderEngineOptions { max_columns: self.options.max_columns, ..Default::default() };
let options = RenderEngineOptions {
max_columns: self.options.max_columns,
max_columns_alignment: self.options.max_columns_alignment,
..Default::default()
};
RenderEngine::new(&mut self.terminal, dimensions, options)
}
}
Expand Down