objective c - Resaltado de sintaxis de NSTextView
objective-c cocoa (4)
Por supuesto. Puede darle a NSTextView
una NSAttributedString
, y algunas de las cosas que puede hacer con la cadena atribuida es aplicar colores a ciertos subrangos de la cadena.
O puedes buscar en Google y ver que muchas personas han hecho cosas con esto antes.
Probablemente recomiendo usar OkudaKit .
Estoy trabajando en un editor de texto Cocoa que utiliza un NSTextView. ¿Es posible cambiar el color de ciertas partes del texto?
Te recomiendo que comiences por leer la página de CocoaDev sobre Sintaxis de resaltado. 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 documento UKSyntaxColoredTextDocument de Uli Kusterer .
Debe agregar su controlador como el delegado del objeto NSTextStorage
del NSTextView
( [textView textStorage]
) y luego implementar el método delegado ‑textStorageDidProcessEditing:
Esto se llama siempre que el texto cambia.
En el método delegado, necesita obtener el objeto NSTextStorage
actual de la vista de texto usando el método NSTextView
de NSTextView
. NSTextStorage
es una subclase de NSAttributedString
y contiene el contenido atribuido de la vista.
Su código debe analizar la cadena y aplicar color a los rangos de texto que le interesen. Aplicas color a un rango usando algo como esto, que 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];
Cómo analizar el texto depende de usted. NSScanner
es una clase útil para usar cuando se analiza texto.
Tenga en cuenta que este método no es de ninguna manera la forma más eficiente de manejar el color de la sintaxis. Si los documentos que está editando son muy grandes, lo más probable es que desee considerar descargar el análisis a un hilo separado y / o ser inteligente con respecto a qué secciones del texto se vuelven a analizar.
La respuesta de Rob Keniger es buena, pero para alguien que busque un ejemplo más concreto, aquí hay un resaltador de sintaxis breve que escribí que debería resaltar la sintaxis de la plantilla RegEx. Quiero que sea gris, y que el personaje que sigue inmediatamente sea negro. Quiero que $
sea rojo, con un carácter de dígito inmediatamente después de $
para que también sea rojo. Todo lo demás debería ser negro. Aquí está mi solución:
Hice una clase de resaltador de plantilla, con un encabezado que se parece a esto:
@interface RMETemplateHighlighter : NSObject <NSTextStorageDelegate>
@end
Lo inicializo en el archivo de plumilla como un objeto y lo conecto a mi controlador de vista con una salida. En awakeFromNib
del controlador de vista, tengo esto (donde replacer
es mi salida NSTextView
y templateHighlighter
es la salida para la clase anterior):
self.replacer.textStorage.delegate = self.templateHighlighter;
Y mi implementación se ve así:
- (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í que ahí van, un ejemplo completamente funcional. Hubo algunos detalles que me hicieron tropezar durante unos 10 minutos, como el hecho de que tienes que quitar la cadena de TextStorage para acceder a los caracteres individuales ... tal vez esto ahorre a otras personas unos minutos.