Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3424 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
29 changed files with 2336 additions and 17 deletions
@ -0,0 +1,91 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Drawing; |
||||||
|
|
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
using ICSharpCode.TextEditor.Document; |
||||||
|
|
||||||
|
namespace ICSharpCode.PythonBinding |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// The interface that the text editor used by the PythonConsole needs to be implement. Note that
|
||||||
|
/// all the methods will be called on another thread not the main UI thread and will therefore need to
|
||||||
|
/// be invoked.
|
||||||
|
/// </summary>
|
||||||
|
public interface ITextEditor |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Fired when a key is pressed but before any text has been added to the text editor.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The KeyPress handler should return true if the text editor should not process the key and not
|
||||||
|
/// insert any text.
|
||||||
|
/// </remarks>
|
||||||
|
event KeyEventHandler KeyPress; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fired when dialog key is pressed but before any text has been added to the text editor.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The DialogKeyPress handler should return true if the text editor should not process the
|
||||||
|
/// dialog key.
|
||||||
|
/// </remarks>
|
||||||
|
event DialogKeyProcessor DialogKeyPress; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the indentation style.
|
||||||
|
/// </summary>
|
||||||
|
IndentStyle IndentStyle {get; set;} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts text at the current cursor location.
|
||||||
|
/// </summary>
|
||||||
|
void Write(string text); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts text at the current cursor location with the specified colour.
|
||||||
|
/// </summary>
|
||||||
|
void Write(string text, Color backgroundColor); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the current column position of the cursor on the current line. This is zero based.
|
||||||
|
/// </summary>
|
||||||
|
int Column {get; set;} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length of the currently selected text.
|
||||||
|
/// </summary>
|
||||||
|
int SelectionLength {get;} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the start position of the currently selected text.
|
||||||
|
/// </summary>
|
||||||
|
int SelectionStart {get;} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current line the cursor is on. This is zero based.
|
||||||
|
/// </summary>
|
||||||
|
int Line {get;} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total number of lines in the text editor.
|
||||||
|
/// </summary>
|
||||||
|
int TotalLines {get;} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the text for the specified line.
|
||||||
|
/// </summary>
|
||||||
|
string GetLine(int index); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shows the code completion window.
|
||||||
|
/// </summary>
|
||||||
|
void ShowCompletionWindow(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,251 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Drawing; |
||||||
|
using System.IO; |
||||||
|
using System.Text; |
||||||
|
using System.Threading; |
||||||
|
using System.Windows.Forms; |
||||||
|
|
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
using ICSharpCode.TextEditor.Document; |
||||||
|
using Microsoft.Scripting.Hosting.Shell; |
||||||
|
|
||||||
|
namespace ICSharpCode.PythonBinding |
||||||
|
{ |
||||||
|
public class PythonConsole : IConsole, IDisposable |
||||||
|
{ |
||||||
|
ITextEditor textEditor; |
||||||
|
int lineReceivedEventIndex = 0; // The index into the waitHandles array where the lineReceivedEvent is stored.
|
||||||
|
ManualResetEvent lineReceivedEvent = new ManualResetEvent(false); |
||||||
|
ManualResetEvent disposedEvent = new ManualResetEvent(false); |
||||||
|
WaitHandle[] waitHandles; |
||||||
|
int promptLength; |
||||||
|
List<string> previousLines = new List<string>(); |
||||||
|
|
||||||
|
public PythonConsole(ITextEditor textEditor) |
||||||
|
{ |
||||||
|
waitHandles = new WaitHandle[] {lineReceivedEvent, disposedEvent}; |
||||||
|
|
||||||
|
this.textEditor = textEditor; |
||||||
|
textEditor.KeyPress += ProcessKeyPress; |
||||||
|
textEditor.DialogKeyPress += ProcessDialogKeyPress; |
||||||
|
textEditor.IndentStyle = IndentStyle.None; |
||||||
|
} |
||||||
|
|
||||||
|
public void Dispose() |
||||||
|
{ |
||||||
|
disposedEvent.Set(); |
||||||
|
//TextArea textArea = textEditor.ActiveTextAreaControl.TextArea;
|
||||||
|
//textArea.KeyEventHandler -= ProcessKeyPress;
|
||||||
|
//textArea.DoProcessDialogKey -= ProcessDialogKey;
|
||||||
|
} |
||||||
|
|
||||||
|
public TextWriter Output { |
||||||
|
get { |
||||||
|
Console.WriteLine("PythonConsole.Output get"); |
||||||
|
return null; |
||||||
|
} |
||||||
|
set { |
||||||
|
Console.WriteLine("PythonConsole.Output set"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public TextWriter ErrorOutput { |
||||||
|
get { |
||||||
|
Console.WriteLine("PythonConsole.ErrorOutput get"); |
||||||
|
return null; |
||||||
|
} |
||||||
|
set { |
||||||
|
Console.WriteLine("PythonConsole.ErrorOutput get"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the next line typed in by the console user. If no line is available this method
|
||||||
|
/// will block.
|
||||||
|
/// </summary>
|
||||||
|
public string ReadLine(int autoIndentSize) |
||||||
|
{ |
||||||
|
Console.WriteLine("PythonConsole.ReadLine(): autoIndentSize: " + autoIndentSize); |
||||||
|
|
||||||
|
string indent = String.Empty; |
||||||
|
if (autoIndentSize > 0) { |
||||||
|
indent = String.Empty.PadLeft(autoIndentSize); |
||||||
|
Write(indent, Style.Prompt); |
||||||
|
} |
||||||
|
|
||||||
|
string line = ReadLineFromTextEditor(); |
||||||
|
if (line != null) { |
||||||
|
Console.WriteLine("ReadLine: " + indent + line); |
||||||
|
return indent + line; |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public void Write(string text, Style style) |
||||||
|
{ |
||||||
|
Console.WriteLine("PythonConsole.Write(text, style): " + text); |
||||||
|
|
||||||
|
textEditor.Write(text); |
||||||
|
|
||||||
|
if (style == Style.Prompt) { |
||||||
|
promptLength = text.Length; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void WriteLine(string text, Style style) |
||||||
|
{ |
||||||
|
Write(text + Environment.NewLine, style); |
||||||
|
} |
||||||
|
|
||||||
|
public void WriteLine() |
||||||
|
{ |
||||||
|
Write(Environment.NewLine, Style.Out); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether there is a line already read by the console and waiting to be processed.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsLineAvailable { |
||||||
|
get { |
||||||
|
lock (previousLines) { |
||||||
|
return previousLines.Count > 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the text that is yet to be processed from the console. This is the text that is being
|
||||||
|
/// typed in by the user who has not yet pressed the enter key.
|
||||||
|
/// </summary>
|
||||||
|
public string GetCurrentLine() |
||||||
|
{ |
||||||
|
string fullLine = GetLastTextEditorLine(); |
||||||
|
return fullLine.Substring(promptLength); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the lines that have not been returned by the ReadLine method. This does not
|
||||||
|
/// include the current line.
|
||||||
|
/// </summary>
|
||||||
|
public string[] GetUnreadLines() |
||||||
|
{ |
||||||
|
return previousLines.ToArray(); |
||||||
|
} |
||||||
|
|
||||||
|
string GetLastTextEditorLine() |
||||||
|
{ |
||||||
|
return textEditor.GetLine(textEditor.TotalLines - 1); |
||||||
|
} |
||||||
|
|
||||||
|
string ReadLineFromTextEditor() |
||||||
|
{ |
||||||
|
int result = WaitHandle.WaitAny(waitHandles); |
||||||
|
if (result == lineReceivedEventIndex) { |
||||||
|
lock (previousLines) { |
||||||
|
string line = previousLines[0]; |
||||||
|
previousLines.RemoveAt(0); |
||||||
|
if (previousLines.Count == 0) { |
||||||
|
lineReceivedEvent.Reset(); |
||||||
|
} |
||||||
|
return line; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processes characters entered into the text editor by the user.
|
||||||
|
/// </summary>
|
||||||
|
bool ProcessKeyPress(char ch) |
||||||
|
{ |
||||||
|
if (IsInReadOnlyRegion) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
if (ch == '\n') { |
||||||
|
OnEnterKeyPressed(); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process dialog keys such as the enter key when typed into the editor by the user.
|
||||||
|
/// </summary>
|
||||||
|
bool ProcessDialogKeyPress(Keys keyData) |
||||||
|
{ |
||||||
|
if (IsInReadOnlyRegion) { |
||||||
|
switch (keyData) { |
||||||
|
case Keys.Left: |
||||||
|
case Keys.Right: |
||||||
|
case Keys.Up: |
||||||
|
case Keys.Down: |
||||||
|
return false; |
||||||
|
default: |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
switch (keyData) { |
||||||
|
case Keys.Back: |
||||||
|
return !CanBackspace; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Move cursor to the end of the line before retrieving the line.
|
||||||
|
/// </summary>
|
||||||
|
void OnEnterKeyPressed() |
||||||
|
{ |
||||||
|
lock (previousLines) { |
||||||
|
// Move cursor to the end of the line.
|
||||||
|
textEditor.Column = GetLastTextEditorLine().Length; |
||||||
|
|
||||||
|
// Append line.
|
||||||
|
string currentLine = GetCurrentLine(); |
||||||
|
previousLines.Add(currentLine); |
||||||
|
lineReceivedEvent.Set(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the cursor is in a readonly text editor region.
|
||||||
|
/// </summary>
|
||||||
|
bool IsInReadOnlyRegion { |
||||||
|
get { return IsCurrentLineReadOnly || IsInPrompt; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only the last line in the text editor is not read only.
|
||||||
|
/// </summary>
|
||||||
|
bool IsCurrentLineReadOnly { |
||||||
|
get { return textEditor.Line < textEditor.TotalLines - 1; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the current cursor position is in a prompt.
|
||||||
|
/// </summary>
|
||||||
|
bool IsInPrompt { |
||||||
|
get { return textEditor.Column - promptLength < 0; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the user can backspace at the current cursor position.
|
||||||
|
/// </summary>
|
||||||
|
bool CanBackspace { |
||||||
|
get { |
||||||
|
int cursorIndex = textEditor.Column - promptLength; |
||||||
|
int selectionStartIndex = textEditor.SelectionStart - promptLength; |
||||||
|
return cursorIndex > 0 && selectionStartIndex > 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,93 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Text; |
||||||
|
using System.Threading; |
||||||
|
|
||||||
|
using IronPython.Hosting; |
||||||
|
using IronPython.Runtime; |
||||||
|
using Microsoft.Scripting.Hosting; |
||||||
|
using Microsoft.Scripting.Hosting.Shell; |
||||||
|
|
||||||
|
namespace ICSharpCode.PythonBinding |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Hosts the python console.
|
||||||
|
/// </summary>
|
||||||
|
public class PythonConsoleHost : ConsoleHost, IDisposable |
||||||
|
{ |
||||||
|
Thread thread; |
||||||
|
ITextEditor textEditor; |
||||||
|
PythonConsole pythonConsole; |
||||||
|
|
||||||
|
public PythonConsoleHost(ITextEditor textEditor) |
||||||
|
{ |
||||||
|
this.textEditor = textEditor; |
||||||
|
} |
||||||
|
|
||||||
|
protected override Type Provider { |
||||||
|
get { return typeof(PythonContext); } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the console host in its own thread.
|
||||||
|
/// </summary>
|
||||||
|
public void Run() |
||||||
|
{ |
||||||
|
thread = new Thread(RunConsole); |
||||||
|
thread.Start(); |
||||||
|
} |
||||||
|
|
||||||
|
public void Dispose() |
||||||
|
{ |
||||||
|
if (pythonConsole != null) { |
||||||
|
pythonConsole.Dispose(); |
||||||
|
} |
||||||
|
|
||||||
|
if (thread != null) { |
||||||
|
thread.Join(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected override CommandLine CreateCommandLine() |
||||||
|
{ |
||||||
|
return new PythonCommandLine(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override OptionsParser CreateOptionsParser() |
||||||
|
{ |
||||||
|
return new PythonOptionsParser(); |
||||||
|
} |
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// After the engine is created the standard output is replaced with our custom Stream class so we
|
||||||
|
/// can redirect the stdout to the text editor window.
|
||||||
|
/// This can be done in this method since the Runtime object will have been created before this method
|
||||||
|
/// is called.
|
||||||
|
/// </remarks>
|
||||||
|
protected override IConsole CreateConsole(ScriptEngine engine, CommandLine commandLine, ConsoleOptions options) |
||||||
|
{ |
||||||
|
SetOutput(new PythonOutputStream(textEditor)); |
||||||
|
pythonConsole = new PythonConsole(textEditor); |
||||||
|
return pythonConsole; |
||||||
|
} |
||||||
|
|
||||||
|
protected virtual void SetOutput(PythonOutputStream stream) |
||||||
|
{ |
||||||
|
Runtime.IO.SetOutput(stream, Encoding.UTF8); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the console.
|
||||||
|
/// </summary>
|
||||||
|
void RunConsole() |
||||||
|
{ |
||||||
|
Run(new string[0]); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Windows.Forms; |
||||||
|
using ICSharpCode.Core; |
||||||
|
using ICSharpCode.SharpDevelop; |
||||||
|
using ICSharpCode.SharpDevelop.Gui; |
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
|
||||||
|
namespace ICSharpCode.PythonBinding |
||||||
|
{ |
||||||
|
public class PythonConsolePad : AbstractPadContent |
||||||
|
{ |
||||||
|
TextEditor textEditor; |
||||||
|
TextEditorControl textEditorControl; |
||||||
|
PythonConsoleHost host; |
||||||
|
|
||||||
|
public PythonConsolePad() |
||||||
|
{ |
||||||
|
textEditorControl = new TextEditorControl(); |
||||||
|
textEditorControl.CreateControl(); |
||||||
|
textEditor = new TextEditor(textEditorControl); |
||||||
|
host = new PythonConsoleHost(textEditor); |
||||||
|
host.Run(); |
||||||
|
} |
||||||
|
|
||||||
|
public override Control Control { |
||||||
|
get { return textEditorControl; } |
||||||
|
} |
||||||
|
|
||||||
|
public override void Dispose() |
||||||
|
{ |
||||||
|
host.Dispose(); |
||||||
|
textEditorControl.Dispose(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace ICSharpCode.PythonBinding |
||||||
|
{ |
||||||
|
public class PythonOutputStream : Stream |
||||||
|
{ |
||||||
|
ITextEditor textEditor; |
||||||
|
|
||||||
|
public PythonOutputStream(ITextEditor textEditor) |
||||||
|
{ |
||||||
|
this.textEditor = textEditor; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool CanRead { |
||||||
|
get { return false; } |
||||||
|
} |
||||||
|
|
||||||
|
public override bool CanSeek { |
||||||
|
get { return false; } |
||||||
|
} |
||||||
|
|
||||||
|
public override bool CanWrite { |
||||||
|
get { return true; } |
||||||
|
} |
||||||
|
|
||||||
|
public override long Length { |
||||||
|
get { return 0; } |
||||||
|
} |
||||||
|
|
||||||
|
public override long Position { |
||||||
|
get { return 0; } |
||||||
|
set { } |
||||||
|
} |
||||||
|
|
||||||
|
public override void Flush() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public override long Seek(long offset, SeekOrigin origin) |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public override void SetLength(long value) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public override int Read(byte[] buffer, int offset, int count) |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assumes the bytes are UTF8 and writes them to the text editor.
|
||||||
|
/// </summary>
|
||||||
|
public override void Write(byte[] buffer, int offset, int count) |
||||||
|
{ |
||||||
|
string text = UTF8Encoding.UTF8.GetString(buffer, offset, count); |
||||||
|
textEditor.Write(text); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,160 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Drawing; |
||||||
|
|
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
using ICSharpCode.TextEditor.Document; |
||||||
|
|
||||||
|
namespace ICSharpCode.PythonBinding |
||||||
|
{ |
||||||
|
public class TextEditor : ITextEditor |
||||||
|
{ |
||||||
|
delegate string GetLineInvoker(int index); |
||||||
|
|
||||||
|
TextEditorControl textEditorControl; |
||||||
|
TextArea textArea; |
||||||
|
Color customLineColour = Color.LightGray; |
||||||
|
|
||||||
|
public TextEditor(TextEditorControl textEditorControl) |
||||||
|
{ |
||||||
|
this.textEditorControl = textEditorControl; |
||||||
|
this.textEditorControl.Document.LineCountChanged += LineCountChanged; |
||||||
|
this.textArea = textEditorControl.ActiveTextAreaControl.TextArea; |
||||||
|
textEditorControl.TextEditorProperties.SupportReadOnlySegments = true; |
||||||
|
} |
||||||
|
|
||||||
|
public IndentStyle IndentStyle { |
||||||
|
get { return textEditorControl.IndentStyle; } |
||||||
|
set { SetIndentStyle(value); } |
||||||
|
} |
||||||
|
|
||||||
|
public event KeyEventHandler KeyPress { |
||||||
|
add { textArea.KeyEventHandler += value; } |
||||||
|
remove { textArea.KeyEventHandler -= value; } |
||||||
|
} |
||||||
|
|
||||||
|
public event DialogKeyProcessor DialogKeyPress { |
||||||
|
add { textArea.DoProcessDialogKey += value; } |
||||||
|
remove { textArea.DoProcessDialogKey -= value; } |
||||||
|
} |
||||||
|
|
||||||
|
public Color CustomLineColour { |
||||||
|
get { return customLineColour; } |
||||||
|
} |
||||||
|
|
||||||
|
public void Write(string text) |
||||||
|
{ |
||||||
|
Write(text, Color.Empty); |
||||||
|
} |
||||||
|
|
||||||
|
public void Write(string text, Color backgroundColour) |
||||||
|
{ |
||||||
|
if (textEditorControl.InvokeRequired) { |
||||||
|
Action<string, Color> action = Write; |
||||||
|
textEditorControl.Invoke(action, new object[] {text, backgroundColour}); |
||||||
|
} else { |
||||||
|
int offset = textEditorControl.Document.PositionToOffset(new TextLocation(Column, Line)); |
||||||
|
textEditorControl.ActiveTextAreaControl.TextArea.InsertString(text); |
||||||
|
|
||||||
|
if (!backgroundColour.IsEmpty) { |
||||||
|
TextMarker marker = new TextMarker(offset, text.Length, TextMarkerType.SolidBlock, backgroundColour); |
||||||
|
textEditorControl.Document.MarkerStrategy.AddMarker(marker); |
||||||
|
textEditorControl.Refresh(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void AddCustomLine(int line) |
||||||
|
{ |
||||||
|
//textEditorControl.Document.CustomLineManager.AddCustomLine(line, customLineColour, false);
|
||||||
|
} |
||||||
|
|
||||||
|
public int Column { |
||||||
|
get { return textEditorControl.ActiveTextAreaControl.Caret.Column; } |
||||||
|
set { textEditorControl.ActiveTextAreaControl.Caret.Column = value; } |
||||||
|
} |
||||||
|
|
||||||
|
public int SelectionStart { |
||||||
|
get { |
||||||
|
ColumnRange range = GetSelectionRange(); |
||||||
|
if (range != ColumnRange.NoColumn) { |
||||||
|
return range.StartColumn; |
||||||
|
} |
||||||
|
return Column; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int SelectionLength { |
||||||
|
get { |
||||||
|
ColumnRange range = GetSelectionRange(); |
||||||
|
return range.EndColumn - range.StartColumn; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current cursor line.
|
||||||
|
/// </summary>
|
||||||
|
public int Line { |
||||||
|
get { return textArea.Caret.Line; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total number of lines in the text editor.
|
||||||
|
/// </summary>
|
||||||
|
public int TotalLines { |
||||||
|
get { return textEditorControl.Document.TotalNumberOfLines; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the text for the specified line.
|
||||||
|
/// </summary>
|
||||||
|
public string GetLine(int index) |
||||||
|
{ |
||||||
|
if (textEditorControl.InvokeRequired) { |
||||||
|
GetLineInvoker invoker = new GetLineInvoker(GetLine); |
||||||
|
return (string)textEditorControl.Invoke(invoker, new object[] {index}); |
||||||
|
} else { |
||||||
|
LineSegment lineSegment = textEditorControl.Document.GetLineSegment(index); |
||||||
|
return textEditorControl.Document.GetText(lineSegment); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void ShowCompletionWindow() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the range of the currently selected text.
|
||||||
|
/// </summary>
|
||||||
|
ColumnRange GetSelectionRange() |
||||||
|
{ |
||||||
|
return textArea.SelectionManager.GetSelectionAtLine(textArea.Caret.Line); |
||||||
|
} |
||||||
|
|
||||||
|
void SetIndentStyle(IndentStyle style) |
||||||
|
{ |
||||||
|
if (textEditorControl.InvokeRequired) { |
||||||
|
Action <IndentStyle> action = SetIndentStyle; |
||||||
|
textEditorControl.Invoke(action, new object[] {style}); |
||||||
|
} else { |
||||||
|
textEditorControl.IndentStyle = style; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void LineCountChanged(object source, LineCountChangeEventArgs e) |
||||||
|
{ |
||||||
|
IDocument doc = textEditorControl.Document; |
||||||
|
int totalLines = doc.TotalNumberOfLines; |
||||||
|
//doc.CustomLineManager.Clear();
|
||||||
|
for (int line = 0; line < totalLines - 1; ++line) { |
||||||
|
// doc.CustomLineManager.AddCustomLine(line, customLineColour, false);
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
|
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using Microsoft.Scripting; |
||||||
|
using Microsoft.Scripting.Hosting; |
||||||
|
using Microsoft.Scripting.Hosting.Shell; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
public class DerivedPythonConsoleHost : PythonConsoleHost |
||||||
|
{ |
||||||
|
ScriptEngine engine; |
||||||
|
Type languageContextType; |
||||||
|
PythonOutputStream outputStream; |
||||||
|
|
||||||
|
public DerivedPythonConsoleHost(ITextEditor textEditor) : base(textEditor) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public Type GetProvider() |
||||||
|
{ |
||||||
|
return base.Provider; |
||||||
|
} |
||||||
|
|
||||||
|
public CommandLine CallCreateCommandLine() |
||||||
|
{ |
||||||
|
return base.CreateCommandLine(); |
||||||
|
} |
||||||
|
|
||||||
|
public IConsole CallCreateConsole(ScriptEngine engine, CommandLine commandLine, ConsoleOptions options) |
||||||
|
{ |
||||||
|
return base.CreateConsole(engine, commandLine, options); |
||||||
|
} |
||||||
|
|
||||||
|
public OptionsParser CallCreateOptionsParser() |
||||||
|
{ |
||||||
|
return base.CreateOptionsParser(); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Script engine to return from base.CreateEngine(Type context).
|
||||||
|
/// </summary>
|
||||||
|
public ScriptEngine ScriptEngineToReturn { |
||||||
|
get { return engine; } |
||||||
|
set { engine = value; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Context type passed to base.CreateEngine(Type context).
|
||||||
|
/// </summary>
|
||||||
|
public Type LanguageContextTypePassedToCreateEngine { |
||||||
|
get { return languageContextType; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the output stream class passed to SetOutput method.
|
||||||
|
/// </summary>
|
||||||
|
public PythonOutputStream OutputStream { |
||||||
|
get { return outputStream; } |
||||||
|
} |
||||||
|
|
||||||
|
protected override void SetOutput(PythonOutputStream stream) |
||||||
|
{ |
||||||
|
outputStream = stream; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Tests the disposing of the PythonConsole.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture] |
||||||
|
public class DisposedPythonConsoleTestFixture |
||||||
|
{ |
||||||
|
[Test] |
||||||
|
public void PythonConsoleImplementsIDisposable() |
||||||
|
{ |
||||||
|
PythonConsole console = new PythonConsole(new MockTextEditor()); |
||||||
|
Assert.IsNotNull(console as IDisposable); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ReadLineReturnsNullWhenConsoleDisposed() |
||||||
|
{ |
||||||
|
PythonConsole console = new PythonConsole(new MockTextEditor()); |
||||||
|
console.Dispose(); |
||||||
|
Assert.IsNull(console.ReadLine(0)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,213 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Drawing; |
||||||
|
using System.Windows.Forms; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
using ICSharpCode.TextEditor.Document; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
public class MockTextEditor : ITextEditor |
||||||
|
{ |
||||||
|
IndentStyle indentStyle = IndentStyle.Auto; |
||||||
|
StringBuilder previousLines = new StringBuilder(); |
||||||
|
StringBuilder lineBuilder = new StringBuilder(); |
||||||
|
bool writeCalled; |
||||||
|
int column; |
||||||
|
int selectionStart; |
||||||
|
int selectionLength; |
||||||
|
int line; |
||||||
|
int totalLines = 1; |
||||||
|
List<Color> textColors = new List<Color>(); |
||||||
|
bool showCompletionWindowCalled; |
||||||
|
|
||||||
|
public MockTextEditor() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public event ICSharpCode.TextEditor.KeyEventHandler KeyPress; |
||||||
|
public event DialogKeyProcessor DialogKeyPress; |
||||||
|
|
||||||
|
public IndentStyle IndentStyle { |
||||||
|
get { return indentStyle; } |
||||||
|
set { indentStyle = value; } |
||||||
|
} |
||||||
|
|
||||||
|
public void Write(string text) |
||||||
|
{ |
||||||
|
writeCalled = true; |
||||||
|
lineBuilder.Append(text); |
||||||
|
column += text.Length; |
||||||
|
} |
||||||
|
|
||||||
|
public void Write(string text, Color backgroundColor) |
||||||
|
{ |
||||||
|
textColors.Add(backgroundColor); |
||||||
|
Write(text); |
||||||
|
} |
||||||
|
|
||||||
|
public bool IsWriteCalled { |
||||||
|
get { return writeCalled; } |
||||||
|
set { writeCalled = value; } |
||||||
|
} |
||||||
|
|
||||||
|
public bool IsShowCompletionWindowCalled { |
||||||
|
get { return showCompletionWindowCalled; } |
||||||
|
} |
||||||
|
|
||||||
|
public string Text { |
||||||
|
get { return previousLines.ToString() + lineBuilder.ToString(); } |
||||||
|
set { |
||||||
|
previousLines = new StringBuilder(); |
||||||
|
lineBuilder = new StringBuilder(); |
||||||
|
totalLines = 1; |
||||||
|
foreach (char ch in value) { |
||||||
|
lineBuilder.Append(ch); |
||||||
|
if (ch == '\n') { |
||||||
|
totalLines++; |
||||||
|
previousLines.Append(lineBuilder.ToString()); |
||||||
|
lineBuilder = new StringBuilder(); |
||||||
|
} |
||||||
|
} |
||||||
|
column = lineBuilder.Length; |
||||||
|
selectionStart = column; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public bool RaiseKeyPressEvent(char ch) |
||||||
|
{ |
||||||
|
bool keyHandled = KeyPress(ch); |
||||||
|
if (!keyHandled) { |
||||||
|
if (IsCursorAtEnd) { |
||||||
|
lineBuilder.Append(ch); |
||||||
|
} else { |
||||||
|
lineBuilder.Insert(column, ch); |
||||||
|
} |
||||||
|
column++; |
||||||
|
selectionStart = column; |
||||||
|
} |
||||||
|
return keyHandled; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls RaiseKeyPressEvent for each character in the string.
|
||||||
|
/// </summary>
|
||||||
|
public void RaiseKeyPressEvents(string text) |
||||||
|
{ |
||||||
|
foreach (char ch in text) { |
||||||
|
RaiseKeyPressEvent(ch); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public bool RaiseDialogKeyPressEvent(Keys keyData) |
||||||
|
{ |
||||||
|
bool keyHandled = DialogKeyPress(keyData); |
||||||
|
if (!keyHandled) { |
||||||
|
switch (keyData) { |
||||||
|
case Keys.Enter: { |
||||||
|
if (!KeyPress('\n')) { |
||||||
|
if (IsCursorAtEnd) { |
||||||
|
lineBuilder.Append(Environment.NewLine); |
||||||
|
previousLines.Append(lineBuilder.ToString()); |
||||||
|
lineBuilder = new StringBuilder(); |
||||||
|
column = 0; |
||||||
|
selectionStart = column; |
||||||
|
} else { |
||||||
|
int length = lineBuilder.Length; |
||||||
|
string currentLine = lineBuilder.ToString(); |
||||||
|
previousLines.Append(currentLine.Substring(0, column) + Environment.NewLine); |
||||||
|
lineBuilder = new StringBuilder(); |
||||||
|
lineBuilder.Append(currentLine.Substring(column)); |
||||||
|
column = length - column; |
||||||
|
selectionStart = column; |
||||||
|
} |
||||||
|
totalLines++; |
||||||
|
line++; |
||||||
|
} |
||||||
|
} |
||||||
|
break; |
||||||
|
case Keys.Back: { |
||||||
|
OnBackspaceKeyPressed(); |
||||||
|
} |
||||||
|
break; |
||||||
|
case Keys.Left: { |
||||||
|
column--; |
||||||
|
selectionStart = column; |
||||||
|
} |
||||||
|
break; |
||||||
|
case Keys.Right: { |
||||||
|
column++; |
||||||
|
selectionStart = column; |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
return keyHandled; |
||||||
|
} |
||||||
|
|
||||||
|
public int Column { |
||||||
|
get { return column; } |
||||||
|
set { column = value; } |
||||||
|
} |
||||||
|
|
||||||
|
public int SelectionStart { |
||||||
|
get { return selectionStart; } |
||||||
|
set { selectionStart = value; } |
||||||
|
} |
||||||
|
|
||||||
|
public int SelectionLength { |
||||||
|
get { return selectionLength; } |
||||||
|
set { selectionLength = value; } |
||||||
|
} |
||||||
|
|
||||||
|
public int Line { |
||||||
|
get { return line; } |
||||||
|
set { line = value; } |
||||||
|
} |
||||||
|
|
||||||
|
public int TotalLines { |
||||||
|
get { return totalLines; } |
||||||
|
} |
||||||
|
|
||||||
|
public string GetLine(int index) |
||||||
|
{ |
||||||
|
if (index == totalLines - 1) { |
||||||
|
return lineBuilder.ToString(); |
||||||
|
} |
||||||
|
return "aaaa"; |
||||||
|
} |
||||||
|
|
||||||
|
public void ShowCompletionWindow() |
||||||
|
{ |
||||||
|
showCompletionWindowCalled = true; |
||||||
|
} |
||||||
|
|
||||||
|
public List<Color> WrittenTextColors { |
||||||
|
get { return textColors; } |
||||||
|
} |
||||||
|
|
||||||
|
bool IsCursorAtEnd { |
||||||
|
get { return column == lineBuilder.ToString().Length; } |
||||||
|
} |
||||||
|
|
||||||
|
void OnBackspaceKeyPressed() |
||||||
|
{ |
||||||
|
if (SelectionLength == 0) { |
||||||
|
// Remove a single character to the left of the cursor position.
|
||||||
|
lineBuilder.Remove(Column - 1, 1); |
||||||
|
} else { |
||||||
|
lineBuilder.Remove(SelectionStart, SelectionLength); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Windows.Forms; |
||||||
|
using System.Threading; |
||||||
|
using Microsoft.Scripting.Hosting.Shell; |
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// When the dot character is typed in after an object the code completion window should appear.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture] |
||||||
|
[Ignore("Not implemented")] |
||||||
|
public class PythonConsoleCodeCompletionTestFixture |
||||||
|
{ |
||||||
|
MockTextEditor textEditor; |
||||||
|
PythonConsole console; |
||||||
|
string prompt = ">>> "; |
||||||
|
IList<string> expectedMembers; |
||||||
|
IList<string> completionItems; |
||||||
|
bool showCompletionWindowCalledBeforeDotTypedIn; |
||||||
|
|
||||||
|
[TestFixtureSetUp] |
||||||
|
public void SetUpFixture() |
||||||
|
{ |
||||||
|
textEditor = new MockTextEditor(); |
||||||
|
console = new PythonConsole(textEditor); |
||||||
|
console.WriteLine(prompt, Style.Prompt); |
||||||
|
|
||||||
|
// expectedMembers = host.GetCommandLine().GetMemberNames("__builtins__");
|
||||||
|
textEditor.RaiseKeyPressEvents("__builtins__"); |
||||||
|
showCompletionWindowCalledBeforeDotTypedIn = textEditor.IsShowCompletionWindowCalled; |
||||||
|
textEditor.RaiseKeyPressEvent('.'); |
||||||
|
} |
||||||
|
|
||||||
|
// [Test]
|
||||||
|
// public void MoreThanZeroExpectedMembers()
|
||||||
|
// {
|
||||||
|
// Assert.IsTrue(expectedMembers.Count > 0);
|
||||||
|
// }
|
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ShowCompletionWindowCalled() |
||||||
|
{ |
||||||
|
Assert.IsTrue(textEditor.IsShowCompletionWindowCalled); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ShowCompletionWindowNotCalledBeforeDotTypedIn() |
||||||
|
{ |
||||||
|
Assert.IsFalse(showCompletionWindowCalledBeforeDotTypedIn); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
using Microsoft.Scripting; |
||||||
|
using Microsoft.Scripting.Hosting; |
||||||
|
using Microsoft.Scripting.Hosting.Shell; |
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Tests the PythonConsole's GetCurrentLine method.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture] |
||||||
|
public class PythonConsoleCurrentLineTestFixture |
||||||
|
{ |
||||||
|
PythonConsole pythonConsole; |
||||||
|
MockTextEditor textEditor; |
||||||
|
string prompt = ">>> "; |
||||||
|
|
||||||
|
[SetUp] |
||||||
|
public void Init() |
||||||
|
{ |
||||||
|
textEditor = new MockTextEditor(); |
||||||
|
pythonConsole = new PythonConsole(textEditor); |
||||||
|
pythonConsole.Write(prompt, Style.Prompt); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CurrentLineIsEmpty() |
||||||
|
{ |
||||||
|
Assert.AreEqual(String.Empty, pythonConsole.GetCurrentLine()); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SingleCharacterAddedToTextEditor() |
||||||
|
{ |
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
Assert.AreEqual("a", pythonConsole.GetCurrentLine()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Windows.Forms; |
||||||
|
using Microsoft.Scripting.Hosting.Shell; |
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Tests that pressing the enter key in the middle of a typed in line in the python console
|
||||||
|
/// leaves the line alone and moves the cursor to the next line. By default the text editor
|
||||||
|
/// will break the line and move the last part to the second line.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture] |
||||||
|
public class PythonConsoleEnterKeyTestFixture |
||||||
|
{ |
||||||
|
MockTextEditor textEditor; |
||||||
|
PythonConsole console; |
||||||
|
string prompt = ">>> "; |
||||||
|
|
||||||
|
[SetUp] |
||||||
|
public void Init() |
||||||
|
{ |
||||||
|
textEditor = new MockTextEditor(); |
||||||
|
console = new PythonConsole(textEditor); |
||||||
|
console.Write(prompt, Style.Prompt); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void EnterKeyDoesNotBreakUpExistingLine() |
||||||
|
{ |
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
textEditor.RaiseKeyPressEvent('b'); |
||||||
|
textEditor.SelectionStart = 1 + prompt.Length; |
||||||
|
textEditor.Column = 1 + prompt.Length; |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Enter); |
||||||
|
|
||||||
|
Assert.AreEqual(">>> ab\r\n", textEditor.Text); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PreviousLineIsReadOnlyAfterEnterPressed() |
||||||
|
{ |
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
textEditor.RaiseKeyPressEvent('b'); |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Enter); |
||||||
|
console.Write(prompt, Style.Prompt); |
||||||
|
|
||||||
|
// Move up a line with cursor.
|
||||||
|
textEditor.Line = 0; |
||||||
|
Assert.IsTrue(textEditor.RaiseKeyPressEvent('c')); |
||||||
|
|
||||||
|
string expectedText = ">>> ab\r\n" + |
||||||
|
">>> "; |
||||||
|
Assert.AreEqual(expectedText, textEditor.Text); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,127 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
using IronPython.Hosting; |
||||||
|
using IronPython.Runtime; |
||||||
|
using NUnit.Framework; |
||||||
|
using Microsoft.Scripting; |
||||||
|
using Microsoft.Scripting.Hosting; |
||||||
|
using Microsoft.Scripting.Hosting.Shell; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Basic tests for the PythonConsoleHost class.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture] |
||||||
|
public class PythonConsoleHostTests |
||||||
|
{ |
||||||
|
DerivedPythonConsoleHost host; |
||||||
|
TextEditorControl textEditorControl; |
||||||
|
ScriptEngine engine; |
||||||
|
ScriptEngine expectedEngine; |
||||||
|
TextEditor textEditor; |
||||||
|
|
||||||
|
[TestFixtureSetUp] |
||||||
|
public void Init() |
||||||
|
{ |
||||||
|
textEditorControl = new TextEditorControl(); |
||||||
|
textEditor = new TextEditor(textEditorControl); |
||||||
|
host = new DerivedPythonConsoleHost(textEditor); |
||||||
|
|
||||||
|
ScriptRuntime runtime = ScriptRuntime.Create(); |
||||||
|
// expectedEngine = runtime.GetEngine(typeof(PythonContext));
|
||||||
|
// host.ScriptEngineToReturn = expectedEngine;
|
||||||
|
// engine = host.CallCreateEngine();
|
||||||
|
} |
||||||
|
|
||||||
|
[TestFixtureTearDown] |
||||||
|
public void TearDown() |
||||||
|
{ |
||||||
|
host.Dispose(); |
||||||
|
textEditorControl.Dispose(); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PythonConsoleHostIsMicrosoftScriptingConsoleHostType() |
||||||
|
{ |
||||||
|
Assert.IsInstanceOfType(typeof(ConsoleHost), host); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void OptionsParserCreatedIsPythonOptionsParser() |
||||||
|
{ |
||||||
|
OptionsParser parser = host.CallCreateOptionsParser(); |
||||||
|
Assert.IsInstanceOfType(typeof(PythonOptionsParser), parser); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CommandLineCreatedIsPythonCommandLine() |
||||||
|
{ |
||||||
|
CommandLine commandLine = host.CallCreateCommandLine(); |
||||||
|
Assert.IsInstanceOfType(typeof(PythonCommandLine), commandLine); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ConsoleCreatedIsPythonConsole() |
||||||
|
{ |
||||||
|
IConsole console = host.CallCreateConsole(null, null, null); |
||||||
|
Assert.IsInstanceOfType(typeof(PythonConsole), console); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void PythonContextIsProvider() |
||||||
|
{ |
||||||
|
Assert.AreEqual(typeof(PythonContext), host.GetProvider()); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ScriptEngineReturnedFromCreateEngine() |
||||||
|
{ |
||||||
|
Assert.AreEqual(expectedEngine, engine); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ConsoleHostImplementsIDisposable() |
||||||
|
{ |
||||||
|
Assert.IsNotNull(host as IDisposable); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When the console is disposed calling ReadLine returns null.
|
||||||
|
/// </summary>
|
||||||
|
[Test] |
||||||
|
public void HostDisposesPythonConsole() |
||||||
|
{ |
||||||
|
DerivedPythonConsoleHost host = new DerivedPythonConsoleHost(new MockTextEditor()); |
||||||
|
PythonConsole console = host.CallCreateConsole(null, null, null) as PythonConsole; |
||||||
|
host.Dispose(); |
||||||
|
|
||||||
|
Assert.IsNull(console.ReadLine(0)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Makes sure the Dispose method checks if the python console is null before trying to dispose it.
|
||||||
|
/// </summary>
|
||||||
|
[Test] |
||||||
|
public void DisposingPythonConsoleHostWithoutCreatingPythonConsole() |
||||||
|
{ |
||||||
|
PythonConsoleHost host = new PythonConsoleHost(new MockTextEditor()); |
||||||
|
host.Dispose(); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void DefaultOutputStreamReplacedByCustomStreamClass() |
||||||
|
{ |
||||||
|
Assert.IsNotNull(host.OutputStream); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,149 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Windows.Forms; |
||||||
|
|
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using Microsoft.Scripting.Hosting.Shell; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Tests that the user cannot type into read-only regions of the text editor. The
|
||||||
|
/// PythonConsole itself restricts typing itself by handling key press events.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture] |
||||||
|
public class PythonConsoleReadOnlyRegionsTestFixture |
||||||
|
{ |
||||||
|
PythonConsole console; |
||||||
|
MockTextEditor textEditor; |
||||||
|
string prompt = ">>> "; |
||||||
|
|
||||||
|
[SetUp] |
||||||
|
public void Init() |
||||||
|
{ |
||||||
|
textEditor = new MockTextEditor(); |
||||||
|
console = new PythonConsole(textEditor); |
||||||
|
console.Write(prompt, Style.Prompt); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void LeftArrowThenInsertNewCharacterInsertsText() |
||||||
|
{ |
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
textEditor.RaiseKeyPressEvent('b'); |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Left); |
||||||
|
textEditor.RaiseKeyPressEvent('c'); |
||||||
|
|
||||||
|
Assert.AreEqual("acb", console.GetCurrentLine()); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MoveOneCharacterIntoPromptTypingShouldBePrevented() |
||||||
|
{ |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Left); |
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
|
||||||
|
Assert.AreEqual(String.Empty, console.GetCurrentLine()); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MoveOneCharacterIntoPromptAndBackspaceKeyShouldNotRemoveAnything() |
||||||
|
{ |
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Left); |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Back); |
||||||
|
|
||||||
|
Assert.AreEqual("a", console.GetCurrentLine()); |
||||||
|
Assert.AreEqual(prompt + "a", textEditor.Text); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void MoveTwoCharactersIntoPromptAndBackspaceKeyShouldNotRemoveAnything() |
||||||
|
{ |
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Left); |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Left); |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Back); |
||||||
|
|
||||||
|
Assert.AreEqual("a", console.GetCurrentLine()); |
||||||
|
Assert.AreEqual(prompt + "a", textEditor.Text); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SelectLastCharacterOfPromptThenPressingTheBackspaceKeyShouldNotRemoveAnything() |
||||||
|
{ |
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
textEditor.SelectionStart = prompt.Length - 1; |
||||||
|
textEditor.SelectionLength = 2; |
||||||
|
textEditor.Column += 2; |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Back); |
||||||
|
|
||||||
|
Assert.AreEqual("a", console.GetCurrentLine()); |
||||||
|
Assert.AreEqual(prompt + "a", textEditor.Text); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CanMoveIntoPromptRegionWithLeftCursorKey() |
||||||
|
{ |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Left); |
||||||
|
Assert.IsFalse(textEditor.RaiseDialogKeyPressEvent(Keys.Left)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CanMoveOutOfPromptRegionWithRightCursorKey() |
||||||
|
{ |
||||||
|
textEditor.Column = 0; |
||||||
|
Assert.IsFalse(textEditor.RaiseDialogKeyPressEvent(Keys.Right)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CanMoveOutOfPromptRegionWithUpCursorKey() |
||||||
|
{ |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Enter); |
||||||
|
console.Write(prompt, Style.Prompt); |
||||||
|
textEditor.Column = 0; |
||||||
|
Assert.IsFalse(textEditor.RaiseDialogKeyPressEvent(Keys.Up)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CanMoveInReadOnlyRegionWithDownCursorKey() |
||||||
|
{ |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Enter); |
||||||
|
console.Write(prompt, Style.Prompt); |
||||||
|
textEditor.Column = 0; |
||||||
|
textEditor.Line = 0; |
||||||
|
Assert.IsFalse(textEditor.RaiseDialogKeyPressEvent(Keys.Down)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void BackspaceKeyPressedIgnoredIfLineIsEmpty() |
||||||
|
{ |
||||||
|
Assert.IsTrue(textEditor.RaiseDialogKeyPressEvent(Keys.Back)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void BackspaceOnPreviousLine() |
||||||
|
{ |
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
textEditor.RaiseKeyPressEvent('b'); |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Enter); |
||||||
|
|
||||||
|
console.Write(prompt, Style.Prompt); |
||||||
|
|
||||||
|
textEditor.RaiseKeyPressEvent('c'); |
||||||
|
|
||||||
|
// Move up a line with cursor.
|
||||||
|
textEditor.Line = 0; |
||||||
|
|
||||||
|
Assert.IsTrue(textEditor.RaiseDialogKeyPressEvent(Keys.Back)); |
||||||
|
Assert.AreEqual("c", console.GetCurrentLine()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,131 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Threading; |
||||||
|
using System.Windows.Forms; |
||||||
|
|
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using ICSharpCode.TextEditor.Document; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Tests the PythonConsole ReadLine method.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture] |
||||||
|
public class PythonConsoleReadTestFixture |
||||||
|
{ |
||||||
|
PythonConsole pythonConsole; |
||||||
|
int initialAutoIndentSize = 4; |
||||||
|
string readLine; |
||||||
|
int autoIndentSize; |
||||||
|
MockTextEditor mockTextEditor; |
||||||
|
bool raiseKeyPressEvent; |
||||||
|
bool raiseDialogKeyPressEvent; |
||||||
|
|
||||||
|
[TestFixtureSetUp] |
||||||
|
public void Init() |
||||||
|
{ |
||||||
|
mockTextEditor = new MockTextEditor(); |
||||||
|
pythonConsole = new PythonConsole(mockTextEditor); |
||||||
|
|
||||||
|
autoIndentSize = initialAutoIndentSize; |
||||||
|
Thread thread = new Thread(ReadLineFromConsoleOnDifferentThread); |
||||||
|
thread.Start(); |
||||||
|
|
||||||
|
int sleepInterval = 10; |
||||||
|
int maxWait = 2000; |
||||||
|
int currentWait = 0; |
||||||
|
while (mockTextEditor.Text.Length < autoIndentSize && currentWait < maxWait) { |
||||||
|
Thread.Sleep(sleepInterval); |
||||||
|
currentWait += sleepInterval; |
||||||
|
} |
||||||
|
|
||||||
|
raiseKeyPressEvent = mockTextEditor.RaiseKeyPressEvent('a'); |
||||||
|
raiseDialogKeyPressEvent = mockTextEditor.RaiseDialogKeyPressEvent(Keys.Enter); |
||||||
|
|
||||||
|
currentWait = 0; |
||||||
|
while (mockTextEditor.Text.Length < autoIndentSize + 2 && currentWait < maxWait) { |
||||||
|
Thread.Sleep(10); |
||||||
|
currentWait += sleepInterval; |
||||||
|
} |
||||||
|
thread.Join(2000); |
||||||
|
} |
||||||
|
|
||||||
|
[TestFixtureTearDown] |
||||||
|
public void TearDown() |
||||||
|
{ |
||||||
|
pythonConsole.Dispose(); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ReadLineFromConsole() |
||||||
|
{ |
||||||
|
string expectedString = String.Empty.PadLeft(initialAutoIndentSize) + "a"; |
||||||
|
Assert.AreEqual(expectedString, readLine); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void ReadLineWithNonZeroAutoIndentSizeWritesSpacesToTextEditor() |
||||||
|
{ |
||||||
|
string expectedString = String.Empty.PadLeft(initialAutoIndentSize) + "a\r\n"; |
||||||
|
Assert.AreEqual(expectedString, mockTextEditor.Text); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void DocumentInsertCalledWhenAutoIndentIsNonZero() |
||||||
|
{ |
||||||
|
Assert.IsTrue(mockTextEditor.IsWriteCalled); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void NoTextWrittenWhenAutoIndentSizeIsZero() |
||||||
|
{ |
||||||
|
MockTextEditor textEditor = new MockTextEditor(); |
||||||
|
PythonConsole console = new PythonConsole(textEditor); |
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Enter); |
||||||
|
|
||||||
|
textEditor.IsWriteCalled = false; |
||||||
|
console.ReadLine(0); |
||||||
|
Assert.IsFalse(textEditor.IsWriteCalled); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void TextEditorIndentStyleSetToNone() |
||||||
|
{ |
||||||
|
Assert.AreEqual(IndentStyle.None, mockTextEditor.IndentStyle); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should return false for any character that should be handled by the text editor itself.s
|
||||||
|
/// </summary>
|
||||||
|
[Test] |
||||||
|
public void RaiseKeyPressEventReturnedFalse() |
||||||
|
{ |
||||||
|
Assert.IsFalse(raiseKeyPressEvent); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should return false for any character that should be handled by the text editor itself.s
|
||||||
|
/// </summary>
|
||||||
|
[Test] |
||||||
|
public void RaiseDialogKeyPressEventReturnedFalse() |
||||||
|
{ |
||||||
|
Assert.IsFalse(raiseDialogKeyPressEvent); |
||||||
|
} |
||||||
|
|
||||||
|
void ReadLineFromConsoleOnDifferentThread() |
||||||
|
{ |
||||||
|
System.Console.WriteLine("Reading on different thread"); |
||||||
|
readLine = pythonConsole.ReadLine(autoIndentSize); |
||||||
|
System.Console.WriteLine("Finished reading on different thread"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Windows.Forms; |
||||||
|
|
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
using ICSharpCode.TextEditor.Document; |
||||||
|
using IronPython.Hosting; |
||||||
|
using IronPython.Runtime; |
||||||
|
using NUnit.Framework; |
||||||
|
using Microsoft.Scripting; |
||||||
|
using Microsoft.Scripting.Hosting; |
||||||
|
using Microsoft.Scripting.Hosting.Shell; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Tests the PythonConsole's GetUnreadLines method.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture] |
||||||
|
public class PythonConsoleUnreadLinesTestFixture |
||||||
|
{ |
||||||
|
PythonConsole pythonConsole; |
||||||
|
MockTextEditor textEditor; |
||||||
|
|
||||||
|
[SetUp] |
||||||
|
public void Init() |
||||||
|
{ |
||||||
|
textEditor = new MockTextEditor(); |
||||||
|
pythonConsole = new PythonConsole(textEditor); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void NoUnreadLinesAtStart() |
||||||
|
{ |
||||||
|
Assert.AreEqual(0, pythonConsole.GetUnreadLines().Length); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void HasUnreadLines() |
||||||
|
{ |
||||||
|
Assert.IsFalse(pythonConsole.IsLineAvailable); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void AddOneLine() |
||||||
|
{ |
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Enter); |
||||||
|
|
||||||
|
string[] expectedLines = new string[] {"a"}; |
||||||
|
|
||||||
|
Assert.AreEqual(expectedLines, pythonConsole.GetUnreadLines()); |
||||||
|
Assert.IsTrue(pythonConsole.IsLineAvailable); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Drawing; |
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using Microsoft.Scripting.Hosting.Shell; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Tests that the PythonConsole Write method correctly update the text editor.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture] |
||||||
|
public class PythonConsoleWriteTestFixture |
||||||
|
{ |
||||||
|
PythonConsole pythonConsole; |
||||||
|
MockTextEditor mockTextEditor; |
||||||
|
|
||||||
|
[SetUp] |
||||||
|
public void Init() |
||||||
|
{ |
||||||
|
mockTextEditor = new MockTextEditor(); |
||||||
|
mockTextEditor.Text = String.Empty; |
||||||
|
pythonConsole = new PythonConsole(mockTextEditor); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void WriteLine() |
||||||
|
{ |
||||||
|
pythonConsole.WriteLine(); |
||||||
|
Assert.AreEqual(Environment.NewLine, mockTextEditor.Text); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void WriteLineWithText() |
||||||
|
{ |
||||||
|
pythonConsole.WriteLine("test", Style.Out); |
||||||
|
Assert.AreEqual("test" + Environment.NewLine, mockTextEditor.Text); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void TwoWrites() |
||||||
|
{ |
||||||
|
pythonConsole.Write("a", Style.Out); |
||||||
|
pythonConsole.Write("b", Style.Out); |
||||||
|
Assert.AreEqual("ab", mockTextEditor.Text); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void DoesNotHasLinesWaitingToBeRead() |
||||||
|
{ |
||||||
|
Assert.IsFalse(pythonConsole.IsLineAvailable); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,68 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
[TestFixture] |
||||||
|
public class PythonOutputStreamTestFixture |
||||||
|
{ |
||||||
|
PythonOutputStream stream; |
||||||
|
MockTextEditor textEditor; |
||||||
|
|
||||||
|
[TestFixtureSetUp] |
||||||
|
public void SetUpFixture() |
||||||
|
{ |
||||||
|
textEditor = new MockTextEditor(); |
||||||
|
stream = new PythonOutputStream(textEditor); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CanReadIsFalse() |
||||||
|
{ |
||||||
|
Assert.IsFalse(stream.CanRead); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CanSeekIsFalse() |
||||||
|
{ |
||||||
|
Assert.IsFalse(stream.CanSeek); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void CanWriteIsTrue() |
||||||
|
{ |
||||||
|
Assert.IsTrue(stream.CanWrite); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void WriteAddsTextToTextEditor() |
||||||
|
{ |
||||||
|
textEditor.Text = String.Empty; |
||||||
|
byte[] bytes = UTF8Encoding.UTF8.GetBytes("test"); |
||||||
|
stream.Write(bytes, 0, bytes.Length); |
||||||
|
|
||||||
|
Assert.AreEqual("test", textEditor.Text); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void OffsetAndLengthUsedInWriteMethod() |
||||||
|
{ |
||||||
|
textEditor.Text = String.Empty; |
||||||
|
byte[] bytes = UTF8Encoding.UTF8.GetBytes("0output1"); |
||||||
|
stream.Write(bytes, 1, bytes.Length - 2); |
||||||
|
|
||||||
|
Assert.AreEqual("output", textEditor.Text); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,372 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Drawing; |
||||||
|
using System.Threading; |
||||||
|
using System.Windows.Forms; |
||||||
|
|
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
using ICSharpCode.TextEditor.Document; |
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using NUnit.Framework; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Tests the TextEditor class.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture] |
||||||
|
public class TextEditorTestFixture |
||||||
|
{ |
||||||
|
TextEditorControl textEditorControl; |
||||||
|
TextEditor textEditor; |
||||||
|
IndentStyle defaultTextEditorControlIndentStyle; |
||||||
|
IndentStyle defaultTextEditorIndentStyle; |
||||||
|
char keyPressed = ' '; |
||||||
|
Keys dialogKeyPressed; |
||||||
|
Exception indentException; |
||||||
|
Exception getLineException; |
||||||
|
string lineReadOnDifferentThread = null; |
||||||
|
|
||||||
|
[TestFixtureSetUp] |
||||||
|
public void SetUpFixture() |
||||||
|
{ |
||||||
|
textEditorControl = new TextEditorControl(); |
||||||
|
|
||||||
|
// Force creation of handle otherwise InvokeRequired always returns false.
|
||||||
|
textEditorControl.CreateControl(); |
||||||
|
|
||||||
|
textEditorControl.IndentStyle = IndentStyle.Smart; |
||||||
|
defaultTextEditorControlIndentStyle = textEditorControl.IndentStyle; |
||||||
|
|
||||||
|
textEditor = new TextEditor(textEditorControl); |
||||||
|
defaultTextEditorIndentStyle = textEditor.IndentStyle; |
||||||
|
} |
||||||
|
|
||||||
|
[TestFixtureTearDown] |
||||||
|
public void TearDownFixture() |
||||||
|
{ |
||||||
|
textEditorControl.Dispose(); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void DefaultTextEditorIndentStyleSameAsTextEditorControl() |
||||||
|
{ |
||||||
|
Assert.AreEqual(defaultTextEditorControlIndentStyle, defaultTextEditorIndentStyle); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void TextEditorImplementsITextEditorInterface() |
||||||
|
{ |
||||||
|
Assert.IsNotNull(textEditor as ITextEditor); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void IndentStyleUpdatesTextEditor() |
||||||
|
{ |
||||||
|
textEditor.IndentStyle = IndentStyle.None; |
||||||
|
Assert.AreEqual(IndentStyle.None, textEditorControl.IndentStyle); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void KeyPressEventHandlerImplemented() |
||||||
|
{ |
||||||
|
textEditor.KeyPress += ProcessKeyPress; |
||||||
|
try { |
||||||
|
textEditorControl.ActiveTextAreaControl.TextArea.SimulateKeyPress('a'); |
||||||
|
Assert.AreEqual('a', keyPressed); |
||||||
|
} finally { |
||||||
|
textEditor.KeyPress -= ProcessKeyPress; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void KeyPressEventHandlerRemoved() |
||||||
|
{ |
||||||
|
keyPressed = ' '; |
||||||
|
textEditor.KeyPress += ProcessKeyPress; |
||||||
|
textEditor.KeyPress -= ProcessKeyPress; |
||||||
|
textEditorControl.ActiveTextAreaControl.TextArea.SimulateKeyPress('b'); |
||||||
|
|
||||||
|
Assert.AreEqual(' ', keyPressed); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void DialogKeyPressEventHandlerImplemented() |
||||||
|
{ |
||||||
|
textEditor.DialogKeyPress += ProcessDialogKeyPress; |
||||||
|
try { |
||||||
|
textEditorControl.ActiveTextAreaControl.TextArea.ExecuteDialogKey(Keys.B); |
||||||
|
Assert.AreEqual(dialogKeyPressed, Keys.B); |
||||||
|
} finally { |
||||||
|
textEditor.DialogKeyPress -= ProcessDialogKeyPress; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void DialogKeyPressEventHandlerRemoved() |
||||||
|
{ |
||||||
|
dialogKeyPressed = Keys.Enter; |
||||||
|
textEditor.DialogKeyPress += ProcessDialogKeyPress; |
||||||
|
textEditor.DialogKeyPress -= ProcessDialogKeyPress; |
||||||
|
textEditorControl.ActiveTextAreaControl.TextArea.ExecuteDialogKey(Keys.Alt); |
||||||
|
|
||||||
|
Assert.AreEqual(Keys.Enter, dialogKeyPressed); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
[Ignore("Change to use read-only marker.")] |
||||||
|
public void AfterEnterKeyPreviousLineIsCustomLine() |
||||||
|
{ |
||||||
|
//textEditorControl.Document.CustomLineManager.Clear();
|
||||||
|
textEditorControl.Text = String.Empty; |
||||||
|
textEditor.Write("abc" + Environment.NewLine); |
||||||
|
//Assert.AreEqual(1, textEditorControl.Document.CustomLineManager.CustomLines.Count);
|
||||||
|
//Assert.AreEqual(textEditor.CustomLineColour, textEditorControl.Document.CustomLineManager.GetCustomColor(0, Color.Empty));
|
||||||
|
Assert.Fail("Implement..."); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void WriteMethodUpdatesTextEditor() |
||||||
|
{ |
||||||
|
textEditorControl.Document.TextContent = String.Empty; |
||||||
|
textEditor.Write("abc"); |
||||||
|
Assert.AreEqual("abc", textEditorControl.Document.TextContent); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void WriteOnDifferentThread() |
||||||
|
{ |
||||||
|
textEditorControl.Document.TextContent = String.Empty; |
||||||
|
Thread t = new Thread(WriteText); |
||||||
|
t.Start(); |
||||||
|
|
||||||
|
// Make sure the GUI events are processed otherwise the
|
||||||
|
// unit test will never complete.
|
||||||
|
int maxWait = 2000; |
||||||
|
int currentWait = 0; |
||||||
|
int sleepInterval = 50; |
||||||
|
Application.DoEvents(); |
||||||
|
while (textEditorControl.Text.Length == 0 && (currentWait < maxWait)) { |
||||||
|
Application.DoEvents(); |
||||||
|
Thread.Sleep(sleepInterval); |
||||||
|
currentWait += sleepInterval; |
||||||
|
} |
||||||
|
|
||||||
|
// Wait for thread to finish.
|
||||||
|
t.Join(); |
||||||
|
|
||||||
|
Assert.AreEqual("test", textEditorControl.Text); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SetIndentStyleOnDifferentThread() |
||||||
|
{ |
||||||
|
textEditorControl.IndentStyle = IndentStyle.Auto; |
||||||
|
Thread t = new Thread(SetIndentStyle); |
||||||
|
t.Start(); |
||||||
|
|
||||||
|
// Make sure the GUI events are processed otherwise the
|
||||||
|
// unit test will never complete.
|
||||||
|
int maxWait = 2000; |
||||||
|
int currentWait = 0; |
||||||
|
int sleepInterval = 50; |
||||||
|
Application.DoEvents(); |
||||||
|
while (textEditorControl.IndentStyle == IndentStyle.Auto && (currentWait < maxWait)) { |
||||||
|
Application.DoEvents(); |
||||||
|
Thread.Sleep(sleepInterval); |
||||||
|
currentWait += sleepInterval; |
||||||
|
} |
||||||
|
|
||||||
|
// Wait for thread to finish.
|
||||||
|
t.Join(); |
||||||
|
|
||||||
|
string message = String.Empty; |
||||||
|
if (indentException != null) { |
||||||
|
message = indentException.ToString(); |
||||||
|
} |
||||||
|
Assert.IsNull(indentException, message); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void GetColumnPosition() |
||||||
|
{ |
||||||
|
textEditorControl.Document.TextContent = "test"; |
||||||
|
textEditorControl.ActiveTextAreaControl.TextArea.Caret.Column = 2; |
||||||
|
|
||||||
|
Assert.AreEqual(2, textEditor.Column); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SetColumnPosition() |
||||||
|
{ |
||||||
|
textEditorControl.Document.TextContent = "test"; |
||||||
|
textEditorControl.ActiveTextAreaControl.TextArea.Caret.Column = 2; |
||||||
|
|
||||||
|
textEditor.Column = 1; |
||||||
|
Assert.AreEqual(1, textEditorControl.ActiveTextAreaControl.TextArea.Caret.Column); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void GetSelectionStartAndLength() |
||||||
|
{ |
||||||
|
textEditorControl.Document.TextContent = "te000xt"; |
||||||
|
TextLocation start = new TextLocation(2, 0); |
||||||
|
TextLocation end = new TextLocation(5, 0); |
||||||
|
textEditorControl.ActiveTextAreaControl.SelectionManager.SetSelection(start, end); |
||||||
|
|
||||||
|
// Sanity check.
|
||||||
|
Assert.AreEqual("000", textEditorControl.ActiveTextAreaControl.SelectionManager.SelectedText); |
||||||
|
|
||||||
|
Assert.AreEqual(2, textEditor.SelectionStart); |
||||||
|
Assert.AreEqual(3, textEditor.SelectionLength); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void GetSelectionStartAndLengthWhenNothingSelected() |
||||||
|
{ |
||||||
|
textEditorControl.Document.TextContent = "text"; |
||||||
|
textEditorControl.ActiveTextAreaControl.SelectionManager.ClearSelection(); |
||||||
|
textEditorControl.ActiveTextAreaControl.Caret.Column = 1; |
||||||
|
|
||||||
|
Assert.AreEqual(1, textEditor.SelectionStart); |
||||||
|
Assert.AreEqual(0, textEditor.SelectionLength); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void TextEditorLineEqualsCaretLine() |
||||||
|
{ |
||||||
|
textEditorControl.Document.TextContent = "abc\r\ndef"; |
||||||
|
textEditorControl.ActiveTextAreaControl.Caret.Line = 0; |
||||||
|
|
||||||
|
Assert.AreEqual(0, textEditor.Line); |
||||||
|
|
||||||
|
textEditorControl.ActiveTextAreaControl.Caret.Line = 1; |
||||||
|
Assert.AreEqual(1, textEditor.Line); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void TextEditorTotalLines() |
||||||
|
{ |
||||||
|
textEditorControl.Document.TextContent = "abc\r\ndef\r\nghi"; |
||||||
|
Assert.AreEqual(3, textEditor.TotalLines); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void GetFirstLine() |
||||||
|
{ |
||||||
|
textEditorControl.Document.TextContent = "abc\r\ndef\r\nghi"; |
||||||
|
Assert.AreEqual("abc", textEditor.GetLine(0)); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void GetLineOnDifferentThread() |
||||||
|
{ |
||||||
|
textEditorControl.IndentStyle = IndentStyle.Auto; |
||||||
|
Thread t = new Thread(GetLine); |
||||||
|
t.Start(); |
||||||
|
|
||||||
|
// Make sure the GUI events are processed otherwise the
|
||||||
|
// unit test will never complete.
|
||||||
|
int maxWait = 2000; |
||||||
|
int currentWait = 0; |
||||||
|
int sleepInterval = 50; |
||||||
|
Application.DoEvents(); |
||||||
|
while (lineReadOnDifferentThread == null && (currentWait < maxWait)) { |
||||||
|
Application.DoEvents(); |
||||||
|
Thread.Sleep(sleepInterval); |
||||||
|
currentWait += sleepInterval; |
||||||
|
} |
||||||
|
|
||||||
|
// Wait for thread to finish.
|
||||||
|
t.Join(); |
||||||
|
|
||||||
|
string message = String.Empty; |
||||||
|
if (getLineException != null) { |
||||||
|
message = getLineException.ToString(); |
||||||
|
} |
||||||
|
Assert.IsNull(getLineException, message); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void WriteTextWithBackgroundColour() |
||||||
|
{ |
||||||
|
textEditorControl.Document.TextContent = "abc\r\n>>>"; |
||||||
|
textEditorControl.ActiveTextAreaControl.Caret.Line = 1; |
||||||
|
textEditor.Write(">>> ", Color.Blue); |
||||||
|
|
||||||
|
int offset = textEditorControl.Document.PositionToOffset(new TextLocation(0, 1)); |
||||||
|
List<TextMarker> markers = textEditorControl.Document.MarkerStrategy.GetMarkers(offset); |
||||||
|
TextMarker marker = markers[0]; |
||||||
|
Assert.AreEqual(Color.Blue, marker.Color); |
||||||
|
Assert.AreEqual(TextMarkerType.SolidBlock, marker.TextMarkerType); |
||||||
|
Assert.AreEqual(4, marker.Length); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SupportReadOnlySegmentsIsTrue() |
||||||
|
{ |
||||||
|
Assert.IsTrue(textEditorControl.TextEditorProperties.SupportReadOnlySegments); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Run on different thread to set the text editor's indent style.
|
||||||
|
/// </summary>
|
||||||
|
void SetIndentStyle() |
||||||
|
{ |
||||||
|
try { |
||||||
|
textEditor.IndentStyle = IndentStyle.None; |
||||||
|
} catch (Exception ex) { |
||||||
|
indentException = ex; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Run on different thread to set the text editor's indent style.
|
||||||
|
/// </summary>
|
||||||
|
void GetLine() |
||||||
|
{ |
||||||
|
try { |
||||||
|
lineReadOnDifferentThread = textEditor.GetLine(0); |
||||||
|
} catch (Exception ex) { |
||||||
|
getLineException = ex; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Run on different thread to write text to the text editor.
|
||||||
|
/// </summary>
|
||||||
|
void WriteText() |
||||||
|
{ |
||||||
|
try { |
||||||
|
textEditor.Write("test"); |
||||||
|
} catch (Exception ex) { |
||||||
|
System.Console.WriteLine("WriteText error: " + ex.ToString()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event handler for the text editor's DialogKeyPress event.
|
||||||
|
/// </summary>
|
||||||
|
bool ProcessDialogKeyPress(Keys keysData) |
||||||
|
{ |
||||||
|
dialogKeyPressed = keysData; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event handler for the text editor's KeyPress event.
|
||||||
|
/// </summary>
|
||||||
|
bool ProcessKeyPress(char ch) |
||||||
|
{ |
||||||
|
keyPressed = ch; |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,108 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Matthew Ward" email="mrward@users.sourceforge.net"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Threading; |
||||||
|
using System.Windows.Forms; |
||||||
|
|
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
using ICSharpCode.TextEditor.Document; |
||||||
|
using IronPython.Hosting; |
||||||
|
using IronPython.Runtime; |
||||||
|
using NUnit.Framework; |
||||||
|
using Microsoft.Scripting; |
||||||
|
using Microsoft.Scripting.Hosting; |
||||||
|
using Microsoft.Scripting.Hosting.Shell; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Console |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Ensures that both lines of text can be read from the python console if they are written
|
||||||
|
/// before ReadLine is called.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture] |
||||||
|
public class TwoPythonConsoleLinesWaitingTestFixture |
||||||
|
{ |
||||||
|
string line1; |
||||||
|
string line2; |
||||||
|
PythonConsole pythonConsole; |
||||||
|
bool lineAvailableBeforeFirstEnterKey; |
||||||
|
bool lineAvailableAfterFirstEnterKey; |
||||||
|
bool lineAvailableAtEnd; |
||||||
|
|
||||||
|
[TestFixtureSetUp] |
||||||
|
public void SetUpFixture() |
||||||
|
{ |
||||||
|
MockTextEditor textEditor = new MockTextEditor(); |
||||||
|
using (pythonConsole = new PythonConsole(textEditor)) { |
||||||
|
|
||||||
|
textEditor.RaiseKeyPressEvent('a'); |
||||||
|
textEditor.RaiseKeyPressEvent('='); |
||||||
|
textEditor.RaiseKeyPressEvent('1'); |
||||||
|
lineAvailableBeforeFirstEnterKey = pythonConsole.IsLineAvailable; |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Enter); |
||||||
|
lineAvailableAfterFirstEnterKey = pythonConsole.IsLineAvailable; |
||||||
|
|
||||||
|
textEditor.RaiseKeyPressEvent('b'); |
||||||
|
textEditor.RaiseKeyPressEvent('='); |
||||||
|
textEditor.RaiseKeyPressEvent('2'); |
||||||
|
textEditor.RaiseDialogKeyPressEvent(Keys.Enter); |
||||||
|
|
||||||
|
Thread t = new Thread(ReadLinesOnSeparateThread); |
||||||
|
t.Start(); |
||||||
|
|
||||||
|
int sleepInterval = 20; |
||||||
|
int currentWait = 0; |
||||||
|
int maxWait = 2000; |
||||||
|
|
||||||
|
while (line2 == null && currentWait < maxWait) { |
||||||
|
Thread.Sleep(sleepInterval); |
||||||
|
currentWait += sleepInterval; |
||||||
|
} |
||||||
|
|
||||||
|
lineAvailableAtEnd = pythonConsole.IsLineAvailable; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void FirstLineRead() |
||||||
|
{ |
||||||
|
Assert.AreEqual("a=1", line1); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void SecondLineRead() |
||||||
|
{ |
||||||
|
Assert.AreEqual("b=2", line2); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void LineAvailableBeforeEnterKeyPressed() |
||||||
|
{ |
||||||
|
Assert.IsFalse(lineAvailableBeforeFirstEnterKey); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void LineAvailableAfterEnterKeyPressed() |
||||||
|
{ |
||||||
|
Assert.IsTrue(lineAvailableAfterFirstEnterKey); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void LineAvailableAfterAllLinesRead() |
||||||
|
{ |
||||||
|
Assert.IsFalse(lineAvailableAtEnd); |
||||||
|
} |
||||||
|
|
||||||
|
void ReadLinesOnSeparateThread() |
||||||
|
{ |
||||||
|
line1 = pythonConsole.ReadLine(0); |
||||||
|
line2 = pythonConsole.ReadLine(0); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue