Convert CUE_File.Command.* to readonly structs with a superinterface
This commit is contained in:
parent
277f57eebd
commit
84a6c5a426
|
@ -412,64 +412,54 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
//global cd text will acquire the cdtext commands set before track commands
|
//global cd text will acquire the cdtext commands set before track commands
|
||||||
curr_cdtext = OUT_GlobalCDText;
|
curr_cdtext = OUT_GlobalCDText;
|
||||||
|
|
||||||
for (int i = 0; i < cue.Commands.Count; i++)
|
foreach (var cmd in cue.Commands) switch (cmd)
|
||||||
{
|
{
|
||||||
var cmd = cue.Commands[i];
|
case CUE_File.Command.CATALOG:
|
||||||
|
case CUE_File.Command.CDTEXTFILE:
|
||||||
//these commands get dealt with globally. nothing to be done here
|
// these commands get dealt with globally. nothing to be done here
|
||||||
//(but in the future we need to accumulate them into the compile pass output)
|
// (but in the future we need to accumulate them into the compile pass output)
|
||||||
if (cmd is CUE_File.Command.CATALOG || cmd is CUE_File.Command.CDTEXTFILE) continue;
|
continue;
|
||||||
|
case CUE_File.Command.REM:
|
||||||
//nothing to be done for comments
|
case CUE_File.Command.COMMENT:
|
||||||
if (cmd is CUE_File.Command.REM) continue;
|
// nothing to be done for comments
|
||||||
if (cmd is CUE_File.Command.COMMENT) continue;
|
continue;
|
||||||
|
case CUE_File.Command.PERFORMER performerCmd:
|
||||||
//CD-text and related
|
curr_cdtext.Performer = performerCmd.Value;
|
||||||
if (cmd is CUE_File.Command.PERFORMER performerCmd) curr_cdtext.Performer = performerCmd.Value;
|
break;
|
||||||
if (cmd is CUE_File.Command.SONGWRITER songwriterCmd) curr_cdtext.Songwriter = songwriterCmd.Value;
|
case CUE_File.Command.SONGWRITER songwriterCmd:
|
||||||
if (cmd is CUE_File.Command.TITLE titleCmd) curr_cdtext.Title = titleCmd.Value;
|
curr_cdtext.Songwriter = songwriterCmd.Value;
|
||||||
if (cmd is CUE_File.Command.ISRC isrcCmd) curr_cdtext.ISRC = isrcCmd.Value;
|
break;
|
||||||
|
case CUE_File.Command.TITLE titleCmd:
|
||||||
//flags can only be set when a track command is running
|
curr_cdtext.Title = titleCmd.Value;
|
||||||
if (cmd is CUE_File.Command.FLAGS flagsCmd)
|
break;
|
||||||
{
|
case CUE_File.Command.ISRC isrcCmd:
|
||||||
if (curr_track == null)
|
curr_cdtext.ISRC = isrcCmd.Value;
|
||||||
Warn("Ignoring invalid flag commands outside of a track command");
|
break;
|
||||||
else
|
case CUE_File.Command.FLAGS flagsCmd:
|
||||||
//take care to |= it here, so the data flag doesn't get cleared
|
// flags can only be set when a track command is running
|
||||||
curr_track.Flags |= flagsCmd.Flags;
|
if (curr_track == null) Warn("Ignoring invalid flag commands outside of a track command");
|
||||||
}
|
else curr_track.Flags |= flagsCmd.Flags; // take care to |= it here, so the data flag doesn't get cleared
|
||||||
|
break;
|
||||||
if (cmd is CUE_File.Command.TRACK trackCmd)
|
case CUE_File.Command.TRACK trackCmd:
|
||||||
{
|
|
||||||
CloseTrack();
|
CloseTrack();
|
||||||
OpenTrack(trackCmd);
|
OpenTrack(trackCmd);
|
||||||
}
|
break;
|
||||||
|
case CUE_File.Command.FILE fileCmd:
|
||||||
if (cmd is CUE_File.Command.FILE fileCmd)
|
|
||||||
{
|
|
||||||
CloseFile();
|
CloseFile();
|
||||||
OpenFile(fileCmd);
|
OpenFile(fileCmd);
|
||||||
}
|
break;
|
||||||
|
case CUE_File.Command.INDEX indexCmd:
|
||||||
if (cmd is CUE_File.Command.INDEX indexCmd)
|
//TODO validate no postgap specified
|
||||||
{
|
|
||||||
//todo - validate no postgap specified
|
|
||||||
AddIndex(indexCmd);
|
AddIndex(indexCmd);
|
||||||
}
|
break;
|
||||||
|
case CUE_File.Command.PREGAP pregapCmd:
|
||||||
if (cmd is CUE_File.Command.PREGAP pregapCmd)
|
//TODO validate track open
|
||||||
{
|
//TODO validate no indexes
|
||||||
//validate track open
|
|
||||||
//validate no indexes
|
|
||||||
curr_track.PregapLength = pregapCmd.Length;
|
curr_track.PregapLength = pregapCmd.Length;
|
||||||
}
|
break;
|
||||||
|
case CUE_File.Command.POSTGAP postgapCmd:
|
||||||
if (cmd is CUE_File.Command.POSTGAP postgapCmd)
|
|
||||||
{
|
|
||||||
curr_track.PostgapLength = postgapCmd.Length;
|
curr_track.PostgapLength = postgapCmd.Length;
|
||||||
}
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//it's a bit odd to close the file before closing the track, but...
|
//it's a bit odd to close the file before closing the track, but...
|
||||||
|
|
|
@ -7,41 +7,171 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class CUE_File
|
internal class CUE_File
|
||||||
{
|
{
|
||||||
// (here are all the commands we can encounter)
|
/// <remarks>
|
||||||
public static class Command
|
/// (here are all the commands we can encounter)
|
||||||
|
/// TODO record line number origin of command? Kind of nice but unessential
|
||||||
|
/// </remarks>
|
||||||
|
public interface Command
|
||||||
{
|
{
|
||||||
//TODO - record line number origin of command? Kind of nice but inessential
|
public readonly struct CATALOG : Command
|
||||||
public class CATALOG { public string Value; public override string ToString() { return $"CATALOG: {Value}"; } }
|
{
|
||||||
public class CDTEXTFILE { public string Path; public override string ToString() { return $"CDTEXTFILE: {Path}"; } }
|
public readonly string Value;
|
||||||
public class FILE { public string Path; public CueFileType Type; public override string ToString() { return $"FILE ({Type}): {Path}"; } }
|
|
||||||
public class FLAGS { public CueTrackFlags Flags; public override string ToString() { return $"FLAGS {Flags}"; } }
|
|
||||||
public class INDEX { public int Number; public Timestamp Timestamp; public override string ToString() { return $"INDEX {Number,2} {Timestamp}"; } }
|
|
||||||
public class ISRC { public string Value; public override string ToString() { return $"ISRC: {Value}"; } }
|
|
||||||
public class PERFORMER { public string Value; public override string ToString() { return $"PERFORMER: {Value}"; } }
|
|
||||||
public class POSTGAP { public Timestamp Length; public override string ToString() { return $"POSTGAP: {Length}"; } }
|
|
||||||
public class PREGAP { public Timestamp Length; public override string ToString() { return $"PREGAP: {Length}"; } }
|
|
||||||
public class REM { public string Value; public override string ToString() { return $"REM: {Value}"; } }
|
|
||||||
public class COMMENT { public string Value; public override string ToString() { return $"COMMENT: {Value}"; } }
|
|
||||||
public class SONGWRITER { public string Value; public override string ToString() { return $"SONGWRITER: {Value}"; } }
|
|
||||||
public class TITLE { public string Value; public override string ToString() { return $"TITLE: {Value}"; } }
|
|
||||||
public class TRACK { public int Number; public CueTrackType Type; public override string ToString() { return $"TRACK {Number,2} ({Type})"; } }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public CATALOG(string value) => Value = value;
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"CATALOG: {Value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct CDTEXTFILE : Command
|
||||||
|
{
|
||||||
|
public readonly string Path;
|
||||||
|
|
||||||
|
public CDTEXTFILE(string path) => Path = path;
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"CDTEXTFILE: {Path}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct FILE : Command
|
||||||
|
{
|
||||||
|
public readonly string Path;
|
||||||
|
|
||||||
|
public readonly CueFileType Type;
|
||||||
|
|
||||||
|
public FILE(string path, CueFileType type)
|
||||||
|
{
|
||||||
|
Path = path;
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"FILE ({Type}): {Path}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct FLAGS : Command
|
||||||
|
{
|
||||||
|
public readonly CueTrackFlags Flags;
|
||||||
|
|
||||||
|
public FLAGS(CueTrackFlags flags) => Flags = flags;
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"FLAGS {Flags}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct INDEX : Command
|
||||||
|
{
|
||||||
|
public readonly int Number;
|
||||||
|
|
||||||
|
public readonly Timestamp Timestamp;
|
||||||
|
|
||||||
|
public INDEX(int number, Timestamp timestamp)
|
||||||
|
{
|
||||||
|
Number = number;
|
||||||
|
Timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"INDEX {Number,2} {Timestamp}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct ISRC : Command
|
||||||
|
{
|
||||||
|
public readonly string Value;
|
||||||
|
|
||||||
|
public ISRC(string value) => Value = value;
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"ISRC: {Value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct PERFORMER : Command
|
||||||
|
{
|
||||||
|
public readonly string Value;
|
||||||
|
|
||||||
|
public PERFORMER(string value) => Value = value;
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"PERFORMER: {Value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct POSTGAP : Command
|
||||||
|
{
|
||||||
|
public readonly Timestamp Length;
|
||||||
|
|
||||||
|
public POSTGAP(Timestamp length) => Length = length;
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"POSTGAP: {Length}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct PREGAP : Command
|
||||||
|
{
|
||||||
|
public readonly Timestamp Length;
|
||||||
|
|
||||||
|
public PREGAP(Timestamp length) => Length = length;
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"PREGAP: {Length}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct REM : Command
|
||||||
|
{
|
||||||
|
public readonly string Value;
|
||||||
|
|
||||||
|
public REM(string value) => Value = value;
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"REM: {Value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct COMMENT : Command
|
||||||
|
{
|
||||||
|
public readonly string Value;
|
||||||
|
|
||||||
|
public COMMENT(string value) => Value = value;
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"COMMENT: {Value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct SONGWRITER : Command
|
||||||
|
{
|
||||||
|
public readonly string Value;
|
||||||
|
|
||||||
|
public SONGWRITER(string value) => Value = value;
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"SONGWRITER: {Value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct TITLE : Command
|
||||||
|
{
|
||||||
|
public readonly string Value;
|
||||||
|
|
||||||
|
public TITLE(string value) => Value = value;
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"TITLE: {Value}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct TRACK : Command
|
||||||
|
{
|
||||||
|
public readonly int Number;
|
||||||
|
|
||||||
|
public readonly CueTrackType Type;
|
||||||
|
|
||||||
|
public TRACK(int number, CueTrackType type)
|
||||||
|
{
|
||||||
|
Number = number;
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override readonly string ToString() => $"TRACK {Number,2} ({Type})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stuff other than the commands, global for the whole disc
|
/// Stuff other than the commands, global for the whole disc
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DiscInfo
|
public class DiscInfo
|
||||||
{
|
{
|
||||||
public Command.CATALOG Catalog;
|
public Command.CATALOG? Catalog;
|
||||||
public Command.ISRC ISRC;
|
public Command.ISRC? ISRC;
|
||||||
public Command.CDTEXTFILE CDTextFile;
|
public Command.CDTEXTFILE? CDTextFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The sequential list of commands parsed out of the cue file
|
/// The sequential list of commands parsed out of the cue file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<object> Commands = new List<object>();
|
public readonly List<Command> Commands = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stuff other than the commands, global for the whole disc
|
/// Stuff other than the commands, global for the whole disc
|
||||||
|
|
|
@ -162,7 +162,7 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
if (startsWithSemicolon)
|
if (startsWithSemicolon)
|
||||||
{
|
{
|
||||||
clp.EOF = true;
|
clp.EOF = true;
|
||||||
OUT_CueFile.Commands.Add(new CUE_File.Command.COMMENT() { Value = line });
|
OUT_CueFile.Commands.Add(new CUE_File.Command.COMMENT(line));
|
||||||
}
|
}
|
||||||
else switch (key)
|
else switch (key)
|
||||||
{
|
{
|
||||||
|
@ -175,7 +175,7 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
job.Warn("Multiple CATALOG commands detected. Subsequent ones are ignored.");
|
job.Warn("Multiple CATALOG commands detected. Subsequent ones are ignored.");
|
||||||
else if (clp.EOF)
|
else if (clp.EOF)
|
||||||
job.Warn("Ignoring empty CATALOG command");
|
job.Warn("Ignoring empty CATALOG command");
|
||||||
else OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.Catalog = new CUE_File.Command.CATALOG() { Value = clp.ReadToken() });
|
else OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.Catalog = new CUE_File.Command.CATALOG(clp.ReadToken()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "CDTEXTFILE":
|
case "CDTEXTFILE":
|
||||||
|
@ -183,7 +183,7 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
job.Warn("Multiple CDTEXTFILE commands detected. Subsequent ones are ignored.");
|
job.Warn("Multiple CDTEXTFILE commands detected. Subsequent ones are ignored.");
|
||||||
else if (clp.EOF)
|
else if (clp.EOF)
|
||||||
job.Warn("Ignoring empty CDTEXTFILE command");
|
job.Warn("Ignoring empty CDTEXTFILE command");
|
||||||
else OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.CDTextFile = new CUE_File.Command.CDTEXTFILE() { Path = clp.ReadPath() });
|
else OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.CDTextFile = new CUE_File.Command.CDTEXTFILE(clp.ReadPath()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "FILE":
|
case "FILE":
|
||||||
|
@ -211,14 +211,13 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
case "MP3": ft = CueFileType.MP3; break;
|
case "MP3": ft = CueFileType.MP3; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OUT_CueFile.Commands.Add(new CUE_File.Command.FILE() { Path = path, Type = ft });
|
OUT_CueFile.Commands.Add(new CUE_File.Command.FILE(path, ft));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "FLAGS":
|
case "FLAGS":
|
||||||
{
|
{
|
||||||
var cmd = new CUE_File.Command.FLAGS();
|
CueTrackFlags flags = default;
|
||||||
OUT_CueFile.Commands.Add(cmd);
|
|
||||||
while (!clp.EOF)
|
while (!clp.EOF)
|
||||||
{
|
{
|
||||||
var flag = clp.ReadToken().ToUpperInvariant();
|
var flag = clp.ReadToken().ToUpperInvariant();
|
||||||
|
@ -228,14 +227,15 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
default:
|
default:
|
||||||
job.Warn($"Unknown FLAG: {flag}");
|
job.Warn($"Unknown FLAG: {flag}");
|
||||||
break;
|
break;
|
||||||
case "DCP": cmd.Flags |= CueTrackFlags.DCP; break;
|
case "DCP": flags |= CueTrackFlags.DCP; break;
|
||||||
case "4CH": cmd.Flags |= CueTrackFlags._4CH; break;
|
case "4CH": flags |= CueTrackFlags._4CH; break;
|
||||||
case "PRE": cmd.Flags |= CueTrackFlags.PRE; break;
|
case "PRE": flags |= CueTrackFlags.PRE; break;
|
||||||
case "SCMS": cmd.Flags |= CueTrackFlags.SCMS; break;
|
case "SCMS": flags |= CueTrackFlags.SCMS; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cmd.Flags == CueTrackFlags.None)
|
if (flags == CueTrackFlags.None)
|
||||||
job.Warn("Empty FLAG command");
|
job.Warn("Empty FLAG command");
|
||||||
|
OUT_CueFile.Commands.Add(new CUE_File.Command.FLAGS(flags));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
job.Error($"Invalid INDEX timestamp: {str_timestamp}");
|
job.Error($"Invalid INDEX timestamp: {str_timestamp}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
OUT_CueFile.Commands.Add(new CUE_File.Command.INDEX() { Number = indexnum, Timestamp = ts });
|
OUT_CueFile.Commands.Add(new CUE_File.Command.INDEX(indexnum, ts));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -282,13 +282,13 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
job.Warn($"Invalid ISRC code ignored: {isrc}");
|
job.Warn($"Invalid ISRC code ignored: {isrc}");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.ISRC = new CUE_File.Command.ISRC() { Value = isrc });
|
OUT_CueFile.Commands.Add(OUT_CueFile.GlobalDiscInfo.ISRC = new CUE_File.Command.ISRC(isrc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "PERFORMER":
|
case "PERFORMER":
|
||||||
OUT_CueFile.Commands.Add(new CUE_File.Command.PERFORMER() { Value = clp.ReadPath() ?? "" });
|
OUT_CueFile.Commands.Add(new CUE_File.Command.PERFORMER(clp.ReadPath() ?? ""));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "POSTGAP":
|
case "POSTGAP":
|
||||||
|
@ -301,23 +301,23 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (key == "POSTGAP")
|
if (key == "POSTGAP")
|
||||||
OUT_CueFile.Commands.Add(new CUE_File.Command.POSTGAP() { Length = msf });
|
OUT_CueFile.Commands.Add(new CUE_File.Command.POSTGAP(msf));
|
||||||
else
|
else
|
||||||
OUT_CueFile.Commands.Add(new CUE_File.Command.PREGAP() { Length = msf });
|
OUT_CueFile.Commands.Add(new CUE_File.Command.PREGAP(msf));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "REM":
|
case "REM":
|
||||||
OUT_CueFile.Commands.Add(new CUE_File.Command.REM() { Value = clp.ReadLine() });
|
OUT_CueFile.Commands.Add(new CUE_File.Command.REM(clp.ReadLine()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "SONGWRITER":
|
case "SONGWRITER":
|
||||||
OUT_CueFile.Commands.Add(new CUE_File.Command.SONGWRITER() { Value = clp.ReadPath() ?? "" });
|
OUT_CueFile.Commands.Add(new CUE_File.Command.SONGWRITER(clp.ReadPath() ?? ""));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "TITLE":
|
case "TITLE":
|
||||||
OUT_CueFile.Commands.Add(new CUE_File.Command.TITLE() { Value = clp.ReadPath() ?? "" });
|
OUT_CueFile.Commands.Add(new CUE_File.Command.TITLE(clp.ReadPath() ?? ""));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "TRACK":
|
case "TRACK":
|
||||||
|
@ -355,7 +355,7 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
case "CDI/2352": tt = CueTrackType.CDI_2352; break;
|
case "CDI/2352": tt = CueTrackType.CDI_2352; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
OUT_CueFile.Commands.Add(new CUE_File.Command.TRACK() { Number = tracknum, Type = tt });
|
OUT_CueFile.Commands.Add(new CUE_File.Command.TRACK(tracknum, tt));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -366,7 +366,7 @@ namespace BizHawk.Emulation.DiscSystem.CUE
|
||||||
if (remainder.TrimStart().StartsWith(";"))
|
if (remainder.TrimStart().StartsWith(";"))
|
||||||
{
|
{
|
||||||
//add a comment
|
//add a comment
|
||||||
OUT_CueFile.Commands.Add(new CUE_File.Command.COMMENT() { Value = remainder });
|
OUT_CueFile.Commands.Add(new CUE_File.Command.COMMENT(remainder));
|
||||||
}
|
}
|
||||||
else job.Warn($"Unknown text at end of line after processing command: {key}");
|
else job.Warn($"Unknown text at end of line after processing command: {key}");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue