Browse Source

Added basic command line history support for the Python Console window.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3627 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Matt Ward 17 years ago
parent
commit
08a7425771
  1. 1
      src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj
  2. 77
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/CommandLineHistory.cs
  3. 5
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/ITextEditor.cs
  4. 41
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConsole.cs
  5. 12
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/TextEditor.cs
  6. 68
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/CommandLineHistoryTestFixture.cs
  7. 46
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/EmptyCommandLineHistoryTestFixture.cs
  8. 6
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/MockTextEditor.cs
  9. 113
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/OneItemCommandLineHistoryTestFixture.cs
  10. 93
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/PythonConsoleCommandLineHistoryTestFixture.cs
  11. 10
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/TextEditorTestFixture.cs
  12. 4
      src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj

1
src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj

@ -62,6 +62,7 @@ @@ -62,6 +62,7 @@
<Compile Include="..\..\..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>Configuration\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Src\CommandLineHistory.cs" />
<Compile Include="Src\ConvertToPythonMenuCommand.cs" />
<Compile Include="Src\ApplicationSettingsPanel.cs" />
<Compile Include="Configuration\AssemblyInfo.cs" />

77
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/CommandLineHistory.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
// <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;
namespace ICSharpCode.PythonBinding
{
/// <summary>
/// Stores the command line history for the PythonConsole.
/// </summary>
public class CommandLineHistory
{
List<string> lines = new List<string>();
int position = -1;
public CommandLineHistory()
{
}
/// <summary>
/// Adds the command line to the history.
/// </summary>
public void Add(string line)
{
if (!String.IsNullOrEmpty(line)) {
int index = lines.Count - 1;
if (index >= 0) {
if (lines[index] != line) {
lines.Add(line);
}
} else {
lines.Add(line);
}
}
position = lines.Count;
}
/// <summary>
/// Gets the current command line. By default this will be the last command line entered.
/// </summary>
public string Current {
get {
if ((position >= 0) && (position < lines.Count)) {
return lines[position];
}
return null;
}
}
/// <summary>
/// Moves to the next command line.
/// </summary>
public bool MoveNext()
{
if (position < lines.Count) {
++position;
}
return position < lines.Count;
}
/// <summary>
/// Moves to the previous command line.
/// </summary>
public bool MovePrevious()
{
if (position >= 0) {
--position;
}
return position >= 0;
}
}
}

5
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/ITextEditor.cs

@ -54,6 +54,11 @@ namespace ICSharpCode.PythonBinding @@ -54,6 +54,11 @@ namespace ICSharpCode.PythonBinding
/// </summary>
void Write(string text, Color backgroundColor);
/// <summary>
/// Replaces the text at the specified index on the current line with the specified text.
/// </summary>
void Replace(int index, int length, string text);
/// <summary>
/// Gets or sets the current column position of the cursor on the current line. This is zero based.
/// </summary>

41
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConsole.cs

@ -29,6 +29,7 @@ namespace ICSharpCode.PythonBinding @@ -29,6 +29,7 @@ namespace ICSharpCode.PythonBinding
int promptLength;
List<string> previousLines = new List<string>();
CommandLine commandLine;
CommandLineHistory commandLineHistory = new CommandLineHistory();
public PythonConsole(ITextEditor textEditor, CommandLine commandLine)
{
@ -229,6 +230,12 @@ namespace ICSharpCode.PythonBinding @@ -229,6 +230,12 @@ namespace ICSharpCode.PythonBinding
case Keys.Home:
MoveToHomePosition();
return true;
case Keys.Down:
MoveToNextCommandLine();
return true;
case Keys.Up:
MoveToPreviousCommandLine();
return true;
}
return false;
}
@ -245,6 +252,8 @@ namespace ICSharpCode.PythonBinding @@ -245,6 +252,8 @@ namespace ICSharpCode.PythonBinding
// Append line.
string currentLine = GetCurrentLine();
previousLines.Add(currentLine);
commandLineHistory.Add(currentLine);
lineReceivedEvent.Set();
}
}
@ -294,5 +303,37 @@ namespace ICSharpCode.PythonBinding @@ -294,5 +303,37 @@ namespace ICSharpCode.PythonBinding
{
textEditor.Column = promptLength;
}
/// <summary>
/// Shows the previous command line in the command line history.
/// </summary>
void MoveToPreviousCommandLine()
{
if (commandLineHistory.MovePrevious()) {
ReplaceCurrentLineTextAfterPrompt(commandLineHistory.Current);
}
}
/// <summary>
/// Shows the next command line in the command line history.
/// </summary>
void MoveToNextCommandLine()
{
if (commandLineHistory.MoveNext()) {
ReplaceCurrentLineTextAfterPrompt(commandLineHistory.Current);
}
}
/// <summary>
/// Replaces the current line text after the prompt with the specified text.
/// </summary>
void ReplaceCurrentLineTextAfterPrompt(string text)
{
string currentLine = GetCurrentLine();
textEditor.Replace(promptLength, currentLine.Length, text);
// Put cursor at end.
textEditor.Column = promptLength + text.Length;
}
}
}

12
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/TextEditor.cs

@ -123,7 +123,17 @@ namespace ICSharpCode.PythonBinding @@ -123,7 +123,17 @@ namespace ICSharpCode.PythonBinding
return textEditorControl.Document.GetText(lineSegment);
}
}
/// <summary>
/// Replaces the text at the specified index on the current line with the specified text.
/// </summary>
public void Replace(int index, int length, string text)
{
int currentLine = textEditorControl.ActiveTextAreaControl.Caret.Line;
LineSegment lineSegment = textEditorControl.Document.GetLineSegment(currentLine);
textEditorControl.Document.Replace(lineSegment.Offset + index, length, text);
}
/// <summary>
/// Makes the current text read only. Text can still be entered at the end.
/// </summary>

68
src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/CommandLineHistoryTestFixture.cs

@ -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 ICSharpCode.PythonBinding;
using NUnit.Framework;
namespace PythonBinding.Tests.Console
{
/// <summary>
/// Tests the CommandLineHistory class.
/// </summary>
[TestFixture]
public class CommandLineHistoryTestFixture
{
CommandLineHistory history;
[SetUp]
public void Init()
{
history = new CommandLineHistory();
history.Add("a");
history.Add("b");
history.Add("c");
}
[Test]
public void LastCommandLineIsNull()
{
Assert.IsNull(history.Current);
}
[Test]
public void MovePreviousOnce()
{
Assert.IsTrue(history.MovePrevious());
}
[Test]
public void CurrentAfterMovePrevious()
{
history.MovePrevious();
Assert.AreEqual("c", history.Current);
}
[Test]
public void AddLineAfterMovePrevious()
{
history.MovePrevious();
history.MovePrevious();
history.Add("d");
Assert.IsNull(history.Current);
}
[Test]
public void EmptyLineIgnored()
{
history.Add(String.Empty);
history.MovePrevious();
Assert.AreEqual("c", history.Current);
}
}
}

46
src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/EmptyCommandLineHistoryTestFixture.cs

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
// <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 CommandLineHistory class.
/// </summary>
[TestFixture]
public class EmptyCommandLineHistoryTestFixture
{
CommandLineHistory history;
[SetUp]
public void Init()
{
history = new CommandLineHistory();
}
[Test]
public void CurrentCommandLineIsNull()
{
Assert.IsNull(history.Current);
}
[Test]
public void MoveNextReturnsFalse()
{
Assert.IsFalse(history.MoveNext());
}
[Test]
public void MovePreviousReturnsFalse()
{
Assert.IsFalse(history.MovePrevious());
}
}
}

6
src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/MockTextEditor.cs

@ -201,6 +201,12 @@ namespace PythonBinding.Tests.Console @@ -201,6 +201,12 @@ namespace PythonBinding.Tests.Console
return "aaaa";
}
public void Replace(int index, int length, string text)
{
lineBuilder.Remove(index, length);
lineBuilder.Insert(index, text);
}
public void ShowCompletionWindow(ICompletionDataProvider completionDataProvider)
{
showCompletionWindowCalled = true;

113
src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/OneItemCommandLineHistoryTestFixture.cs

@ -0,0 +1,113 @@ @@ -0,0 +1,113 @@
// <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
{
[TestFixture]
public class OneItemCommandLineHistoryTestFixture
{
CommandLineHistory history;
[SetUp]
public void Init()
{
history = new CommandLineHistory();
history.Add("a");
}
[Test]
public void Current()
{
Assert.AreEqual(null, history.Current);
}
[Test]
public void MovePrevious()
{
Assert.IsTrue(history.MovePrevious());
}
[Test]
public void MovePreviousTwice()
{
history.MovePrevious();
Assert.IsFalse(history.MovePrevious());
}
[Test]
public void MoveNextFails()
{
Assert.IsFalse(history.MoveNext());
}
[Test]
public void CurrentAfterMovePrevious()
{
history.MovePrevious();
Assert.AreEqual("a", history.Current);
}
[Test]
public void CurrentAfterMovePreviousTwice()
{
history.MovePrevious();
history.MovePrevious();
Assert.IsNull(history.Current);
}
[Test]
public void MovePreviousThenBack()
{
history.MovePrevious();
Assert.IsFalse(history.MoveNext());
}
[Test]
public void CurrentAfterMovePreviousThenBack()
{
history.MovePrevious();
history.MoveNext();
Assert.IsNull(history.Current);
}
[Test]
public void CurrentAfterMovePreviousTwiceThenBack()
{
history.MovePrevious();
history.MovePrevious();
history.MoveNext();
Assert.AreEqual("a", history.Current);
}
[Test]
public void MoveNextTwiceThenBack()
{
history.MoveNext();
history.MoveNext();
Assert.IsTrue(history.MovePrevious());
}
[Test]
public void CurrentAfterMoveNextTwiceThenBack()
{
MoveNextTwiceThenBack();
Assert.AreEqual("a", history.Current);
}
[Test]
public void IgnoreSameCommandLineEntered()
{
history.Add("a");
history.MovePrevious();
Assert.IsFalse(history.MovePrevious());
}
}
}

93
src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/PythonConsoleCommandLineHistoryTestFixture.cs

@ -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.Windows.Forms;
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 command line history.
/// </summary>
[TestFixture]
public class PythonConsoleCommandLineHistoryTestFixture
{
PythonConsole pythonConsole;
MockTextEditor textEditor;
string prompt = ">>> ";
[SetUp]
public void Init()
{
textEditor = new MockTextEditor();
pythonConsole = new PythonConsole(textEditor, null);
pythonConsole.Write(prompt, Style.Prompt);
textEditor.RaiseKeyPressEvent('a');
textEditor.RaiseDialogKeyPressEvent(Keys.Enter);
pythonConsole.Write(prompt, Style.Prompt);
textEditor.RaiseKeyPressEvent('b');
textEditor.RaiseKeyPressEvent('c');
textEditor.RaiseDialogKeyPressEvent(Keys.Enter);
pythonConsole.Write(prompt, Style.Prompt);
}
[Test]
public void UpArrowKeyPressed()
{
Assert.IsTrue(textEditor.RaiseDialogKeyPressEvent(Keys.Up));
}
[Test]
public void CurrentLineAfterUpArrowKeyPressed()
{
textEditor.RaiseDialogKeyPressEvent(Keys.Up);
Assert.AreEqual("bc", pythonConsole.GetCurrentLine());
}
[Test]
public void TextEditorCursorIsAtEndOfLineAfterUpArrowKeyPressed()
{
textEditor.RaiseDialogKeyPressEvent(Keys.Up);
Assert.AreEqual(prompt.Length + 2, textEditor.Column);
}
[Test]
public void TextAfterUpArrowKeyPressedTwiceThenDownArrowKey()
{
UpArrowKeyPressedTwiceThenDownArrowKey();
Assert.AreEqual("bc", pythonConsole.GetCurrentLine());
}
[Test]
public void TextEditorCursorAfterUpArrowKeyPressedTwice()
{
textEditor.RaiseDialogKeyPressEvent(Keys.Up);
textEditor.RaiseDialogKeyPressEvent(Keys.Up);
Assert.AreEqual(prompt.Length + 1, textEditor.Column);
}
[Test]
public void DownArrowKeyHandled()
{
Assert.IsTrue(textEditor.RaiseDialogKeyPressEvent(Keys.Down));
}
void UpArrowKeyPressedTwiceThenDownArrowKey()
{
textEditor.RaiseDialogKeyPressEvent(Keys.Up);
textEditor.RaiseDialogKeyPressEvent(Keys.Up);
textEditor.RaiseDialogKeyPressEvent(Keys.Down);
}
}
}

10
src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/TextEditorTestFixture.cs

@ -317,6 +317,16 @@ namespace PythonBinding.Tests.Console @@ -317,6 +317,16 @@ namespace PythonBinding.Tests.Console
Assert.IsTrue(textEditorControl.TextEditorProperties.SupportReadOnlySegments);
}
[Test]
public void ReplaceText()
{
textEditorControl.Document.TextContent = "abc\r\ndef";
textEditorControl.ActiveTextAreaControl.Caret.Line = 1;
textEditor.Replace(1, 1, "test");
Assert.AreEqual("abc\r\ndtestf", textEditorControl.Document.TextContent);
}
/// <summary>
/// Run on different thread to set the text editor's indent style.
/// </summary>

4
src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj

@ -70,9 +70,13 @@ @@ -70,9 +70,13 @@
<Compile Include="AddInFileTestFixture.cs" />
<Compile Include="CompilingOptionsPanelTestFixture.cs" />
<Compile Include="Console\BuiltinCodeCompletionTestFixture.cs" />
<Compile Include="Console\CommandLineHistoryTestFixture.cs" />
<Compile Include="Console\DerivedPythonConsoleHost.cs" />
<Compile Include="Console\DisposedPythonConsoleTestFixture.cs" />
<Compile Include="Console\CodeCompletionTests.cs" />
<Compile Include="Console\EmptyCommandLineHistoryTestFixture.cs" />
<Compile Include="Console\OneItemCommandLineHistoryTestFixture.cs" />
<Compile Include="Console\PythonConsoleCommandLineHistoryTestFixture.cs" />
<Compile Include="Console\PythonConsoleHomeKeyTestFixture.cs" />
<Compile Include="Console\MockMemberProvider.cs" />
<Compile Include="Console\MockTextEditor.cs" />

Loading…
Cancel
Save