#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

168 lines
5.4 KiB

// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows.Documents;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Utils;
namespace ICSharpCode.SharpDevelop.Editor
{
/// <summary>
/// Extension methods for ITextEditor and IDocument.
/// </summary>
public static class DocumentUtilitites
{
/// <summary>
/// Gets the word in front of the caret.
/// </summary>
public static string GetWordBeforeCaret(this ITextEditor editor)
{
if (editor == null)
throw new ArgumentNullException("editor");
int endOffset = editor.Caret.Offset;
int startOffset = FindPrevWordStart(editor.Document, endOffset);
if (startOffset < 0)
return string.Empty;
else
return editor.Document.GetText(startOffset, endOffset - startOffset);
}
static readonly char[] whitespaceChars = {' ', '\t'};
/// <summary>
/// Replaces the text in a line.
/// If only whitespace at the beginning and end of the line was changed, this method
/// only adjusts the whitespace and doesn't replace the other text.
/// </summary>
public static void SmartReplaceLine(this IDocument document, IDocumentLine line, string newLineText)
{
if (document == null)
throw new ArgumentNullException("document");
if (line == null)
throw new ArgumentNullException("line");
if (newLineText == null)
throw new ArgumentNullException("newLineText");
string newLineTextTrim = newLineText.Trim(whitespaceChars);
string oldLineText = line.Text;
if (oldLineText == newLineText)
return;
int pos = oldLineText.IndexOf(newLineTextTrim, StringComparison.Ordinal);
if (newLineTextTrim.Length > 0 && pos >= 0) {
using (document.OpenUndoGroup()) {
// find whitespace at beginning
int startWhitespaceLength = 0;
while (startWhitespaceLength < newLineText.Length) {
char c = newLineText[startWhitespaceLength];
if (c != ' ' && c != '\t')
break;
startWhitespaceLength++;
}
// find whitespace at end
int endWhitespaceLength = newLineText.Length - newLineTextTrim.Length - startWhitespaceLength;
// replace whitespace sections
int lineOffset = line.Offset;
document.Replace(lineOffset + pos + newLineTextTrim.Length, line.Length - pos - newLineTextTrim.Length, newLineText.Substring(newLineText.Length - endWhitespaceLength));
document.Replace(lineOffset, pos, newLineText.Substring(0, startWhitespaceLength));
}
} else {
document.Replace(line.Offset, line.Length, newLineText);
}
}
/// <summary>
/// Finds the first word start in the document before offset.
/// </summary>
/// <returns>The offset of the word start, or -1 if there is no word start before the specified offset.</returns>
public static int FindPrevWordStart(this IDocument document, int offset)
{
return TextUtilities.GetNextCaretPosition(GetTextSource(document), offset, LogicalDirection.Backward, CaretPositioningMode.WordStart);
}
/// <summary>
/// Gets the word at the specified position.
/// </summary>
public static string GetWordAt(this IDocument document, int offset)
{
if (document == null)
throw new ArgumentNullException("document");
throw new NotImplementedException();
}
/// <summary>
/// Gets all indentation starting at offset.
/// </summary>
/// <param name="document">The document.</param>
/// <param name="offset">The offset where the indentation starts.</param>
/// <returns>The indentation text.</returns>
public static string GetIndentation(IDocument document, int offset)
{
ISegment segment = TextUtilities.GetWhitespaceAfter(GetTextSource(document), offset);
return document.GetText(segment.Offset, segment.Length);
}
/// <summary>
/// Gets the line terminator for the document around the specified line number.
/// </summary>
public static string GetLineTerminator(IDocument document, int lineNumber)
{
IDocumentLine line = document.GetLine(lineNumber);
if (line.DelimiterLength == 0) {
// at the end of the document, there's no line delimiter, so use the delimiter
// from the previous line
if (lineNumber == 1)
return Environment.NewLine;
line = document.GetLine(lineNumber - 1);
}
return document.GetText(line.Offset + line.Length, line.DelimiterLength);
}
#region ITextSource implementation
public static ICSharpCode.AvalonEdit.Document.ITextSource GetTextSource(IDocument document)
{
if (document == null)
throw new ArgumentNullException("document");
return new DocumentTextSource(document);
}
sealed class DocumentTextSource : ICSharpCode.AvalonEdit.Document.ITextSource
{
readonly IDocument document;
public DocumentTextSource(IDocument document)
{
this.document = document;
}
public event EventHandler TextChanged {
add { document.TextChanged += value; }
remove { document.TextChanged -= value; }
}
public string Text {
get { return document.Text; }
}
public int TextLength {
get { return document.TextLength; }
}
public char GetCharAt(int offset)
{
return document.GetCharAt(offset);
}
public string GetText(int offset, int length)
{
return document.GetText(offset, length);
}
}
#endregion
}
}