diff --git a/CHANGELOG.md b/CHANGELOG.md index a4339bb..433634a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,12 @@ Procedure when bumping the version number: ## Unreleased +### Added + +- Unicode-based grapheme width estimation method + - `width_estimation_method` config option + - `--width-estimation-method` option + ### Changed - Updated documentation for `time_zone` config option diff --git a/Cargo.lock b/Cargo.lock index 6b262c4..86ebb73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1647,7 +1647,7 @@ dependencies = [ [[package]] name = "toss" version = "0.3.1" -source = "git+https://github.com/Garmelon/toss.git?tag=v0.3.1#be7eff0979e0e95d070e7c9cea42c328ffd04cc4" +source = "git+https://github.com/Garmelon/toss.git?rev=423dd100c1360decffc5107ea4757d751ac0f4db#423dd100c1360decffc5107ea4757d751ac0f4db" dependencies = [ "async-trait", "crossterm", diff --git a/Cargo.toml b/Cargo.toml index 93e13c4..f8445e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ features = ["bot"] [workspace.dependencies.toss] git = "https://github.com/Garmelon/toss.git" -tag = "v0.3.1" +rev = "423dd100c1360decffc5107ea4757d751ac0f4db" [workspace.dependencies.vault] git = "https://github.com/Garmelon/vault.git" diff --git a/cove-config/src/lib.rs b/cove-config/src/lib.rs index 0d350ed..85b418e 100644 --- a/cove-config/src/lib.rs +++ b/cove-config/src/lib.rs @@ -5,7 +5,7 @@ use std::{ }; use doc::Document; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; pub use crate::{euph::*, keys::*}; @@ -21,6 +21,14 @@ pub enum Error { Toml(#[from] toml::de::Error), } +#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, Document)] +#[serde(rename_all = "snake_case")] +pub enum WidthEstimationMethod { + #[default] + Legacy, + Unicode, +} + #[derive(Debug, Default, Deserialize, Document)] pub struct Config { /// The directory that cove stores its data in when not running in ephemeral @@ -41,12 +49,26 @@ pub struct Config { #[serde(default)] pub ephemeral: bool, - /// Whether to measure the width of characters as displayed by the terminal - /// emulator instead of guessing the width. + /// How to estimate the width of graphemes (i.e. characters) as displayed by + /// the terminal emulator. + /// + /// `"legacy"`: Use a legacy method that should mostly work on most terminal + /// emulators. This method will never be correct in all cases since every + /// terminal emulator handles grapheme widths slightly differently. However, + /// those cases are usually rare (unless you view a lot of emoji). + /// + /// `"unicode"`: Use the unicode standard in a best-effort manner to + /// determine grapheme widths. + /// + /// This method is used when `measure_widths` is set to `false`. + #[serde(default)] + pub width_estimation_method: WidthEstimationMethod, + + /// Whether to measure the width of graphemes (i.e. characters) as displayed + /// by the terminal emulator instead of estimating the width. /// /// Enabling this makes rendering a bit slower but more accurate. The screen - /// might also flash when encountering new characters (or, more accurately, - /// graphemes). + /// might also flash when encountering new graphemes. /// /// See also the `--measure-widths` command line option. #[serde(default)] diff --git a/cove/src/main.rs b/cove/src/main.rs index 642b62e..51bc502 100644 --- a/cove/src/main.rs +++ b/cove/src/main.rs @@ -46,6 +46,12 @@ enum Command { HelpConfig, } +#[derive(Debug, Clone, Copy, clap::ValueEnum)] +enum WidthEstimationMethod { + Legacy, + Unicode, +} + impl Default for Command { fn default() -> Self { Self::Run @@ -79,6 +85,11 @@ struct Args { #[arg(long, short)] offline: bool, + /// Method for estimating the width of characters as displayed by the + /// terminal emulator. + #[arg(long, short)] + width_estimation_method: Option, + /// Measure the width of characters as displayed by the terminal emulator /// instead of guessing the width. #[arg(long, short)] @@ -114,6 +125,12 @@ fn update_config_with_args(config: &mut Config, args: &Args) { } config.ephemeral |= args.ephemeral; + if let Some(method) = args.width_estimation_method { + config.width_estimation_method = match method { + WidthEstimationMethod::Legacy => cove_config::WidthEstimationMethod::Legacy, + WidthEstimationMethod::Unicode => cove_config::WidthEstimationMethod::Unicode, + } + } config.measure_widths |= args.measure_widths; config.offline |= args.offline; } @@ -182,6 +199,10 @@ async fn run( let mut terminal = Terminal::new()?; terminal.set_measuring(config.measure_widths); + terminal.set_width_estimation_method(match config.width_estimation_method { + cove_config::WidthEstimationMethod::Legacy => toss::WidthEstimationMethod::Legacy, + cove_config::WidthEstimationMethod::Unicode => toss::WidthEstimationMethod::Unicode, + }); Ui::run(config, tz, &mut terminal, vault.clone(), logger, logger_rx).await?; drop(terminal);