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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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