Merge pull request #2965 from InspectorCaracal/slash-sort Add `/sort` slash command

33a126491ef513c1393bd53afba532be92ef216c

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
1 files changed, +79 -0Showing whitespace changes
public/scripts/variables.js+79 -0
@@ -836,6 +836,40 @@ function randValuesCallback(from, to, args) {
836836 return value;
837837}
838838
839+function customSortComparitor(a, b) {
840+ if (typeof a != typeof b) {
841+ a = typeof a;
842+ b = typeof b;
843+ }
844+ return a > b ? 1 : a < b ? -1 : 0;
845+}
846+
847+function sortArrayObjectCallback(args, value) {
848+ let parsedValue;
849+ if (typeof value == 'string') {
850+ try {
851+ parsedValue = JSON.parse(value);
852+ } catch {
853+ // return the original input if it was invalid
854+ return value;
855+ }
856+ } else {
857+ parsedValue = value;
858+ }
859+ if (Array.isArray(parsedValue)) {
860+ // always sort lists by value
861+ parsedValue.sort(customSortComparitor);
862+ } else if (typeof parsedValue == 'object') {
863+ let keysort = args.keysort;
864+ if (isFalseBoolean(keysort)) {
865+ parsedValue = Object.keys(parsedValue).sort(function (a, b) { return customSortComparitor(parsedValue[a], parsedValue[b]); });
866+ } else {
867+ parsedValue = Object.keys(parsedValue).sort(customSortComparitor);
868+ }
869+ }
870+ return JSON.stringify(parsedValue);
871+}
872+
839873/**
840874 * Declare a new variable in the current scope.
841875 * @param {NamedArguments} args Named arguments.
@@ -2110,6 +2144,51 @@ export function registerVariableCommands() {
21102144 `,
21112145 }));
21122146 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
2147+ name: 'sort',
2148+ callback: sortArrayObjectCallback,
2149+ returns: 'the sorted list or dictionary keys',
2150+ namedArgumentList: [
2151+ SlashCommandNamedArgument.fromProps({ name: 'keysort',
2152+ description: 'whether to sort by key or value; ignored for lists',
2153+ typeList: [ARGUMENT_TYPE.BOOLEAN],
2154+ enumList: ['true', 'false'],
2155+ defaultValue: 'true',
2156+ }),
2157+ ],
2158+ unnamedArgumentList: [
2159+ SlashCommandArgument.fromProps({
2160+ description: 'value',
2161+ typeList: [ARGUMENT_TYPE.STRING, ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.LIST, ARGUMENT_TYPE.DICTIONARY],
2162+ isRequired: true,
2163+ forceEnum: false,
2164+ }),
2165+ ],
2166+ helpString: `
2167+ <div>
2168+ Sorts a list or dictionary in ascending order and passes the result down the pipe.
2169+ <ul>
2170+ <li>
2171+ For lists, returns the list sorted by value.
2172+ </li>
2173+ <li>
2174+ For dictionaries, returns the ordered list of keys after sorting. Setting keysort=false means keys are sorted by associated value.
2175+ </li>
2176+ </ul>
2177+ </div>
2178+ <div>
2179+ <strong>Examples:</strong>
2180+ <ul>
2181+ <li>
2182+ <pre><code class="language-stscript">/sort [5,3,4,1,2] | /echo</code></pre>
2183+ </li>
2184+ <li>
2185+ <pre><code class="language-stscript">/sort keysort=false {"a": 1, "d": 3, "c": 2, "b": 5} | /echo</code></pre>
2186+ </li>
2187+ </ul>
2188+ </div>
2189+ `,
2190+ }));
2191+ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
21132192 name: 'rand',
21142193 callback: (args, value) => String(randValuesCallback(Number(args.from ?? 0), Number(args.to ?? (value ? value : 1)), args)),
21152194 returns: 'random number',