Skip to content

Instantly share code, notes, and snippets.

@haacked
Created February 11, 2021 19:36
Show Gist options
  • Save haacked/adbdc12fc6c8ea21d639deb3763fdd98 to your computer and use it in GitHub Desktop.
Save haacked/adbdc12fc6c8ea21d639deb3763fdd98 to your computer and use it in GitHub Desktop.
Code from Abbot's Argument Parsing
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Serious.Abbot.Messages;
using Serious.Abbot.Scripting;
namespace Serious.Abbot.Models
{
public class Arguments : List<IArgument>, IArguments
{
static readonly MissingArgument MissingArgument = new();
static readonly Regex Tokenized = new(@"'(?<value>.+?)'|[\""](?<value>.+?)[\""]|(?<value>[^ ]+)", RegexOptions.Compiled);
public Arguments(string arguments)
: this(ParseTokens(Normalize(arguments)))
{
}
Arguments((string, IEnumerable<Argument>) normalizedAndTokenized)
{
var (value, args) = normalizedAndTokenized;
Value = value;
AddRange(args);
}
public Arguments(IEnumerable<IArgument> arguments, string rawArguments)
{
Value = rawArguments;
AddRange(arguments);
}
Arguments(IList<IArgument> arguments)
: this(arguments, string.Join(' ', arguments.Cast<IOriginalArgument>().Select(og => og.OriginalText)))
{
}
public void Deconstruct(out IArgument first, out IArgument second)
{
first = ElementAt(0);
second = Rest(1);
}
public void Deconstruct(out IArgument first, out IArgument second, out IArgument third)
{
first = ElementAt(0);
second = ElementAt(1);
third = Rest(2);
}
public void Deconstruct(out IArgument first, out IArgument second, out IArgument third, out IArgument fourth)
{
first = ElementAt(0);
second = ElementAt(1);
third = ElementAt(2);
fourth = Rest(3);
}
IArgument ElementAt(int index)
{
return Count > index ? this[index] : MissingArgument;
}
public string Value { get; }
IArgument Rest(int index)
{
return index >= Count
? MissingArgument
: index == Count - 1
? this[index]
: new Arguments(this.Skip(index).ToList());
}
public override string ToString()
{
return Value;
}
static (string, IEnumerable<Argument>) ParseTokens(string arguments)
{
return (arguments, Tokenized.Matches(arguments)
.Select(m => new Argument { Value = m.Groups["value"].Value, OriginalText = m.Value }));
}
static readonly Regex FixUrlRegex = new(@"(?<=\s|^|"")<(?<url>https?://.*?)(?:\|.*?)?>(?=""|\s|$)", RegexOptions.Compiled);
static string Normalize(string value)
{
var normalized = value.Trim()
.Replace("“", "\"", StringComparison.Ordinal)
.Replace("”", "\"", StringComparison.Ordinal)
.Replace("‘", "'", StringComparison.Ordinal)
.Replace("’", "'", StringComparison.Ordinal);
return FixUrlRegex.Replace(normalized, "${url}");
}
}
}
using Serious.Abbot.Scripting;
namespace Serious.Abbot.Messages
{
public class Argument : IOriginalArgument
{
public Argument()
{
}
public Argument(IOriginalArgument argument) : this(argument.Value, argument.OriginalText)
{
}
public Argument(string value)
{
Value = value;
OriginalText = value;
}
public Argument(string value, string originalText)
{
Value = value;
OriginalText = originalText;
}
public string Value { get; set; } = string.Empty;
public string OriginalText { get; set; } = string.Empty;
public override string ToString()
{
return Value;
}
}
public class MentionArgument : Argument, IMentionArgument
{
public MentionArgument()
{
}
public MentionArgument(IOriginalArgument argument, IChatUser mentioned) : base(argument)
{
Mentioned = mentioned;
}
public IChatUser Mentioned { get; set; } = null!;
}
public class MissingArgument : Argument, IMissingArgument
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment