chiark / gitweb /
shapelib: Provide sort key information
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 6 Apr 2021 19:16:57 +0000 (20:16 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 6 Apr 2021 19:22:04 +0000 (20:22 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/shapelib-toml.rs
src/shapelib.rs

index 99e180b2b85a57e394da79ce904f284ba0dd0c9e..9b9922eb0a698b4288d4d904943d2bc19dbb35c7 100644 (file)
@@ -79,7 +79,11 @@ pub struct GroupDefn {
   /// 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
@@ -91,6 +95,16 @@ pub struct GroupDefn {
   #[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,
 }
index 1f0443d1253c9bc7af1e0201ae72f632af313c92..ce7abd87d1f8fc61a43a9618323052672433744e 100644 (file)
@@ -48,6 +48,7 @@ struct ItemDetails {
 #[derive(Debug,Clone)]
 struct ItemData {
   d: Arc<ItemDetails>,
+  sort: Option<String>,
   group: Arc<GroupData>,
   outline: Outline,
   occ: OccData,
@@ -164,6 +165,7 @@ struct FaceTransform {
 #[derive(Debug,Serialize,Deserialize)]
 pub struct Item {
   itemname: String,
+  sort: Option<String>,
   faces: IndexVec<FaceId, ItemFace>,
   svgs: IndexVec<SvgId, Html>,
   descs: IndexVec<DescId, Html>,
@@ -451,7 +453,8 @@ impl Contents {
       },
     };
 
-    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)
   }
@@ -611,6 +614,13 @@ fn load_catalogue(libname: &str, dirname: &str, toml_path: &str) -> Contents {
                               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 }) => {
@@ -635,7 +645,7 @@ fn load_catalogue(libname: &str, dirname: &str, toml_path: &str) -> Contents {
         },
       };
 
-      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 {
@@ -645,6 +655,7 @@ fn load_catalogue(libname: &str, dirname: &str, toml_path: &str) -> Contents {
           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>;
@@ -663,12 +674,14 @@ fn load_catalogue(libname: &str, dirname: &str, toml_path: &str) -> Contents {
       };
 
       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)?;
         }
 
       }