I’m working on a Visual Studio 2022 C# extension to customize the text of C++ #pragma region #pragma endregion
1: default, 2: modified using the code below, 3: collapsed
I would like to ask how i could customize the text show when the block is collapsed and how to remove that outline border around it.
What i’m trying to achieve is to make it show just // REGION when collapsed:
And if possible to customize the text when its at the "collapsed state", i.e another font color, size, etc.
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Text.Tagging;
using Microsoft.VisualStudio.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Windows.Media;
namespace Extension;
internal class PragmaRegion : ITagger<ClassificationTag>
{
private IClassificationType _regionClassificationType = null;
private IClassificationType _transparentClassificationType = null;
internal PragmaRegion(ITextBuffer buffer,
IClassificationTypeRegistryService classificationTypeRegistry)
{
_regionClassificationType = classificationTypeRegistry.GetClassificationType("region");
_transparentClassificationType = classificationTypeRegistry.GetClassificationType("transparent");
}
public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
private static bool isPragmaRegion(string lineText, out int i)
{
for (i = 0; i < lineText.Length; i++)
{
char textAt = lineText[i];
if (textAt == '#') // Search for \s*#p
{
if (i + 1 < lineText.Length && lineText[i + 1] == 'p')
return true;
return false;
}
if (textAt != ' ' && textAt != '\t')
return false;
}
i = -1;
return false;
}
private static int _minLength = 14; // Length of the text "#pragma region"
IEnumerable<ITagSpan<ClassificationTag>> ITagger<ClassificationTag>.GetTags(NormalizedSnapshotSpanCollection spans)
{
if (spans.Count == 0)
yield break;
foreach (var currentSpan in spans)
{
foreach (var line in currentSpan.Snapshot.Lines)
{
var lineText = line.GetText();
if (lineText.Length < _minLength || !isPragmaRegion(lineText, out int regionIndex))
continue;
// Starting from regionIndex, look for "#pragma region" or "#pragma endregion"
string pragmaText = lineText.Substring(regionIndex);
if (pragmaText.Length < _minLength)
continue;
// Check if its #pragma region (14) or #pragma endregion (17)
int pragmaLength = pragmaText[8] == 'r' ? _minLength : 17;
int displayNameIndex = regionIndex + pragmaLength;
// Create tag for the pragma directive
yield return new TagSpan<ClassificationTag>(
new SnapshotSpan(line.Start + regionIndex, pragmaLength),
new ClassificationTag(_transparentClassificationType));
// Create tag for the display name (if any)
if (displayNameIndex >= 0 && displayNameIndex < lineText.Length)
{
string displayName = lineText.Substring(displayNameIndex);
if (!string.IsNullOrWhiteSpace(displayName))
{
yield return new TagSpan<ClassificationTag>(
new SnapshotSpan(line.Start + displayNameIndex, displayName.Length),
new ClassificationTag(_regionClassificationType));
}
}
}
}
}
}
// https://github.com/smhoff/regionsareevil
internal sealed class ClassifierProvider
{
[Export]
[Name("transparent")]
internal static ClassificationTypeDefinition TransparentDefinition;
[Export]
[Name("region")]
internal static ClassificationTypeDefinition RegionDefinition;
}
[Export(typeof(EditorFormatDefinition))]
[ClassificationType(ClassificationTypeNames = "transparent")]
[Name("Transparent")]
[DisplayName("Transparent")]
[UserVisible(true)]
[Order(After = "Default Priority", Before = "High Priority")]
internal sealed class TransparentClassification : ClassificationFormatDefinition
{
public TransparentClassification()
{
FontRenderingSize = 0.1;
}
}
[Export(typeof(EditorFormatDefinition))]
[ClassificationType(ClassificationTypeNames = "region")]
[Name("Region")]
[DisplayName("Region")]
[UserVisible(true)]
[Order(After = "Default Priority", Before = "High Priority")]
internal sealed class RegionClassification : ClassificationFormatDefinition
{
public RegionClassification()
{
ForegroundColor = Color.FromArgb(255, 71, 165, 10);
FontRenderingSize = 10;
//ForegroundOpacity = 0.5;
}
}
[Export(typeof(ITaggerProvider))]
[ContentType("C/C++")]
[TagType(typeof(ClassificationTag))]
internal class TaggerProvider : ITaggerProvider
{
[Import]
internal IClassificationTypeRegistryService _classificationTypeRegistry = null;
public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag
{
if (buffer == null)
return null;
return buffer.Properties.GetOrCreateSingletonProperty(
() => new PragmaRegion(buffer, _classificationTypeRegistry)) as ITagger<T>;
}
}

