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; } } }