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
### Added
- Unicode-based grapheme width estimation method
- `width_estimation_method` config option
- `--width-estimation-method` option
### Changed
- Updated documentation for `time_zone` config option

2
Cargo.lock generated
View file

@ -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",

View file

@ -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"

View file

@ -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)]

View file

@ -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<WidthEstimationMethod>,
/// 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);