2010-02-07 12 views

Répondre

29

Vous devez ajouter votre contrôleur en tant que délégué de l'objet NSTextStorage du NSTextView ([textView textStorage]), puis implémenter la méthode de délégation ‑textStorageDidProcessEditing:. Ceci est appelé chaque fois que le texte change.

Dans la méthode déléguée, vous devez obtenir l'objet NSTextStorage actuel à partir de la vue de texte à l'aide de la méthode -textStorage de NSTextView. NSTextStorage est une sous-classe de NSAttributedString et contient le contenu attribué de la vue.

Votre code doit ensuite analyser la chaîne et appliquer une coloration à toutes les plages de texte qui vous intéressent. Vous appliquez la couleur à une plage en utilisant quelque chose comme ça, qui applique une couleur jaune à la chaîne entière:

//get the range of the entire run of text 
NSRange area = NSMakeRange(0, [textStorage length]); 

//remove existing coloring 
[textStorage removeAttribute:NSForegroundColorAttributeName range:area]; 

//add new coloring 
[textStorage addAttribute:NSForegroundColorAttributeName 
        value:[NSColor yellowColor] 
        range:area]; 

Comment vous analysez le texte est à vous. NSScanner est une classe utile à utiliser lors de l'analyse du texte. Notez que cette méthode n'est en aucun cas la manière la plus efficace de gérer la coloration de la syntaxe.

Si les documents que vous éditez sont très volumineux, vous voudrez probablement envisager de décharger l'analyse dans un fil séparé et/ou d'être astucieux sur les sections de texte réparées.

+1

Ceci est un peu vieux, mais comment j'implémenterais '-textStorageDidProcessEditing:' dans le délégué? – Sirens

+0

Comme toute autre méthode de délégué. Recherchez la [signature de la méthode] (http://developer.apple.com/library/mac/documentation/cocoa/reference/NSTextStorageDelegate_Protocol/Reference/Reference.html#//apple_ref/doc/uid/TP40008627-CH1- DontLinkElementID_3) dans les documents et placez-le dans l'implémentation de votre objet délégué. Assurez-vous que votre objet délégué est défini en tant que délégué de 'NSTextStorage'. –

+0

Merci, +1. Votre méthode fonctionne beaucoup mieux que ma tentative – Sirens

2

Bien sûr. Vous pouvez donner à la NSTextView une NSAttributedString, et certaines des choses que vous pouvez faire avec la chaîne attribuée sont appliquer des couleurs à certaines sous-chaînes de la chaîne.

Ou vous pouvez search on Google et voir que beaucoup de gens ont fait des choses avec cela avant.

Je recommanderais probablement d'utiliser OkudaKit.

+1

il semble OkudaKit n'est plus en développement – Stephan

4

Je vous recommande de commencer par lire le CocoaDev page à propos de Syntax Highlighing. Beaucoup de gens sont venus avec des solutions pour divers objectifs.

Si vous souhaitez mettre en surbrillance la syntaxe du code source, je vous suggère de regarder le UKSyntaxColoredTextDocument de Uli Kusterer.

+0

Lol, jamais téléchargé autant d'échantillons à partir de 1 site unique, génial! –

+0

l'outil mentionné est maintenant sur github: [UKSyntaxColoredTextDocument] (https://github.com/uliwitness/UKSyntaxColoredTextDocument) – Stephan

9

Rob Keniger's answer est bon, mais pour quelqu'un qui cherche un exemple plus concret, voici une petite syntaxe surlignée que j'ai écrit qui devrait mettre en évidence la syntaxe du modèle RegEx. Je veux que \ soit gris, avec le personnage qui les suit immédiatement pour être noir. Je veux que $ soit rouge, avec un caractère immédiatement après le $ pour être également rouge. Tout le reste devrait être noir. Voici ma solution:

J'ai fait une classe surligneur de modèle, avec un en-tête qui ressemble à ceci:

@interface RMETemplateHighlighter : NSObject <NSTextStorageDelegate> 

@end 

J'initialize dans le fichier nib comme un objet et de le raccorder à mon contrôleur de vue avec un sortie.En awakeFromNib du contrôleur de vue, j'ai ce (où replacer est mon exutoire NSTextView et templateHighlighter est la sortie de la classe ci-dessus):

self.replacer.textStorage.delegate = self.templateHighlighter; 

Et mon implémentation ressemble à ceci:

- (void)textStorageDidProcessEditing:(NSNotification *)notification { 
    NSTextStorage *textStorage = notification.object; 
    NSString *string = textStorage.string; 
    NSUInteger n = string.length; 
    [textStorage removeAttribute:NSForegroundColorAttributeName range:NSMakeRange(0, n)]; 
    for (NSUInteger i = 0; i < n; i++) { 
     unichar c = [string characterAtIndex:i]; 
     if (c == '\\') { 
      [textStorage addAttribute:NSForegroundColorAttributeName value:[NSColor lightGrayColor] range:NSMakeRange(i, 1)]; 
      i++; 
     } else if (c == '$') { 
      NSUInteger l = ((i < n - 1) && isdigit([string characterAtIndex:i+1])) ? 2 : 1; 
      [textStorage addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:NSMakeRange(i, l)]; 
      i++; 
     } 
    } 
} 

Alors là vous allez, un exemple pleinement fonctionnel. Il y avait quelques détails qui m'ont fait trébucher pendant ~ 10 minutes, comme le fait que vous devez sortir la chaîne de textStorage pour accéder aux caractères individuels ... peut-être que cela sauvera d'autres personnes quelques minutes.

+0

Merci, fonctionne comme annoncé et m'a sauvé un certain temps. –

+0

Cela fonctionne très bien pour la mise en évidence de la syntaxe, mais dans mon cas, semble également casser le 'contentSize' de mon UITextView. Plus précisément, 'contentSize' semble toujours être la largeur de UITextView x la hauteur d'une seule ligne. – carloe

+0

@carloe: Ceci est une solution OS X ... vous mentionnez 'UITextView' (pas ** NS **' TextView') donc je suppose que vous travaillez avec iOS. Il peut y avoir de petites différences entre les API ... ce qui est le mieux sur OS X n'est peut-être pas le meilleur sur iOS. – ArtOfWarfare