diff --git a/src/layout/parser/splits.rs b/src/layout/parser/splits.rs
index b4ddadc0..7e2697d2 100644
--- a/src/layout/parser/splits.rs
+++ b/src/layout/parser/splits.rs
@@ -1,14 +1,14 @@
use super::{
- accuracy, comparison_override, end_tag, parse_bool, parse_children, text, text_parsed,
- timing_method_override, Error, GradientBuilder, GradientKind, ListGradientKind, Result,
+ Error, GradientBuilder, GradientKind, ListGradientKind, Result, accuracy, comparison_override,
+ end_tag, parse_bool, parse_children, text, text_parsed, timing_method_override,
};
use crate::{
component::splits::{
self, ColumnKind, ColumnSettings, ColumnStartWith, ColumnUpdateTrigger, ColumnUpdateWith,
- TimeColumn,
+ TimeColumn, VariableColumn,
},
platform::prelude::*,
- util::xml::{helper::text_as_escaped_string_err, Reader},
+ util::xml::{Reader, helper::text_as_escaped_string_err},
};
pub use crate::component::splits::Component;
@@ -49,6 +49,7 @@ pub fn settings(reader: &mut Reader<'_>, component: &mut Component) -> Result<()
parse_children(reader, |reader, _, _| {
let mut column_name = String::new();
let mut column = TimeColumn::default();
+ let mut custom_variable = false;
parse_children(reader, |reader, tag, _| match tag.name() {
"Name" => text(reader, |v| column_name = v.into_owned()),
"Comparison" => {
@@ -58,41 +59,44 @@ pub fn settings(reader: &mut Reader<'_>, component: &mut Component) -> Result<()
timing_method_override(reader, |v| column.timing_method = v)
}
"Type" => text_as_escaped_string_err(reader, |v| {
- (
- column.start_with,
- column.update_with,
- column.update_trigger,
- ) = match v {
- "Delta" => (
- ColumnStartWith::Empty,
- ColumnUpdateWith::Delta,
- ColumnUpdateTrigger::Contextual,
- ),
- "SplitTime" => (
- ColumnStartWith::ComparisonTime,
- ColumnUpdateWith::SplitTime,
- ColumnUpdateTrigger::OnEndingSegment,
- ),
- "DeltaorSplitTime" => (
- ColumnStartWith::ComparisonTime,
- ColumnUpdateWith::DeltaWithFallback,
- ColumnUpdateTrigger::Contextual,
- ),
- "SegmentDelta" => (
- ColumnStartWith::Empty,
- ColumnUpdateWith::SegmentDelta,
- ColumnUpdateTrigger::Contextual,
- ),
- "SegmentTime" => (
- ColumnStartWith::ComparisonSegmentTime,
- ColumnUpdateWith::SegmentTime,
- ColumnUpdateTrigger::OnEndingSegment,
- ),
- "SegmentDeltaorSegmentTime" => (
- ColumnStartWith::ComparisonSegmentTime,
- ColumnUpdateWith::SegmentDeltaWithFallback,
- ColumnUpdateTrigger::Contextual,
- ),
+ match v {
+ "Delta" => {
+ column.start_with = ColumnStartWith::Empty;
+ column.update_with = ColumnUpdateWith::Delta;
+ column.update_trigger = ColumnUpdateTrigger::Contextual;
+ }
+ "SplitTime" => {
+ column.start_with = ColumnStartWith::ComparisonTime;
+ column.update_with = ColumnUpdateWith::SplitTime;
+ column.update_trigger =
+ ColumnUpdateTrigger::OnEndingSegment;
+ }
+ "DeltaorSplitTime" => {
+ column.start_with = ColumnStartWith::ComparisonTime;
+ column.update_with =
+ ColumnUpdateWith::DeltaWithFallback;
+ column.update_trigger = ColumnUpdateTrigger::Contextual;
+ }
+ "SegmentDelta" => {
+ column.start_with = ColumnStartWith::Empty;
+ column.update_with = ColumnUpdateWith::SegmentDelta;
+ column.update_trigger = ColumnUpdateTrigger::Contextual;
+ }
+ "SegmentTime" => {
+ column.start_with =
+ ColumnStartWith::ComparisonSegmentTime;
+ column.update_with = ColumnUpdateWith::SegmentTime;
+ column.update_trigger =
+ ColumnUpdateTrigger::OnEndingSegment;
+ }
+ "SegmentDeltaorSegmentTime" => {
+ column.start_with =
+ ColumnStartWith::ComparisonSegmentTime;
+ column.update_with =
+ ColumnUpdateWith::SegmentDeltaWithFallback;
+ column.update_trigger = ColumnUpdateTrigger::Contextual;
+ }
+ "CustomVariable" => custom_variable = true,
_ => return Err(Error::ParseColumnType),
};
@@ -103,8 +107,14 @@ pub fn settings(reader: &mut Reader<'_>, component: &mut Component) -> Result<()
settings.columns.insert(
0,
splits::ColumnSettings {
+ kind: if custom_variable {
+ ColumnKind::Variable(VariableColumn {
+ variable_name: column_name.clone(),
+ })
+ } else {
+ ColumnKind::Time(column)
+ },
name: column_name,
- kind: ColumnKind::Time(column),
},
);
Ok(())
diff --git a/src/layout/parser/text.rs b/src/layout/parser/text.rs
index 6bafe107..207d905f 100644
--- a/src/layout/parser/text.rs
+++ b/src/layout/parser/text.rs
@@ -1,4 +1,4 @@
-use super::{color, end_tag, parse_bool, parse_children, text, GradientBuilder, Result};
+use super::{GradientBuilder, Result, color, end_tag, parse_bool, parse_children, text};
use crate::{component::text::Text, platform::prelude::*, util::xml::Reader};
pub use crate::component::text::Component;
@@ -8,6 +8,14 @@ pub fn settings(reader: &mut Reader<'_>, component: &mut Component) -> Result<()
let mut background_builder = GradientBuilder::new();
let (mut override_label, mut override_value) = (false, false);
let (mut left_center, mut right) = (String::new(), String::new());
+ // - Normally, when `custom_variable` is false,
+ // `Text2`/`right` is interpreted as text to be displayed as-is,
+ // through `Text::Split` or `Text::Center`.
+ // - But when `custom_variable` is true,
+ // `Text2`/`right` is interpreted as the custom variable name,
+ // and the value of the custom variable is displayed instead,
+ // through `Text::Variable`.
+ let mut custom_variable = false;
parse_children(reader, |reader, tag, _| {
if !background_builder.parse_background(reader, tag.name())? {
@@ -19,6 +27,7 @@ pub fn settings(reader: &mut Reader<'_>, component: &mut Component) -> Result<()
"Text1" => text(reader, |v| left_center = v.into_owned()),
"Text2" => text(reader, |v| right = v.into_owned()),
"Display2Rows" => parse_bool(reader, |b| settings.display_two_rows = b),
+ "CustomVariable" => parse_bool(reader, |b| custom_variable = b),
_ => {
// FIXME:
// Font1
@@ -39,10 +48,11 @@ pub fn settings(reader: &mut Reader<'_>, component: &mut Component) -> Result<()
if !override_value {
settings.right_color = None;
}
- settings.text = match (left_center.is_empty(), right.is_empty()) {
- (false, false) => Text::Split(left_center, right),
- (false, true) => Text::Center(left_center),
- _ => Text::Center(right),
+ settings.text = match (custom_variable, left_center.is_empty(), right.is_empty()) {
+ (true, lc_empty, _) => Text::Variable(right, !lc_empty),
+ (false, false, false) => Text::Split(left_center, right),
+ (false, false, true) => Text::Center(left_center),
+ (false, true, _) => Text::Center(right),
};
settings.background = background_builder.build();
diff --git a/tests/layout_files/custom_variable_ls1l.ls1l b/tests/layout_files/custom_variable_ls1l.ls1l
new file mode 100644
index 00000000..7c3e7c49
--- /dev/null
+++ b/tests/layout_files/custom_variable_ls1l.ls1l
@@ -0,0 +1,306 @@
+{
+ "components": [
+ {
+ "Title": {
+ "background": {
+ "Vertical": [
+ [
+ 0.16470589,
+ 0.16470589,
+ 0.16470589,
+ 1.0
+ ],
+ [
+ 0.07450981,
+ 0.07450981,
+ 0.07450981,
+ 1.0
+ ]
+ ]
+ },
+ "text_color": null,
+ "show_game_name": true,
+ "show_category_name": true,
+ "show_finished_runs_count": false,
+ "show_attempt_count": true,
+ "text_alignment": "Auto",
+ "display_as_single_line": false,
+ "display_game_icon": true,
+ "show_region": false,
+ "show_platform": false,
+ "show_variables": true
+ }
+ },
+ {
+ "Splits": {
+ "background": {
+ "Alternating": [
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.0
+ ],
+ [
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.04215355
+ ]
+ ]
+ },
+ "visual_split_count": 8,
+ "split_preview_count": 1,
+ "show_thin_separators": true,
+ "separator_last_split": true,
+ "always_show_last_split": true,
+ "fill_with_blank_space": true,
+ "display_two_rows": false,
+ "current_split_gradient": {
+ "Vertical": [
+ [
+ 0.20000002,
+ 0.45098042,
+ 0.9568628,
+ 1.0
+ ],
+ [
+ 0.08235294,
+ 0.20784315,
+ 0.454902,
+ 1.0
+ ]
+ ]
+ },
+ "split_time_accuracy": "Seconds",
+ "segment_time_accuracy": "Seconds",
+ "delta_time_accuracy": "Tenths",
+ "delta_drop_decimals": true,
+ "show_column_labels": false,
+ "columns": [
+ {
+ "name": "Time",
+ "start_with": "ComparisonTime",
+ "update_with": "SplitTime",
+ "update_trigger": "OnEndingSegment",
+ "comparison_override": null,
+ "timing_method": null
+ },
+ {
+ "name": "+/-",
+ "start_with": "Empty",
+ "update_with": "Delta",
+ "update_trigger": "Contextual",
+ "comparison_override": null,
+ "timing_method": null
+ },
+ {
+ "name": "delta hits",
+ "variable_name": "delta hits"
+ },
+ {
+ "name": "segment hits",
+ "variable_name": "segment hits"
+ }
+ ]
+ }
+ },
+ {
+ "Text": {
+ "background": "Transparent",
+ "display_two_rows": false,
+ "left_center_color": null,
+ "right_color": null,
+ "text": {
+ "Variable": [
+ "hits",
+ true
+ ]
+ }
+ }
+ },
+ {
+ "Text": {
+ "background": "Transparent",
+ "display_two_rows": false,
+ "left_center_color": null,
+ "right_color": null,
+ "text": {
+ "Variable": [
+ "pb hits",
+ true
+ ]
+ }
+ }
+ },
+ {
+ "Timer": {
+ "background": "Transparent",
+ "timing_method": "GameTime",
+ "height": 54,
+ "color_override": null,
+ "show_gradient": true,
+ "digits_format": "SingleDigitSeconds",
+ "accuracy": "Hundredths",
+ "is_segment_timer": false
+ }
+ },
+ {
+ "Timer": {
+ "background": "Transparent",
+ "timing_method": "RealTime",
+ "height": 39,
+ "color_override": null,
+ "show_gradient": true,
+ "digits_format": "SingleDigitSeconds",
+ "accuracy": "Hundredths",
+ "is_segment_timer": false
+ }
+ },
+ {
+ "PreviousSegment": {
+ "background": {
+ "Vertical": [
+ [
+ 0.10980393,
+ 0.10980393,
+ 0.10980393,
+ 1.0
+ ],
+ [
+ 0.050980397,
+ 0.050980397,
+ 0.050980397,
+ 1.0
+ ]
+ ]
+ },
+ "comparison_override": null,
+ "display_two_rows": false,
+ "label_color": null,
+ "drop_decimals": true,
+ "accuracy": "Tenths",
+ "show_possible_time_save": false
+ }
+ },
+ {
+ "CurrentPace": {
+ "background": "Transparent",
+ "comparison_override": "Best Segments",
+ "display_two_rows": false,
+ "label_color": null,
+ "value_color": null,
+ "accuracy": "Hundredths"
+ }
+ },
+ {
+ "CurrentComparison": {
+ "background": {
+ "Vertical": [
+ [
+ 0.10980393,
+ 0.10980393,
+ 0.10980393,
+ 1.0
+ ],
+ [
+ 0.050980397,
+ 0.050980397,
+ 0.050980397,
+ 1.0
+ ]
+ ]
+ },
+ "display_two_rows": false,
+ "label_color": null,
+ "value_color": null
+ }
+ }
+ ],
+ "general": {
+ "direction": "Vertical",
+ "timer_font": null,
+ "times_font": null,
+ "text_font": null,
+ "text_shadow": [
+ 0.0,
+ 0.0,
+ 0.0,
+ 0.27156216
+ ],
+ "background": {
+ "Plain": [
+ 0.058823533,
+ 0.058823533,
+ 0.058823533,
+ 1.0
+ ]
+ },
+ "best_segment_color": [
+ 0.8470589,
+ 0.6862745,
+ 0.121568635,
+ 1.0
+ ],
+ "ahead_gaining_time_color": [
+ 0.0,
+ 0.8000001,
+ 0.21176472,
+ 1.0
+ ],
+ "ahead_losing_time_color": [
+ 0.32156864,
+ 0.8000001,
+ 0.45098042,
+ 1.0
+ ],
+ "behind_gaining_time_color": [
+ 0.8000001,
+ 0.36078432,
+ 0.32156864,
+ 1.0
+ ],
+ "behind_losing_time_color": [
+ 0.8000001,
+ 0.07058824,
+ 0.0,
+ 1.0
+ ],
+ "not_running_color": [
+ 0.6745098,
+ 0.6745098,
+ 0.6745098,
+ 1.0
+ ],
+ "personal_best_color": [
+ 0.08627451,
+ 0.6509804,
+ 1.0,
+ 1.0
+ ],
+ "paused_color": [
+ 0.4784314,
+ 0.4784314,
+ 0.4784314,
+ 1.0
+ ],
+ "thin_separators_color": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.07897232
+ ],
+ "separators_color": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 0.32670057
+ ],
+ "text_color": [
+ 1.0,
+ 1.0,
+ 1.0,
+ 1.0
+ ]
+ }
+}
diff --git a/tests/layout_files/custom_variable_splits.lsl b/tests/layout_files/custom_variable_splits.lsl
new file mode 100644
index 00000000..468b2c0f
--- /dev/null
+++ b/tests/layout_files/custom_variable_splits.lsl
@@ -0,0 +1,278 @@
+
+
+ Vertical
+ 7
+ 647
+ 286
+ 388
+ -1
+ -1
+
+ FFFFFFFF
+ FF0F0F0F
+ 00000000
+ 03FFFFFF
+ 24FFFFFF
+ FF16A6FF
+ FF00CC36
+ FF52CC73
+ FFCC5C52
+ FFCC1200
+ FFD8AF1F
+ False
+ FFACACAC
+ FF7A7A7A
+ 00000000
+ 80000000
+
+
+
+
+
+
+
+
+
+ True
+ True
+ True
+ True
+ SolidColor
+
+ 1
+ 0
+ 0.59
+ False
+
+
+
+ LiveSplit.Title.dll
+
+ 1.7.3
+ True
+ True
+ True
+ False
+ False
+ False
+
+
+
+ False
+ FFFFFFFF
+ FF2A2A2A
+ FF131313
+ Vertical
+ True
+ False
+ False
+ True
+ 0
+
+
+
+ LiveSplit.Splits.dll
+
+ 1.6
+ FF3373F4
+ FF153574
+ 8
+ 1
+ True
+ True
+ True
+ 20
+ Seconds
+ False
+ FFFFFFFF
+ FFFFFFFF
+ FFFFFFFF
+ False
+ FFFFFFFF
+ FFFFFFFF
+ FFFFFFFF
+ False
+ True
+ True
+ 24
+ True
+ 3.6
+ Vertical
+ 00FFFFFF
+ 01FFFFFF
+ Alternating
+ True
+ Tenths
+ True
+ False
+ FFFFFFFF
+ False
+ False
+ FFFFFFFF
+
+
+ 1.5
+ segment hits
+ CustomVariable
+ Current Comparison
+ Current Timing Method
+
+
+ 1.5
+ delta hits
+ CustomVariable
+ Current Comparison
+ Current Timing Method
+
+
+ 1.5
+ +/-
+ Delta
+ Current Comparison
+ Current Timing Method
+
+
+ 1.5
+ Time
+ SplitTime
+ Current Comparison
+ Current Timing Method
+
+
+
+
+
+ LiveSplit.Text.dll
+
+ 1.4
+ FFFFFFFF
+ False
+ FFFFFFFF
+ False
+ 00FFFFFF
+ 00FFFFFF
+ Plain
+ hits
+ hits
+
+
+
+
+
+
+ False
+ False
+ False
+ True
+
+
+
+ LiveSplit.Text.dll
+
+ 1.4
+ FFFFFFFF
+ False
+ FFFFFFFF
+ False
+ 00FFFFFF
+ 00FFFFFF
+ Plain
+ pb hits
+ pb hits
+
+
+
+
+
+
+ False
+ False
+ False
+ True
+
+
+
+ LiveSplit.Timer.dll
+
+ 1.5
+ 69
+ 225
+ 1.23
+ False
+ True
+ FFAAAAAA
+ 00000000
+ FF222222
+ Plain
+ False
+ Game Time
+ 35
+
+
+
+ LiveSplit.Timer.dll
+
+ 1.5
+ 50
+ 225
+ 1.23
+ False
+ True
+ FFAAAAAA
+ 00FFFFFF
+ 00FFFFFF
+ Plain
+ False
+ Real Time
+ 35
+
+
+
+ LiveSplit.PreviousSegment.dll
+
+ 1.6
+ FFFFFFFF
+ False
+ FF1C1C1C
+ FF0D0D0D
+ Vertical
+ Tenths
+ True
+ Current Comparison
+ False
+ False
+ Tenths
+
+
+
+ LiveSplit.RunPrediction.dll
+
+ 1.4
+ FFFFFFFF
+ False
+ FFFFFFFF
+ False
+ Hundredths
+ 00FFFFFF
+ 00FFFFFF
+ Plain
+ Best Segments
+ False
+
+
+
+ LiveSplit.CurrentComparison.dll
+
+ 1.4
+ FFFFFFFF
+ False
+ FFFFFFFF
+ False
+ FF1C1C1C
+ FF0D0D0D
+ Vertical
+ False
+
+
+
+
diff --git a/tests/layout_files/custom_variable_subsplits.lsl b/tests/layout_files/custom_variable_subsplits.lsl
new file mode 100644
index 00000000..9148ec40
--- /dev/null
+++ b/tests/layout_files/custom_variable_subsplits.lsl
@@ -0,0 +1,306 @@
+
+
+ Vertical
+ 5
+ 635
+ 286
+ 398
+ -1
+ -1
+
+ FFFFFFFF
+ FF0F0F0F
+ 00000000
+ 03FFFFFF
+ 24FFFFFF
+ FF16A6FF
+ FF00CC36
+ FF52CC73
+ FFCC5C52
+ FFCC1200
+ FFD8AF1F
+ False
+ FFACACAC
+ FF7A7A7A
+ 00000000
+ 80000000
+
+
+
+
+
+
+
+
+
+ True
+ True
+ True
+ True
+ SolidColor
+
+ 1
+ 0
+ 0.59
+ False
+
+
+
+ LiveSplit.Title.dll
+
+ 1.7.3
+ True
+ True
+ True
+ False
+ False
+ False
+
+
+
+ False
+ FFFFFFFF
+ FF2A2A2A
+ FF131313
+ Vertical
+ True
+ False
+ False
+ True
+ 0
+
+
+
+ LiveSplit.Subsplits.dll
+
+ 1.7
+ False
+ FF3373F4
+ FF153574
+ 8
+ 1
+ 0
+ True
+ True
+ True
+ 20
+ Seconds
+ FFFFFFFF
+ FFFFFFFF
+ FFFFFFFF
+ False
+ FFFFFFFF
+ FFFFFFFF
+ FFFFFFFF
+ False
+ True
+ 24
+ True
+ 6
+ Vertical
+ 00FFFFFF
+ 01FFFFFF
+ Alternating
+ True
+ Tenths
+ True
+ False
+ FFFFFFFF
+ Current Comparison
+ Current Timing Method
+ False
+ True
+ True
+ False
+ False
+ False
+ False
+ Plain
+ True
+ True
+ True
+ True
+ Vertical
+ False
+ True
+ True
+ Tenths
+ True
+ True
+ Tenths
+ 8D000000
+ 00FFFFFF
+ 2BFFFFFF
+ D8000000
+ FFFFFFFF
+ FFFFFFFF
+ FF777777
+ False
+ FFFFFFFF
+
+
+ 1.5
+ segment hits
+ CustomVariable
+ Current Comparison
+ Current Timing Method
+
+
+ 1.5
+ delta hits
+ CustomVariable
+ Current Comparison
+ Current Timing Method
+
+
+ 1.5
+ +/-
+ Delta
+ Current Comparison
+ Current Timing Method
+
+
+ 1.5
+ Time
+ SplitTime
+ Current Comparison
+ Current Timing Method
+
+
+
+
+
+ LiveSplit.Text.dll
+
+ 1.4
+ FFFFFFFF
+ False
+ FFFFFFFF
+ False
+ 00FFFFFF
+ 00FFFFFF
+ Plain
+ hits
+ hits
+
+
+
+
+
+
+ False
+ False
+ False
+ True
+
+
+
+ LiveSplit.Text.dll
+
+ 1.4
+ FFFFFFFF
+ False
+ FFFFFFFF
+ False
+ 00FFFFFF
+ 00FFFFFF
+ Plain
+ pb hits
+ pb hits
+
+
+
+
+
+
+ False
+ False
+ False
+ True
+
+
+
+ LiveSplit.Timer.dll
+
+ 1.5
+ 69
+ 225
+ 1.23
+ False
+ True
+ FFAAAAAA
+ 00000000
+ FF222222
+ Plain
+ False
+ Game Time
+ 35
+
+
+
+ LiveSplit.Timer.dll
+
+ 1.5
+ 50
+ 225
+ 1.23
+ False
+ True
+ FFAAAAAA
+ 00FFFFFF
+ 00FFFFFF
+ Plain
+ False
+ Real Time
+ 35
+
+
+
+ LiveSplit.PreviousSegment.dll
+
+ 1.6
+ FFFFFFFF
+ False
+ FF1C1C1C
+ FF0D0D0D
+ Vertical
+ Tenths
+ True
+ Current Comparison
+ False
+ False
+ Tenths
+
+
+
+ LiveSplit.RunPrediction.dll
+
+ 1.4
+ FFFFFFFF
+ False
+ FFFFFFFF
+ False
+ Hundredths
+ 00FFFFFF
+ 00FFFFFF
+ Plain
+ Best Segments
+ False
+
+
+
+ LiveSplit.CurrentComparison.dll
+
+ 1.4
+ FFFFFFFF
+ False
+ FFFFFFFF
+ False
+ FF1C1C1C
+ FF0D0D0D
+ Vertical
+ False
+
+
+
+
diff --git a/tests/layout_files/mod.rs b/tests/layout_files/mod.rs
index ac34b526..5892c178 100644
--- a/tests/layout_files/mod.rs
+++ b/tests/layout_files/mod.rs
@@ -7,3 +7,6 @@ pub const WSPLIT: &str = include_str!("WSplit.lsl");
pub const WITH_TIMER_DELTA_BACKGROUND: &str = include_str!("WithTimerDeltaBackground.lsl");
pub const WITH_BACKGROUND_IMAGE: &str = include_str!("WithBackgroundImage.lsl");
pub const TEXT_SHADOW: &str = include_str!("TextShadow.ls1l");
+pub const CUSTOM_VARIABLE_SPLITS: &str = include_str!("custom_variable_splits.lsl");
+pub const CUSTOM_VARIABLE_SUBSPLITS: &str = include_str!("custom_variable_subsplits.lsl");
+pub const CUSTOM_VARIABLE_LS1L: &str = include_str!("custom_variable_ls1l.ls1l");
diff --git a/tests/layout_parsing.rs b/tests/layout_parsing.rs
index b2b03e63..ec5aad50 100644
--- a/tests/layout_parsing.rs
+++ b/tests/layout_parsing.rs
@@ -2,13 +2,22 @@ mod layout_files;
mod parse {
use crate::layout_files;
- use livesplit_core::layout::{parser::parse, Layout};
+ use livesplit_core::{
+ Component,
+ component::{splits, text},
+ layout::{Layout, parser::parse},
+ };
#[track_caller]
fn livesplit(data: &str) -> Layout {
parse(data).unwrap()
}
+ #[track_caller]
+ fn ls1l(data: &str) -> Layout {
+ Layout::from_settings(serde_json::from_str(data).unwrap())
+ }
+
#[test]
fn all() {
livesplit(layout_files::ALL);
@@ -34,6 +43,108 @@ mod parse {
livesplit(layout_files::WITH_TIMER_DELTA_BACKGROUND);
}
+ #[test]
+ fn custom_variable_splits() {
+ let l = livesplit(layout_files::CUSTOM_VARIABLE_SPLITS);
+ let Some(splits) = l.components.iter().find_map(|c| match c {
+ Component::Splits(s) => Some(s),
+ _ => None,
+ }) else {
+ panic!("Splits component not found");
+ };
+ let texts: Vec<_> = l
+ .components
+ .iter()
+ .filter_map(|c| match c {
+ Component::Text(t) => Some(t),
+ _ => None,
+ })
+ .collect();
+ {
+ let splits::ColumnKind::Variable(splits::VariableColumn { ref variable_name }) =
+ splits.settings().columns[2].kind
+ else {
+ panic!("expected ColumnKind::Variable");
+ };
+ assert_eq!(variable_name, "delta hits");
+ }
+ {
+ let splits::ColumnKind::Variable(splits::VariableColumn { ref variable_name }) =
+ splits.settings().columns[3].kind
+ else {
+ panic!("expected ColumnKind::Variable");
+ };
+ assert_eq!(variable_name, "segment hits");
+ }
+ {
+ let text::Text::Variable(ref variable_name, is_split) = texts[0].settings().text else {
+ panic!("expected Text::Variable");
+ };
+ assert_eq!(variable_name, "hits");
+ assert_eq!(is_split, true);
+ }
+ {
+ let text::Text::Variable(ref variable_name, is_split) = texts[1].settings().text else {
+ panic!("expected Text::Variable");
+ };
+ assert_eq!(variable_name, "pb hits");
+ assert_eq!(is_split, true);
+ }
+ let l1 = ls1l(layout_files::CUSTOM_VARIABLE_LS1L);
+ assert_eq!(serde_json::to_string(&l.settings()).ok(), serde_json::to_string(&l1.settings()).ok());
+ }
+
+ #[test]
+ fn custom_variable_subsplits() {
+ let l = livesplit(layout_files::CUSTOM_VARIABLE_SUBSPLITS);
+ let Some(splits) = l.components.iter().find_map(|c| match c {
+ Component::Splits(s) => Some(s),
+ _ => None,
+ }) else {
+ panic!("Splits component not found");
+ };
+ let texts: Vec<_> = l
+ .components
+ .iter()
+ .filter_map(|c| match c {
+ Component::Text(t) => Some(t),
+ _ => None,
+ })
+ .collect();
+ {
+ let splits::ColumnKind::Variable(splits::VariableColumn { ref variable_name }) =
+ splits.settings().columns[2].kind
+ else {
+ panic!("expected ColumnKind::Variable");
+ };
+ assert_eq!(variable_name, "delta hits");
+ }
+ {
+ let splits::ColumnKind::Variable(splits::VariableColumn { ref variable_name }) =
+ splits.settings().columns[3].kind
+ else {
+ panic!("expected ColumnKind::Variable");
+ };
+ assert_eq!(variable_name, "segment hits");
+ }
+ {
+ let text::Text::Variable(ref variable_name, is_split) = texts[0].settings().text else {
+ panic!("expected Text::Variable");
+ };
+ assert_eq!(variable_name, "hits");
+ assert_eq!(is_split, true);
+ }
+ {
+ let text::Text::Variable(ref variable_name, is_split) = texts[1].settings().text else {
+ panic!("expected Text::Variable");
+ };
+ assert_eq!(variable_name, "pb hits");
+ assert_eq!(is_split, true);
+ }
+ let l1 = ls1l(layout_files::CUSTOM_VARIABLE_LS1L);
+ assert_eq!(serde_json::to_string(&l.settings()).ok(), serde_json::to_string(&l1.settings()).ok());
+ }
+
#[test]
fn assert_order_of_default_columns() {
use livesplit_core::component::splits;