mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-02 18:17:09 +02:00
* Include argument name in completion suggestions * Support optional args * It (not so shrimply) works * Add tests * Add TestGenericPipeInference * Fix tests * Release notes * Overzealous YAMLLinter * Improve help signatures, fix map command * Improve NoImplementationError * Better type argument help signatures * better pipe syntax * fix NRE * Add test * a * Fix silent toolshed failure * Fix GetConcreteMethodInternal * Improve vars command * EntProtoId IAsType * More GetConcreteMethodInternal fixes * I hate this so much * update tp command description The command arguments call the the "other" entity the "target" * Support localized argument hints/signatures
84 lines
2.7 KiB
C#
84 lines
2.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using Robust.Shared.Console;
|
|
using Robust.Shared.Toolshed.Syntax;
|
|
using Robust.Shared.Toolshed.TypeParsers;
|
|
|
|
namespace Robust.Shared.Toolshed.Commands.Generic;
|
|
|
|
[ToolshedCommand]
|
|
public sealed class ReduceCommand : ToolshedCommand
|
|
{
|
|
[CommandImplementation, TakesPipedTypeAsGeneric]
|
|
public T Reduce<T>(
|
|
IInvocationContext ctx,
|
|
[PipedArgument] IEnumerable<T> input,
|
|
[CommandArgument(typeof(ReduceBlockParser))] Block reducer
|
|
)
|
|
{
|
|
var localCtx = new LocalVarInvocationContext(ctx);
|
|
localCtx.SetLocal("value", default(T));
|
|
|
|
using var enumerator = input.GetEnumerator();
|
|
|
|
if (!enumerator.MoveNext())
|
|
throw new InvalidOperationException($"Input contains no elements");
|
|
|
|
var result = enumerator.Current;
|
|
|
|
while (enumerator.MoveNext())
|
|
{
|
|
localCtx.SetLocal("value", enumerator.Current);
|
|
result = (T) reducer.Invoke(result, localCtx)!;
|
|
if (ctx.HasErrors)
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Custom block parser for the <see cref="ReduceCommand"/> that is aware of the "$value" variable.
|
|
/// </summary>
|
|
private sealed class ReduceBlockParser : CustomTypeParser<Block>
|
|
{
|
|
public override bool TryParse(ParserContext ctx, [NotNullWhen(true)] out Block? result)
|
|
{
|
|
result = null;
|
|
if (ctx.Bundle.PipedType is not {IsGenericType: true})
|
|
return false;
|
|
|
|
var localParser = new LocalVarParser(ctx.VariableParser);
|
|
var type = ctx.Bundle.PipedType.GetGenericArguments()[0];
|
|
localParser.SetLocalType("value", type, false);
|
|
ctx.VariableParser = localParser;
|
|
|
|
if (!Block.TryParseBlock(ctx, type, type, out var run))
|
|
{
|
|
result = null;
|
|
ctx.VariableParser = localParser.Inner;
|
|
return false;
|
|
}
|
|
|
|
ctx.VariableParser = localParser.Inner;
|
|
result = new Block(run);
|
|
return true;
|
|
}
|
|
|
|
public override CompletionResult? TryAutocomplete(ParserContext ctx, CommandArgument? arg)
|
|
{
|
|
if (ctx.Bundle.PipedType is not {IsGenericType: true})
|
|
return null;
|
|
|
|
var localParser = new LocalVarParser(ctx.VariableParser);
|
|
var type = ctx.Bundle.PipedType.GetGenericArguments()[0];
|
|
localParser.SetLocalType("value", type, false);
|
|
ctx.VariableParser = localParser;
|
|
Block.TryParseBlock(ctx, type, type, out _);
|
|
ctx.VariableParser = localParser.Inner;
|
|
return ctx.Completions;
|
|
}
|
|
}
|
|
}
|