Add unicode-based grapheme width estimation method

This commit is contained in:
Joscha 2025-02-23 18:31:20 +01:00
parent 900a686d0d
commit 17185ea536
5 changed files with 56 additions and 7 deletions

View file

@ -16,6 +16,12 @@ Procedure when bumping the version number:
## Unreleased ## Unreleased
### Added
- Unicode-based grapheme width estimation method
- `width_estimation_method` config option
- `--width-estimation-method` option
### Changed ### Changed
- Updated documentation for `time_zone` config option - Updated documentation for `time_zone` config option

2
Cargo.lock generated
View file

@ -1647,7 +1647,7 @@ dependencies = [
[[package]] [[package]]
name = "toss" name = "toss"
version = "0.3.1" 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 = [ dependencies = [
"async-trait", "async-trait",
"crossterm", "crossterm",

View file

@ -39,7 +39,7 @@ features = ["bot"]
[workspace.dependencies.toss] [workspace.dependencies.toss]
git = "https://github.com/Garmelon/toss.git" git = "https://github.com/Garmelon/toss.git"
tag = "v0.3.1" rev = "423dd100c1360decffc5107ea4757d751ac0f4db"
[workspace.dependencies.vault] [workspace.dependencies.vault]
git = "https://github.com/Garmelon/vault.git" git = "https://github.com/Garmelon/vault.git"

View file

@ -5,7 +5,7 @@ use std::{
}; };
use doc::Document; use doc::Document;
use serde::Deserialize; use serde::{Deserialize, Serialize};
pub use crate::{euph::*, keys::*}; pub use crate::{euph::*, keys::*};
@ -21,6 +21,14 @@ pub enum Error {
Toml(#[from] toml::de::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)] #[derive(Debug, Default, Deserialize, Document)]
pub struct Config { pub struct Config {
/// The directory that cove stores its data in when not running in ephemeral /// The directory that cove stores its data in when not running in ephemeral
@ -41,12 +49,26 @@ pub struct Config {
#[serde(default)] #[serde(default)]
pub ephemeral: bool, pub ephemeral: bool,
/// Whether to measure the width of characters as displayed by the terminal /// How to estimate the width of graphemes (i.e. characters) as displayed by
/// emulator instead of guessing the width. /// 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 /// Enabling this makes rendering a bit slower but more accurate. The screen
/// might also flash when encountering new characters (or, more accurately, /// might also flash when encountering new graphemes.
/// graphemes).
/// ///
/// See also the `--measure-widths` command line option. /// See also the `--measure-widths` command line option.
#[serde(default)] #[serde(default)]

View file

@ -46,6 +46,12 @@ enum Command {
HelpConfig, HelpConfig,
} }
#[derive(Debug, Clone, Copy, clap::ValueEnum)]
enum WidthEstimationMethod {
Legacy,
Unicode,
}
impl Default for Command { impl Default for Command {
fn default() -> Self { fn default() -> Self {
Self::Run Self::Run
@ -79,6 +85,11 @@ struct Args {
#[arg(long, short)] #[arg(long, short)]
offline: bool, offline: bool,
/// Method for estimating the width of characters as displayed by the
/// terminal emulator.
#[arg(long, short)]
width_estimation_method: Option<WidthEstimationMethod>,
/// Measure the width of characters as displayed by the terminal emulator /// Measure the width of characters as displayed by the terminal emulator
/// instead of guessing the width. /// instead of guessing the width.
#[arg(long, short)] #[arg(long, short)]
@ -114,6 +125,12 @@ fn update_config_with_args(config: &mut Config, args: &Args) {
} }
config.ephemeral |= args.ephemeral; 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.measure_widths |= args.measure_widths;
config.offline |= args.offline; config.offline |= args.offline;
} }
@ -182,6 +199,10 @@ async fn run(
let mut terminal = Terminal::new()?; let mut terminal = Terminal::new()?;
terminal.set_measuring(config.measure_widths); 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?; Ui::run(config, tz, &mut terminal, vault.clone(), logger, logger_rx).await?;
drop(terminal); drop(terminal);