mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 04:36:39 +00:00
Merge pull request #1316 from PowerShell/jasonsh/psreadline_windows_fixes
Fix UNIX/Windows/CORE story for PSReadLine
This commit is contained in:
commit
4f98ee7418
17 files changed
+431
-335
No files matched your search
@@ -12,6 +12,7 @@ using System.Reflection;
|
||||
using System.Linq;
|
||||
#if CORECLR
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.PowerShell.Internal;
|
||||
#endif
|
||||
|
||||
namespace Microsoft.PowerShell
|
||||
@@ -72,33 +73,24 @@ namespace Microsoft.PowerShell
|
||||
|
||||
public class PSConsoleReadlineOptions
|
||||
{
|
||||
#if CORECLR
|
||||
#if LINUX // TODO: why different schemes for LINUX?
|
||||
public const ConsoleColor DefaultCommentForegroundColor = ConsoleColor.Magenta;
|
||||
public const ConsoleColor DefaultKeywordForegroundColor = ConsoleColor.Green;
|
||||
public const ConsoleColor DefaultStringForegroundColor = ConsoleColor.DarkCyan;
|
||||
public const ConsoleColor DefaultOperatorForegroundColor = ConsoleColor.Gray;
|
||||
public const ConsoleColor DefaultVariableForegroundColor = ConsoleColor.Green;
|
||||
public const ConsoleColor DefaultCommandForegroundColor = ConsoleColor.Yellow;
|
||||
public const ConsoleColor DefaultParameterForegroundColor = ConsoleColor.Green;
|
||||
public const ConsoleColor DefaultTypeForegroundColor = ConsoleColor.Gray;
|
||||
public const ConsoleColor DefaultNumberForegroundColor = ConsoleColor.White;
|
||||
public const ConsoleColor DefaultMemberForegroundColor = ConsoleColor.Gray;
|
||||
public const ConsoleColor DefaultEmphasisForegroundColor = ConsoleColor.Cyan;
|
||||
public const ConsoleColor DefaultErrorForegroundColor = ConsoleColor.Red;
|
||||
#else
|
||||
public const ConsoleColor DefaultCommentForegroundColor = ConsoleColor.DarkGreen;
|
||||
public const ConsoleColor DefaultOperatorForegroundColor = ConsoleColor.DarkGray;
|
||||
public const ConsoleColor DefaultParameterForegroundColor = ConsoleColor.DarkGray;
|
||||
#endif
|
||||
public const ConsoleColor DefaultKeywordForegroundColor = ConsoleColor.Green;
|
||||
public const ConsoleColor DefaultStringForegroundColor = ConsoleColor.DarkCyan;
|
||||
public const ConsoleColor DefaultOperatorForegroundColor = ConsoleColor.DarkGray;
|
||||
public const ConsoleColor DefaultVariableForegroundColor = ConsoleColor.Green;
|
||||
public const ConsoleColor DefaultCommandForegroundColor = ConsoleColor.Yellow;
|
||||
public const ConsoleColor DefaultParameterForegroundColor = ConsoleColor.DarkGray;
|
||||
public const ConsoleColor DefaultTypeForegroundColor = ConsoleColor.Gray;
|
||||
public const ConsoleColor DefaultNumberForegroundColor = ConsoleColor.White;
|
||||
public const ConsoleColor DefaultMemberForegroundColor = ConsoleColor.Gray;
|
||||
public const ConsoleColor DefaultEmphasisForegroundColor = ConsoleColor.Cyan;
|
||||
public const ConsoleColor DefaultErrorForegroundColor = ConsoleColor.Red;
|
||||
#endif
|
||||
|
||||
public const EditMode DefaultEditMode = EditMode.Windows;
|
||||
|
||||
@@ -171,37 +163,29 @@ namespace Microsoft.PowerShell
|
||||
HistorySaveStyle = DefaultHistorySaveStyle;
|
||||
|
||||
string historyFileName = hostName + "_history.txt";
|
||||
#if CORECLR
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) // MS Windows
|
||||
#if LINUX
|
||||
// PSReadline does not have access to Utils.CorePSPlatform. Must set PSReadline path separately
|
||||
string historyPath = System.Environment.GetEnvironmentVariable("XDG_DATA_HOME");
|
||||
|
||||
if (!String.IsNullOrEmpty(historyPath))
|
||||
{
|
||||
HistorySavePath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("APPDATA"),
|
||||
@"Microsoft\Windows\PowerShell\PSReadline\",
|
||||
historyFileName);
|
||||
historyPath = System.IO.Path.Combine(historyPath, "powershell", "PSReadLine", historyFileName);
|
||||
HistorySavePath = historyPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
// PSReadline does not have access to Utils.CorePSPlatform. Must set PSReadline path separately
|
||||
string historyPath = System.Environment.GetEnvironmentVariable("XDG_DATA_HOME");
|
||||
|
||||
if (!String.IsNullOrEmpty(historyPath))
|
||||
{
|
||||
historyPath = System.IO.Path.Combine(historyPath, "powershell", "PSReadLine", historyFileName);
|
||||
HistorySavePath = historyPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
// History is data, so it goes into .local/share/powershell folder
|
||||
HistorySavePath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("HOME"),
|
||||
".local",
|
||||
"share",
|
||||
"powershell",
|
||||
"PSReadLine",
|
||||
historyFileName);
|
||||
}
|
||||
// History is data, so it goes into .local/share/powershell folder
|
||||
HistorySavePath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("HOME"),
|
||||
".local",
|
||||
"share",
|
||||
"powershell",
|
||||
"PSReadLine",
|
||||
historyFileName);
|
||||
}
|
||||
#else
|
||||
HistorySavePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
|
||||
+ @"\Microsoft\Windows\PowerShell\PSReadline\" + historyFileName;
|
||||
HistorySavePath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("APPDATA"),
|
||||
@"Microsoft\Windows\PowerShell\PSReadline\",
|
||||
historyFileName);
|
||||
#endif
|
||||
CommandValidationHandler = null;
|
||||
CommandsToValidateScriptBlockArguments = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
@@ -396,9 +380,7 @@ namespace Microsoft.PowerShell
|
||||
[OutputType(typeof(PSConsoleReadlineOptions))]
|
||||
public class GetPSReadlineOption : PSCmdlet
|
||||
{
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
protected override void EndProcessing()
|
||||
{
|
||||
WriteObject(PSConsoleReadLine.GetOptions());
|
||||
@@ -641,9 +623,7 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
internal ConsoleColor? _backgroundColor;
|
||||
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
protected override void EndProcessing()
|
||||
{
|
||||
PSConsoleReadLine.SetOptions(this);
|
||||
@@ -661,9 +641,7 @@ namespace Microsoft.PowerShell
|
||||
[Parameter]
|
||||
public ViMode ViMode { get; set; }
|
||||
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
protected IDisposable UseRequestedDispatchTables()
|
||||
{
|
||||
bool inViMode = PSConsoleReadLine.GetOptions().EditMode == EditMode.Vi;
|
||||
@@ -706,9 +684,7 @@ namespace Microsoft.PowerShell
|
||||
private const string FunctionParameter = "Function";
|
||||
private const string FunctionParameterSet = "Function";
|
||||
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
protected override void EndProcessing()
|
||||
{
|
||||
using (UseRequestedDispatchTables())
|
||||
@@ -716,15 +692,9 @@ namespace Microsoft.PowerShell
|
||||
if (ParameterSetName.Equals(FunctionParameterSet))
|
||||
{
|
||||
var function = (string)_dynamicParameters.Value[FunctionParameter].Value;
|
||||
#if CORECLR
|
||||
MethodInfo mi = typeof (PSConsoleReadLine).GetMethod(function);
|
||||
var keyHandler = (Action<ConsoleKeyInfo?, object>)
|
||||
mi.CreateDelegate(typeof (Action<ConsoleKeyInfo?, object>));
|
||||
#else
|
||||
var keyHandler = (Action<ConsoleKeyInfo?, object>)
|
||||
Delegate.CreateDelegate(typeof (Action<ConsoleKeyInfo?, object>),
|
||||
typeof (PSConsoleReadLine).GetMethod(function));
|
||||
#endif
|
||||
BriefDescription = function;
|
||||
PSConsoleReadLine.SetKeyHandler(Chord, keyHandler, BriefDescription, Description);
|
||||
}
|
||||
@@ -792,9 +762,7 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
private SwitchParameter? _unbound;
|
||||
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
protected override void EndProcessing()
|
||||
{
|
||||
bool bound = true;
|
||||
@@ -821,9 +789,7 @@ namespace Microsoft.PowerShell
|
||||
[Cmdlet("Remove", "PSReadlineKeyHandler", HelpUri = "http://go.microsoft.com/fwlink/?LinkId=528809")]
|
||||
public class RemoveKeyHandlerCommand : ChangePSReadlineKeyHandlerCommandBase
|
||||
{
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
protected override void EndProcessing()
|
||||
{
|
||||
using (UseRequestedDispatchTables())
|
||||
|
||||
@@ -27,9 +27,7 @@ namespace Microsoft.PowerShell
|
||||
private static string DirectorySeparatorString = System.IO.Path.DirectorySeparatorChar.ToString();
|
||||
|
||||
// Stub helper method so completion can be mocked
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
CommandCompletion IPSConsoleReadLineMockableMethods.CompleteInput(string input, int cursorIndex, Hashtable options, System.Management.Automation.PowerShell powershell)
|
||||
{
|
||||
return CalloutUsingDefaultConsoleMode(
|
||||
@@ -300,24 +298,14 @@ namespace Microsoft.PowerShell
|
||||
return replacementText;
|
||||
}
|
||||
|
||||
private static void InvertSelectedCompletion(CHAR_INFO[] buffer, int selectedItem, int menuColumnWidth, int menuRows)
|
||||
private static void InvertSelectedCompletion(BufferChar[] buffer, int selectedItem, int menuColumnWidth, int menuRows)
|
||||
{
|
||||
var selectedX = selectedItem / menuRows;
|
||||
var selectedY = selectedItem - (selectedX * menuRows);
|
||||
var start = selectedY * _singleton._console.BufferWidth + selectedX * menuColumnWidth;
|
||||
for (int i = 0; i < menuColumnWidth; i++)
|
||||
{
|
||||
int j = i + start;
|
||||
#if CORECLR
|
||||
ConsoleColor tempColor = (int)buffer[j].ForegroundColor == -1
|
||||
? ConsoleColor.White : buffer[j].ForegroundColor;
|
||||
buffer[j].ForegroundColor = (int)buffer[j].BackgroundColor == -1
|
||||
? ConsoleColor.Black : buffer[j].BackgroundColor;
|
||||
buffer[j].BackgroundColor = tempColor;
|
||||
#else
|
||||
buffer[j].ForegroundColor = (ConsoleColor)((int)buffer[j].ForegroundColor ^ 7);
|
||||
buffer[j].BackgroundColor = (ConsoleColor)((int)buffer[j].BackgroundColor ^ 7);
|
||||
#endif
|
||||
buffer[i + start].Inverse = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,18 +10,18 @@ namespace Microsoft.PowerShell
|
||||
{
|
||||
internal class ConsoleBufferBuilder
|
||||
{
|
||||
private List<CHAR_INFO> buffer;
|
||||
private List<BufferChar> buffer;
|
||||
private IConsole _console;
|
||||
|
||||
public ConsoleBufferBuilder(int capacity, IConsole console)
|
||||
{
|
||||
buffer = new List<CHAR_INFO>(capacity);
|
||||
buffer = new List<BufferChar>(capacity);
|
||||
_console = console;
|
||||
}
|
||||
|
||||
CHAR_INFO NewCharInfo(char c)
|
||||
BufferChar NewCharInfo(char c)
|
||||
{
|
||||
return new CHAR_INFO
|
||||
return new BufferChar
|
||||
{
|
||||
UnicodeChar = c,
|
||||
BackgroundColor = _console.BackgroundColor,
|
||||
@@ -45,7 +45,7 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
}
|
||||
|
||||
public CHAR_INFO[] ToArray()
|
||||
public BufferChar[] ToArray()
|
||||
{
|
||||
return buffer.ToArray();
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
#if CORECLR
|
||||
#if LINUX
|
||||
using System.Reflection;
|
||||
#endif
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -214,7 +214,7 @@ namespace Microsoft.PowerShell
|
||||
{
|
||||
// default for unprintables and unhandled
|
||||
char keyChar = '\u0000';
|
||||
#if CORECLR
|
||||
#if LINUX
|
||||
Type keyType = typeof (Keys);
|
||||
FieldInfo[] keyFields = keyType.GetFields();
|
||||
|
||||
|
||||
@@ -227,9 +227,7 @@ namespace Microsoft.PowerShell.Internal
|
||||
public short Right;
|
||||
public short Bottom;
|
||||
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format(CultureInfo.InvariantCulture, "{0},{1},{2},{3}", Left, Top, Right, Bottom);
|
||||
@@ -241,9 +239,7 @@ namespace Microsoft.PowerShell.Internal
|
||||
public short X;
|
||||
public short Y;
|
||||
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format(CultureInfo.InvariantCulture, "{0},{1}", X, Y);
|
||||
@@ -313,75 +309,65 @@ namespace Microsoft.PowerShell.Internal
|
||||
internal string FontFace;
|
||||
}
|
||||
|
||||
public struct CHAR_INFO
|
||||
public struct BufferChar
|
||||
{
|
||||
#if CORECLR
|
||||
public char UnicodeChar;
|
||||
public ConsoleColor ForegroundColor;
|
||||
public ConsoleColor BackgroundColor;
|
||||
#if !LINUX
|
||||
public bool IsLeadByte;
|
||||
public bool IsTrailByte;
|
||||
#endif
|
||||
public bool Inverse;
|
||||
|
||||
public CHAR_INFO(char c, ConsoleColor foreground, ConsoleColor background)
|
||||
#if !LINUX
|
||||
public CHAR_INFO ToCharInfo()
|
||||
{
|
||||
UnicodeChar = c;
|
||||
ForegroundColor = foreground;
|
||||
BackgroundColor = background;
|
||||
}
|
||||
#else
|
||||
public ushort UnicodeChar;
|
||||
public ushort Attributes;
|
||||
int fg = (int) ForegroundColor;
|
||||
int bg = (int) BackgroundColor;
|
||||
|
||||
public CHAR_INFO(char c, ConsoleColor foreground, ConsoleColor background)
|
||||
{
|
||||
UnicodeChar = c;
|
||||
Attributes = (ushort)(((int)background << 4) | (int)foreground);
|
||||
}
|
||||
if (fg < 0 || fg > 0xf || bg < 0 || bg > 0xf)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public ConsoleColor ForegroundColor
|
||||
{
|
||||
get { return (ConsoleColor)(Attributes & 0xf); }
|
||||
set { Attributes = (ushort)((Attributes & 0xfff0) | ((int)value & 0xf)); }
|
||||
}
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public ConsoleColor BackgroundColor
|
||||
{
|
||||
get { return (ConsoleColor)((Attributes & 0xf0) >> 4); }
|
||||
set { Attributes = (ushort)((Attributes & 0xff0f) | (((int)value & 0xf) << 4)); }
|
||||
}
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public override string ToString()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append((char)UnicodeChar);
|
||||
if (ForegroundColor != Console.ForegroundColor)
|
||||
sb.AppendFormat(" fg: {0}", ForegroundColor);
|
||||
if (BackgroundColor != Console.BackgroundColor)
|
||||
sb.AppendFormat(" bg: {0}", BackgroundColor);
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is CHAR_INFO))
|
||||
if (Inverse)
|
||||
{
|
||||
return false;
|
||||
// TODO: check $host.UI.SupportsVirtualTerminal and maybe set Inverse instead (it does look weird)
|
||||
fg = fg ^ 7;
|
||||
bg = bg ^ 7;
|
||||
}
|
||||
ushort attrs = (ushort)(fg | (bg << 4));
|
||||
if (IsLeadByte)
|
||||
attrs |= (ushort)CHAR_INFO_Attributes.COMMON_LVB_LEADING_BYTE;
|
||||
if (IsTrailByte)
|
||||
attrs |= (ushort)CHAR_INFO_Attributes.COMMON_LVB_TRAILING_BYTE;
|
||||
CHAR_INFO result = new CHAR_INFO
|
||||
{
|
||||
UnicodeChar = UnicodeChar,
|
||||
Attributes = attrs,
|
||||
};
|
||||
|
||||
var other = (CHAR_INFO)obj;
|
||||
return this.UnicodeChar == other.UnicodeChar && this.Attributes == other.Attributes;
|
||||
return result;
|
||||
}
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public override int GetHashCode()
|
||||
public static BufferChar FromCharInfo(CHAR_INFO charInfo)
|
||||
{
|
||||
return UnicodeChar.GetHashCode() + Attributes.GetHashCode();
|
||||
BufferChar result = new BufferChar
|
||||
{
|
||||
UnicodeChar = (char) charInfo.UnicodeChar,
|
||||
ForegroundColor = (ConsoleColor)(charInfo.Attributes & 0xf),
|
||||
BackgroundColor = (ConsoleColor)((charInfo.Attributes & 0x00f0) >> 4),
|
||||
};
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public struct CHAR_INFO
|
||||
{
|
||||
public ushort UnicodeChar;
|
||||
public ushort Attributes;
|
||||
}
|
||||
|
||||
internal static class ConsoleKeyInfoExtension
|
||||
{
|
||||
public static string ToGestureString(this ConsoleKeyInfo key)
|
||||
@@ -400,9 +386,10 @@ namespace Microsoft.PowerShell.Internal
|
||||
sb.Append("Alt");
|
||||
}
|
||||
|
||||
#if CORECLR
|
||||
#if LINUX
|
||||
if (sb.Length > 0)
|
||||
sb.Append("+");
|
||||
// TODO: find better way to map these characters to something more friendly
|
||||
if ((key.Key >= ConsoleKey.D0 && key.Key <= ConsoleKey.D9)
|
||||
|| (key.Key >= ConsoleKey.Oem1 && key.Key <= ConsoleKey.Oem8))
|
||||
{
|
||||
@@ -442,6 +429,7 @@ namespace Microsoft.PowerShell.Internal
|
||||
}
|
||||
}
|
||||
|
||||
#if !LINUX
|
||||
internal class ConhostConsole : IConsole
|
||||
{
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
|
||||
@@ -498,18 +486,42 @@ namespace Microsoft.PowerShell.Internal
|
||||
return new SafeFileHandle(handle, true);
|
||||
});
|
||||
|
||||
public uint GetConsoleInputMode()
|
||||
public object GetConsoleInputMode()
|
||||
{
|
||||
uint mode;
|
||||
var handle = _inputHandle.Value.DangerousGetHandle();
|
||||
uint result;
|
||||
NativeMethods.GetConsoleMode(handle, out result);
|
||||
return result;
|
||||
NativeMethods.GetConsoleMode(handle, out mode);
|
||||
return mode;
|
||||
}
|
||||
|
||||
public void SetConsoleInputMode(uint mode)
|
||||
public void SetConsoleInputMode(object modeObj)
|
||||
{
|
||||
var handle = _inputHandle.Value.DangerousGetHandle();
|
||||
NativeMethods.SetConsoleMode(handle, mode);
|
||||
if (modeObj is uint)
|
||||
{
|
||||
// Clear a couple flags so we can actually receive certain keys:
|
||||
// ENABLE_PROCESSED_INPUT - enables Ctrl+C
|
||||
// ENABLE_LINE_INPUT - enables Ctrl+S
|
||||
// Also clear a couple flags so we don't mask the input that we ignore:
|
||||
// ENABLE_MOUSE_INPUT - mouse events
|
||||
// ENABLE_WINDOW_INPUT - window resize events
|
||||
var mode = (uint)modeObj &
|
||||
~(NativeMethods.ENABLE_PROCESSED_INPUT |
|
||||
NativeMethods.ENABLE_LINE_INPUT |
|
||||
NativeMethods.ENABLE_WINDOW_INPUT |
|
||||
NativeMethods.ENABLE_MOUSE_INPUT);
|
||||
|
||||
var handle = _inputHandle.Value.DangerousGetHandle();
|
||||
NativeMethods.SetConsoleMode(handle, mode);
|
||||
}
|
||||
}
|
||||
|
||||
public void RestoreConsoleInputMode(object modeObj)
|
||||
{
|
||||
if (modeObj is uint)
|
||||
{
|
||||
var handle = _inputHandle.Value.DangerousGetHandle();
|
||||
NativeMethods.SetConsoleMode(handle, (uint)modeObj);
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleKeyInfo ReadKey()
|
||||
@@ -602,16 +614,13 @@ namespace Microsoft.PowerShell.Internal
|
||||
Console.WriteLine(value);
|
||||
}
|
||||
|
||||
public void WriteBufferLines(CHAR_INFO[] buffer, ref int top)
|
||||
public void WriteBufferLines(BufferChar[] buffer, ref int top)
|
||||
{
|
||||
WriteBufferLines(buffer, ref top, true);
|
||||
}
|
||||
|
||||
public void WriteBufferLines(CHAR_INFO[] buffer, ref int top, bool ensureBottomLineVisible)
|
||||
public void WriteBufferLines(BufferChar[] buffer, ref int top, bool ensureBottomLineVisible)
|
||||
{
|
||||
#if !CORECLR
|
||||
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
|
||||
#endif
|
||||
int bufferWidth = Console.BufferWidth;
|
||||
int bufferLineCount = buffer.Length / bufferWidth;
|
||||
if ((top + bufferLineCount) > Console.BufferHeight)
|
||||
@@ -620,23 +629,8 @@ namespace Microsoft.PowerShell.Internal
|
||||
ScrollBuffer(scrollCount);
|
||||
top -= scrollCount;
|
||||
}
|
||||
#if CORECLR
|
||||
ConsoleColor foregroundColor = Console.ForegroundColor;
|
||||
ConsoleColor backgroundColor = Console.BackgroundColor;
|
||||
|
||||
Console.SetCursorPosition(0, (top>=0) ? top : 0);
|
||||
|
||||
for (int i = 0; i < buffer.Length; ++i)
|
||||
{
|
||||
Console.ForegroundColor = buffer[i].ForegroundColor;
|
||||
Console.BackgroundColor = buffer[i].BackgroundColor;
|
||||
|
||||
Console.Write((char)buffer[i].UnicodeChar);
|
||||
}
|
||||
|
||||
Console.BackgroundColor = backgroundColor;
|
||||
Console.ForegroundColor = foregroundColor;
|
||||
#else
|
||||
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
|
||||
var bufferSize = new COORD
|
||||
{
|
||||
X = (short) bufferWidth,
|
||||
@@ -651,7 +645,7 @@ namespace Microsoft.PowerShell.Internal
|
||||
Bottom = (short) bottom,
|
||||
Right = (short) (bufferWidth - 1)
|
||||
};
|
||||
NativeMethods.WriteConsoleOutput(handle, buffer,
|
||||
NativeMethods.WriteConsoleOutput(handle, ToCharInfoBuffer(buffer),
|
||||
bufferSize, bufferCoord, ref writeRegion);
|
||||
|
||||
// Now make sure the bottom line is visible
|
||||
@@ -660,18 +654,10 @@ namespace Microsoft.PowerShell.Internal
|
||||
{
|
||||
Console.CursorTop = bottom;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public void ScrollBuffer(int lines)
|
||||
{
|
||||
#if CORECLR
|
||||
for (int i=0; i<lines; ++i)
|
||||
{
|
||||
Console.SetCursorPosition(Console.BufferWidth, Console.BufferHeight - 1);
|
||||
Console.WriteLine();
|
||||
}
|
||||
#else
|
||||
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
|
||||
|
||||
var scrollRectangle = new SMALL_RECT
|
||||
@@ -682,22 +668,17 @@ namespace Microsoft.PowerShell.Internal
|
||||
Right = (short)Console.BufferWidth
|
||||
};
|
||||
var destinationOrigin = new COORD {X = 0, Y = 0};
|
||||
var fillChar = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor);
|
||||
var fillChar = new CHAR_INFO
|
||||
{
|
||||
UnicodeChar = ' ',
|
||||
Attributes = (ushort)((int)Console.ForegroundColor | ((int)Console.BackgroundColor << 4))
|
||||
};
|
||||
NativeMethods.ScrollConsoleScreenBuffer(handle, ref scrollRectangle, IntPtr.Zero, destinationOrigin, ref fillChar);
|
||||
#endif
|
||||
}
|
||||
|
||||
public CHAR_INFO[] ReadBufferLines(int top, int count)
|
||||
public BufferChar[] ReadBufferLines(int top, int count)
|
||||
{
|
||||
var result = new CHAR_INFO[BufferWidth * count];
|
||||
#if CORECLR
|
||||
for (int i=0; i<BufferWidth*count; ++i)
|
||||
{
|
||||
result[i].UnicodeChar = ' ';
|
||||
result[i].ForegroundColor = Console.ForegroundColor;
|
||||
result[i].BackgroundColor = Console.BackgroundColor;
|
||||
}
|
||||
#else
|
||||
var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output);
|
||||
|
||||
var readBufferSize = new COORD {
|
||||
@@ -713,8 +694,8 @@ namespace Microsoft.PowerShell.Internal
|
||||
};
|
||||
NativeMethods.ReadConsoleOutput(handle, result,
|
||||
readBufferSize, readBufferCoord, ref readRegion);
|
||||
#endif
|
||||
return result;
|
||||
|
||||
return ToBufferCharBuffer(result);
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods",
|
||||
@@ -909,13 +890,230 @@ namespace Microsoft.PowerShell.Internal
|
||||
}
|
||||
}
|
||||
|
||||
#if CORECLR
|
||||
private CHAR_INFO[] cachedBuffer;
|
||||
private CHAR_INFO[] ToCharInfoBuffer(BufferChar[] buffer)
|
||||
{
|
||||
if (cachedBuffer == null || cachedBuffer.Length != buffer.Length)
|
||||
{
|
||||
cachedBuffer = new CHAR_INFO[buffer.Length];
|
||||
}
|
||||
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
cachedBuffer[i] = buffer[i].ToCharInfo();
|
||||
}
|
||||
|
||||
return cachedBuffer;
|
||||
}
|
||||
|
||||
private BufferChar[] ToBufferCharBuffer(CHAR_INFO[] buffer)
|
||||
{
|
||||
var result = new BufferChar[buffer.Length];
|
||||
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
result[i] = BufferChar.FromCharInfo(buffer[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
internal class TTYConsole : IConsole
|
||||
{
|
||||
public object GetConsoleInputMode()
|
||||
{
|
||||
return Console.TreatControlCAsInput;
|
||||
}
|
||||
|
||||
public void SetConsoleInputMode(object modeObj)
|
||||
{
|
||||
Console.TreatControlCAsInput = true;
|
||||
}
|
||||
|
||||
public void RestoreConsoleInputMode(object modeObj)
|
||||
{
|
||||
if (modeObj is bool)
|
||||
{
|
||||
Console.TreatControlCAsInput = (bool)modeObj;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleKeyInfo ReadKey()
|
||||
{
|
||||
return Console.ReadKey(true);
|
||||
}
|
||||
|
||||
public bool KeyAvailable
|
||||
{
|
||||
get { return Console.KeyAvailable; }
|
||||
}
|
||||
|
||||
public int CursorLeft
|
||||
{
|
||||
get { return Console.CursorLeft; }
|
||||
set { Console.CursorLeft = value; }
|
||||
}
|
||||
|
||||
public int CursorTop
|
||||
{
|
||||
get { return Console.CursorTop; }
|
||||
set { Console.CursorTop = value; }
|
||||
}
|
||||
|
||||
public int CursorSize
|
||||
{
|
||||
get { return Console.CursorSize; }
|
||||
set { Console.CursorSize = value; }
|
||||
}
|
||||
|
||||
public int BufferWidth
|
||||
{
|
||||
get { return Console.BufferWidth; }
|
||||
set { Console.BufferWidth = value; }
|
||||
}
|
||||
|
||||
public int BufferHeight
|
||||
{
|
||||
get { return Console.BufferHeight; }
|
||||
set { Console.BufferHeight = value; }
|
||||
}
|
||||
|
||||
public int WindowWidth
|
||||
{
|
||||
get { return Console.WindowWidth; }
|
||||
set { Console.WindowWidth = value; }
|
||||
}
|
||||
|
||||
public int WindowHeight
|
||||
{
|
||||
get { return Console.WindowHeight; }
|
||||
set { Console.WindowHeight = value; }
|
||||
}
|
||||
|
||||
public int WindowTop
|
||||
{
|
||||
get { return Console.WindowTop; }
|
||||
set { Console.WindowTop = value; }
|
||||
}
|
||||
|
||||
public ConsoleColor BackgroundColor
|
||||
{
|
||||
get { return Console.BackgroundColor; }
|
||||
set { Console.BackgroundColor = value; }
|
||||
}
|
||||
|
||||
public ConsoleColor ForegroundColor
|
||||
{
|
||||
get { return Console.ForegroundColor; }
|
||||
set { Console.ForegroundColor = value; }
|
||||
}
|
||||
|
||||
public void SetWindowPosition(int left, int top)
|
||||
{
|
||||
Console.SetWindowPosition(left, top);
|
||||
}
|
||||
|
||||
public void SetCursorPosition(int left, int top)
|
||||
{
|
||||
Console.SetCursorPosition(left, top);
|
||||
}
|
||||
|
||||
public void Write(string value)
|
||||
{
|
||||
Console.Write(value);
|
||||
}
|
||||
|
||||
public void WriteLine(string value)
|
||||
{
|
||||
Console.WriteLine(value);
|
||||
}
|
||||
|
||||
public void WriteBufferLines(BufferChar[] buffer, ref int top)
|
||||
{
|
||||
WriteBufferLines(buffer, ref top, true);
|
||||
}
|
||||
|
||||
public void WriteBufferLines(BufferChar[] buffer, ref int top, bool ensureBottomLineVisible)
|
||||
{
|
||||
int bufferWidth = Console.BufferWidth;
|
||||
int bufferLineCount = buffer.Length / bufferWidth;
|
||||
if ((top + bufferLineCount) > Console.BufferHeight)
|
||||
{
|
||||
var scrollCount = (top + bufferLineCount) - Console.BufferHeight;
|
||||
ScrollBuffer(scrollCount);
|
||||
top -= scrollCount;
|
||||
}
|
||||
|
||||
ConsoleColor foregroundColor = Console.ForegroundColor;
|
||||
ConsoleColor backgroundColor = Console.BackgroundColor;
|
||||
|
||||
Console.SetCursorPosition(0, (top>=0) ? top : 0);
|
||||
|
||||
for (int i = 0; i < buffer.Length; ++i)
|
||||
{
|
||||
// TODO: use escape sequences for better perf
|
||||
Console.ForegroundColor = buffer[i].ForegroundColor;
|
||||
Console.BackgroundColor = buffer[i].BackgroundColor;
|
||||
|
||||
Console.Write(buffer[i].UnicodeChar);
|
||||
}
|
||||
|
||||
Console.BackgroundColor = backgroundColor;
|
||||
Console.ForegroundColor = foregroundColor;
|
||||
}
|
||||
|
||||
public void ScrollBuffer(int lines)
|
||||
{
|
||||
for (int i=0; i<lines; ++i)
|
||||
{
|
||||
Console.SetCursorPosition(Console.BufferWidth, Console.BufferHeight - 1);
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
public BufferChar[] ReadBufferLines(int top, int count)
|
||||
{
|
||||
var result = new BufferChar[BufferWidth * count];
|
||||
for (int i=0; i<BufferWidth*count; ++i)
|
||||
{
|
||||
result[i].UnicodeChar = ' ';
|
||||
result[i].ForegroundColor = Console.ForegroundColor;
|
||||
result[i].BackgroundColor = Console.BackgroundColor;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int LengthInBufferCells(char c)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void StartRender()
|
||||
{
|
||||
}
|
||||
|
||||
public void EndRender()
|
||||
{
|
||||
}
|
||||
|
||||
// TODO: this is not correct, PSReadline never clears the screen, it should only scroll
|
||||
public void Clear()
|
||||
{
|
||||
Console.Clear();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CORECLR // TODO: remove if CORECLR adds this attribute back
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event)]
|
||||
sealed class ExcludeFromCodeCoverageAttribute : Attribute
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma warning restore 1591
|
||||
}
|
||||
@@ -6,12 +6,13 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
#if CORECLR
|
||||
using Microsoft.PowerShell.Internal;
|
||||
#endif
|
||||
|
||||
namespace Microsoft.PowerShell
|
||||
{
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
[ExcludeFromCodeCoverage]
|
||||
internal sealed class QueueDebugView<T>
|
||||
{
|
||||
private readonly HistoryQueue<T> _queue;
|
||||
@@ -116,9 +117,7 @@ namespace Microsoft.PowerShell
|
||||
return result;
|
||||
}
|
||||
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace Microsoft.PowerShell
|
||||
{ Keys.CtrlSpace, MakeKeyHandler(MenuComplete, "MenuComplete") },
|
||||
{ Keys.Tab, MakeKeyHandler(TabCompleteNext, "TabCompleteNext") },
|
||||
{ Keys.ShiftTab, MakeKeyHandler(TabCompletePrevious, "TabCompletePrevious") },
|
||||
#if !CORECLR
|
||||
#if !LINUX
|
||||
{ Keys.VolumeDown, MakeKeyHandler(Ignore, "Ignore") },
|
||||
{ Keys.VolumeUp, MakeKeyHandler(Ignore, "Ignore") },
|
||||
{ Keys.VolumeMute, MakeKeyHandler(Ignore, "Ignore") },
|
||||
@@ -181,7 +181,7 @@ namespace Microsoft.PowerShell
|
||||
{ Keys.ShiftF3, MakeKeyHandler(CharacterSearchBackward, "CharacterSearchBackward") },
|
||||
{ Keys.F8, MakeKeyHandler(HistorySearchBackward, "HistorySearchBackward") },
|
||||
{ Keys.ShiftF8, MakeKeyHandler(HistorySearchForward, "HistorySearchForward") },
|
||||
#if !CORECLR
|
||||
#if !LINUX
|
||||
{ Keys.PageUp, MakeKeyHandler(ScrollDisplayUp, "ScrollDisplayUp") },
|
||||
{ Keys.PageDown, MakeKeyHandler(ScrollDisplayDown, "ScrollDisplayDown") },
|
||||
{ Keys.CtrlPageUp, MakeKeyHandler(ScrollDisplayUpLine, "ScrollDisplayUpLine") },
|
||||
@@ -265,7 +265,7 @@ namespace Microsoft.PowerShell
|
||||
{ Keys.AltPeriod, MakeKeyHandler(YankLastArg, "YankLastArg") },
|
||||
{ Keys.AltUnderbar, MakeKeyHandler(YankLastArg, "YankLastArg") },
|
||||
{ Keys.AltCtrlY, MakeKeyHandler(YankNthArg, "YankNthArg") },
|
||||
#if !CORECLR
|
||||
#if !LINUX
|
||||
{ Keys.VolumeDown, MakeKeyHandler(Ignore, "Ignore") },
|
||||
{ Keys.VolumeUp, MakeKeyHandler(Ignore, "Ignore") },
|
||||
{ Keys.VolumeMute, MakeKeyHandler(Ignore, "Ignore") },
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Microsoft.PowerShell
|
||||
{ Keys.Tab, MakeKeyHandler(ViTabCompleteNext, "ViTabCompleteNext") },
|
||||
{ Keys.ShiftTab, MakeKeyHandler(ViTabCompletePrevious, "ViTabCompletePrevious") },
|
||||
{ Keys.CtrlV, MakeKeyHandler(Paste, "Paste") },
|
||||
#if !CORECLR
|
||||
#if !LINUX
|
||||
{ Keys.VolumeDown, MakeKeyHandler(Ignore, "Ignore") },
|
||||
{ Keys.VolumeUp, MakeKeyHandler(Ignore, "Ignore") },
|
||||
{ Keys.VolumeMute, MakeKeyHandler(Ignore, "Ignore") },
|
||||
@@ -109,7 +109,7 @@ namespace Microsoft.PowerShell
|
||||
{ Keys.Tab, MakeKeyHandler(TabCompleteNext, "TabCompleteNext") },
|
||||
{ Keys.ShiftTab, MakeKeyHandler(TabCompletePrevious, "TabCompletePrevious") },
|
||||
{ Keys.CtrlV, MakeKeyHandler(Paste, "Paste") },
|
||||
#if !CORECLR
|
||||
#if !LINUX
|
||||
{ Keys.VolumeDown, MakeKeyHandler(Ignore, "Ignore") },
|
||||
{ Keys.VolumeUp, MakeKeyHandler(Ignore, "Ignore") },
|
||||
{ Keys.VolumeMute, MakeKeyHandler(Ignore, "Ignore") },
|
||||
|
||||
@@ -290,10 +290,10 @@ namespace Microsoft.PowerShell
|
||||
public static ConsoleKeyInfo ShiftF8 = new ConsoleKeyInfo((char)0, ConsoleKey.F8, true, false, false);
|
||||
|
||||
// Keys to ignore
|
||||
#if !CORECLR
|
||||
public static ConsoleKeyInfo VolumeUp = new ConsoleKeyInfo((char)0, ConsoleKey.VolumeUp, false, false, false);
|
||||
public static ConsoleKeyInfo VolumeDown = new ConsoleKeyInfo((char)0, ConsoleKey.VolumeDown, false, false, false);
|
||||
public static ConsoleKeyInfo VolumeMute = new ConsoleKeyInfo((char)0, ConsoleKey.VolumeMute, false, false, false);
|
||||
#if !LINUX
|
||||
public static ConsoleKeyInfo VolumeUp = new ConsoleKeyInfo((char)0, /*ConsoleKey.VolumeUp*/(ConsoleKey)175, false, false, false);
|
||||
public static ConsoleKeyInfo VolumeDown = new ConsoleKeyInfo((char)0, /*ConsoleKey.VolumeDown*/(ConsoleKey)174, false, false, false);
|
||||
public static ConsoleKeyInfo VolumeMute = new ConsoleKeyInfo((char)0, /*ConsoleKey.VolumeMute*/(ConsoleKey)173, false, false, false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Management.Automation.Language;
|
||||
#if !CORECLR
|
||||
#if !CORECLR // TODO: clipboard
|
||||
using System.Windows.Forms;
|
||||
#endif
|
||||
|
||||
@@ -478,7 +478,7 @@ namespace Microsoft.PowerShell
|
||||
[SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")]
|
||||
public static void Paste(ConsoleKeyInfo? key = null, object arg = null)
|
||||
{
|
||||
#if !CORECLR
|
||||
#if !CORECLR // TODO: clipboard
|
||||
string textToPaste = null;
|
||||
ExecuteOnSTAThread(() => {
|
||||
if (Clipboard.ContainsText())
|
||||
@@ -510,7 +510,7 @@ namespace Microsoft.PowerShell
|
||||
[SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")]
|
||||
public static void Copy(ConsoleKeyInfo? key = null, object arg = null)
|
||||
{
|
||||
#if !CORECLR
|
||||
#if !CORECLR // TODO: clipboard
|
||||
string textToSet;
|
||||
if (_singleton._visualSelectionCommandCount > 0)
|
||||
{
|
||||
@@ -551,15 +551,15 @@ namespace Microsoft.PowerShell
|
||||
[SuppressMessage("Microsoft.Design", "CA1026:DefaultParametersShouldNotBeUsed")]
|
||||
public static void Cut(ConsoleKeyInfo? key = null, object arg = null)
|
||||
{
|
||||
#if !CORECLR
|
||||
if (_singleton._visualSelectionCommandCount > 0)
|
||||
{
|
||||
int start, length;
|
||||
_singleton.GetRegion(out start, out length);
|
||||
#if !CORECLR // TODO: clipboard
|
||||
ExecuteOnSTAThread(() => Clipboard.SetText(_singleton._buffer.ToString(start, length)));
|
||||
#endif
|
||||
Delete(start, length);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -434,7 +434,7 @@ namespace Microsoft.PowerShell
|
||||
public static void ClearScreen(ConsoleKeyInfo? key = null, object arg = null)
|
||||
{
|
||||
var console = _singleton._console;
|
||||
#if CORECLR
|
||||
#if LINUX // TODO: this is not correct, it should only scroll
|
||||
console.Clear();
|
||||
_singleton._initialY = 0;
|
||||
_singleton.Render();
|
||||
|
||||
@@ -28,8 +28,9 @@ namespace Microsoft.PowerShell
|
||||
[SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
|
||||
public interface IConsole
|
||||
{
|
||||
uint GetConsoleInputMode();
|
||||
void SetConsoleInputMode(uint mode);
|
||||
object GetConsoleInputMode();
|
||||
void SetConsoleInputMode(object mode);
|
||||
void RestoreConsoleInputMode(object mode);
|
||||
ConsoleKeyInfo ReadKey();
|
||||
bool KeyAvailable { get; }
|
||||
int CursorLeft { get; set; }
|
||||
@@ -46,15 +47,15 @@ namespace Microsoft.PowerShell
|
||||
void SetCursorPosition(int left, int top);
|
||||
void WriteLine(string s);
|
||||
void Write(string s);
|
||||
void WriteBufferLines(CHAR_INFO[] buffer, ref int top);
|
||||
void WriteBufferLines(CHAR_INFO[] buffer, ref int top, bool ensureBottomLineVisible);
|
||||
void WriteBufferLines(BufferChar[] buffer, ref int top);
|
||||
void WriteBufferLines(BufferChar[] buffer, ref int top, bool ensureBottomLineVisible);
|
||||
void ScrollBuffer(int lines);
|
||||
CHAR_INFO[] ReadBufferLines(int top, int count);
|
||||
BufferChar[] ReadBufferLines(int top, int count);
|
||||
|
||||
void StartRender();
|
||||
int LengthInBufferCells(char c);
|
||||
void EndRender();
|
||||
#if CORECLR
|
||||
#if LINUX
|
||||
void Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Microsoft.PowerShell
|
||||
private IConsole _console;
|
||||
|
||||
private EngineIntrinsics _engineIntrinsics;
|
||||
#if !CORECLR
|
||||
#if !LINUX
|
||||
private static GCHandle _breakHandlerGcHandle;
|
||||
#endif
|
||||
private Thread _readKeyThread;
|
||||
@@ -43,11 +43,7 @@ namespace Microsoft.PowerShell
|
||||
private ManualResetEvent _closingWaitHandle;
|
||||
private WaitHandle[] _threadProcWaitHandles;
|
||||
private WaitHandle[] _requestKeyWaitHandles;
|
||||
#if CORECLR
|
||||
private bool _prePSReadlineControlCMode;
|
||||
#else
|
||||
private uint _prePSReadlineConsoleMode;
|
||||
#endif
|
||||
private object _savedConsoleInputMode;
|
||||
|
||||
private readonly StringBuilder _buffer;
|
||||
private readonly StringBuilder _statusBuffer;
|
||||
@@ -266,32 +262,13 @@ namespace Microsoft.PowerShell
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
#if CORECLR
|
||||
_singleton._prePSReadlineControlCMode = Console.TreatControlCAsInput;
|
||||
#else
|
||||
_singleton._prePSReadlineConsoleMode = console.GetConsoleInputMode();
|
||||
#endif
|
||||
_singleton._savedConsoleInputMode = _singleton._console.GetConsoleInputMode();
|
||||
bool firstTime = true;
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
#if CORECLR
|
||||
Console.TreatControlCAsInput = true;
|
||||
#else
|
||||
// Clear a couple flags so we can actually receive certain keys:
|
||||
// ENABLE_PROCESSED_INPUT - enables Ctrl+C
|
||||
// ENABLE_LINE_INPUT - enables Ctrl+S
|
||||
// Also clear a couple flags so we don't mask the input that we ignore:
|
||||
// ENABLE_MOUSE_INPUT - mouse events
|
||||
// ENABLE_WINDOW_INPUT - window resize events
|
||||
var mode = _singleton._prePSReadlineConsoleMode &
|
||||
~(NativeMethods.ENABLE_PROCESSED_INPUT |
|
||||
NativeMethods.ENABLE_LINE_INPUT |
|
||||
NativeMethods.ENABLE_WINDOW_INPUT |
|
||||
NativeMethods.ENABLE_MOUSE_INPUT);
|
||||
console.SetConsoleInputMode(mode);
|
||||
#endif
|
||||
_singleton._console.SetConsoleInputMode(_singleton._savedConsoleInputMode);
|
||||
|
||||
if (firstTime)
|
||||
{
|
||||
@@ -362,11 +339,7 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if CORECLR
|
||||
Console.TreatControlCAsInput = _singleton._prePSReadlineControlCMode;
|
||||
#else
|
||||
console.SetConsoleInputMode(_singleton._prePSReadlineConsoleMode);
|
||||
#endif
|
||||
_singleton._console.RestoreConsoleInputMode(_singleton._savedConsoleInputMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -454,29 +427,16 @@ namespace Microsoft.PowerShell
|
||||
|
||||
T CalloutUsingDefaultConsoleMode<T>(Func<T> func)
|
||||
{
|
||||
#if CORECLR
|
||||
bool psReadlineControlCMode = Console.TreatControlCAsInput;
|
||||
var currentMode = _console.GetConsoleInputMode();
|
||||
try
|
||||
{
|
||||
Console.TreatControlCAsInput = _prePSReadlineControlCMode;
|
||||
_console.RestoreConsoleInputMode(_savedConsoleInputMode);
|
||||
return func();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.TreatControlCAsInput = psReadlineControlCMode;
|
||||
_console.RestoreConsoleInputMode(currentMode);
|
||||
}
|
||||
#else
|
||||
uint psReadlineConsoleMode = _console.GetConsoleInputMode();
|
||||
try
|
||||
{
|
||||
_console.SetConsoleInputMode(_prePSReadlineConsoleMode);
|
||||
return func();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_console.SetConsoleInputMode(psReadlineConsoleMode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CalloutUsingDefaultConsoleMode(Action action)
|
||||
@@ -519,7 +479,11 @@ namespace Microsoft.PowerShell
|
||||
private PSConsoleReadLine()
|
||||
{
|
||||
_mockableMethods = this;
|
||||
#if LINUX
|
||||
_console = new TTYConsole();
|
||||
#else
|
||||
_console = new ConhostConsole();
|
||||
#endif
|
||||
|
||||
SetDefaultWindowsBindings();
|
||||
|
||||
@@ -580,7 +544,12 @@ namespace Microsoft.PowerShell
|
||||
_initialY = _console.CursorTop - Options.ExtraPromptLineCount;
|
||||
_initialBackgroundColor = _console.BackgroundColor;
|
||||
_initialForegroundColor = _console.ForegroundColor;
|
||||
_space = new CHAR_INFO(' ', _initialForegroundColor, _initialBackgroundColor);
|
||||
_space = new BufferChar
|
||||
{
|
||||
UnicodeChar = ' ',
|
||||
BackgroundColor = _initialBackgroundColor,
|
||||
ForegroundColor = _initialForegroundColor
|
||||
};
|
||||
_bufferWidth = _console.BufferWidth;
|
||||
_killCommandCount = 0;
|
||||
_yankCommandCount = 0;
|
||||
@@ -590,7 +559,7 @@ namespace Microsoft.PowerShell
|
||||
_statusIsErrorMessage = false;
|
||||
|
||||
_consoleBuffer = ReadBufferLines(_initialY, 1 + Options.ExtraPromptLineCount);
|
||||
#if CORECLR
|
||||
#if LINUX // TODO: not necessary if ReadBufferLines worked, or if rendering worked on spans instead of complete lines
|
||||
string newPrompt = GetPrompt();
|
||||
for (int i=0; i<newPrompt.Length; ++i)
|
||||
{
|
||||
@@ -644,7 +613,7 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
}
|
||||
|
||||
#if CORECLR
|
||||
#if LINUX
|
||||
_historyFileMutex = new Mutex(false);
|
||||
#else
|
||||
_historyFileMutex = new Mutex(false, GetHistorySaveFileMutexName());
|
||||
@@ -681,7 +650,7 @@ namespace Microsoft.PowerShell
|
||||
_killIndex = -1; // So first add indexes 0.
|
||||
_killRing = new List<string>(Options.MaximumKillRingCount);
|
||||
|
||||
#if !CORECLR
|
||||
#if !LINUX
|
||||
_breakHandlerGcHandle = GCHandle.Alloc(new BreakHandler(_singleton.BreakHandler));
|
||||
NativeMethods.SetConsoleCtrlHandler((BreakHandler)_breakHandlerGcHandle.Target, true);
|
||||
#endif
|
||||
@@ -691,11 +660,11 @@ namespace Microsoft.PowerShell
|
||||
_singleton._requestKeyWaitHandles = new WaitHandle[] {_singleton._keyReadWaitHandle, _singleton._closingWaitHandle};
|
||||
_singleton._threadProcWaitHandles = new WaitHandle[] {_singleton._readKeyWaitHandle, _singleton._closingWaitHandle};
|
||||
|
||||
#if !CORECLR
|
||||
// This is for a "being hosted in an alternate appdomain scenario" (the
|
||||
// DomainUnload event is not raised for the default appdomain). It allows us
|
||||
// to exit cleanly when the appdomain is unloaded but the process is not going
|
||||
// away.
|
||||
#if !CORECLR
|
||||
if (!AppDomain.CurrentDomain.IsDefaultAppDomain())
|
||||
{
|
||||
AppDomain.CurrentDomain.DomainUnload += (x, y) =>
|
||||
@@ -733,13 +702,14 @@ namespace Microsoft.PowerShell
|
||||
|
||||
private static void ExecuteOnSTAThread(Action action)
|
||||
{
|
||||
#if !CORECLR
|
||||
#if CORECLR
|
||||
action();
|
||||
#else
|
||||
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
|
||||
{
|
||||
action();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Exception exception = null;
|
||||
var thread = new Thread(() =>
|
||||
@@ -754,9 +724,7 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
});
|
||||
|
||||
#if !CORECLR
|
||||
thread.SetApartmentState(ApartmentState.STA);
|
||||
#endif
|
||||
thread.Start();
|
||||
thread.Join();
|
||||
|
||||
@@ -764,6 +732,7 @@ namespace Microsoft.PowerShell
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#region Miscellaneous bindable functions
|
||||
@@ -788,13 +757,11 @@ namespace Microsoft.PowerShell
|
||||
return;
|
||||
}
|
||||
|
||||
#region VI special case
|
||||
if (_singleton._options.EditMode == EditMode.Vi && key.Value.KeyChar == '0')
|
||||
{
|
||||
BeginningOfLine();
|
||||
return;
|
||||
}
|
||||
#endregion VI special case
|
||||
|
||||
bool sawDigit = false;
|
||||
_singleton._statusLinePrompt = "digit-argument: ";
|
||||
@@ -899,7 +866,7 @@ namespace Microsoft.PowerShell
|
||||
|
||||
_singleton._initialX = _singleton._console.CursorLeft;
|
||||
_singleton._consoleBuffer = ReadBufferLines(_singleton._initialY, 1 + _singleton.Options.ExtraPromptLineCount);
|
||||
#if CORECLR
|
||||
#if LINUX // TODO: ReadBufferLines only needed for extra line, but doesn't work on Linux
|
||||
for (int i=0; i<newPrompt.Length; ++i)
|
||||
{
|
||||
_singleton._consoleBuffer[i].UnicodeChar = newPrompt[i];
|
||||
|
||||
@@ -13,13 +13,16 @@ namespace Microsoft.PowerShell
|
||||
{
|
||||
public partial class PSConsoleReadLine
|
||||
{
|
||||
private CHAR_INFO[] _consoleBuffer;
|
||||
#if LINUX
|
||||
private const ConsoleColor UnknownColor = (ConsoleColor) (-1);
|
||||
#endif
|
||||
private BufferChar[] _consoleBuffer;
|
||||
private int _initialX;
|
||||
private int _initialY;
|
||||
private int _bufferWidth;
|
||||
private ConsoleColor _initialBackgroundColor;
|
||||
private ConsoleColor _initialForegroundColor;
|
||||
private CHAR_INFO _space;
|
||||
private BufferChar _space;
|
||||
private int _current;
|
||||
private int _emphasisStart;
|
||||
private int _emphasisLength;
|
||||
@@ -100,14 +103,11 @@ namespace Microsoft.PowerShell
|
||||
|
||||
try
|
||||
{
|
||||
#if !CORECLR
|
||||
_console.StartRender();
|
||||
#endif
|
||||
|
||||
bufferLineCount = ConvertOffsetToCoordinates(text.Length).Y - _initialY + 1 + statusLineCount;
|
||||
if (_consoleBuffer.Length != bufferLineCount * bufferWidth)
|
||||
{
|
||||
var newBuffer = new CHAR_INFO[bufferLineCount * bufferWidth];
|
||||
var newBuffer = new BufferChar[bufferLineCount * bufferWidth];
|
||||
Array.Copy(_consoleBuffer, newBuffer, _initialX + (Options.ExtraPromptLineCount * _bufferWidth));
|
||||
if (_consoleBuffer.Length > bufferLineCount * bufferWidth)
|
||||
{
|
||||
@@ -228,21 +228,17 @@ namespace Microsoft.PowerShell
|
||||
MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
|
||||
|
||||
}
|
||||
#if !LINUX
|
||||
else if (size > 1)
|
||||
{
|
||||
_consoleBuffer[j].UnicodeChar = charToRender;
|
||||
#if !CORECLR
|
||||
_consoleBuffer[j].Attributes = (ushort)(_consoleBuffer[j].Attributes |
|
||||
(uint)CHAR_INFO_Attributes.COMMON_LVB_LEADING_BYTE);
|
||||
#endif
|
||||
_consoleBuffer[j].IsLeadByte = true;
|
||||
MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
|
||||
_consoleBuffer[j].UnicodeChar = charToRender;
|
||||
#if !CORECLR
|
||||
_consoleBuffer[j].Attributes = (ushort)(_consoleBuffer[j].Attributes |
|
||||
(uint)CHAR_INFO_Attributes.COMMON_LVB_TRAILING_BYTE);
|
||||
#endif
|
||||
_consoleBuffer[j].IsTrailByte = true;
|
||||
MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
_consoleBuffer[j].UnicodeChar = charToRender;
|
||||
@@ -253,9 +249,7 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if !CORECLR
|
||||
_console.EndRender();
|
||||
#endif
|
||||
}
|
||||
|
||||
for (; j < (_consoleBuffer.Length - (statusLineCount * _bufferWidth)); j++)
|
||||
@@ -294,7 +288,7 @@ namespace Microsoft.PowerShell
|
||||
|
||||
while (promptChar >= 0)
|
||||
{
|
||||
var c = (char)_consoleBuffer[promptChar].UnicodeChar;
|
||||
var c = _consoleBuffer[promptChar].UnicodeChar;
|
||||
if (char.IsWhiteSpace(c))
|
||||
{
|
||||
promptChar -= 1;
|
||||
@@ -319,7 +313,7 @@ namespace Microsoft.PowerShell
|
||||
|
||||
if ((_initialY + bufferLineCount) > (_console.WindowTop + _console.WindowHeight))
|
||||
{
|
||||
#if !CORECLR
|
||||
#if !LINUX // TODO: verify this isn't necessary for LINUX
|
||||
_console.WindowTop = _initialY + bufferLineCount - _console.WindowHeight;
|
||||
#endif
|
||||
}
|
||||
@@ -340,7 +334,7 @@ namespace Microsoft.PowerShell
|
||||
private static void WriteBlankLines(int count, int top)
|
||||
{
|
||||
var console = _singleton._console;
|
||||
var blanks = new CHAR_INFO[count * console.BufferWidth];
|
||||
var blanks = new BufferChar[count * console.BufferWidth];
|
||||
for (int i = 0; i < blanks.Length; i++)
|
||||
{
|
||||
blanks[i].BackgroundColor = console.BackgroundColor;
|
||||
@@ -350,7 +344,7 @@ namespace Microsoft.PowerShell
|
||||
console.WriteBufferLines(blanks, ref top);
|
||||
}
|
||||
|
||||
private static CHAR_INFO[] ReadBufferLines(int top, int count)
|
||||
private static BufferChar[] ReadBufferLines(int top, int count)
|
||||
{
|
||||
return _singleton._console.ReadBufferLines(top, count);
|
||||
}
|
||||
@@ -458,7 +452,7 @@ namespace Microsoft.PowerShell
|
||||
return i >= start && i < end;
|
||||
}
|
||||
|
||||
private void MaybeEmphasize(ref CHAR_INFO charInfo, int i, ConsoleColor foregroundColor, ConsoleColor backgroundColor)
|
||||
private void MaybeEmphasize(ref BufferChar charInfo, int i, ConsoleColor foregroundColor, ConsoleColor backgroundColor)
|
||||
{
|
||||
if (i >= _emphasisStart && i < (_emphasisStart + _emphasisLength))
|
||||
{
|
||||
@@ -472,9 +466,9 @@ namespace Microsoft.PowerShell
|
||||
// to invert only the lower 3 bits to change the color is somewhat
|
||||
// but looks best with the 2 default color schemes - starting PowerShell
|
||||
// from it's shortcut or from a cmd shortcut.
|
||||
#if CORECLR
|
||||
ConsoleColor tempColor = ((int)foregroundColor == -1) ? ConsoleColor.White : foregroundColor;
|
||||
foregroundColor = ((int)backgroundColor == -1) ? ConsoleColor.Black : backgroundColor;
|
||||
#if LINUX // TODO: set Inverse attribute and let render choose what to do.
|
||||
ConsoleColor tempColor = (foregroundColor == UnknownColor) ? ConsoleColor.White : foregroundColor;
|
||||
foregroundColor = (backgroundColor == UnknownColor) ? ConsoleColor.Black : backgroundColor;
|
||||
backgroundColor = tempColor;
|
||||
#else
|
||||
foregroundColor = (ConsoleColor)((int)foregroundColor ^ 7);
|
||||
@@ -654,24 +648,24 @@ namespace Microsoft.PowerShell
|
||||
return (_statusLinePrompt.Length + _statusBuffer.Length) / _console.BufferWidth + 1;
|
||||
}
|
||||
|
||||
#if !CORECLR
|
||||
[ExcludeFromCodeCoverage]
|
||||
#endif
|
||||
void IPSConsoleReadLineMockableMethods.Ding()
|
||||
{
|
||||
#if !CORECLR
|
||||
switch (Options.BellStyle)
|
||||
{
|
||||
case BellStyle.None:
|
||||
break;
|
||||
case BellStyle.Audible:
|
||||
#if LINUX
|
||||
Console.Beep();
|
||||
#else
|
||||
Console.Beep(Options.DingTone, Options.DingDuration);
|
||||
#endif
|
||||
break;
|
||||
case BellStyle.Visual:
|
||||
// TODO: flash prompt? command line?
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -694,9 +688,9 @@ namespace Microsoft.PowerShell
|
||||
return key.Key == ConsoleKey.Y;
|
||||
}
|
||||
|
||||
#region Screen scrolling
|
||||
#region Screen scrolling
|
||||
|
||||
#if !CORECLR
|
||||
#if !LINUX
|
||||
/// <summary>
|
||||
/// Scroll the display up one screen.
|
||||
/// </summary>
|
||||
@@ -816,6 +810,6 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
|
||||
#endif
|
||||
#endregion Screen scrolling
|
||||
#endregion Screen scrolling
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,11 @@
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
--********************************************************************/
|
||||
|
||||
#if !CORECLR
|
||||
#if !LINUX
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.PowerShell.Internal;
|
||||
|
||||
namespace Microsoft.PowerShell
|
||||
@@ -19,16 +18,8 @@ namespace Microsoft.PowerShell
|
||||
var buffer = ReadBufferLines(start, count);
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
#if CORECLR
|
||||
ConsoleColor tempColor = (int)buffer[i].ForegroundColor == -1
|
||||
? ConsoleColor.White : buffer[i].ForegroundColor;
|
||||
buffer[i].ForegroundColor = (int)buffer[i].BackgroundColor == -1
|
||||
? ConsoleColor.Black : buffer[i].BackgroundColor;
|
||||
buffer[i].BackgroundColor = tempColor;
|
||||
#else
|
||||
buffer[i].ForegroundColor = (ConsoleColor)((int)buffer[i].ForegroundColor ^ 7);
|
||||
buffer[i].BackgroundColor = (ConsoleColor)((int)buffer[i].BackgroundColor ^ 7);
|
||||
#endif
|
||||
}
|
||||
_singleton._console.WriteBufferLines(buffer, ref start, false);
|
||||
}
|
||||
@@ -237,7 +228,6 @@ namespace Microsoft.PowerShell
|
||||
var buffer = ReadBufferLines(top, count);
|
||||
var bufferWidth = _singleton._console.BufferWidth;
|
||||
|
||||
var dataObject = new DataObject();
|
||||
var textBuffer = new StringBuilder(buffer.Length + count);
|
||||
|
||||
var rtfBuffer = new StringBuilder();
|
||||
@@ -307,9 +297,12 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
rtfBuffer.Append("}}");
|
||||
|
||||
dataObject.SetData(DataFormats.Text, textBuffer.ToString());
|
||||
dataObject.SetData(DataFormats.Rtf, rtfBuffer.ToString());
|
||||
ExecuteOnSTAThread(() => Clipboard.SetDataObject(dataObject, copy: true));
|
||||
#if !CORECLR // TODO: break dependency on Window.Forms w/ p/invokes to clipboard directly, for now, just silently skip the copy.
|
||||
var dataObject = new System.Windows.Forms.DataObject();
|
||||
dataObject.SetData(System.Windows.Forms.DataFormats.Text, textBuffer.ToString());
|
||||
dataObject.SetData(System.Windows.Forms.DataFormats.Rtf, rtfBuffer.ToString());
|
||||
ExecuteOnSTAThread(() => System.Windows.Forms.Clipboard.SetDataObject(dataObject, copy: true));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,6 @@ namespace Microsoft.PowerShell
|
||||
private static string GetPreferredEditor()
|
||||
{
|
||||
string[] names = {"VISUAL", "EDITOR"};
|
||||
#if CORECLR
|
||||
foreach (string name in names)
|
||||
{
|
||||
string editor = Environment.GetEnvironmentVariable(name);
|
||||
@@ -105,24 +104,7 @@ namespace Microsoft.PowerShell
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
#else
|
||||
EnvironmentVariableTarget[] targets = {
|
||||
EnvironmentVariableTarget.Machine,
|
||||
EnvironmentVariableTarget.Process,
|
||||
EnvironmentVariableTarget.User
|
||||
};
|
||||
foreach (string name in names)
|
||||
{
|
||||
foreach (EnvironmentVariableTarget target in targets)
|
||||
{
|
||||
string editor = Environment.GetEnvironmentVariable(name, target);
|
||||
if (!string.IsNullOrWhiteSpace(editor))
|
||||
{
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,14 @@
|
||||
"warningsAsErrors": true
|
||||
},
|
||||
|
||||
"configurations": {
|
||||
"Linux": {
|
||||
"buildOptions": {
|
||||
"define": [ "LINUX" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"System.Management.Automation": "1.0.0-*"
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user