From b239976e1ef2a10e05352c14fdaaee22cea3dca5 Mon Sep 17 00:00:00 2001 From: Ruben Beltran del Rio Date: Wed, 17 Dec 2025 10:58:36 +0100 Subject: Allow stdout output --- Cargo.toml | 3 + README.md | 148 ++++++++++-- man/wmap.1 | 14 +- map.svg | 781 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 39 ++- 5 files changed, 946 insertions(+), 39 deletions(-) create mode 100644 map.svg diff --git a/Cargo.toml b/Cargo.toml index 0056321..795c2b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,3 +43,6 @@ unreachable = "deny" undocumented_unsafe_blocks = "deny" unwrap_in_result = "deny" ok_expect = "deny" + +[target.x86_64-apple-darwin] +image = "ghcr.io/cross-rs/x86_64-apple-darwin-cross:local" diff --git a/README.md b/README.md index 5d856a5..5c2c24a 100644 --- a/README.md +++ b/README.md @@ -12,42 +12,138 @@ wmap [OPTIONS] INPUT_FILE ### Description -wmap is a tool that lets you create png or svg images from a wmap formatted file. +The **wmap** utility creates an image file from a *wmap* formatted file. +If *INPUT_FILE* is absent, **wmap** reads from the standard input. If +piped or redirected, it will output the file data to *stdout*. ### Options - **-h, --help**: Display help. - **-v, --version**: Display version information. -- **-t, --type **: Specifies the output type. Can be one of: `png`, or `svg`. Defaults to `png`. -- **-s, --stage **: Specifies the stage labels to use. Defaults to `activities`. -- **-o, --output **: The output file in which to write the image. Defaults to the same filename as the input map, but replacing the extension with either `png`, or `svg`. +- **-t, --type **: Specifies the output type. Can be one of: `png`, + or `svg`. Defaults to `png`. +- **-s, --stage **: Specifies the stage labels to use. Defaults tool + `activities`. +- **-o, --output **: The output file in which to write the image. + Defaults to the same filename as the input map, but replacing the extension + with either `png`, or `svg`. Setting this flag will suppress stdout if piped + or redirected. ### Stages The renderer has the following built-in stage types available: -- **activities** - Genesis / Custom / Product (+rental) / Commodity (+utility) -- **behavior** - Uncertain when to use / Learning when to use / Learning through use / Known / common usage -- **certainty** - Poorly Understood / exploring the unknown / Rapid Increase In Learning / discovery becomes refining / Rapid increase in use / increasing fit for purpose / Commonly understood (in terms of use) -- **comparison** - Constantly changing / a differential / unstable / Learning from others / testing the water / some evidential support / Competing models / feature difference / evidential support / Essential / any advantage is operational / accepted norm -- **cynefin** - Chaotic / Complex / Complicated / Clear -- **data** - Unmodelled / Divergent / Convergent / Modelled -- **decision_drivers** - Heritage / culture / Analyses & synthesis / Analyses & synthesis / Previous Experience -- **efficiency** - Reducing the cost of change (experimentation) / Reducing cost of waste (Learning) / Reducing cost of waste (Learning) / Reducing cost of deviation (Volume) -- **failure** - High / tolerated / assumed to be wrong / Moderate / unsurprising if wrong but disappointed / Not tolerated / focus on constant improvement / assumed to be in the right direction / resistance to changing the model / Surprised by failure / focus on operational efficiency -- **focus_of_value** - High future worth but immediate investment / Seeking ways to profit and a ROI / seeking confirmation of value / High profitability per unit / a valuable model / a feeling of understanding / focus on exploitation / High volume / reducing margin / important but invisible / an essential component of something more complex -- **knowledge** - Concept / Hypothesis / Theory / Accepted -- **knowledge_management** - Uncertain / Learning on use / focused on testing prediction / Learning on operation / using prediction / verification / Known / accepted -- **market** - Undefined Market / Forming Market / an array of competing forms and models of understanding / Growing Market / consolidation to a few competing but more accepted forms / Mature Market / stabilised to an accepted form -- **market_action** - Gambling / driven by gut / Exploring a "found" value / Market analysis / listening to customers / Metric driven / build what is needed -- **market_perception** - Chaotic (non-linear) / domain of the "crazy" / Domain of "experts" / Increasing expectation of use / domain of "professionals" / Ordered (appearance of being linear) / trivial / formula to be applied -- **perception_in_industry** - Future source of competitive advantage / unpredictable / unknown / Seen as a scompetitive advantage / a differential / ROI / case examples / Advantage through implementation / features / this model is better than that / Cost of doing business / accepted / specific defined models -- **practice** - Novel / Emerging / Good / Best -- **publication** - Describe the wonder of the thing / the discovery of some marvel / a new land / an unknown frontier / Focused on build / construct / awareness and learning / many models of explanation / no accepted forms / a wild west / Maintenance / operations / installation / comparison between competing forms / feature analysis / Focused on use / increasingly an accepted, almost invisible component -- **ubiquity** - Rare / Slowly Increasing / Rapidly Increasing / Widespread in the applicable market / ecosystem -- **understanding** - Poorly Understood / unpredictable / Increasing understanding / development of measures / Increasing education / constant refinement of needs / measures / Believed to be well defined / stable / measurable -- **user_perception** - Different / confusing / exciting / surprising / dangerous / Leading edge / emerging / unceirtanty over results / Increasingly common / disappointed if not used or available / feeling left behind / Standard / expected / feeling of shock if not used -- **evolution_stage** - Stage I / Stage II / Stage III / Stage IV +* **Activities** (`activities`) + 1. Genesis + 2. Custom + 3. Product (+rental) + 4. Commodity (+utility) + +* **Behavior** (`behavior`) + 1. Uncertain when to use + 2. Learning when to use + 3. Learning through use + 4. Known / common usage +* **Certainty** (`certainty`) + 1. Poorly Understood / exploring the unknown + 2. Rapid Increase In Learning / discovery becomes refining + 3. Rapid increase in use / increasing fit for purpose + 4. Commonly understood (in terms of use) +* **Comparison** (`comparison`) + 1. Constantly changing / a differential / unstable + 2. Learning from others / testing the water / some evidential support + 3. Competing models / feature difference / evidential support + 4. Essential / any advantage is operational / accepted norm +* **Cynefin** (`cynefin`) + 1. Chaotic + 2. Complex + 3. Complicated + 4. Clear +* **Data** (`data`) + 1. Unmodelled + 2. Divergent + 3. Convergent + 4. Modelled +* **Decision Drivers** (`decision_drivers`) + 1. Heritage / culture + 2. Analyses & synthesis + 3. Analyses & synthesis + 4. Previous Experience +* **Efficiency** (`efficiency`) + 1. Reducing the cost of change (experimentation) + 2. Reducing cost of waste (Learning) + 3. Reducing cost of waste (Learning) + 4. Reducing cost of deviation (Volume) +* **Failure** (`failure`) + 1. High / tolerated / assumed to be wrong + 2. Moderate / unsurprising if wrong but disappointed + 3. Not tolerated / focus on constant improvement / assumed to be in the right direction / resistance to changing the model + 4. Surprised by failure / focus on operational efficiency +* **Focus Of Value** (`focus_of_value`) + 1. High future worth but immediate investment + 2. Seeking ways to profit and a ROI / seeking confirmation of value + 3. High profitability per unit / a valuable model / a feeling of understanding / focus on exploitation + 4. High volume / reducing margin / important but invisible / an essential component of something more complex +* **Knowledge** (`knowledge`) + 1. Concept + 2. Hypothesis + 3. Theory + 4. Accepted +* **Knowledge Management** (`knowledge_management`) + 1. Uncertain + 2. Learning on use / focused on testing prediction + 3. Learning on operation / using prediction / verification + 4. Known / accepted +* **Market** (`market`) + 1. Undefined Market + 2. Forming Market / an array of competing forms and models of understanding + 3. Growing Market / consolidation to a few competing but more accepted forms + 4. Mature Market / stabilised to an accepted form +* **Market Action** (`market_action`) + 1. Gambling / driven by gut + 2. Exploring a "found" value + 3. Market analysis / listening to customers + 4. Metric driven / build what is needed +* **Market Perception** (`market_perception`) + 1. Chaotic (non-linear) / domain of the "crazy" + 2. Domain of "experts" + 3. Increasing expectation of use / domain of "professionals" + 4. Ordered (appearance of being linear) / trivial / formula to be applied +* **Perception In Industry** (`perception_in_industry`) + 1. Future source of competitive advantage / unpredictable / unknown + 2. Seen as a scompetitive advantage / a differential / ROI / case examples + 3. Advantage through implementation / features / this model is better than that + 4. Cost of doing business / accepted / specific defined models +* **Practice** (`practice`) + 1. Novel + 2. Emerging + 3. Good + 4. Best +* **Publication Types** (`publication`) + 1. Describe the wonder of the thing / the discovery of some marvel / a new land / an unknown frontier + 2. Focused on build / construct / awareness and learning / many models of explanation / no accepted forms / a wild west + 3. Maintenance / operations / installation / comparison between competing forms / feature analysis + 4. Focused on use / increasingly an accepted, almost invisible component +* **Ubiquity** (`ubiquity`) + 1. Rare + 2. Slowly Increasing + 3. Rapidly Increasing + 4. Widespread in the applicable market / ecosystem +* **Understanding** (`understanding`) +1. Poorly Understood / unpredictable +2. Increasing understanding / development of measures +3. Increasing education / constant refinement of needs / measures +4. Believed to be well defined / stable / measurable +* **User Perception** (`user_perception`) +1. Different / confusing / exciting / surprising / dangerous +2. Leading edge / emerging / unceirtanty over results +3. Increasingly common / disappointed if not used or available / feeling left behind +4. Standard / expected / feeling of shock if not used +* **Evolution Stage** (`evolution_stage`) +1. Stage I +2. Stage II +3. Stage III +4. Stage IV # Building diff --git a/man/wmap.1 b/man/wmap.1 index 6d8f578..833771a 100644 --- a/man/wmap.1 +++ b/man/wmap.1 @@ -2,11 +2,14 @@ .SH NAME wmap \- generate wardley map images from wmap files. .SH SYNOPSIS -.B wmap [\fIOPTIONS\fP] \fIINPUT_FILE\fP +.B wmap +.RI [ OPTIONS ] +.I INPUT_FILE .SH DESCRIPTION .PP -wmap is a tool that lets you create png or scg images from a wmap formatted -file. +The \fBwmap\fP utility creates an image file from a \fIwmap\fP formatted file. +If \fIINPUT_FILE\fP is absent, \fBwmap\fP reads from the standard input. If +piped or redirected, it will output the file data to \fIstdout\fP. .SH OPTIONS .TP .B -h, --help @@ -25,6 +28,7 @@ Specifies the stage labels to use. Defaults to \fIactivities\fR. .B -o, --output <\fIOUTPUT_FILE\fP> The output file in which to write the image. Defaults to the same filename as the input map, but replacing the extension with either \fIpng\fR, or \fIsvg\fR. +Setting this flag will suppress stdout if piped or redirected. .SH STAGES The renderer has the following built-in sources available: .SS Activities (\fIactivities\fP) @@ -218,13 +222,13 @@ Increasingly common / disappointed if not used or available / feeling left behin Standard / expected / feeling of shock if not used .SS Evolution Stage (\fIevolution_stage\fP) .TP -tage I +Stage I .TP Stage II .TP Stage III .TP -Stage IV" +Stage IV .SH VERSION .BR 1.0.0 .SH HOMEPAGE diff --git a/map.svg b/map.svg new file mode 100644 index 0000000..4dbab9c --- /dev/null +++ b/map.svg @@ -0,0 +1,781 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main.rs b/src/main.rs index 833c846..fe0ba04 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use std::fmt; use std::fs::{read_to_string, write}; -use std::io::{Error as IoError, Result as IoResult}; +use std::io::{self, Error as IoError, IsTerminal, Read, Result as IoResult, Write}; use std::path::PathBuf; use std::str::FromStr; use wmap_renderer::{Configuration, StageType, render_to_png, render_to_svg}; @@ -71,14 +71,17 @@ fn stage_from_str(s: &str) -> Option { } struct Arguments { - input: PathBuf, + input: Option, output: PathBuf, + write_to_stdout: bool, stage: StageType, image_type: ImageType, } fn print_help() { - println!("Usage: wmap [-t|--type IMAGE_TYPE] [-s|--stage STAGE] [-o|--output OUTPUT_FILE] INPUT_FILE"); + println!( + "Usage: wmap [-t|--type IMAGE_TYPE] [-s|--stage STAGE] [-o|--output OUTPUT_FILE] INPUT_FILE" + ); } fn parse_arguments() -> Result { @@ -86,6 +89,7 @@ fn parse_arguments() -> Result { let mut input = None; let mut output: String = String::new(); + let mut write_to_stdout: bool = false; let mut stage = StageType::Activities; let mut image_type = ImageType::Png; @@ -117,9 +121,17 @@ fn parse_arguments() -> Result { _ => return Err(argument.unexpected()), } } - let input = PathBuf::from(input.ok_or("missing argument INPUT_FILE")?); + let input = input.map(PathBuf::from); let output = if output.is_empty() { - input.with_extension(image_type.to_string()) + if io::stdout().is_terminal() { + match &input { + Some(path) => path.with_extension(image_type.to_string()), + None => PathBuf::from(format!("./map.{image_type}")), + } + } else { + write_to_stdout = true; + PathBuf::new() + } } else { PathBuf::from(output) }; @@ -127,6 +139,7 @@ fn parse_arguments() -> Result { Ok(Arguments { input, output, + write_to_stdout, stage, image_type, }) @@ -135,8 +148,14 @@ fn parse_arguments() -> Result { fn run() -> IoResult<()> { let arguments = parse_arguments().map_err(|_| IoError::other("Unable to parse arguments"))?; - arguments.input.try_exists()?; - let source = read_to_string(arguments.input)?; + let source = if let Some(input_path) = arguments.input { + input_path.try_exists()?; + read_to_string(input_path)? + } else { + let mut buffer = String::new(); + io::stdin().read_to_string(&mut buffer)?; + buffer + }; let map = wmap_parser::parse(&source); let configuration = Configuration::default(); @@ -147,7 +166,11 @@ fn run() -> IoResult<()> { .map_err(|_| IoError::other("Unable to render SVG"))? .into_bytes(), }; - write(arguments.output, image_data)?; + if arguments.write_to_stdout { + io::stdout().write_all(&image_data)?; + } else { + write(arguments.output, image_data)?; + } Ok(()) } -- cgit