[IronPython] Using an IronPython console with a Winforms component supporting the interactive I/O

Dino Viehland dinov at exchange.microsoft.com
Thu Apr 27 05:20:56 CEST 2006


You're on the right track.  You'll probably want to create a seperate thread for the PythonEngine to run on, and then whenever you get a write to your stream you can just do a Control.Invoke onto your UI thread to update the current output.

I was playing around w/ this around the 0.9.4 time-frame and came up w/ the code below.  This is a little old and I haven't looked at it in some time so there's no guarantees but maybe it'll help clarify things.  It also doesn't sound like it's quite what you want (I was doing seperate windows for input/output), but it shouldn't be hard to get both going in the same text box.

Good luck!






    class StreamToTextBox : Stream {
        RichTextBox _textBox;
        Color _targetColor;
        public StreamToTextBox(RichTextBox textBox, Color color) {
            _textBox = textBox;
            _targetColor = color;
        }
        public override void Write(byte[] buffer, int offset, int count) {
            string text = System.Text.Encoding.ASCII.GetString(buffer, offset, count);
            text.Replace("\r", "\r\n");
            _textBox.BeginInvoke((System.Threading.ThreadStart)delegate() {
                _textBox.AppendText(text);
                _textBox.Select(_textBox.Text.Length-text.Length, text.Length);
                _textBox.SelectionColor = _targetColor;
                _textBox.Select(_textBox.Text.Length-1,0);
                _textBox.ScrollToCaret();
            });
        }
        // rest is uninteresting ...
  }

    class StreamReaderToTextBox : Stream {
        TextBox _textBox;
        Queue<string> _pendingStrings;
        string _pendingStr;
        object _lockObj = new object();
        public StreamReaderToTextBox(TextBox textBox) {
            _textBox = textBox;
            _textBox.KeyDown += new KeyEventHandler(_textBox_KeyDown);
            _pendingStrings = new Queue<string>();
        }
        /// <summary>
        /// Called on UI thread
        /// </summary>
        void _textBox_KeyDown(object sender, KeyEventArgs e) {
            if (e.KeyData == Keys.Enter) {
                e.Handled = true;
                e.SuppressKeyPress = true;
                // read the text
                lock (_lockObj) {
                    _pendingStrings.Enqueue(_textBox.Text);
                    Monitor.Pulse(_lockObj);
                }

                _textBox.Text = null;
            }
        }
        /// <summary>
        /// Must be called on non-UI thread!
        /// </summary>
        public override int Read(byte[] buffer, int offset, int count) {
            string s;
            _textBox.BeginInvoke((ThreadStart)delegate() {
                _textBox.Visible = true;
            });
            lock (_lockObj) {
                while (_pendingStrings.Count == 0 && _pendingStr == null) {
                    Monitor.Wait(_lockObj);
                }
                s = (_pendingStr != null) ? _pendingStr : _pendingStrings.Dequeue();
                _pendingStr = null;
            }
            int i = offset, curIndex = 0;
            for (; i < offset + count; i++, curIndex++) {
                if (curIndex == s.Length) {
                    buffer[i] = (byte)'\n';
                    i++;
                    _textBox.BeginInvoke((ThreadStart)delegate() {
                        _textBox.Visible = false;
                    });
                    return i - offset;
                }
                buffer[i] = (byte)s[curIndex];
            }
            if (curIndex != s.Length) {
                _pendingStr = s.Substring(curIndex);
            }
            _textBox.Visible = false;
            return i - offset;
        }
  }
________________________________________
From: users-bounces at lists.ironpython.com On Behalf Of Jean-Michel.Perraud at csiro.au
Sent: Tuesday, April 25, 2006 9:15 PM
To: users at lists.ironpython.com
Subject: [IronPython] Using an IronPython console with a Winforms component     supporting the interactive I/O

Hi,

I'd like to use IP in an interactive mode, but with the console being
typically in an MDI child form that can be launched from the main
application. After looking at a few possiblities I thought I should
start from the SuperConsole or BasicConsole distributed with IP, and
replace the System.Console with "some reusable code" with I/O streams
redirected to/from a Winforms text-related control.

Has anyone done that or something similar, or has links to relevant
information? After 'googling' quite a bit, surprisingly I did not find
much in the way of a Windows-based shell implementation doing the
aforementioned. The closets (and niftiest) example I saw was the
IronPython console sample in the latest preview Visual Studio SDK, but
I'd really like it not to depend at all on the SDK API, so this makes it
hard to reuse it without significant re-write.

I don't deal often with console-based approaches, so bear with me if I
missed something you think is obvious...

Cheers,
J-M
_______________________________________________
users mailing list
users at lists.ironpython.com
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com



More information about the Ironpython-users mailing list