[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