using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.Scripting.Editors.Document;
namespace Tango.Scripting.Editors.Folding
{
///
/// Allows producing foldings from a document based on braces.
///
public class BraceFoldingStrategy
{
private class FoldingDefinition
{
public String Open { get; set; }
public String Close { get; set; }
public FoldingDefinition(String open, String close)
{
Open = open;
Close = close;
}
}
private class FoldingOffset
{
public FoldingDefinition Definition { get; set; }
public int Offset { get; set; }
}
private List foldings = new List()
{
new FoldingDefinition("namespace","}"),
new FoldingDefinition("public","}"),
new FoldingDefinition("private","}"),
new FoldingDefinition("internal","}"),
new FoldingDefinition("if","}"),
new FoldingDefinition("class","}"),
new FoldingDefinition("while","}"),
new FoldingDefinition("static void","}"),
new FoldingDefinition("/// ","/// "),
};
///
/// Gets/Sets the opening brace. The default value is '{'.
///
public char OpeningBrace { get; set; }
///
/// Gets/Sets the closing brace. The default value is '}'.
///
public char ClosingBrace { get; set; }
///
/// Creates a new BraceFoldingStrategy.
///
public BraceFoldingStrategy()
{
this.OpeningBrace = '{';
this.ClosingBrace = '}';
}
public void UpdateFoldings(FoldingManager manager, TextDocument document)
{
int firstErrorOffset;
IEnumerable newFoldings = CreateNewFoldings(document, out firstErrorOffset);
manager.UpdateFoldings(newFoldings, firstErrorOffset);
}
///
/// Create s for the specified document.
///
public IEnumerable CreateNewFoldings(TextDocument document, out int firstErrorOffset)
{
firstErrorOffset = -1;
return CreateNewFoldings(document);
}
///
/// Create s for the specified document.
///
public IEnumerable CreateNewFoldings(ITextSource document)
{
List newFoldings = new List();
Stack startOffsets = new Stack();
int lastNewLineOffset = 0;
char openingBrace = this.OpeningBrace;
char closingBrace = this.ClosingBrace;
var doc = document as TextDocument;
String current_line = String.Empty;
foreach (var line in doc.Lines)
{
String lineTextFull = doc.GetText(line);
String lineText = lineTextFull.TrimStart('\t', ' ').TrimEnd('\t', ' ');
var open_definition = foldings.SingleOrDefault(x => lineText.StartsWith(x.Open + " ") || lineText == x.Open);
if (open_definition != null)
{
current_line = lineTextFull;
startOffsets.Push(new FoldingOffset()
{
Definition = open_definition,
Offset = line.EndOffset
});
}
else if (foldings.Any(x => lineText.EndsWith(x.Close)))
{
if (startOffsets.Count > 0)
{
var startOffset = startOffsets.Pop();
//if (startOffset < lastNewLineOffset)
//{
newFoldings.Add(new NewFolding(startOffset.Offset, Math.Min(line.EndOffset, doc.TextLength))
{
//Name = current_line,
});
}
//}
}
else if (lineText.EndsWith("\n") || lineText.EndsWith("\r"))
{
lastNewLineOffset = line.Offset + 1;
}
}
//for (int i = 0; i < document.TextLength; i++)
//{
// char c = document.GetCharAt(i);
// if (c == openingBrace)
// {
// startOffsets.Push(i);
// }
// else if (c == closingBrace && startOffsets.Count > 0)
// {
// int startOffset = startOffsets.Pop();
// // don't fold if opening and closing brace are on the same line
// if (startOffset < lastNewLineOffset)
// {
// newFoldings.Add(new NewFolding(startOffset, i + 1));
// }
// }
// else if (c == '\n' || c == '\r')
// {
// lastNewLineOffset = i + 1;
// }
//}
newFoldings.Sort((a, b) => a.StartOffset.CompareTo(b.StartOffset));
return newFoldings;
}
}
}