diff --git a/Content.Tests/DMProject/Tests/Text/Splittext.dm b/Content.Tests/DMProject/Tests/Text/Splittext.dm new file mode 100644 index 0000000000..da2d898418 --- /dev/null +++ b/Content.Tests/DMProject/Tests/Text/Splittext.dm @@ -0,0 +1,34 @@ +/proc/RunTest() + var/test_text = "The average of 1, 2, 3, 4, 5 is: 3" + var/list/test1 = splittext(test_text, " ") + var/list/test1_expected = list("The","average","of","1,","2,","3,","4,","5","is:","3") + ASSERT(test1 ~= test1_expected) + + var/list/test2 = splittext(test_text, " ", 5) + var/test2_expected = list("average","of","1,","2,","3,","4,","5","is:","3") + ASSERT(test2 ~= test2_expected) + + var/list/test3 = splittext(test_text, " ", 5, 10) + var/test3_expected = list("avera") + ASSERT(test3 ~= test3_expected) + + var/list/test4 = splittext(test_text, " ", 10, 20) + var/test4_expected = list("ge","of","1,","2") + ASSERT(test4 ~= test4_expected) + + var/list/test5 = splittext(test_text, " ", 10, 20, 1) + var/test5_expected = list("ge"," ","of"," ","1,"," ","2") + ASSERT(test5 ~= test5_expected) + + //it's regex time + var/test6 = splittext(test_text, regex(@"\d")) + var/test6_expected = list("The average of ",", ",", ",", ",", "," is: ","") + ASSERT(test6 ~= test6_expected) + + var/test7 = splittext(test_text, regex(@"\d"), 5, 30) + var/test7_expected = list("average of ",", ",", ",", ",", "," ") + ASSERT(test7 ~= test7_expected) + + var/test8 = splittext(test_text, regex(@"\d"), 5, 30, 1) + var/test8_expected = list("average of ","1",", ","2",", ","3",", ","4",", ","5"," ") + ASSERT(test8 ~= test8_expected) \ No newline at end of file diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs index 224e5b5ea2..b111ac6325 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs @@ -2361,22 +2361,65 @@ public static DreamValue NativeProc_splicetext_char(NativeProc.Bundle bundle, Dr [DreamProc("splittext")] [DreamProcParameter("Text", Type = DreamValueTypeFlag.String)] [DreamProcParameter("Delimiter", Type = DreamValueTypeFlag.String)] + [DreamProcParameter("Start", Type = DreamValueTypeFlag.Float, DefaultValue = 1)] + [DreamProcParameter("End", Type = DreamValueTypeFlag.Float, DefaultValue = 0)] + [DreamProcParameter("include_delimiters", Type = DreamValueTypeFlag.Float, DefaultValue = 0)] public static DreamValue NativeProc_splittext(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { if (!bundle.GetArgument(0, "Text").TryGetValueAsString(out var text)) { return new DreamValue(bundle.ObjectTree.CreateList()); } - var arg2 = bundle.GetArgument(1, "Delimiter"); - if (!arg2.TryGetValueAsString(out var delimiter)) { - if (!arg2.Equals(DreamValue.Null)) { - return new DreamValue(bundle.ObjectTree.CreateList()); + int start = 0; + int end = 0; + if(bundle.GetArgument(2, "Start").TryGetValueAsInteger(out start)) + start -= 1; //1-indexed + if(bundle.GetArgument(3, "End").TryGetValueAsInteger(out end)) + if(end == 0) + end = text.Length; + else + end -= 1; //1-indexed + bool includeDelimiters = false; + if(bundle.GetArgument(4, "include_delimiters").TryGetValueAsInteger(out var includeDelimitersInt)) + includeDelimiters = includeDelimitersInt != 0; //idk why BYOND doesn't just use truthiness, but it doesn't, so... + + if(start > 0 || end < text.Length) + text = text[Math.Max(start,0)..Math.Min(end, text.Length)]; + + var delim = bundle.GetArgument(1, "Delimiter"); //can either be a regex or string + + if (delim.TryGetValueAsDreamObject(out var regexObject)) { + if(includeDelimiters) { + var values = new List(); + int pos = 0; + foreach (Match m in regexObject.Regex.Matches(text)) { + values.Add(text.Substring(pos, m.Index - pos)); + values.Add(m.Value); + pos = m.Index + m.Length; + } + values.Add(text.Substring(pos)); + return new DreamValue(bundle.ObjectTree.CreateList(values.ToArray())); + } else { + return new DreamValue(bundle.ObjectTree.CreateList(regexObject.Regex.Split(text))); + } + } else if (delim.TryGetValueAsString(out var delimiter)) { + string[] splitText; + if(includeDelimiters) { + //basically split on delimeter, and then add the delimiter back in after each split (except the last one) + splitText= text.Split(delimiter); + string[] longerSplitText = new string[splitText.Length * 2 - 1]; + for(int i = 0; i < splitText.Length; i++) { + longerSplitText[i * 2] = splitText[i]; + if(i < splitText.Length - 1) + longerSplitText[i * 2 + 1] = delimiter; + } + splitText = longerSplitText; + } else { + splitText = text.Split(delimiter); } + return new DreamValue(bundle.ObjectTree.CreateList(splitText)); + } else { + return new DreamValue(bundle.ObjectTree.CreateList()); } - - string[] splitText = text.Split(delimiter); - DreamList list = bundle.ObjectTree.CreateList(splitText); - - return new DreamValue(list); } private static void OutputToStatPanel(DreamManager dreamManager, DreamConnection connection, DreamValue name, DreamValue value) {