From af5a6c6ade32769ab9a278e42d169fd85829b13e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 12 Jul 2009 08:14:56 +0000 Subject: [PATCH] ported Indent and Comment commands to SharpDevelop 4.0 git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4431 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- AddIns/ICSharpCode.SharpDevelop.addin | 24 +-- .../CSharpFormattingStrategy.cs | 10 +- .../AvalonEdit.AddIn/AvalonEdit.AddIn.addin | 24 +-- .../Project/Src/XmlFormattingStrategy.cs | 5 + .../Project/ICSharpCode.SharpDevelop.csproj | 3 + .../Src/Editor/Commands/CommentRegion.cs | 33 ++++ .../Src/Editor/Commands/IndentSelection.cs | 43 +++++ .../Project/Src/Editor/IFormattingStrategy.cs | 179 ++++++++++++++++++ 8 files changed, 298 insertions(+), 23 deletions(-) create mode 100644 src/Main/Base/Project/Src/Editor/Commands/CommentRegion.cs create mode 100644 src/Main/Base/Project/Src/Editor/Commands/IndentSelection.cs diff --git a/AddIns/ICSharpCode.SharpDevelop.addin b/AddIns/ICSharpCode.SharpDevelop.addin index 749ab298b4..d4604bb2b3 100644 --- a/AddIns/ICSharpCode.SharpDevelop.addin +++ b/AddIns/ICSharpCode.SharpDevelop.addin @@ -1236,7 +1236,7 @@ class = "ICSharpCode.SharpDevelop.Commands.ClearRecentProjects" /> - + - - - - - + class = "ICSharpCode.SharpDevelop.Editor.Commands.CommentRegion"/> - + class = "ICSharpCode.SharpDevelop.Editor.Commands.IndentSelection" /> + + + + + @@ -1809,11 +1808,11 @@ - + + class = "ICSharpCode.SharpDevelop.Editor.Commands.CommentRegion"/> "); + } + static void TryIndent(ITextEditor editor, int begin, int end) { string currentIndentation = ""; diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 472e9226fd..f61a3361fa 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -90,6 +90,8 @@ + + @@ -816,6 +818,7 @@ + diff --git a/src/Main/Base/Project/Src/Editor/Commands/CommentRegion.cs b/src/Main/Base/Project/Src/Editor/Commands/CommentRegion.cs new file mode 100644 index 0000000000..84fedb7ef8 --- /dev/null +++ b/src/Main/Base/Project/Src/Editor/Commands/CommentRegion.cs @@ -0,0 +1,33 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.SharpDevelop.Gui; +using System; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop; + +namespace ICSharpCode.SharpDevelop.Editor.Commands +{ + /// + /// Description of CommentRegion + /// + public class CommentRegion : AbstractMenuCommand + { + /// + /// Starts the command + /// + public override void Run() + { + ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; + + if (provider == null) + return; + + provider.TextEditor.FormattingStrategy.SurroundSelectionWithComment(provider.TextEditor); + } + } +} diff --git a/src/Main/Base/Project/Src/Editor/Commands/IndentSelection.cs b/src/Main/Base/Project/Src/Editor/Commands/IndentSelection.cs new file mode 100644 index 0000000000..819e480be8 --- /dev/null +++ b/src/Main/Base/Project/Src/Editor/Commands/IndentSelection.cs @@ -0,0 +1,43 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.SharpDevelop.Gui; +using System; +using System.Windows.Forms; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Editor; + +namespace ICSharpCode.SharpDevelop.Editor.Commands +{ + /// + /// Description of IndentSelection + /// + public class IndentSelection : AbstractMenuCommand + { + /// + /// Starts the command + /// + public override void Run() + { + ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; + + if (provider == null) + return; + + int beginLine = 1; + int endLine = provider.TextEditor.Document.TotalNumberOfLines; + + if (provider.TextEditor.SelectionLength != 0) { + beginLine = provider.TextEditor.Document.GetLineForOffset(provider.TextEditor.SelectionStart).LineNumber; + endLine = provider.TextEditor.Document.GetLineForOffset(provider.TextEditor.SelectionStart + provider.TextEditor.SelectionLength).LineNumber; + } + + provider.TextEditor.FormattingStrategy.IndentLines(provider.TextEditor, beginLine, endLine); + } + } +} diff --git a/src/Main/Base/Project/Src/Editor/IFormattingStrategy.cs b/src/Main/Base/Project/Src/Editor/IFormattingStrategy.cs index 94eb32e8f4..94ea72bb90 100644 --- a/src/Main/Base/Project/Src/Editor/IFormattingStrategy.cs +++ b/src/Main/Base/Project/Src/Editor/IFormattingStrategy.cs @@ -6,6 +6,8 @@ // using System; +using ICSharpCode.NRefactory; +using System.Collections.Generic; namespace ICSharpCode.SharpDevelop.Editor { @@ -28,6 +30,11 @@ namespace ICSharpCode.SharpDevelop.Editor /// This function sets the indentation in a range of lines. /// void IndentLines(ITextEditor editor, int beginLine, int endLine); + + /// + /// This function surrounds the selected text with a comment. + /// + void SurroundSelectionWithComment(ITextEditor editor); } public class DefaultFormattingStrategy : IFormattingStrategy @@ -59,5 +66,177 @@ namespace ICSharpCode.SharpDevelop.Editor } } } + + public virtual void SurroundSelectionWithComment(ITextEditor editor) + { + } + + /// + /// Default implementation for single line comments. + /// + protected void SurroundSelectionWithSingleLineComment(ITextEditor editor, string comment) + { + using (editor.Document.OpenUndoGroup()) { + Location startPosition = editor.Document.OffsetToPosition(editor.SelectionStart); + Location endPosition = editor.Document.OffsetToPosition(editor.SelectionStart + editor.SelectionLength); + + List lines = new List(); + bool removeComment = true; + + for (int i = startPosition.Line; i <= endPosition.Line; i++) { + lines.Add(editor.Document.GetLine(i)); + if (!lines[i - startPosition.Line].Text.Trim().StartsWith(comment)) + removeComment = false; + } + + foreach (IDocumentLine line in lines) { + if (removeComment) { + editor.Document.Remove(line.Offset + line.Text.IndexOf(comment), comment.Length); + } else { + editor.Document.Insert(line.Offset, comment); + } + } + } + } + + /// + /// Default implementation for multiline comments. + /// + protected void SurroundSelectionWithBlockComment(ITextEditor editor, string blockStart, string blockEnd) + { + using (editor.Document.OpenUndoGroup()) { + int startOffset = editor.SelectionStart; + int endOffset = editor.SelectionStart + editor.SelectionLength; + + if (editor.SelectionLength == 0) { + IDocumentLine line = editor.Document.GetLineForOffset(editor.SelectionStart); + startOffset = line.Offset; + endOffset = line.Offset + line.Length; + } + + BlockCommentRegion region = FindSelectedCommentRegion(editor, blockStart, blockEnd); + + if (region != null) { + editor.Document.Remove(region.EndOffset, region.CommentEnd.Length); + editor.Document.Remove(region.StartOffset, region.CommentStart.Length); + } else { + editor.Document.Insert(endOffset, blockEnd); + editor.Document.Insert(startOffset, blockStart); + } + } + } + + public static BlockCommentRegion FindSelectedCommentRegion(ITextEditor editor, string commentStart, string commentEnd) + { + IDocument document = editor.Document; + + if (document.TextLength == 0) { + return null; + } + + // Find start of comment in selected text. + + int commentEndOffset = -1; + string selectedText = editor.SelectedText; + + int commentStartOffset = selectedText.IndexOf(commentStart); + if (commentStartOffset >= 0) { + commentStartOffset += editor.SelectionStart; + } + + // Find end of comment in selected text. + + if (commentStartOffset >= 0) { + commentEndOffset = selectedText.IndexOf(commentEnd, commentStartOffset + commentStart.Length - editor.SelectionStart); + } else { + commentEndOffset = selectedText.IndexOf(commentEnd); + } + + if (commentEndOffset >= 0) { + commentEndOffset += editor.SelectionStart; + } + + // Find start of comment before or partially inside the + // selected text. + + int commentEndBeforeStartOffset = -1; + if (commentStartOffset == -1) { + int offset = editor.SelectionStart + editor.SelectionLength + commentStart.Length - 1; + if (offset > document.TextLength) { + offset = document.TextLength; + } + string text = document.GetText(0, offset); + commentStartOffset = text.LastIndexOf(commentStart); + if (commentStartOffset >= 0) { + // Find end of comment before comment start. + commentEndBeforeStartOffset = text.IndexOf(commentEnd, commentStartOffset, editor.SelectionStart - commentStartOffset); + if (commentEndBeforeStartOffset > commentStartOffset) { + commentStartOffset = -1; + } + } + } + + // Find end of comment after or partially after the + // selected text. + + if (commentEndOffset == -1) { + int offset = editor.SelectionStart + 1 - commentEnd.Length; + if (offset < 0) { + offset = editor.SelectionStart; + } + string text = document.GetText(offset, document.TextLength - offset); + commentEndOffset = text.IndexOf(commentEnd); + if (commentEndOffset >= 0) { + commentEndOffset += offset; + } + } + + if (commentStartOffset != -1 && commentEndOffset != -1) { + return new BlockCommentRegion(commentStart, commentEnd, commentStartOffset, commentEndOffset); + } + + return null; + } + } + + public class BlockCommentRegion + { + public string CommentStart { get; private set; } + public string CommentEnd { get; private set; } + public int StartOffset { get; private set; } + public int EndOffset { get; private set; } + + /// + /// The end offset is the offset where the comment end string starts from. + /// + public BlockCommentRegion(string commentStart, string commentEnd, int startOffset, int endOffset) + { + this.CommentStart = commentStart; + this.CommentEnd = commentEnd; + this.StartOffset = startOffset; + this.EndOffset = endOffset; + } + + public override int GetHashCode() + { + int hashCode = 0; + unchecked { + if (CommentStart != null) hashCode += 1000000007 * CommentStart.GetHashCode(); + if (CommentEnd != null) hashCode += 1000000009 * CommentEnd.GetHashCode(); + hashCode += 1000000021 * StartOffset.GetHashCode(); + hashCode += 1000000033 * EndOffset.GetHashCode(); + } + return hashCode; + } + + public override bool Equals(object obj) + { + BlockCommentRegion other = obj as BlockCommentRegion; + if (other == null) return false; + return this.CommentStart == other.CommentStart && + this.CommentEnd == other.CommentEnd && + this.StartOffset == other.StartOffset && + this.EndOffset == other.EndOffset; + } } }