Skip to content

Commit

Permalink
core: add support for sign text transformations
Browse files Browse the repository at this point in the history
Add support for regexp replacement patterns, which can be useful when
the text matched by --sign-filter or --sign-prefix should not be
displayed.
  • Loading branch information
neocturne committed Jan 26, 2024
1 parent a99a734 commit 8a1a26c
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 2 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ All prefixes and filters are applied to the front and back text separately, but
both the front and the back text will be shown in the popup when one of them
matches.

Finally, `--sign-transform` allows to specify sed-style replacement patterns to
modify the text displayed on the map. This can be used if the text matched by
`--sign-prefix` or `--sign-filter` should not be displayed:
`--sign-filter 's/\[Map\]//'` would replace each occurence of "\[Map\]" with
the empty string.

## Installation

Binary builds of the map generator for Linux and Windows, as well as an archive
Expand Down
30 changes: 29 additions & 1 deletion src/core/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{

use anyhow::{Context, Result};
use indexmap::IndexSet;
use regex::RegexSet;
use regex::{Regex, RegexSet};
use serde::{Deserialize, Serialize};

use crate::{
Expand Down Expand Up @@ -130,6 +130,7 @@ pub enum TileKind {
}

/// Common configuration based on command line arguments
#[derive(Debug)]
pub struct Config {
/// Number of threads for parallel processing
pub num_threads: usize,
Expand All @@ -151,6 +152,8 @@ pub struct Config {
pub viewer_entities_path: PathBuf,
/// Sign text filter patterns
pub sign_patterns: RegexSet,
/// Sign text transformation pattern
pub sign_transforms: Vec<(Regex, String)>,
}

impl Config {
Expand All @@ -173,6 +176,8 @@ impl Config {
.collect();

let sign_patterns = Self::sign_patterns(args).context("Failed to parse sign patterns")?;
let sign_transforms =
Self::sign_transforms(args).context("Failed to parse sign transforms")?;

Ok(Config {
num_threads,
Expand All @@ -185,6 +190,7 @@ impl Config {
viewer_info_path,
viewer_entities_path,
sign_patterns,
sign_transforms,
})
}

Expand All @@ -200,6 +206,28 @@ impl Config {
)?)
}

/// Parses the sign transform argument into a vector of [Regex] and
/// corresponding replacement strings
fn sign_transforms(args: &super::Args) -> Result<Vec<(Regex, String)>> {
let splitter = Regex::new(r"^s/((?:[^\\/]|\\.)*)/((?:[^\\/]|\\.)*)/$").unwrap();

args.sign_transform
.iter()
.map(|t| Self::sign_transform(&splitter, t))
.collect()
}

/// Parses the sign transform argument into a [Regex] and its corresponding
/// replacement string
fn sign_transform(splitter: &Regex, transform: &str) -> Result<(Regex, String)> {
let captures = splitter
.captures(transform)
.with_context(|| format!("Invalid transform pattern '{}'", transform))?;
let regexp = Regex::new(&captures[1])?;
let replacement = captures[2].to_string();
Ok((regexp, replacement))
}

/// Constructs the path to an input region file
pub fn region_path(&self, coords: TileCoords) -> PathBuf {
let filename = coord_filename(coords, "mca");
Expand Down
31 changes: 30 additions & 1 deletion src/core/metadata_writer.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
//! The [MetadataWriter] and related types
use anyhow::{Context, Result};
use regex::Regex;
use serde::Serialize;

use crate::{
core::common::*,
io::{fs, storage},
world::{
block_entity::{self, BlockEntity, BlockEntityData},
de,
de, sign,
},
};

Expand Down Expand Up @@ -145,6 +146,28 @@ impl<'a> MetadataWriter<'a> {
false
}

/// Applies a single transform to a [sign::SignText]
///
/// The regular expression is applied for each line of the sign text
/// separately (actually for each element when JSON text is used)
fn sign_text_transform(sign_text: &mut sign::SignText, transform: &(Regex, String)) {
let (regexp, replacement) = transform;

for line in &mut sign_text.0 {
for text in &mut line.0 {
text.text = regexp.replace_all(&text.text, replacement).into_owned()
}
}
}

/// Applies the configured transforms to the text of a sign
fn sign_transform(&self, sign: &mut block_entity::Sign) {
for transform in &self.config.sign_transforms {
Self::sign_text_transform(&mut sign.front_text, transform);
Self::sign_text_transform(&mut sign.back_text, transform);
}
}

/// Generates [Entities] data from collected entity lists
fn entities(&self) -> Result<Entities> {
let data: ProcessedEntities =
Expand All @@ -158,6 +181,12 @@ impl<'a> MetadataWriter<'a> {
.filter(|entity| match &entity.data {
BlockEntityData::Sign(sign) => self.sign_filter(sign),
})
.map(|mut entity| {
match &mut entity.data {
BlockEntityData::Sign(sign) => self.sign_transform(sign),
};
entity
})
.collect(),
};

Expand Down
6 changes: 6 additions & 0 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ pub struct Args {
/// To make all signs visible, pass an empty string to either option.
#[arg(long)]
pub sign_filter: Vec<String>,
/// Regular expression replacement pattern for sign texts
///
/// Accepts patterns of the form 's/regexp/replacement/'. Transforms
/// are applied to each line of sign texts separately.
#[arg(long)]
pub sign_transform: Vec<String>,
/// Minecraft save directory
pub input_dir: PathBuf,
/// MinedMap data directory
Expand Down

0 comments on commit 8a1a26c

Please sign in to comment.