2010-02-07 28 views

Respuesta

29

Usted debe agregar el controlador como el delegado del NSTextStorage objeto de la NSTextView ([textView textStorage]) y luego poner en práctica el método delegado ‑textStorageDidProcessEditing:. Esto se llama cada vez que el texto cambia.

En el método de delegado necesita obtener el objeto NSTextStorage actual de la vista de texto utilizando el método -textStorage de NSTextView. NSTextStorage es una subclase de NSAttributedString y contiene los contenidos atribuidos de la vista.

Su código debe analizar la cadena y aplicar color a los intervalos de texto que le interesen. Aplicar color a un rango usando algo como esto, que se aplicará un color amarillo a toda la cadena:

//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]; 

La forma de analizar el texto depende de usted. NSScanner es una clase útil para usar al analizar texto.

Tenga en cuenta que este método no es la forma más eficaz de manejar la coloración de sintaxis. Si los documentos que está editando son muy grandes, lo más probable es que desee considerar descargar el análisis sintáctico a un hilo separado y/o ser inteligente sobre qué secciones de texto se reparan.

+1

Esto es un poco viejo, pero ¿cómo implementaría '-textStorageDidProcessEditing:' en el delegado? – Sirens

+0

Al igual que cualquier otro método delegado. Busque la [firma del método] (http://developer.apple.com/library/mac/documentation/cocoa/reference/NSTextStorageDelegate_Protocol/Reference/Reference.html#//apple_ref/doc/uid/TP40008627-CH1- DontLinkElementID_3) en los documentos y colocarlo en la implementación de su objeto delegado. Asegúrese de que su objeto delegado esté configurado como el delegado de 'NSTextStorage'. –

+0

Gracias, +1. Su método funciona mucho mejor que mi intento – Sirens

2

Sure. Puede dar NSTextView al NSAttributedString, y algunas de las cosas que puede hacer con la cadena atribuida son aplicar colores a ciertos subintervalos de la cadena.

O puede search on Google y ver que mucha gente ha hecho cosas con esto antes.

Probablemente recomendaría usar OkudaKit.

+1

parece que OkudaKit ya no está en desarrollo – Stephan

4

Le recomiendo que empiece por leer el CocoaDev page sobre Resaltado de sintaxis. Mucha gente ha venido con soluciones para varios objetivos.

Si desea realizar el resaltado de sintaxis del código fuente, le sugiero que eche un vistazo al UKSyntaxColoredTextDocument desde Uli Kusterer.

+0

jajaja, nunca se han descargado tantas muestras de 1 solo sitio, ¡genial! –

+0

la herramienta mencionada ahora está en github: [UKSyntaxColoredTextDocument] (https://github.com/uliwitness/UKSyntaxColoredTextDocument) – Stephan

9

Rob Keniger's answer es bueno, pero para alguien que busca un ejemplo más concreto, aquí hay un resaltador de sintaxis corto que escribí que debería resaltar la sintaxis de la plantilla RegEx. Quiero que \ sea gris, con el carácter que los sigue inmediatamente para que sea negro. Quiero que $ sea rojo, con un dígito que sigue inmediatamente al $ para que también sea rojo. Todo lo demás debería ser negro. Aquí está mi solución:

hice una clase de plantilla marcador, con un encabezado que se parece a esto:

@interface RMETemplateHighlighter : NSObject <NSTextStorageDelegate> 

@end 

que inicializarlo en el archivo de la semilla como un objeto y conectarlo a mi controlador de vista con una salida.En awakeFromNib del controlador de vista, tengo este (donde replacer es mi NSTextView salida y templateHighlighter es la salida para la clase anterior):

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

Y mi aplicación tiene el siguiente aspecto:

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

Así ahí tienes, un ejemplo completamente funcional. Hubo algunos detalles que me hicieron tropezar durante ~ 10 minutos, como el hecho de que tienes que sacar la cadena de textStorage para acceder a los personajes individuales ... tal vez esto le ahorre a otras personas unos minutos.

+0

Gracias, funciona como se anuncia y me ahorró bastante tiempo. –

+0

Esto funciona muy bien para el resaltado de sintaxis, pero en mi caso también parece romper el 'contentSize' de mi UITextView. Más específicamente, el 'contentSize' parece ser siempre el ancho de la UITextView x la altura de una sola línea. – carloe

+0

@carloe: Esta es una solución de OS X ... mencionas 'UITextView' (no ** NS **' TextView') así que supongo que estás trabajando con iOS. Puede haber pequeñas diferencias entre las API ... lo que es mejor en OS X puede no ser lo mejor en iOS. – ArtOfWarfare

Cuestiones relacionadas