/// adding fields to each line. This is done by adding a line at
/// the start starting with `:` and then additing one additional
/// whitespace separated value on each data line. Unknown
- /// `fieldname` values are ignored.
+ /// `fieldname` values are ignored. Currently the extra fields
+ /// supported are:
+ ///
+ /// * `sort`: Specifies the sort key. See the `sort` group
+ /// definition property.
///
/// The values for these extra fields come just before the
/// dwscription, after the other whitespace-delimited fields, in the
#[serde(default)] pub item_prefix: String,
#[serde(default)] pub item_suffix: String,
+ /// The sort key (used for item sorting in hands).
+ ///
+ /// If neither the group property, nor the `files` extra field, are
+ /// specified, the item name is used.
+ ///
+ /// If both are specified, the group property is used as a template.
+ /// `_s` is replaced by the sort extra field from the `files` list
+ /// `_c` is replaced by the colour, if applicable.
+ #[serde(default)] pub sort: String,
+
#[doc(hidden)]
#[serde(flatten)] pub d: GroupDetails,
}
#[derive(Debug,Clone)]
struct ItemData {
d: Arc<ItemDetails>,
+ sort: Option<String>,
group: Arc<GroupData>,
outline: Outline,
occ: OccData,
#[derive(Debug,Serialize,Deserialize)]
pub struct Item {
itemname: String,
+ sort: Option<String>,
faces: IndexVec<FaceId, ItemFace>,
svgs: IndexVec<SvgId, Html>,
descs: IndexVec<DescId, Html>,
},
};
- let it = Item { faces, descs, svgs, outline, back,
+ let sort = idata.sort.clone();
+ let it = Item { faces, sort, descs, svgs, outline, back,
itemname: name.to_string() };
(Box::new(it), occultable)
}
fe.item_spec, gdefn.item_suffix);
let item_name: GoodItemName = item_name.try_into()?;
+ let sort = match (gdefn.sort.as_str(), fe.extra_fields.get("sort")) {
+ ("", None) => None,
+ (gd, None) => Some(gd.to_string()),
+ ("", Some(ef)) => Some(ef.to_string()),
+ (gd, Some(ef)) => Some(subst(gd, "_s", ef)?),
+ };
+
let occ = match &group.d.occulted {
None => OccData::None,
Some(OccultationMethod::ByColour { colour }) => {
},
};
- let mut add1 = |item_name: &GoodItemName, desc: &str| {
+ let mut add1 = |item_name: &GoodItemName, sort, desc: &str| {
let desc = if let Some(desc_template) = &group.d.desc_template {
subst(desc_template, "_desc", &desc)?.to_html()
} else {
group: group.clone(),
occ: occ.clone(),
outline: outline.clone(),
+ sort,
d: Arc::new(ItemDetails { desc }),
};
type H<'e,X,Y> = hash_map::Entry<'e,X,Y>;
};
if group.d.colours.is_empty() {
- add1(&item_name, &fe.desc.clone())?;
+ add1(&item_name, sort, &fe.desc.clone())?;
} else {
for (colour, recolourdata) in &group.d.colours {
+ let t_sort = sort.as_ref().map(
+ |s| subst(&s, "_c", colour)).transpose()?;
let t_item_name = subst(item_name.as_str(), "_c", &recolourdata.abbrev)?;
let t_desc = subst(&fe.desc, "_colour", colour)?;
- add1(&t_item_name.try_into()?, &t_desc)?;
+ add1(&t_item_name.try_into()?, t_sort, &t_desc)?;
}
}