Added some terminal interrupt systems. Later it will kill active commands.
This commit is contained in:
parent
51f58e6e82
commit
5412b023a0
@ -3,6 +3,7 @@ global using SharpCompress.Archives.Rar;
|
||||
global using SharpCompress.Archives.SevenZip;
|
||||
global using SharpCompress.Readers;
|
||||
global using SrcMod.Shell;
|
||||
global using SrcMod.Shell.Interop;
|
||||
global using SrcMod.Shell.Modules.ObjectModels;
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
|
||||
25
SrcMod/Shell/Interop/Winmm.cs
Normal file
25
SrcMod/Shell/Interop/Winmm.cs
Normal file
@ -0,0 +1,25 @@
|
||||
namespace SrcMod.Shell.Interop;
|
||||
|
||||
internal static partial class Winmm
|
||||
{
|
||||
[LibraryImport("winmm.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static partial bool PlaySound([MarshalAs(UnmanagedType.LPStr)] string pszSound, nint hMod, uint fdwSound);
|
||||
|
||||
public enum PlaySoundFlags : uint
|
||||
{
|
||||
SND_SYNC = 0x00000000,
|
||||
SND_ASYNC = 0x00000001,
|
||||
SND_NODEFAULT = 0x00000002,
|
||||
SND_MEMORY = 0x00000004,
|
||||
SND_LOOP = 0x00000008,
|
||||
SND_NOSTOP = 0x00000010,
|
||||
SND_PURGE = 0x00000040,
|
||||
SND_APPLICATION = 0x00000080,
|
||||
SND_NOWAIT = 0x00002000,
|
||||
SND_ALIAS = 0x00010000,
|
||||
SND_FILENAME = 0x00020000,
|
||||
SND_RESOURCE = 0x00040000,
|
||||
SND_ALIAS_ID = 0x00100000,
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,4 @@
|
||||
using SrcMod.Shell.Interop;
|
||||
|
||||
namespace SrcMod.Shell.Modules;
|
||||
namespace SrcMod.Shell.Modules;
|
||||
|
||||
[Module("clipboard")]
|
||||
public static class ClipboardModule
|
||||
|
||||
@ -16,6 +16,9 @@ public class Shell
|
||||
public List<HistoryItem> History;
|
||||
public string WorkingDirectory;
|
||||
|
||||
private bool lastCancel;
|
||||
private bool printedCancel;
|
||||
|
||||
public Shell()
|
||||
{
|
||||
Console.CursorVisible = false;
|
||||
@ -79,6 +82,9 @@ public class Shell
|
||||
Write(" by ", ConsoleColor.White, false);
|
||||
Write($"{Author}", ConsoleColor.DarkYellow);
|
||||
|
||||
lastCancel = false;
|
||||
Console.CancelKeyPress += HandleCancel;
|
||||
|
||||
ActiveGame = null;
|
||||
|
||||
ReloadDirectoryInfo();
|
||||
@ -106,8 +112,6 @@ public class Shell
|
||||
|
||||
public string ReadLine()
|
||||
{
|
||||
Console.CursorVisible = true;
|
||||
|
||||
Write($"\n{WorkingDirectory}", ConsoleColor.DarkGreen, false);
|
||||
if (ActiveGame is not null) Write($" {ActiveGame}", ConsoleColor.DarkYellow, false);
|
||||
if (ActiveMod is not null) Write($" {ActiveMod}", ConsoleColor.Magenta, false);
|
||||
@ -116,17 +120,55 @@ public class Shell
|
||||
Write($" {Name}", ConsoleColor.DarkCyan, false);
|
||||
Write(" > ", ConsoleColor.White, false);
|
||||
|
||||
bool printed = false;
|
||||
|
||||
if (lastCancel && !printedCancel)
|
||||
{
|
||||
// Print the warning. A little bit of mess because execution must
|
||||
// continue without funny printing errors but it's alright I guess.
|
||||
|
||||
int originalLeft = Console.CursorLeft;
|
||||
|
||||
Console.CursorTop -= 3;
|
||||
Write("Press ^C again to exit the shell.", ConsoleColor.Red);
|
||||
// Send a warning sound.
|
||||
|
||||
Winmm.PlaySound("SystemAsterisk", nint.Zero,
|
||||
(uint)(Winmm.PlaySoundFlags.SND_ALIAS | Winmm.PlaySoundFlags.SND_ASYNC));
|
||||
|
||||
printedCancel = true;
|
||||
Console.CursorTop += 2;
|
||||
|
||||
Console.CursorLeft = originalLeft;
|
||||
printed = true;
|
||||
}
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.CursorVisible = true;
|
||||
string message = Console.ReadLine()!;
|
||||
Console.CursorVisible = false;
|
||||
Console.ResetColor();
|
||||
|
||||
Console.CursorVisible = false;
|
||||
if (!printed)
|
||||
{
|
||||
lastCancel = false;
|
||||
printedCancel = false;
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public void InvokeCommand(string cmd)
|
||||
{
|
||||
if (cmd is null)
|
||||
{
|
||||
// This usually won't happen, but might if for example
|
||||
// the shell cancel interrupt is called. This probably
|
||||
// happens for other shell interrupts are called.
|
||||
Write(null);
|
||||
return;
|
||||
}
|
||||
|
||||
List<string> parts = new();
|
||||
string active = string.Empty;
|
||||
|
||||
@ -205,4 +247,22 @@ public class Shell
|
||||
if (ActiveMod is not null) title += $" - {ActiveMod.Name}";
|
||||
Console.Title = title;
|
||||
}
|
||||
|
||||
private void HandleCancel(object? sender, ConsoleCancelEventArgs args)
|
||||
{
|
||||
// Due to some funny multithreading issues, we want to make the warning label
|
||||
// single-threaded on the shell.
|
||||
if (!lastCancel)
|
||||
{
|
||||
// Enable the warning. The "ReadLine" method will do the rest.
|
||||
lastCancel = true;
|
||||
args.Cancel = true; // "Cancel" referring to the cancellation of the cancel operation.
|
||||
return;
|
||||
}
|
||||
|
||||
// Actually kill the shell. We do still have to worry about some multithreaded
|
||||
// nonsense, but a bearable amount of it.
|
||||
Console.ResetColor();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user