2017-04-17 12 views
0

Je sais comment utiliser VS Extensibility pour obtenir le texte entier du document actif. Malheureusement, cela me donne seulement le texte et ne me donne pas le formatage, et je le veux aussi.Comment obtenir l'intégralité du document actif Visual Studio ... avec formatage

Je peux, par exemple, obtenir un IWpfTextView mais une fois que je l'ai compris, je ne sais pas quoi en faire. Existe-t-il des exemples de formatage? Je ne suis vraiment intéressé par la couleur de premier plan/arrière-plan du texte, c'est tout.

Note: J'ai besoin du texte mis en forme sur chaque modification, donc malheureusement faire et couper-coller en utilisant le presse-papiers est pas une option.

+0

Pouvez-vous donner des détails plus précis sur ce que vous essayez de faire avec le texte? Il pourrait y avoir quelque chose d'autre qui fonctionnerait mieux que les couleurs ... – Jimmy

+0

@Jimmy Je dois simplement stocker le texte. avec le formatage. sur chaque touche tapée ou chaque changement (par exemple, refactoring) effectué. Je suis d'accord avec les données * diff *, si c'est possible. –

+0

@DmitryNesteruk Pour le dire autrement, est-ce que * color * est important, ou est-ce qu'une autre indication des limites de formatage fonctionnerait pour vous? – Jimmy

Répondre

1

La méthode la plus simple est probablement de sélectionner tout le texte et de le copier dans le presse-papiers. VS met le texte riche dans le presse-papiers, donc quand vous collez, ailleurs, vous obtiendrez les couleurs (en supposant que vous manipulez du texte riche dans votre destination).

+0

Malheureusement, cela est impossible du point de vue informatique car j'ai besoin du formatage à chaque édition. Je vais clarifier la réponse. –

1

Voici ma solution pas la plus simple. TL; DR: vous pouvez passer au code https://github.com/jimmylewis/GetVSTextViewFormattedTextSample.

L'éditeur VS utilise des "classifications" pour afficher des segments de texte ayant une signification particulière. Ces classifications peuvent ensuite être formatées différemment en fonction de la langue et des paramètres utilisateur.

Il existe une API pour obtenir les classifications dans un document, mais cela n'a pas fonctionné pour moi. Ou other people, apparemment. Mais nous pouvons encore obtenir les classifications par un ITagAggregator<IClassificationTag>, comme décrit dans le lien précédent, ou ici:

[Import] 
IViewTagAggregatorFactoryService tagAggregatorFactory = null; 

// in some method... 
var classificationAggregator = tagAggregatorFactory.CreateTagAggregator<IClassificationTag>(textView); 
var wholeBufferSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, 0, textBuffer.CurrentSnapshot.Length); 
var tags = classificationAggregator.GetTags(wholeBufferSpan); 

Armé de ceux-ci, nous pouvons reconstruire le document. Il est important de noter que certains textes sont et non classés, donc vous devez tout assembler en morceaux. Il est également notable qu'à ce stade, nous n'avons aucune idée de la façon dont l'une de ces étiquettes est formatée, c'est-à-dire les couleurs utilisées pendant le rendu. Si vous le souhaitez, vous pouvez définir votre propre correspondance de IClassificationType à la couleur de votre choix. Ou, nous pouvons demander à VS pour ce qu'il ferait en utilisant un IClassificationFormatMap. Encore une fois, rappelez-vous, cela est affectée par les paramètres utilisateur, la lumière par rapport à thème sombre, etc.

De toute façon, il pourrait ressembler à ceci:

// Magic sauce pt1: See the example repo for an RTFStringBuilder I threw together. 
RTFStringBuilder sb = new RTFStringBuilder(); 
var wholeBufferSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, 0, textBuffer.CurrentSnapshot.Length); 
// Magic sauce pt2: see the example repo, but it's basically just 
// mapping the spans from the snippet above with the formatting settings 
// from the IClassificationFormatMap. 
var textSpans = GetTextSpansWithFormatting(textBuffer); 

int currentPos = 0; 
var formattedSpanEnumerator = textSpans.GetEnumerator(); 
while (currentPos < wholeBufferSpan.Length && formattedSpanEnumerator.MoveNext()) 
{ 
    var spanToFormat = formattedSpanEnumerator.Current; 
    if (currentPos < spanToFormat.Span.Start) 
    { 
     int unformattedLength = spanToFormat.Span.Start - currentPos; 
     SnapshotSpan unformattedSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, currentPos, unformattedLength); 
     sb.AppendText(unformattedSpan.GetText(), System.Drawing.Color.Black); 
    } 

    System.Drawing.Color textColor = GetTextColor(spanToFormat.Formatting.ForegroundBrush); 
    sb.AppendText(spanToFormat.Span.GetText(), textColor); 

    currentPos = spanToFormat.Span.End; 
} 

if (currentPos < wholeBufferSpan.Length) 
{ 
    // append any remaining unformatted text 
    SnapshotSpan unformattedSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, currentPos, wholeBufferSpan.Length - currentPos); 
    sb.AppendText(unformattedSpan.GetText(), System.Drawing.Color.Black); 
} 

return sb.ToString(); 

Hope this helps avec tout ce que vous faites. L'exemple de repo vous demandera si vous voulez que le texte mis en forme dans le presse-papiers après chaque édition, mais c'était juste une manière sale que je pourrais tester et voir que cela a fonctionné. C'est agaçant, mais c'était juste un PoC.