fix suppressed console output not suppressing newlines

This commit is contained in:
Jesse Plamondon-Willard 2022-01-15 12:21:22 -05:00
parent e30e427628
commit a8985e122e
No known key found for this signature in database
GPG Key ID: CF8B1456B3E29F49
3 changed files with 28 additions and 5 deletions

View File

@ -5,6 +5,7 @@
* For players: * For players:
* SMAPI now auto-fixes maps loaded without a required tilesheet to prevent errors. * SMAPI now auto-fixes maps loaded without a required tilesheet to prevent errors.
* Added the new game build number to the SMAPI console + log. * Added the new game build number to the SMAPI console + log.
* Fixed extra newlines shown in the console in non-developer mode.
* Fixed outdated instructions in Steam error message. * Fixed outdated instructions in Steam error message.
* Fixed uninstaller not removing `StardewModdingAPI.deps.json` file. * Fixed uninstaller not removing `StardewModdingAPI.deps.json` file.
* Fixed launch issue on macOS when using some terminals (thanks to bruce2409!). * Fixed launch issue on macOS when using some terminals (thanks to bruce2409!).

View File

@ -26,6 +26,10 @@ namespace StardewModdingAPI.Framework.Logging
/// <summary>The event raised when a message is written to the console directly.</summary> /// <summary>The event raised when a message is written to the console directly.</summary>
public event Action<string> OnMessageIntercepted; public event Action<string> OnMessageIntercepted;
/// <summary>Whether the text writer should ignore the next input if it's a newline.</summary>
/// <remarks>This is used when log output is suppressed from the console, since <c>Console.WriteLine</c> writes the trailing newline as a separate call.</remarks>
public bool IgnoreNextIfNewline { get; set; }
/********* /*********
** Public methods ** Public methods
@ -42,12 +46,18 @@ namespace StardewModdingAPI.Framework.Logging
/// <inheritdoc /> /// <inheritdoc />
public override void Write(char[] buffer, int index, int count) public override void Write(char[] buffer, int index, int count)
{ {
bool ignoreIfNewline = this.IgnoreNextIfNewline;
this.IgnoreNextIfNewline = false;
if (buffer.Length == 0) if (buffer.Length == 0)
this.Out.Write(buffer, index, count); this.Out.Write(buffer, index, count);
else if (buffer[0] == this.IgnoreChar) else if (buffer[0] == this.IgnoreChar)
this.Out.Write(buffer, index + 1, count - 1); this.Out.Write(buffer, index + 1, count - 1);
else if (this.IsEmptyOrNewline(buffer)) else if (this.IsEmptyOrNewline(buffer))
{
if (!ignoreIfNewline)
this.Out.Write(buffer, index, count); this.Out.Write(buffer, index, count);
}
else else
this.OnMessageIntercepted?.Invoke(new string(buffer, index, count).TrimEnd('\r', '\n')); this.OnMessageIntercepted?.Invoke(new string(buffer, index, count).TrimEnd('\r', '\n'));
} }

View File

@ -22,9 +22,15 @@ namespace StardewModdingAPI.Framework.Logging
/********* /*********
** Fields ** Fields
*********/ *********/
/// <summary>Whether to show trace messages in the console.</summary>
private readonly bool ShowTraceInConsole;
/// <summary>The log file to which to write messages.</summary> /// <summary>The log file to which to write messages.</summary>
private readonly LogFileManager LogFile; private readonly LogFileManager LogFile;
/// <summary>The text writer which intercepts console output.</summary>
private readonly InterceptingTextWriter ConsoleInterceptor;
/// <summary>Prefixing a low-level message with this character indicates that the console interceptor should write the string without intercepting it. (The character itself is not written.)</summary> /// <summary>Prefixing a low-level message with this character indicates that the console interceptor should write the string without intercepting it. (The character itself is not written.)</summary>
private readonly char IgnoreChar = '\u200B'; private readonly char IgnoreChar = '\u200B';
@ -91,10 +97,11 @@ namespace StardewModdingAPI.Framework.Logging
public LogManager(string logPath, ColorSchemeConfig colorConfig, bool writeToConsole, bool isVerbose, bool isDeveloperMode, Func<int?> getScreenIdForLog) public LogManager(string logPath, ColorSchemeConfig colorConfig, bool writeToConsole, bool isVerbose, bool isDeveloperMode, Func<int?> getScreenIdForLog)
{ {
// init construction logic // init construction logic
this.ShowTraceInConsole = isDeveloperMode;
this.GetMonitorImpl = name => new Monitor(name, this.IgnoreChar, this.LogFile, colorConfig, isVerbose, getScreenIdForLog) this.GetMonitorImpl = name => new Monitor(name, this.IgnoreChar, this.LogFile, colorConfig, isVerbose, getScreenIdForLog)
{ {
WriteToConsole = writeToConsole, WriteToConsole = writeToConsole,
ShowTraceInConsole = isDeveloperMode, ShowTraceInConsole = this.ShowTraceInConsole,
ShowFullStampInConsole = isDeveloperMode ShowFullStampInConsole = isDeveloperMode
}; };
@ -104,10 +111,10 @@ namespace StardewModdingAPI.Framework.Logging
this.MonitorForGame = this.GetMonitor("game"); this.MonitorForGame = this.GetMonitor("game");
// redirect direct console output // redirect direct console output
var output = new InterceptingTextWriter(Console.Out, this.IgnoreChar); this.ConsoleInterceptor = new InterceptingTextWriter(Console.Out, this.IgnoreChar);
if (writeToConsole) if (writeToConsole)
output.OnMessageIntercepted += message => this.HandleConsoleMessage(this.MonitorForGame, message); this.ConsoleInterceptor.OnMessageIntercepted += message => this.HandleConsoleMessage(this.MonitorForGame, message);
Console.SetOut(output); Console.SetOut(this.ConsoleInterceptor);
// enable Unicode handling on Windows // enable Unicode handling on Windows
// (the terminal defaults to UTF-8 on Linux/macOS) // (the terminal defaults to UTF-8 on Linux/macOS)
@ -363,7 +370,10 @@ namespace StardewModdingAPI.Framework.Logging
// ignore suppressed message // ignore suppressed message
if (level != LogLevel.Error && this.SuppressConsolePatterns.Any(p => p.IsMatch(message))) if (level != LogLevel.Error && this.SuppressConsolePatterns.Any(p => p.IsMatch(message)))
{
this.ConsoleInterceptor.IgnoreNextIfNewline = true;
return; return;
}
// show friendly error if applicable // show friendly error if applicable
foreach (ReplaceLogPattern entry in this.ReplaceConsolePatterns) foreach (ReplaceLogPattern entry in this.ReplaceConsolePatterns)
@ -383,6 +393,8 @@ namespace StardewModdingAPI.Framework.Logging
// forward to monitor // forward to monitor
gameMonitor.Log(message, level); gameMonitor.Log(message, level);
if (level == LogLevel.Trace && !this.ShowTraceInConsole)
this.ConsoleInterceptor.IgnoreNextIfNewline = true;
} }
/// <summary>Write a summary of mod warnings to the console and log.</summary> /// <summary>Write a summary of mod warnings to the console and log.</summary>