diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj index 5686e7fafd..f46591e5c8 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj @@ -104,6 +104,7 @@ + diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormattingStrategy.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormattingStrategy.cs index eac8142527..44e5652125 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormattingStrategy.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormattingStrategy.cs @@ -2,87 +2,20 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; -using System.Text; +using ICSharpCode.Scripting; using ICSharpCode.SharpDevelop.Editor; namespace ICSharpCode.PythonBinding { - public class PythonFormattingStrategy : DefaultFormattingStrategy + public class PythonFormattingStrategy : ScriptingFormattingStrategy { - public PythonFormattingStrategy() - { - } - - public override void IndentLine(ITextEditor editor, IDocumentLine line) - { - if (line.LineNumber == 1) { - base.IndentLine(editor, line); - return; - } - - IDocument document = editor.Document; - IDocumentLine previousLine = document.GetLine(line.LineNumber - 1); - string previousLineText = previousLine.Text.Trim(); - - if (previousLineText.EndsWith(":")) { - IncreaseLineIndent(editor, line); - } else if (previousLineText == "pass") { - DecreaseLineIndent(editor, line); - } else if ((previousLineText == "return") || (previousLineText.StartsWith("return "))) { - DecreaseLineIndent(editor, line); - } else if ((previousLineText == "raise") || (previousLineText.StartsWith("raise "))) { - DecreaseLineIndent(editor, line); - } else if (previousLineText == "break") { - DecreaseLineIndent(editor, line); - } else { - base.IndentLine(editor, line); - } - } - - void IncreaseLineIndent(ITextEditor editor, IDocumentLine line) - { - ModifyLineIndent(editor, line, true); - } - - void DecreaseLineIndent(ITextEditor editor, IDocumentLine line) - { - ModifyLineIndent(editor, line, false); - } - - void ModifyLineIndent(ITextEditor editor, IDocumentLine line, bool increaseIndent) - { - string indentation = GetLineIndentation(editor, line.LineNumber - 1); - indentation = GetNewLineIndentation(indentation, editor.Options.IndentationString, increaseIndent); - string newIndentedText = indentation + line.Text; - editor.Document.Replace(line.Offset, line.Length, newIndentedText); - } - - string GetLineIndentation(ITextEditor editor, int line) - { - IDocumentLine documentLine = editor.Document.GetLine(line); - StringBuilder whitespace = new StringBuilder(); - foreach (char ch in documentLine.Text) { - if (Char.IsWhiteSpace(ch)) { - whitespace.Append(ch); - } else { - break; - } - } - return whitespace.ToString(); + public override string LineComment { + get { return "#"; } } - string GetNewLineIndentation(string previousLineIndentation, string singleIndent, bool increaseIndent) + protected override LineIndenter CreateLineIndenter(ITextEditor editor, IDocumentLine line) { - if (increaseIndent) { - return previousLineIndentation + singleIndent; - } - - // Decrease the new line indentation. - int decreaselength = previousLineIndentation.Length - singleIndent.Length; - if (decreaselength < 0) { - decreaselength = 0; - } - return previousLineIndentation.Substring(0, decreaselength); + return new PythonLineIndenter(editor, line); } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonLineIndenter.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonLineIndenter.cs new file mode 100644 index 0000000000..e216ee874a --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonLineIndenter.cs @@ -0,0 +1,46 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.Scripting; +using ICSharpCode.SharpDevelop.Editor; + +namespace ICSharpCode.PythonBinding +{ + public class PythonLineIndenter : LineIndenter + { + public PythonLineIndenter(ITextEditor editor, IDocumentLine line) + : base(editor, line) + { + } + + protected override bool ShouldIncreaseLineIndent() + { + return PreviousLine.EndsWith(":"); + } + + protected override bool ShouldDecreaseLineIndent() + { + if (PreviousLine == "pass") { + return true; + } else if (PreviousLineIsReturnStatement()) { + return true; + } else if (PreviousLineIsRaiseStatement()) { + return true; + } else if (PreviousLine == "break") { + return true; + } + return false; + } + + bool PreviousLineIsReturnStatement() + { + return (PreviousLine == "return") || PreviousLine.StartsWith("return "); + } + + bool PreviousLineIsRaiseStatement() + { + return (PreviousLine == "raise") || PreviousLine.StartsWith("raise "); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Gui/PythonIndentationTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Gui/PythonFormattingStrategyTests.cs similarity index 53% rename from src/AddIns/BackendBindings/Python/PythonBinding/Test/Gui/PythonIndentationTests.cs rename to src/AddIns/BackendBindings/Python/PythonBinding/Test/Gui/PythonFormattingStrategyTests.cs index 9c3d6ed5d7..6ca7570a84 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Gui/PythonIndentationTests.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Gui/PythonFormattingStrategyTests.cs @@ -5,26 +5,20 @@ using System; using ICSharpCode.AvalonEdit; using ICSharpCode.PythonBinding; using ICSharpCode.Scripting.Tests.Utils; -using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor.AvalonEdit; using NUnit.Framework; -using PythonBinding.Tests.Utils; namespace PythonBinding.Tests.Gui { - /// - /// Tests that the PythonFormattingStrategy indents the new line added after pressing the ':' character. - /// [TestFixture] - public class PythonIndentationTestFixture + public class PythonFormattingStrategyTests { TextEditor textEditor; AvalonEditTextEditorAdapter textEditorAdapter; PythonFormattingStrategy formattingStrategy; - [SetUp] - public void Init() + void CreatePythonFormattingStrategy() { MockTextEditorOptions textEditorOptions = new MockTextEditorOptions(); textEditorOptions.IndentationSize = 4; @@ -35,62 +29,74 @@ namespace PythonBinding.Tests.Gui formattingStrategy = new PythonFormattingStrategy(); } + [Test] - public void NewMethodDefinition() + public void IndentLine_IndentLineAfterNewMethodDefinition_LineIsIndentedByOneTab() { + CreatePythonFormattingStrategy(); + textEditor.Text = "def newMethod:\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); - formattingStrategy.IndentLine(textEditorAdapter, line); + formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def newMethod:\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void NoExtraIndentationRequired() + public void IndentLine_NoExtraIndentationRequiredAfterPrintLineStatement_SecondLineIsIndentedToSameLevelAsPrintStatementLine() { + CreatePythonFormattingStrategy(); + textEditor.Text = "\tprint 'abc'\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "\tprint 'abc'\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void PassStatementDecreasesIndentOnThirdLine() + public void IndentLine_IndentAfterPassStatementOnSecondLine_DecreasesIndentOnThirdLine() { - textEditor.Text = + CreatePythonFormattingStrategy(); + + textEditor.Text = "def method1:\r\n" + "\tpass\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(3); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1:\r\n" + "\tpass\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void ReturnValueStatementDecreasesIndentOnThirdLine() + public void IndentLine_IndentAfterReturnValueStatementOnSecondLine_DecreasesIndentOnThirdLine() { + CreatePythonFormattingStrategy(); + textEditor.Text = "def method1:\r\n" + "\treturn 0\r\n" + @@ -98,173 +104,216 @@ namespace PythonBinding.Tests.Gui IDocumentLine line = textEditorAdapter.Document.GetLine(3); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1:\r\n" + "\treturn 0\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void ReturnStatementDecreasesIndentOnThirdLine() + public void IndentLine_IndentAfterReturnStatementOnSecondLine_DecreasesIndentOnThirdLine() { - textEditor.Text = + CreatePythonFormattingStrategy(); + + textEditor.Text = "def method1:\r\n" + "\treturn\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(3); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1:\r\n" + "\treturn\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void ReturnStatementWithNoIndentOnPreviousLine() + public void IndentLine_ReturnStatementWithNoIndentPreviousLine_SecondLineIsNotIndented() { + CreatePythonFormattingStrategy(); + textEditor.Text = "return\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "return\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void StatementIsNotAReturnOnPreviousLine() + public void IndentLine_StatementIsNotReturnOnPreviousLineAndIsIndentedByOneTab_LineIsIndentedByOneTab() { + CreatePythonFormattingStrategy(); + textEditor.Text = "\treturnValue\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "\treturnValue\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void RaiseStatementWithObjectDecreasesIndentOnThirdLine() + public void IndentLine_RaiseStatementWithObjectOneSecondLine_DecreasesIndentOnThirdLineByOne() { + CreatePythonFormattingStrategy(); + textEditor.Text = "def method1:\r\n" + "\traise 'a'\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(3); - formattingStrategy.IndentLine(textEditorAdapter, line); + formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1:\r\n" + "\traise 'a'\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void RaiseStatementDecreasesIndentOnThirdLine() + public void IndentLine_RaiseStatementOnSecondLine_IndentOnThirdLineIsDecreasedByOne() { + CreatePythonFormattingStrategy(); + textEditor.Text = "def method1:\r\n" + "\traise\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(3); - formattingStrategy.IndentLine(textEditorAdapter, line); + formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1:\r\n" + "\traise\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void StatementIsNotARaiseStatementOnPreviousLine() + public void IndentLine_StatementIsNotRaiseStatementOnPreviousLine_LineIsIndentedToSameLevelAsPreviouisLine() { + CreatePythonFormattingStrategy(); + textEditor.Text = "def method1:\r\n" + "\traiseThis\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(3); - formattingStrategy.IndentLine(textEditorAdapter, line); + formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1:\r\n" + "\traiseThis\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void BreakStatementDecreasesIndentOnThirdLine() + public void IndentLine_BreakStatementOnSecondLine_DecreasesIndentOnThirdLine() { + CreatePythonFormattingStrategy(); + textEditor.Text = "def method1:\r\n" + "\tbreak\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(3); - formattingStrategy.IndentLine(textEditorAdapter, line); - + formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; + string expectedText = "def method1:\r\n" + "\tbreak\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void StatementIsNotABreakStatementOnPreviousLine() + public void IndentLine_StatementIsNotBreakStatementOnPreviousLine_LineIsIndentedToSameLevelAsPreviousLine() { + CreatePythonFormattingStrategy(); + textEditor.Text = "def method1:\r\n" + "\tbreakThis\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(3); - formattingStrategy.IndentLine(textEditorAdapter, line); + formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1:\r\n" + "\tbreakThis\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void IndentingFirstLineDoesNotThrowArgumentOutOfRangeException() + public void IndentLine_LineNumberOutOfRange_DoesNotThrowArgumentOutOfRangeException() { + CreatePythonFormattingStrategy(); + textEditor.Text = "print 'hello'"; IDocumentLine line = textEditorAdapter.Document.GetLine(1); - Assert.DoesNotThrow(delegate { formattingStrategy.IndentLine(textEditorAdapter, line); }); + string text = textEditor.Text; + + string expectedText = "print 'hello'"; + + Assert.AreEqual(expectedText, text); + } + + [Test] + public void SurroundSelectionWithComment_CursorOnFirstLineAndNothingSelected_FirstLineIsCommented() + { + CreatePythonFormattingStrategy(); + + textEditor.Text = "print 'hello'"; + formattingStrategy.SurroundSelectionWithComment(textEditorAdapter); + string text = textEditor.Text; + + string expectedText = "#print 'hello'"; - Assert.AreEqual("print 'hello'", textEditor.Text); + Assert.AreEqual(expectedText, text); } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj index e7e27dad6b..c887f2fc3a 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj @@ -315,7 +315,7 @@ - + diff --git a/src/AddIns/BackendBindings/Ruby/RubyBinding.sln b/src/AddIns/BackendBindings/Ruby/RubyBinding.sln index 9b9b36cd2b..13193abf19 100644 --- a/src/AddIns/BackendBindings/Ruby/RubyBinding.sln +++ b/src/AddIns/BackendBindings/Ruby/RubyBinding.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -# SharpDevelop 4.0.0.6676 +# SharpDevelop 4.0.0.6737 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RubyBinding", "RubyBinding\Project\RubyBinding.csproj", "{C896FFFF-5B6C-4B0E-B6DF-049865F501B4}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RubyBinding.Tests", "RubyBinding\Test\RubyBinding.Tests.csproj", "{01DF0475-0CB2-4E81-971B-BADC60CDE3A5}" diff --git a/src/AddIns/BackendBindings/Ruby/RubyBinding/Project/RubyBinding.csproj b/src/AddIns/BackendBindings/Ruby/RubyBinding/Project/RubyBinding.csproj index 95c55fa59f..bf3288f270 100644 --- a/src/AddIns/BackendBindings/Ruby/RubyBinding/Project/RubyBinding.csproj +++ b/src/AddIns/BackendBindings/Ruby/RubyBinding/Project/RubyBinding.csproj @@ -111,6 +111,7 @@ + diff --git a/src/AddIns/BackendBindings/Ruby/RubyBinding/Project/Src/RubyFormattingStrategy.cs b/src/AddIns/BackendBindings/Ruby/RubyBinding/Project/Src/RubyFormattingStrategy.cs index 264a0cf82a..3e366a7ab0 100644 --- a/src/AddIns/BackendBindings/Ruby/RubyBinding/Project/Src/RubyFormattingStrategy.cs +++ b/src/AddIns/BackendBindings/Ruby/RubyBinding/Project/Src/RubyFormattingStrategy.cs @@ -2,202 +2,20 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; -using System.Collections.Generic; -using System.Text; +using ICSharpCode.Scripting; using ICSharpCode.SharpDevelop.Editor; namespace ICSharpCode.RubyBinding { - public class RubyFormattingStrategy : DefaultFormattingStrategy + public class RubyFormattingStrategy : ScriptingFormattingStrategy { - ITextEditor textEditor; - IDocumentLine currentLine; - IDocumentLine previousLine; - string previousLineTextTrimmed; - List decreaseLineIndentStatements = new List(); - List decreaseLineIndentStartsWithStatements = new List(); - - List increaseLineIndentStatements = new List(); - List increaseLineIndentStartsWithStatements = new List(); - List increaseLineIndentEndsWithStatements = new List(); - List increaseLineIndentContainsStatements = new List(); - - public RubyFormattingStrategy() - { - CreateDecreaseLineIndentStatements(); - CreateDecreaseLineIndentStartsWithStatements(); - CreateIncreaseLineIndentStatements(); - CreateIncreaseLineIndentStartsWithStatements(); - CreateIncreaseLineIndentEndsWithStatements(); - CreateIncreaseLineIndentContainsStatements(); - } - - void CreateDecreaseLineIndentStatements() - { - decreaseLineIndentStatements.Add("break"); - decreaseLineIndentStatements.Add("return"); - decreaseLineIndentStatements.Add("raise"); - } - - void CreateDecreaseLineIndentStartsWithStatements() - { - decreaseLineIndentStartsWithStatements.Add("return "); - decreaseLineIndentStartsWithStatements.Add("raise "); - } - - void CreateIncreaseLineIndentStatements() - { - increaseLineIndentStatements.Add("else"); - increaseLineIndentStatements.Add("begin"); - increaseLineIndentStatements.Add("rescue"); - increaseLineIndentStatements.Add("ensure"); - } - - void CreateIncreaseLineIndentStartsWithStatements() - { - increaseLineIndentStartsWithStatements.Add("if "); - increaseLineIndentStartsWithStatements.Add("def "); - increaseLineIndentStartsWithStatements.Add("class "); - increaseLineIndentStartsWithStatements.Add("while "); - increaseLineIndentStartsWithStatements.Add("elsif "); - increaseLineIndentStartsWithStatements.Add("loop "); - increaseLineIndentStartsWithStatements.Add("unless "); - increaseLineIndentStartsWithStatements.Add("until "); - increaseLineIndentStartsWithStatements.Add("for "); - increaseLineIndentStartsWithStatements.Add("rescue "); - increaseLineIndentStartsWithStatements.Add("module "); - increaseLineIndentStartsWithStatements.Add("when "); - increaseLineIndentStartsWithStatements.Add("case "); - } - - void CreateIncreaseLineIndentEndsWithStatements() - { - increaseLineIndentEndsWithStatements.Add(" then"); - increaseLineIndentEndsWithStatements.Add(" do"); - increaseLineIndentEndsWithStatements.Add(" {"); - } - void CreateIncreaseLineIndentContainsStatements() - { - increaseLineIndentContainsStatements.Add(" case "); - } - - public override void IndentLine(ITextEditor editor, IDocumentLine line) - { - this.textEditor = editor; - this.currentLine = line; - - GetPreviousLineText(); - - if (ShouldDecreaseLineIndent()) { - DecreaseLineIndent(); - } else if (ShouldIncreaseLineIndent()) { - IncreaseLineIndent(); - } else { - base.IndentLine(editor, line); - } - } - - void GetPreviousLineText() - { - previousLine = textEditor.Document.GetLine(currentLine.LineNumber - 1); - previousLineTextTrimmed = previousLine.Text.Trim(); - } - - bool ShouldIncreaseLineIndent() - { - if (increaseLineIndentStatements.Contains(previousLineTextTrimmed)) { - return true; - } - if (PreviousLineStartsWith(increaseLineIndentStartsWithStatements)) { - return true; - } - if (PreviousLineContains(increaseLineIndentContainsStatements)) { - return true; - } - return PreviousLineEndsWith(increaseLineIndentEndsWithStatements); - } - - bool ShouldDecreaseLineIndent() - { - if (decreaseLineIndentStatements.Contains(previousLineTextTrimmed)) { - return true; - } - return PreviousLineStartsWith(decreaseLineIndentStartsWithStatements); - } - - bool PreviousLineStartsWith(List items) - { - foreach (string item in items) { - if (previousLineTextTrimmed.StartsWith(item)) { - return true; - } - } - return false; - } - - bool PreviousLineEndsWith(List items) - { - foreach (string item in items) { - if (previousLineTextTrimmed.EndsWith(item)) { - return true; - } - } - return false; - } - - bool PreviousLineContains(List items) - { - foreach (string item in items) { - if (previousLineTextTrimmed.Contains(item)) { - return true; - } - } - return false; - } - - void IncreaseLineIndent() - { - ModifyLineIndent(true); - } - - void DecreaseLineIndent() - { - ModifyLineIndent(false); - } - - void ModifyLineIndent(bool increaseIndent) - { - string indentation = GetPreviousLineIndentation(); - indentation = GetNewLineIndentation(indentation, textEditor.Options.IndentationString, increaseIndent); - string newIndentedText = indentation + currentLine.Text; - textEditor.Document.Replace(currentLine.Offset, currentLine.Length, newIndentedText); - } - - string GetPreviousLineIndentation() - { - StringBuilder whitespace = new StringBuilder(); - foreach (char ch in previousLine.Text) { - if (Char.IsWhiteSpace(ch)) { - whitespace.Append(ch); - } else { - break; - } - } - return whitespace.ToString(); + public override string LineComment { + get { return "#"; } } - string GetNewLineIndentation(string previousLineIndentation, string singleIndent, bool increaseIndent) + protected override LineIndenter CreateLineIndenter(ITextEditor editor, IDocumentLine line) { - if (increaseIndent) { - return previousLineIndentation + singleIndent; - } - - // Decrease the new line indentation. - int decreaselength = previousLineIndentation.Length - singleIndent.Length; - if (decreaselength < 0) { - decreaselength = 0; - } - return previousLineIndentation.Substring(0, decreaselength); + return new RubyLineIndenter(editor, line); } } } diff --git a/src/AddIns/BackendBindings/Ruby/RubyBinding/Project/Src/RubyLineIndenter.cs b/src/AddIns/BackendBindings/Ruby/RubyBinding/Project/Src/RubyLineIndenter.cs new file mode 100644 index 0000000000..d2fc7e6ebf --- /dev/null +++ b/src/AddIns/BackendBindings/Ruby/RubyBinding/Project/Src/RubyLineIndenter.cs @@ -0,0 +1,134 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.Scripting; +using ICSharpCode.SharpDevelop.Editor; + +namespace ICSharpCode.RubyBinding +{ + public class RubyLineIndenter : LineIndenter + { + List decreaseLineIndentStatements = new List(); + List decreaseLineIndentStartsWithStatements = new List(); + + List increaseLineIndentStatements = new List(); + List increaseLineIndentStartsWithStatements = new List(); + List increaseLineIndentEndsWithStatements = new List(); + List increaseLineIndentContainsStatements = new List(); + + public RubyLineIndenter(ITextEditor editor, IDocumentLine line) + : base(editor, line) + { + CreateDecreaseLineIndentStatements(); + CreateDecreaseLineIndentStartsWithStatements(); + CreateIncreaseLineIndentStatements(); + CreateIncreaseLineIndentStartsWithStatements(); + CreateIncreaseLineIndentEndsWithStatements(); + CreateIncreaseLineIndentContainsStatements(); + } + + void CreateDecreaseLineIndentStatements() + { + decreaseLineIndentStatements.Add("break"); + decreaseLineIndentStatements.Add("return"); + decreaseLineIndentStatements.Add("raise"); + } + + void CreateDecreaseLineIndentStartsWithStatements() + { + decreaseLineIndentStartsWithStatements.Add("return "); + decreaseLineIndentStartsWithStatements.Add("raise "); + } + + void CreateIncreaseLineIndentStatements() + { + increaseLineIndentStatements.Add("else"); + increaseLineIndentStatements.Add("begin"); + increaseLineIndentStatements.Add("rescue"); + increaseLineIndentStatements.Add("ensure"); + } + + void CreateIncreaseLineIndentStartsWithStatements() + { + increaseLineIndentStartsWithStatements.Add("if "); + increaseLineIndentStartsWithStatements.Add("def "); + increaseLineIndentStartsWithStatements.Add("class "); + increaseLineIndentStartsWithStatements.Add("while "); + increaseLineIndentStartsWithStatements.Add("elsif "); + increaseLineIndentStartsWithStatements.Add("loop "); + increaseLineIndentStartsWithStatements.Add("unless "); + increaseLineIndentStartsWithStatements.Add("until "); + increaseLineIndentStartsWithStatements.Add("for "); + increaseLineIndentStartsWithStatements.Add("rescue "); + increaseLineIndentStartsWithStatements.Add("module "); + increaseLineIndentStartsWithStatements.Add("when "); + increaseLineIndentStartsWithStatements.Add("case "); + } + + void CreateIncreaseLineIndentEndsWithStatements() + { + increaseLineIndentEndsWithStatements.Add(" then"); + increaseLineIndentEndsWithStatements.Add(" do"); + increaseLineIndentEndsWithStatements.Add(" {"); + } + + void CreateIncreaseLineIndentContainsStatements() + { + increaseLineIndentContainsStatements.Add(" case "); + } + + protected override bool ShouldIncreaseLineIndent() + { + if (increaseLineIndentStatements.Contains(PreviousLine)) { + return true; + } + if (PreviousLineStartsWith(increaseLineIndentStartsWithStatements)) { + return true; + } + if (PreviousLineContains(increaseLineIndentContainsStatements)) { + return true; + } + return PreviousLineEndsWith(increaseLineIndentEndsWithStatements); + } + + protected override bool ShouldDecreaseLineIndent() + { + if (decreaseLineIndentStatements.Contains(PreviousLine)) { + return true; + } + return PreviousLineStartsWith(decreaseLineIndentStartsWithStatements); + } + + bool PreviousLineStartsWith(List items) + { + foreach (string item in items) { + if (PreviousLine.StartsWith(item)) { + return true; + } + } + return false; + } + + bool PreviousLineEndsWith(List items) + { + foreach (string item in items) { + if (PreviousLine.EndsWith(item)) { + return true; + } + } + return false; + } + + bool PreviousLineContains(List items) + { + foreach (string item in items) { + if (PreviousLine.Contains(item)) { + return true; + } + } + return false; + } + } +} diff --git a/src/AddIns/BackendBindings/Ruby/RubyBinding/Test/Gui/RubyIndentationTests.cs b/src/AddIns/BackendBindings/Ruby/RubyBinding/Test/Gui/RubyFormattingStrategyTests.cs similarity index 59% rename from src/AddIns/BackendBindings/Ruby/RubyBinding/Test/Gui/RubyIndentationTests.cs rename to src/AddIns/BackendBindings/Ruby/RubyBinding/Test/Gui/RubyFormattingStrategyTests.cs index d897eaa459..5e95e9aede 100644 --- a/src/AddIns/BackendBindings/Ruby/RubyBinding/Test/Gui/RubyIndentationTests.cs +++ b/src/AddIns/BackendBindings/Ruby/RubyBinding/Test/Gui/RubyFormattingStrategyTests.cs @@ -13,18 +13,14 @@ using RubyBinding.Tests.Utils; namespace RubyBinding.Tests.Gui { - /// - /// Tests that the RubyFormattingStrategy indents the new line added after method and class definitions. - /// [TestFixture] - public class RubyNewMethodIndentationTestFixture + public class RubyFormattingStrategyTests { TextEditor textEditor; RubyFormattingStrategy formattingStrategy; AvalonEditTextEditorAdapter textEditorAdapter; - [SetUp] - public void Init() + void CreateFormattingStrategy() { MockTextEditorOptions textEditorOptions = new MockTextEditorOptions(); textEditorOptions.IndentationSize = 4; @@ -37,76 +33,90 @@ namespace RubyBinding.Tests.Gui } [Test] - public void NewMethodDefinition() + public void IndentLine_NewMethodDefinitionOnPreviousLine_NextLineIsIndented() { + CreateFormattingStrategy(); + textEditor.Text = "def newMethod\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def newMethod\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void NewMethodDefinitionWithBrackets() + public void IndentLine_NewMethodDefinitionWithBracketsOnPreviousLine_NextLineIsIndented() { + CreateFormattingStrategy(); + textEditor.Text = "def newMethod()\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def newMethod()\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void NewClassDefinition() + public void IndentLine_NewClassDefinitionOnPreviousLine_NextLineIsIndented() { + CreateFormattingStrategy(); + textEditor.Text = "class MyClass\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "class MyClass\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void NoExtraIndentationRequired() + public void IndentLine_PrintStatementOnPreviousLineSoNoExtraIndentationRequired_NextLineIndentedToSameLevelAsPreviousLine() { + CreateFormattingStrategy(); + textEditor.Text = "\tprint 'abc'\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "\tprint 'abc'\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void ReturnValueStatementDecreasesIndentOnThirdLine() + public void IndentLine_ReturnValueStatementOnPreviousLine_DecreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "def method1\r\n" + "\treturn 0\r\n" + @@ -114,18 +124,21 @@ namespace RubyBinding.Tests.Gui IDocumentLine line = textEditorAdapter.Document.GetLine(3); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1\r\n" + "\treturn 0\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void ReturnStatementDecreasesIndentOnThirdLine() + public void IndentLine_ReturnStatementOnPreviousLine_DecreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "def method1\r\n" + "\treturn\r\n" + @@ -133,51 +146,61 @@ namespace RubyBinding.Tests.Gui IDocumentLine line = textEditorAdapter.Document.GetLine(3); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1\r\n" + "\treturn\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); - } + Assert.AreEqual(expectedText, text); + } + [Test] - public void ReturnStatementWithNoIndentOnPreviousLine() + public void IndentLine_ReturnStatementOnPreviousLineWithNoIndentOnPreviousLine_NextLineIsNotIndented() { + CreateFormattingStrategy(); + textEditor.Text = "return\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "return\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void StatementIsNotAReturnOnPreviousLine() + public void IndentLine_StatementIsNotReturnOnPreviousLine_NextLineIndentedToSameLevelAsPreviousLine() { + CreateFormattingStrategy(); + textEditor.Text = "\treturnValue\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "\treturnValue\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void RaiseStatementWithObjectDecreasesIndentOnThirdLine() + public void IndentLine_RaiseStatementWithObjectOnPreviousLine_DecreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "def method1\r\n" + "\traise 'a'\r\n" + @@ -185,18 +208,21 @@ namespace RubyBinding.Tests.Gui IDocumentLine line = textEditorAdapter.Document.GetLine(3); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1\r\n" + "\traise 'a'\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void RaiseStatementDecreasesIndentOnThirdLine() + public void IndentLine_RaiseStatementOnPreviousLine_DecreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "def method1\r\n" + "\traise\r\n" + @@ -204,18 +230,21 @@ namespace RubyBinding.Tests.Gui IDocumentLine line = textEditorAdapter.Document.GetLine(3); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1\r\n" + "\traise\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void StatementIsNotARaiseStatementOnPreviousLine() + public void IndentLine_StatementIsNotRaiseStatementOnPreviousLine_NextLineIsIndentedToSameLevelAsPreviousLine() { + CreateFormattingStrategy(); + textEditor.Text = "def method1\r\n" + "\traiseThis\r\n" + @@ -223,18 +252,21 @@ namespace RubyBinding.Tests.Gui IDocumentLine line = textEditorAdapter.Document.GetLine(3); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1\r\n" + "\traiseThis\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void BreakStatementDecreasesIndentOnThirdLine() + public void IndentLine_BreakStatementOnPreviousLine_DecreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "def method1\r\n" + "\tbreak\r\n" + @@ -242,18 +274,21 @@ namespace RubyBinding.Tests.Gui IDocumentLine line = textEditorAdapter.Document.GetLine(3); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1\r\n" + "\tbreak\r\n" + ""; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void StatementIsNotABreakStatementOnPreviousLine() + public void IndentLine_StatementIsNotBreakStatementOnPreviousLine_LineIsIndentedToSameLevelAsPreviousLine() { + CreateFormattingStrategy(); + textEditor.Text = "def method1\r\n" + "\tbreakThis\r\n" + @@ -261,273 +296,321 @@ namespace RubyBinding.Tests.Gui IDocumentLine line = textEditorAdapter.Document.GetLine(3); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "def method1\r\n" + "\tbreakThis\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void IfThenStatementIncreasesIndentOnNextLine() + public void IndentLine_IfThenStatementOnPreviousLine_IndentIncreasedOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "if i > 0 then\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "if i > 0 then\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void IfStatementIncreasesIndentOnNextLine() + public void IndentLine_IfStatementOnPreviousLine_IndentIncreasedOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "if i > 0\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "if i > 0\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void ElseStatementIncreasesIndentOnNextLine() + public void IndentLine_ElseStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "else\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "else\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void ElseIfStatementIncreasesIndentOnNextLine() + public void IndentLine_ElseIfStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "elsif i > 0\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "elsif i > 0\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void LoopStatementIncreasesIndentOnNextLine() + public void IndentLine_LoopStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "loop do\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "loop do\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void UnlessStatementIncreasesIndentOnNextLine() + public void IndentLine_UnlessStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "unless i > 0\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "unless i > 0\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void UntilStatementIncreasesIndentOnNextLine() + public void IndentLine_UntilStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "until i > 0\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "until i > 0\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void ForStatementIncreasesIndentOnNextLine() + public void IndentLine_ForStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "for i in 1..5\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "for i in 1..5\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void DoStatementAtEndOfLineIncreasesIndentOnNextLine() + public void IndentLine_DoStatementAtEndOfPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "expr do\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "expr do\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void OpenCurlyBraceAtEndOfLineIncreasesIndentOnNextLine() + public void IndentLine_OpenCurlyBraceAtEndOfPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "expr {\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "expr {\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void BeginStatementIncreasesIndentOnNextLine() + public void IndentLine_BeginStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "begin\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "begin\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void RescueStatementWithExceptionIncreasesIndentOnNextLine() + public void IndentLine_RescueStatementWithExceptionOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "rescue Exception => ex\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "rescue Exception => ex\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void RescueStatementIncreasesIndentOnNextLine() + public void IndentLine_RescueStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "rescue\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "rescue\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void EnsureStatementIncreasesIndentOnNextLine() + public void IndentLine_EnsureStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "ensure\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "ensure\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void ModuleStatementIncreasesIndentOnNextLine() + public void IndentLine_ModuleStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "module Foo\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "module Foo\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void CaseWhenStatementIncreasesIndentOnNextLine() + public void IndentLine_CaseWhenStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "case num\r\n" + "\twhen 0\r\n" + @@ -535,47 +618,68 @@ namespace RubyBinding.Tests.Gui IDocumentLine line = textEditorAdapter.Document.GetLine(3); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "case num\r\n" + "\twhen 0\r\n" + "\t\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void CaseStatementIncreasesIndentOnNextLine() + public void IndentLine_CaseStatementOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "case num\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "case num\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); } [Test] - public void CaseStatementInMiddleOfLineIncreasesIndentOnNextLine() + public void IndentLine_CaseStatementInMiddleOnPreviousLine_IncreasesIndentOnNextLine() { + CreateFormattingStrategy(); + textEditor.Text = "value = case num\r\n" + ""; IDocumentLine line = textEditorAdapter.Document.GetLine(2); formattingStrategy.IndentLine(textEditorAdapter, line); + string text = textEditor.Text; string expectedText = "value = case num\r\n" + "\t"; - Assert.AreEqual(expectedText, textEditor.Text); + Assert.AreEqual(expectedText, text); + } + + [Test] + public void SurroundSelectionWithComment_CursorOnFirstLineNothingSelected_CommentsFirstLine() + { + CreateFormattingStrategy(); + + textEditor.Text = "print 'hello'"; + formattingStrategy.SurroundSelectionWithComment(textEditorAdapter); + string text = textEditor.Text; + + string expectedText = "#print 'hello'"; + + Assert.AreEqual(expectedText, text); } } } diff --git a/src/AddIns/BackendBindings/Ruby/RubyBinding/Test/RubyBinding.Tests.csproj b/src/AddIns/BackendBindings/Ruby/RubyBinding/Test/RubyBinding.Tests.csproj index 1d31f9d487..eb224040fb 100644 --- a/src/AddIns/BackendBindings/Ruby/RubyBinding/Test/RubyBinding.Tests.csproj +++ b/src/AddIns/BackendBindings/Ruby/RubyBinding/Test/RubyBinding.Tests.csproj @@ -267,7 +267,7 @@ - + diff --git a/src/AddIns/BackendBindings/Scripting/Project/ICSharpCode.Scripting.csproj b/src/AddIns/BackendBindings/Scripting/Project/ICSharpCode.Scripting.csproj index 32dc5f572e..3f4e163dbe 100644 --- a/src/AddIns/BackendBindings/Scripting/Project/ICSharpCode.Scripting.csproj +++ b/src/AddIns/BackendBindings/Scripting/Project/ICSharpCode.Scripting.csproj @@ -80,6 +80,7 @@ + @@ -96,6 +97,7 @@ + diff --git a/src/AddIns/BackendBindings/Scripting/Project/Src/LineIndenter.cs b/src/AddIns/BackendBindings/Scripting/Project/Src/LineIndenter.cs new file mode 100644 index 0000000000..930e00a292 --- /dev/null +++ b/src/AddIns/BackendBindings/Scripting/Project/Src/LineIndenter.cs @@ -0,0 +1,125 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Text; +using ICSharpCode.SharpDevelop.Editor; + +namespace ICSharpCode.Scripting +{ + public class LineIndenter + { + ITextEditor editor; + IDocument document; + IDocumentLine line; + IDocumentLine previousLine; + string previousLineText; + + public LineIndenter(ITextEditor editor, IDocumentLine line) + { + this.editor = editor; + this.line = line; + this.document = editor.Document; + } + + public bool Indent() + { + if (IsFirstLine()) { + return false; + } + + GetPreviousLine(); + + if (ShouldIncreaseLineIndent()) { + IncreaseLineIndent(); + return true; + } else if (ShouldDecreaseLineIndent()) { + DecreaseLineIndent(); + return true; + } + return false; + } + + bool IsFirstLine() + { + return line.LineNumber == 1; + } + + void GetPreviousLine() + { + int lineNumber = line.LineNumber - 1; + previousLine = document.GetLine(lineNumber); + previousLineText = previousLine.Text.Trim(); + } + + protected string PreviousLine { + get { return previousLineText; } + } + + protected virtual bool ShouldIncreaseLineIndent() + { + return false; + } + + protected virtual bool ShouldDecreaseLineIndent() + { + return false; + } + + void IncreaseLineIndent() + { + ModifyLineIndent(true); + } + + void DecreaseLineIndent() + { + ModifyLineIndent(false); + } + + void ModifyLineIndent(bool increaseIndent) + { + string previousLineIndentation = GetPreviousLineIndentation(); + string indentation = GetNewLineIndentation(previousLineIndentation, increaseIndent); + string newLineText = indentation + line.Text; + ReplaceLine(newLineText); + } + + string GetPreviousLineIndentation() + { + return GetIndentation(previousLine); + } + + string GetIndentation(IDocumentLine documentLine) + { + StringBuilder whitespace = new StringBuilder(); + foreach (char ch in documentLine.Text) { + if (Char.IsWhiteSpace(ch)) { + whitespace.Append(ch); + } else { + break; + } + } + return whitespace.ToString(); + } + + string GetNewLineIndentation(string previousLineIndentation, bool increaseIndent) + { + string singleIndent = editor.Options.IndentationString; + if (increaseIndent) { + return previousLineIndentation + singleIndent; + } + + // Decrease the new line indentation. + int decreaselength = previousLineIndentation.Length - singleIndent.Length; + if (decreaselength < 0) { + decreaselength = 0; + } + return previousLineIndentation.Substring(0, decreaselength); + } + + void ReplaceLine(string newLineText) + { + document.Replace(line.Offset, line.Length, newLineText); + } + } +} diff --git a/src/AddIns/BackendBindings/Scripting/Project/Src/ScriptingFormattingStrategy.cs b/src/AddIns/BackendBindings/Scripting/Project/Src/ScriptingFormattingStrategy.cs new file mode 100644 index 0000000000..6502b4a5b7 --- /dev/null +++ b/src/AddIns/BackendBindings/Scripting/Project/Src/ScriptingFormattingStrategy.cs @@ -0,0 +1,30 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.SharpDevelop.Editor; + +namespace ICSharpCode.Scripting +{ + public abstract class ScriptingFormattingStrategy : DefaultFormattingStrategy + { + public override void IndentLine(ITextEditor editor, IDocumentLine line) + { + LineIndenter indenter = CreateLineIndenter(editor, line); + if (!indenter.Indent()) { + base.IndentLine(editor, line); + } + } + + protected abstract LineIndenter CreateLineIndenter(ITextEditor editor, IDocumentLine line); + + public override void SurroundSelectionWithComment(ITextEditor editor) + { + SurroundSelectionWithSingleLineComment(editor, LineComment); + } + + public virtual string LineComment { + get { return String.Empty; } + } + } +}