[mapguide-commits] r8539 - in trunk/Tools/Maestro: Maestro.AddIn.Scripting/Lang/Python Thirdparty/SharpDevelop/ICSharpCode.TextEditor/Src/Document/LineManager
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Wed Feb 11 04:55:33 PST 2015
Author: jng
Date: 2015-02-11 04:55:33 -0800 (Wed, 11 Feb 2015)
New Revision: 8539
Modified:
trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonConsole.cs
trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonConsoleHost.cs
trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonOutputStream.cs
trunk/Tools/Maestro/Thirdparty/SharpDevelop/ICSharpCode.TextEditor/Src/Document/LineManager/LineManager.cs
Log:
#2537: Add support for reading input from stdin via input() and raw_input() from the Maestro IronPython console
Modified: trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonConsole.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonConsole.cs 2015-02-10 08:06:33 UTC (rev 8538)
+++ trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonConsole.cs 2015-02-11 12:55:33 UTC (rev 8539)
@@ -38,8 +38,10 @@
using Microsoft.Scripting.Hosting.Shell;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Drawing;
using System.IO;
+using System.Text;
using System.Threading;
using System.Windows.Forms;
@@ -49,6 +51,7 @@
{
private ITextEditor textEditor;
private int lineReceivedEventIndex = 0; // The index into the waitHandles array where the lineReceivedEvent is stored.
+ private ManualResetEvent inputLineReceivedEvent = new ManualResetEvent(false);
private ManualResetEvent lineReceivedEvent = new ManualResetEvent(false);
private ManualResetEvent disposedEvent = new ManualResetEvent(false);
private WaitHandle[] waitHandles;
@@ -59,8 +62,11 @@
public CommandLine CommandLine { get { return this.commandLine; } }
- public PythonConsole(ITextEditor textEditor, CommandLine commandLine)
+ private IConsoleLineHook _hook;
+
+ public PythonConsole(ITextEditor textEditor, CommandLine commandLine, IConsoleLineHook hook)
{
+ _hook = hook;
waitHandles = new WaitHandle[] { lineReceivedEvent, disposedEvent };
this.commandLine = commandLine;
@@ -83,16 +89,12 @@
{
get
{
-#if DEBUG
- Console.WriteLine("PythonConsole.Output get");
-#endif
+ Debug.WriteLine("PythonConsole.Output get");
return null;
}
set
{
-#if DEBUG
- Console.WriteLine("PythonConsole.Output set");
-#endif
+ Debug.WriteLine("PythonConsole.Output set");
}
}
@@ -100,16 +102,12 @@
{
get
{
-#if DEBUG
- Console.WriteLine("PythonConsole.ErrorOutput get");
-#endif
+ Debug.WriteLine("PythonConsole.ErrorOutput get");
return null;
}
set
{
-#if DEBUG
- Console.WriteLine("PythonConsole.ErrorOutput get");
-#endif
+ Debug.WriteLine("PythonConsole.ErrorOutput get");
}
}
@@ -132,9 +130,7 @@
/// </summary>
public string ReadLine(int autoIndentSize)
{
-#if DEBUG
- Console.WriteLine("PythonConsole.ReadLine(): autoIndentSize: " + autoIndentSize);
-#endif
+ Debug.WriteLine("PythonConsole.ReadLine(): autoIndentSize: " + autoIndentSize);
string indent = String.Empty;
if (autoIndentSize > 0)
{
@@ -145,9 +141,7 @@
string line = ReadLineFromTextEditor();
if (line != null)
{
-#if DEBUG
- Console.WriteLine("ReadLine: " + indent + line);
-#endif
+ Debug.WriteLine("ReadLine: " + indent + line);
return indent + line;
}
return null;
@@ -160,9 +154,7 @@
/// </summary>
public void Write(string text, Style style)
{
-#if DEBUG
- Console.WriteLine("PythonConsole.Write(text, style): " + text);
-#endif
+ Debug.WriteLine("PythonConsole.Write(text, style): " + text);
if (style == Style.Error)
textEditor.Write(text, Color.Red, Color.White);
else if (style == Style.Warning)
@@ -238,17 +230,65 @@
return textEditor.GetLine(textEditor.TotalLines - 1);
}
+ private readonly object _syncInput = new object();
+ private bool _IsReadingInput;
+
+ internal bool IsReadingInput
+ {
+ get
+ {
+ lock (_syncInput)
+ return _IsReadingInput;
+ }
+ set
+ {
+ lock (_syncInput)
+ {
+ _IsReadingInput = value;
+ Debug.WriteLine("({0}): IsReadingInput: {1}", Thread.CurrentThread.ManagedThreadId, value);
+ if (!value)
+ {
+ Debug.WriteLine("({0}): IsReadingInput - Reset line received event", Thread.CurrentThread.ManagedThreadId);
+ inputLineReceivedEvent.Reset();
+ }
+ }
+ }
+ }
+
+ private string _inputLine;
+
+ internal string GetLineForInput(string lastWrittenLine)
+ {
+ Debug.WriteLine(string.Format("({0}): GetLineForInput() - BEGIN", Thread.CurrentThread.ManagedThreadId));
+ inputLineReceivedEvent.WaitOne();
+ Debug.WriteLine("({0}): GetLineForInput() - {1}", Thread.CurrentThread.ManagedThreadId, _inputLine);
+ string lineInput = null;
+ if (_inputLine != null)
+ {
+ lineInput = _inputLine.Substring(lastWrittenLine.Substring(promptLength).Length);
+ _inputLine = null;
+ }
+ this.IsReadingInput = false;
+ return lineInput;
+ }
+
+
+
private string ReadLineFromTextEditor()
{
+ Debug.WriteLine(string.Format("({0}): ReadLineFromTextEditor()", Thread.CurrentThread.ManagedThreadId));
+ _hook.OnBeginWaitForNextLine();
int result = WaitHandle.WaitAny(waitHandles);
if (result == lineReceivedEventIndex)
{
+ Debug.WriteLine(string.Format("({0}): Received line", Thread.CurrentThread.ManagedThreadId));
lock (previousLines)
{
string line = previousLines[0];
previousLines.RemoveAt(0);
if (previousLines.Count == 0)
{
+ Debug.WriteLine(string.Format("({0}): ReadLineFromTextEditor - Reset line received event", Thread.CurrentThread.ManagedThreadId));
lineReceivedEvent.Reset();
}
return line;
@@ -266,7 +306,7 @@
{
return true;
}
-
+
if (ch == '\n')
{
OnEnterKeyPressed();
@@ -332,6 +372,7 @@
/// </summary>
private void OnEnterKeyPressed()
{
+ Debug.WriteLine(string.Format("({0}): OnEnterKeyPressed", Thread.CurrentThread.ManagedThreadId));
lock (previousLines)
{
// Move cursor to the end of the line.
@@ -339,10 +380,21 @@
// Append line.
string currentLine = GetCurrentLine();
- previousLines.Add(currentLine);
- commandLineHistory.Add(currentLine);
- lineReceivedEvent.Set();
+ if (IsReadingInput)
+ {
+ _inputLine = currentLine;
+ Debug.WriteLine(string.Format("({0}): Set input line received event", Thread.CurrentThread.ManagedThreadId));
+ inputLineReceivedEvent.Set();
+ }
+ else
+ {
+ previousLines.Add(currentLine);
+ commandLineHistory.Add(currentLine);
+
+ Debug.WriteLine(string.Format("({0}): Set line received event", Thread.CurrentThread.ManagedThreadId));
+ lineReceivedEvent.Set();
+ }
}
}
Modified: trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonConsoleHost.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonConsoleHost.cs 2015-02-10 08:06:33 UTC (rev 8538)
+++ trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonConsoleHost.cs 2015-02-11 12:55:33 UTC (rev 8539)
@@ -45,10 +45,15 @@
namespace Maestro.AddIn.Scripting.Lang.Python
{
+ internal interface IConsoleLineHook
+ {
+ void OnBeginWaitForNextLine();
+ }
+
/// <summary>
/// Hosts the python console.
/// </summary>
- internal class PythonConsoleHost : ConsoleHost, IDisposable
+ internal class PythonConsoleHost : ConsoleHost, IDisposable, IConsoleLineHook
{
private Thread thread;
private ITextEditor textEditor;
@@ -134,16 +139,26 @@
/// </remarks>
protected override IConsole CreateConsole(ScriptEngine engine, CommandLine commandLine, ConsoleOptions options)
{
- SetOutput(new PythonOutputStream(textEditor));
- pythonConsole = new PythonConsole(textEditor, commandLine);
+ pythonConsole = new PythonConsole(textEditor, commandLine, this);
+ SetScriptStream(new PythonOutputStream(pythonConsole, textEditor));
return pythonConsole;
}
- protected virtual void SetOutput(PythonOutputStream stream)
+ private PythonOutputStream _pyStream;
+
+ void IConsoleLineHook.OnBeginWaitForNextLine()
{
- Runtime.IO.SetOutput(stream, Encoding.UTF8);
+ if (_pyStream != null)
+ _pyStream.DoneReadingForNow = false;
}
+ protected virtual void SetScriptStream(PythonOutputStream stream)
+ {
+ _pyStream = stream;
+ Runtime.IO.SetInput(_pyStream, Encoding.UTF8);
+ Runtime.IO.SetOutput(_pyStream, Encoding.UTF8);
+ }
+
/// <summary>
/// Runs the console.
/// </summary>
Modified: trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonOutputStream.cs
===================================================================
--- trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonOutputStream.cs 2015-02-10 08:06:33 UTC (rev 8538)
+++ trunk/Tools/Maestro/Maestro.AddIn.Scripting/Lang/Python/PythonOutputStream.cs 2015-02-11 12:55:33 UTC (rev 8539)
@@ -33,23 +33,28 @@
#endregion Disclaimer / License
using Maestro.Editors.Common;
+using System.Diagnostics;
using System.IO;
using System.Text;
+using System.Threading;
+using System.Windows.Forms;
namespace Maestro.AddIn.Scripting.Lang.Python
{
internal class PythonOutputStream : Stream
{
+ private PythonConsole _console;
private ITextEditor textEditor;
- public PythonOutputStream(ITextEditor textEditor)
+ public PythonOutputStream(PythonConsole console, ITextEditor textEditor)
{
+ _console = console;
this.textEditor = textEditor;
}
public override bool CanRead
{
- get { return false; }
+ get { return true; }
}
public override bool CanSeek
@@ -86,17 +91,53 @@
{
}
+ /// <summary>
+ /// This is a control flag to determine if the read stream should end. Set to true to signal end of stream when
+ /// the next line is received. Set to false to signal that reading the next line should start or continue
+ /// </summary>
+ public bool DoneReadingForNow
+ {
+ get;
+ set;
+ }
+
public override int Read(byte[] buffer, int offset, int count)
{
- return 0;
+ if (this.DoneReadingForNow)
+ return 0;
+
+ Debug.WriteLine("({0}): PythonOutputStream.Read() - buffer: {1}, offset: {2}, count: {3}, currently reading: {4}", Thread.CurrentThread.ManagedThreadId, buffer.Length, offset, count, _console.IsReadingInput);
+ _console.IsReadingInput = true;
+ int read = 0;
+ string line = _console.GetLineForInput(_lastWrittenText);
+ if (line != null)
+ {
+ using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(line)))
+ {
+ read = ms.Read(buffer, offset, count);
+ }
+ _lastCapturedText = line;
+ }
+ else
+ {
+ this.DoneReadingForNow = false;
+ return 0;
+ }
+ Debug.WriteLine("({0}): PythonOutputStream.Read() read {1} bytes", Thread.CurrentThread.ManagedThreadId, read);
+ this.DoneReadingForNow = true;
+ return read;
}
+ private string _lastCapturedText;
+ private string _lastWrittenText;
+
/// <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);
+ _lastWrittenText = text;
textEditor.Write(text);
}
}
Modified: trunk/Tools/Maestro/Thirdparty/SharpDevelop/ICSharpCode.TextEditor/Src/Document/LineManager/LineManager.cs
===================================================================
--- trunk/Tools/Maestro/Thirdparty/SharpDevelop/ICSharpCode.TextEditor/Src/Document/LineManager/LineManager.cs 2015-02-10 08:06:33 UTC (rev 8538)
+++ trunk/Tools/Maestro/Thirdparty/SharpDevelop/ICSharpCode.TextEditor/Src/Document/LineManager/LineManager.cs 2015-02-11 12:55:33 UTC (rev 8539)
@@ -77,7 +77,7 @@
public void Replace(int offset, int length, string text)
{
- Debug.WriteLine("Replace offset="+offset+" length="+length+" text.Length="+text.Length);
+ //Debug.WriteLine("Replace offset="+offset+" length="+length+" text.Length="+text.Length);
int lineStart = GetLineNumberForOffset(offset);
int oldNumberOfLines = this.TotalNumberOfLines;
DeferredEventList deferredEventList = new DeferredEventList();
More information about the mapguide-commits
mailing list