protected override bool ReadContent() { var blockInfo = new CodeBlockInfo { OuterStart = new TextRange(stream.Position, 0) }; lineStart = stream.Position; if (!TryReadSpaces(spaceCount)) { return(false); } while (true) { var thisLineStart = lineStart; var range = TryConsumeContentLine(); if (range == null) { break; } blockInfo.OuterEnd = new TextRange(range.End, 0); // Get the character count of the indent, which may be different if tabs are involved. var indentSize = range.Start - thisLineStart; range.Expand(-indentSize, 0); ReportArtifact(new CodeLineArtifact(blockInfo, range, indentSize, 0)); } return(true); }
static string Caption(CodeBlockInfo block) { if (string.IsNullOrEmpty(block.Language)) { return("[ Code Block ]"); } return("[ " + block.Language + " Code Block ]"); }
public IEnumerable <ITagSpan <IOutliningRegionTag> > GetTags(NormalizedSnapshotSpanCollection spans) { if (!spans.Any()) { yield break; } var artifacts = artifactsGetter(); // Start from the first artifact after the start // position. Since code blocks will always have // an end-boundary artifact, this will work even // if we start in the middle of a code block. int i = artifacts.GetFirstItemAfterOrAtPosition(spans[0].Start); if (i < 0) { yield break; } CodeBlockInfo lastBlock = null; for (; i < artifacts.Count; i++) { var cba = artifacts[i] as ICodeBlockArtifact; // Skip artifacts that aren't in code blocks, and // those in code blocks we have already returned. if (cba == null || cba.BlockInfo == lastBlock) { continue; } lastBlock = cba.BlockInfo; // Skip single-line indented code blocks, but not single-line fenced code blocks if (lastBlock.CodeLines.Count == 1 && lastBlock.OuterEnd.End == lastBlock.CodeLines[0].End) { continue; } yield return(new TagSpan <IOutliningRegionTag>( new SnapshotSpan(spans[0].Snapshot, Span.FromBounds(lastBlock.OuterStart.Start, lastBlock.OuterEnd.End)), tagCreator( Caption(lastBlock), lastBlock.CodeLines .Select(a => a.InnerRange.ToSnapshotSpan(spans[0].Snapshot)) .ToList() // Force eager evaluation; this query is only enumerated when a tooltip is shown, so we need to grab the snapshot ) )); if (lastBlock.OuterStart.Start > spans.Last().End) { break; // If we have completely passed the requested range, stop. } } }
static string Caption(CodeBlockInfo block) { if (string.IsNullOrEmpty(block.Language)) { return("[ code block ]"); } return("[ " + block.Language.ToUpperInvariant() + " code block ]"); }
public CodeLineArtifact(CodeBlockInfo blockInfo, ITextRange range, int leftLength, int rightLength) : base(ArtifactTreatAs.Code, range, leftLength, rightLength, MarkdownClassificationTypes.MarkdownCode, true) { if (blockInfo == null) { throw new ArgumentNullException("blockInfo"); } BlockInfo = blockInfo; }
public BlockBoundaryArtifact(CodeBlockInfo blockInfo, BoundaryType type) : base(ArtifactTreatAs.Code, type == BoundaryType.Start ? blockInfo.OuterStart : blockInfo.OuterEnd, 0, 0, MarkdownClassificationTypes.MarkdownCode, true) { BlockInfo = blockInfo; Boundary = type; // Replace the BlockInfo's TextRanges with our created // artifacts so that they will be adjusted as the user // edits the text. TextRangeCollection shifts existing // artifacts as the user types elsewhere. if (type == BoundaryType.Start) BlockInfo.OuterStart = this; else BlockInfo.OuterEnd = this; }
protected override bool ReadContent() { SkipSpaces(3); var sepStart = stream.Position; if (TryConsume("```")) { fence = "```"; } else if (TryConsume("~~~")) { fence = "~~~"; } else { return(false); } blockInfo = new CodeBlockInfo { OuterStart = TextRange.FromBounds(sepStart, stream.Position) }; var langRange = TryConsumeContentLine(); if (langRange != null) { blockInfo.Language = stream.GetSubstringAt(langRange.Start, langRange.Length); } while (true) { var range = TryConsumeContentLine(); if (range == null) { break; } ReportArtifact(new CodeLineArtifact(blockInfo, range, 0, 0)); } // If the stream ended without a closing fence, give an empty end. if (blockInfo.OuterEnd == null) { blockInfo.OuterEnd = new TextRange(stream.Length, 0); } return(true); }
public BlockBoundaryArtifact(CodeBlockInfo blockInfo, BoundaryType type) : base(ArtifactTreatAs.Code, type == BoundaryType.Start ? blockInfo.OuterStart : blockInfo.OuterEnd, 0, 0, MarkdownClassificationTypes.MarkdownCode, true) { BlockInfo = blockInfo; Boundary = type; // Replace the BlockInfo's TextRanges with our created // artifacts so that they will be adjusted as the user // edits the text. TextRangeCollection shifts existing // artifacts as the user types elsewhere. if (type == BoundaryType.Start) { BlockInfo.OuterStart = this; } else { BlockInfo.OuterEnd = this; } }
public void GetArtifacts(ITextProvider text, ArtifactCollection artifactCollection) { var parser = new MarkdownParser(new TabAwareCharacterStream(text)); CodeBlockInfo lastBlock = null; parser.ArtifactFound += (s, e) => { var cla = e.Artifact as CodeLineArtifact; if (cla != null) { if (lastBlock == null || lastBlock != cla.BlockInfo) { if (lastBlock != null) { artifactCollection.Add(new BlockBoundaryArtifact(lastBlock, BoundaryType.End)); } lastBlock = cla.BlockInfo; artifactCollection.Add(new BlockBoundaryArtifact(cla.BlockInfo, BoundaryType.Start)); } // Don't add artifacts for HTML code lines. //if ((cla.BlockInfo.Language ?? "").StartsWith("htm", StringComparison.OrdinalIgnoreCase)) //{ // cla.BlockInfo.IsExtradited = true; // return; //} } // If we got a non-block artifact after a block end, add the end marker. else if (lastBlock != null && e.Artifact.Start >= lastBlock.OuterEnd.End) { artifactCollection.Add(new BlockBoundaryArtifact(lastBlock, BoundaryType.End)); lastBlock = null; } artifactCollection.Add(e.Artifact); }; parser.Parse(); if (lastBlock != null) { artifactCollection.Add(new BlockBoundaryArtifact(lastBlock, BoundaryType.End)); } }
public CodeLineArtifact(CodeBlockInfo blockInfo, ITextRange range, int leftLength, int rightLength) : base(ArtifactTreatAs.Code, range, leftLength, rightLength, MarkdownClassificationTypes.MarkdownCode, true) { if (blockInfo == null) throw new ArgumentNullException("blockInfo"); BlockInfo = blockInfo; }
protected override bool ReadContent() { SkipSpaces(3); var sepStart = stream.Position; if (TryConsume("```")) fence = "```"; else if (TryConsume("~~~")) fence = "~~~"; else return false; blockInfo = new CodeBlockInfo { OuterStart = TextRange.FromBounds(sepStart, stream.Position) }; var langRange = TryConsumeContentLine(); if (langRange != null) blockInfo.Language = stream.GetSubstringAt(langRange.Start, langRange.Length); while (true) { var range = TryConsumeContentLine(); if (range == null) break; ReportArtifact(new CodeLineArtifact(blockInfo, range, 0, 0)); } // If the stream ended without a closing fence, give an empty end. if (blockInfo.OuterEnd == null) blockInfo.OuterEnd = new TextRange(stream.Length, 0); return true; }
protected override bool ReadContent() { var blockInfo = new CodeBlockInfo { OuterStart = new TextRange(stream.Position, 0) }; lineStart = stream.Position; if (!TryReadSpaces(spaceCount)) return false; while (true) { var thisLineStart = lineStart; var range = TryConsumeContentLine(); if (range == null) break; blockInfo.OuterEnd = new TextRange(range.End, 0); // Get the character count of the indent, which may be different if tabs are involved. var indentSize = range.Start - thisLineStart; range.Expand(-indentSize, 0); ReportArtifact(new CodeLineArtifact(blockInfo, range, indentSize, 0)); } return true; }