Refactor command system
This commit is contained in:
77
PluralKit.Bot/CommandSystem/Parameters.cs
Normal file
77
PluralKit.Bot/CommandSystem/Parameters.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PluralKit.Bot.CommandSystem
|
||||
{
|
||||
public class Parameters
|
||||
{
|
||||
private static readonly Dictionary<char, char> _quotePairs = new Dictionary<char, char>()
|
||||
{
|
||||
{'\'', '\''}, {'"', '"'}
|
||||
};
|
||||
|
||||
private readonly string _cmd;
|
||||
private int _ptr;
|
||||
|
||||
public Parameters(string cmd)
|
||||
{
|
||||
_cmd = cmd;
|
||||
_ptr = 0;
|
||||
}
|
||||
|
||||
public string Pop()
|
||||
{
|
||||
var positions = NextWordPosition();
|
||||
if (positions == null) return "";
|
||||
|
||||
var (start, end, advance) = positions.Value;
|
||||
_ptr = end + advance;
|
||||
return _cmd.Substring(start, end - start).Trim();
|
||||
}
|
||||
|
||||
public string Peek()
|
||||
{
|
||||
var positions = NextWordPosition();
|
||||
if (positions == null) return "";
|
||||
|
||||
var (start, end, _) = positions.Value;
|
||||
return _cmd.Substring(start, end - start).Trim();
|
||||
}
|
||||
|
||||
public string Remainder() => _cmd.Substring(_ptr).Trim();
|
||||
public string FullCommand => _cmd;
|
||||
|
||||
// Returns tuple of (startpos, endpos, advanceafter)
|
||||
private ValueTuple<int, int, int>? NextWordPosition()
|
||||
{
|
||||
// Is this the end of the string?
|
||||
if (_cmd.Length <= _ptr) return null;
|
||||
|
||||
// Is this a quoted word?
|
||||
if (_quotePairs.ContainsKey(_cmd[_ptr]))
|
||||
{
|
||||
// This is a quoted word, find corresponding end quote and return span
|
||||
var endQuote = _quotePairs[_cmd[_ptr]];
|
||||
var endQuotePosition = _cmd.IndexOf(endQuote, _ptr + 1);
|
||||
|
||||
// Position after the end quote should be a space (or EOL)
|
||||
// Otherwise treat it as a standard word that's not quoted
|
||||
if (_cmd.Length == endQuotePosition + 1 || _cmd[endQuotePosition + 1] == ' ')
|
||||
{
|
||||
if (endQuotePosition == -1)
|
||||
{
|
||||
// This is an unterminated quoted word, just return the entire word including the start quote
|
||||
// TODO: should we do something else here?
|
||||
return (_ptr, _cmd.Length, 0);
|
||||
}
|
||||
|
||||
return (_ptr + 1, endQuotePosition, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Not a quoted word, just find the next space and return as appropriate
|
||||
var wordEnd = _cmd.IndexOf(' ', _ptr + 1);
|
||||
return wordEnd != -1 ? (_ptr, wordEnd, 1) : (_ptr, _cmd.Length, 0);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user