This repository has been archived on 2026-05-13. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
owlry-plugins/docs/superpowers/specs/2026-03-26-converter-plugin-design.md
T

14 KiB

Converter Plugin — Design Spec

Date: 2026-03-26 Status: Draft Goal: Create an owlry plugin for unit and currency conversion with natural speech input.


1. Overview

A dynamic plugin that converts between units of measurement and currencies. Users type natural expressions like 102F to C or > 50 kg in lb and see conversion results inline.

Key UX decisions:

  • Trigger prefix > for explicit conversion, plus auto-detection
  • Accepts to and in as connector words
  • No space required between number and unit (102F works)
  • When no target unit specified, shows the most common conversions for that category
  • Currency rates from ECB (free, no API key, ~30 fiat currencies, daily)
  • Case-insensitive matching with generous aliases

2. Plugin Identity

Field Value
Plugin ID converter
Provider ID converter
Type ID conv
Provider Kind Dynamic
Trigger prefix >
Search prefix :conv
Position Normal
Priority 9000
Icon accessories-text-editor (or edit-find-replace)
Crate owlry-plugin-converter
Repo owlry-plugins

3. Query Parsing

Input patterns

All of these are valid and must parse correctly:

102F to C              → 102 Fahrenheit → Celsius
102 F to C             → same
102 fahrenheit in celsius → same (full names)
102°F to °C            → same (symbols)
> 102 F                → prefix, no target → show all temperature conversions
102 F                  → auto-detect, no target → show all
102F                   → auto-detect, no space, no target → show all
> 50 kg in lb          → prefix, specific target
50 kg                  → auto-detect, show common weight conversions
100 eur to usd         → currency
100€ to $              → currency with symbols

Parser rules

  1. Strip prefix > if present (and trim whitespace)
  2. Extract number: integer or decimal at start of input (102, 3.5, .5, 0.25)
  3. Extract source unit: immediately adjacent to number OR space-separated. Match against known unit aliases (case-insensitive, longest match first)
  4. If remaining input contains to or in (case-insensitive, word boundary), extract target unit from what follows
  5. If no connector word and remaining text after source unit is non-empty, try to parse it as a target unit anyway (handles 100 km miles)

Auto-detection

The plugin's query() is called for every keystroke. To avoid false positives:

  • Only match if the input starts with a number
  • Only match if the text after the number resolves to a known unit alias
  • Minimum input length: 2 characters (number + unit)
  • Don't match if the text after the number is not a unit alias (e.g., 100x, 102nd)

Ambiguity resolution

Input Resolves to Why
oz Ounce (weight) More common than fluid ounce
fl oz, floz Fluid ounce Explicit
ton Metric ton (1000 kg) International default
short_ton, ton_us US short ton (907 kg) Explicit
gal US gallon More common globally in software
gal_uk, imp_gal Imperial gallon Explicit

4. Unit System Architecture

Conversion model

Each category has a base unit. Every unit defines a conversion factor relative to the base:

value_in_base = input_value * from_unit.to_base(input_value)
result = target_unit.from_base(value_in_base)

For most units this is a simple multiply/divide by factor. Temperature uses offset formulas.

Unit definition

struct UnitDef {
    id: &'static str,                    // canonical name: "kilometer"
    symbol: &'static str,                // display symbol: "km"
    aliases: &'static [&'static str],    // match aliases: ["km", "kms", "kilometers", "kilometre"]
    category: Category,
    conversion: Conversion,
}

enum Conversion {
    Factor(f64),                         // multiply by factor to get base unit
    Custom {                             // for temperature
        to_base: fn(f64) -> f64,
        from_base: fn(f64) -> f64,
    },
}

enum Category {
    Temperature,
    Length,
    Weight,
    Volume,
    Speed,
    Area,
    Data,
    Time,
    Pressure,
    Energy,
    Currency,
}

Base units per category

Category Base unit Rationale
Temperature Kelvin Standard SI, no negative zero issues
Length Meter SI
Weight Kilogram SI
Volume Liter Practical
Speed m/s SI
Area SI
Data Byte Fundamental
Time Second SI
Pressure Pascal SI
Energy Joule SI
Currency EUR ECB reports rates relative to EUR

Temperature conversions (special case)

Celsius → Kelvin:    K = C + 273.15
Fahrenheit → Kelvin: K = (F - 32) * 5/9 + 273.15
Kelvin → Celsius:    C = K - 273.15
Kelvin → Fahrenheit: F = (K - 273.15) * 9/5 + 32

5. Unit Table

Temperature

Unit Symbol Aliases Factor/Conversion
Celsius °C c, °c, celsius, degc, centigrade Custom
Fahrenheit °F f, °f, fahrenheit, degf Custom
Kelvin K k, kelvin Base

Length

Unit Symbol Aliases Factor (to meters)
Millimeter mm mm, millimeter, millimeters, millimetre 0.001
Centimeter cm cm, centimeter, centimeters, centimetre 0.01
Meter m m, meter, meters, metre, metres 1.0 (base)
Kilometer km km, kms, kilometer, kilometers, kilometre 1000.0
Inch in in, inch, inches, " 0.0254
Foot ft ft, foot, feet, ' 0.3048
Yard yd yd, yard, yards 0.9144
Mile mi mi, mile, miles 1609.344
Nautical mile nmi nmi, nautical_mile, nautical_miles 1852.0

Weight/Mass

Unit Symbol Aliases Factor (to kg)
Milligram mg mg, milligram, milligrams 0.000001
Gram g g, gram, grams 0.001
Kilogram kg kg, kilogram, kilograms, kilo, kilos 1.0 (base)
Metric ton t t, ton, tons, tonne, tonnes, metric_ton 1000.0
US short ton short_ton short_ton, ton_us 907.185
Ounce oz oz, ounce, ounces 0.0283495
Pound lb lb, lbs, pound, pounds 0.453592
Stone st st, stone, stones 6.35029

Volume

Unit Symbol Aliases Factor (to liters)
Milliliter ml ml, milliliter, milliliters, millilitre 0.001
Liter l l, liter, liters, litre, litres 1.0 (base)
US gallon gal gal, gallon, gallons 3.78541
Imperial gallon imp_gal imp_gal, gal_uk, imperial_gallon 4.54609
Quart qt qt, quart, quarts 0.946353
Pint pt pt, pint, pints 0.473176
Cup cup cup, cups 0.236588
Fluid ounce fl oz floz, fl_oz, fluid_ounce, fluid_ounces 0.0295735
Tablespoon tbsp tbsp, tablespoon, tablespoons 0.0147868
Teaspoon tsp tsp, teaspoon, teaspoons 0.00492892

Speed

Unit Symbol Aliases Factor (to m/s)
m/s m/s m/s, mps, meters_per_second 1.0 (base)
km/h km/h km/h, kmh, kph, kilometers_per_hour 0.277778
mph mph mph, miles_per_hour 0.44704
Knot kn kn, kt, knot, knots 0.514444
ft/s ft/s ft/s, fps, feet_per_second 0.3048

Area

Unit Symbol Aliases Factor (to m²)
mm² mm² mm2, sqmm, square_millimeter 0.000001
cm² cm² cm2, sqcm, square_centimeter 0.0001
m2, sqm, square_meter, square_meters 1.0 (base)
km² km² km2, sqkm, square_kilometer 1000000.0
ft² ft² ft2, sqft, square_foot, square_feet 0.092903
Acre ac ac, acre, acres 4046.86
Hectare ha ha, hectare, hectares 10000.0

Data

Unit Symbol Aliases Factor (to bytes)
Byte B b, byte, bytes 1.0 (base)
Kilobyte KB kb, kilobyte, kilobytes 1000.0
Megabyte MB mb, megabyte, megabytes 1000000.0
Gigabyte GB gb, gigabyte, gigabytes 1000000000.0
Terabyte TB tb, terabyte, terabytes 1000000000000.0
Kibibyte KiB kib, kibibyte, kibibytes 1024.0
Mebibyte MiB mib, mebibyte, mebibytes 1048576.0
Gibibyte GiB gib, gibibyte, gibibytes 1073741824.0
Tebibyte TiB tib, tebibyte, tebibytes 1099511627776.0

Time

Unit Symbol Aliases Factor (to seconds)
Second s s, sec, second, seconds 1.0 (base)
Minute min min, minute, minutes 60.0
Hour h h, hr, hour, hours 3600.0
Day d d, day, days 86400.0
Week wk wk, week, weeks 604800.0
Month mo mo, month, months 2592000.0 (30 days)
Year yr yr, year, years 31536000.0 (365 days)

Pressure

Unit Symbol Aliases Factor (to Pa)
Pascal Pa pa, pascal, pascals 1.0 (base)
Hectopascal hPa hpa, hectopascal 100.0
Kilopascal kPa kpa, kilopascal 1000.0
Bar bar bar, bars 100000.0
Millibar mbar mbar, millibar 100.0
PSI psi psi, pounds_per_square_inch 6894.76
Atmosphere atm atm, atmosphere, atmospheres 101325.0
mmHg mmHg mmhg, torr 133.322

Energy

Unit Symbol Aliases Factor (to Joules)
Joule J j, joule, joules 1.0 (base)
Kilojoule kJ kj, kilojoule, kilojoules 1000.0
Calorie cal cal, calorie, calories 4.184
Kilocalorie kcal kcal, kilocalorie, kilocalories 4184.0
Watt-hour Wh wh, watt_hour 3600.0
Kilowatt-hour kWh kwh, kilowatt_hour 3600000.0
BTU BTU btu, british_thermal_unit 1055.06

6. Currency

Data source

ECB daily reference rates: https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml

Returns ~30 currencies with rates relative to EUR.

Caching

  • Cache file: ~/.cache/owlry/ecb_rates.json
  • Format: { "date": "2026-03-26", "rates": { "USD": 1.0832, "GBP": 0.8345, ... } }
  • Refresh when cache is older than 24 hours
  • If fetch fails, use cached rates silently (stale rates > no rates)
  • If no cache exists and fetch fails, currency conversions return no results

Currency aliases

Each currency accepts ISO code, lowercase, full name, and common symbol:

Currency Aliases
EUR eur, euro, euros,
USD usd, dollar, dollars, $, us_dollar
GBP gbp, pound_sterling, £, british_pound
JPY jpy, yen, ¥, japanese_yen
CHF chf, swiss_franc, francs
CAD cad, canadian_dollar, c$
AUD aud, australian_dollar, a$
CNY cny, yuan, renminbi, rmb
SEK sek, swedish_krona, kronor
NOK nok, norwegian_krone
DKK dkk, danish_krone
PLN pln, zloty, złoty
CZK czk, czech_koruna
HUF huf, forint
TRY try, turkish_lira, lira
(others) ISO code + lowercase

Conversion

EUR is the base. To convert A→B: result = value / rate_A * rate_B

(EUR rate is implicitly 1.0 since ECB reports everything relative to EUR.)


7. Result Display

With target unit specified

One result:

Name:        37.78 °C
Description: 100 °F = 37.78 °C
Icon:        edit-find-replace
Command:     (copy "37.78" to clipboard via wl-copy)

Without target unit

Up to 5 results showing common conversions for that category:

Query: "100 F"

Result 1:  37.78 °C     │ 100 °F = 37.78 °C
Result 2:  310.93 K     │ 100 °F = 310.93 K
Query: "100 km"

Result 1:  62.14 mi     │ 100 km = 62.14 mi
Result 2:  100000 m     │ 100 km = 100,000 m
Result 3:  328084 ft    │ 100 km = 328,084 ft
Result 4:  109361 yd    │ 100 km = 109,361 yd

Common conversions per category

Category Show (excluding source unit)
Temperature °C, °F, K
Length m, km, ft, mi, in
Weight kg, lb, oz, g, st
Volume l, gal, ml, cup, fl oz
Speed km/h, mph, m/s, kn
Area m², ft², acres, ha, km²
Data MB, GB, MiB, GiB, TB
Time s, min, h, days, weeks
Pressure bar, psi, atm, hPa, mmHg
Energy kJ, kcal, kWh, BTU, Wh
Currency USD, EUR, GBP, JPY, CNY

Number formatting

  • Up to 4 decimal places, trailing zeros stripped
  • Large numbers get thousand separators: 1,000,000
  • Very small numbers use scientific notation if < 0.0001
  • Currency always shows 2 decimal places

8. File Structure

owlry-plugins/crates/owlry-plugin-converter/
├── Cargo.toml
└── src/
    ├── lib.rs          # Plugin interface (vtable, init, query dispatch)
    ├── parser.rs       # Query parsing (number + unit extraction)
    ├── units.rs        # Unit definitions, conversion logic, category tables
    └── currency.rs     # ECB fetch, cache, currency-specific handling

Dependencies

[dependencies]
owlry-plugin-api = { git = "https://somegit.dev/Owlibou/owlry.git", tag = "plugin-api-v1.0.0" }
abi_stable = "0.11"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
reqwest = { version = "0.13", features = ["blocking"] }
dirs = "5"

9. Out of Scope

  • Cryptocurrency (future addition)
  • Compound units (km/h² to m/s²)
  • Math expressions in conversion (2 * 50 kg to lb)
  • Configurable default targets per category
  • Locale-aware number formatting (use . as decimal separator always)
  • Offline currency rate bundling (rely on cache)