2010-02-07 41 views
16

Tôi đang làm việc trên trình soạn thảo văn bản Ca cao sử dụng NSTextView. Có thể thay đổi màu sắc của một số phần nhất định của văn bản không?NSTextView tô sáng cú pháp

Trả lời

29

Bạn nên thêm bộ điều khiển làm đại biểu của đối tượng NSTextStorage của NSTextView ([textView textStorage]) và sau đó triển khai phương thức ủy nhiệm ‑textStorageDidProcessEditing:. Điều này được gọi bất cứ khi nào văn bản thay đổi.

Trong phương thức ủy nhiệm, bạn cần lấy đối tượng NSTextStorage hiện tại từ chế độ xem văn bản bằng cách sử dụng phương thức -textStorageNSTextView. NSTextStorage là một phân lớp của NSAttributedString và chứa nội dung được phân bổ của chế độ xem.

Mã của bạn sau đó phải phân tích cú pháp chuỗi và áp dụng màu cho bất kỳ phạm vi văn bản nào thú vị đối với bạn. Bạn áp dụng màu cho một phạm vi bằng cách sử dụng một cái gì đó như thế này, sẽ áp dụng màu vàng cho toàn bộ chuỗi:

//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ách bạn phân tích văn bản tùy thuộc vào bạn. NSScanner là một lớp hữu ích để sử dụng khi phân tích cú pháp văn bản.

Lưu ý rằng phương pháp này không phải là cách hiệu quả nhất để xử lý màu cú pháp. Nếu các tài liệu bạn đang chỉnh sửa rất lớn, rất có thể bạn sẽ muốn cân nhắc việc phân tích cú pháp phân tích thành một chuỗi riêng biệt và/hoặc thông minh về các phần văn bản được sửa lại.

+1

Đây là một chút cũ, nhưng làm thế nào tôi sẽ thực hiện '-textStorageDidProcessEditing:' vào đại biểu? – Sirens

+0

Giống như bất kỳ phương thức đại biểu nào khác. Tra cứu [chữ ký của phương thức] (http://developer.apple.com/library/mac/documentation/cocoa/reference/NSTextStorageDelegate_Protocol/Reference/Reference.html#//apple_ref/doc/uid/TP40008627-CH1- DontLinkElementID_3) trong tài liệu và đặt nó vào thực hiện đối tượng đại biểu của bạn. Đảm bảo đối tượng ủy nhiệm của bạn được đặt làm đại biểu của 'NSTextStorage'. –

+0

Cảm ơn, +1. Phương pháp của bạn hoạt động tốt hơn nhiều so với nỗ lực của tôi – Sirens

2

Chắc chắn. Bạn có thể cung cấp cho NSTextView một NSAttributedString và một số nội dung bạn có thể thực hiện với chuỗi được phân bổ là áp dụng màu cho các vị trí con nhất định của chuỗi.

Hoặc bạn có thể search on Google và thấy rằng nhiều người đã làm công cụ này trước đây.

Tôi có thể khuyên bạn nên sử dụng OkudaKit.

+1

có vẻ như OkudaKit không còn trong quá trình phát triển – Stephan

4

Tôi khuyên bạn nên bắt đầu bằng cách đọc số CocoaDev page về Cú pháp Highlighing. Rất nhiều người đã đến với các giải pháp cho các mục tiêu khác nhau.

Nếu bạn muốn thực hiện làm nổi bật cú pháp mã nguồn, tôi khuyên bạn nên xem UKSyntaxColoredTextDocument từ Uli Kusterer.

+0

Lol, không bao giờ tải xuống rất nhiều mẫu từ 1 trang web duy nhất, tuyệt vời! –

+0

công cụ được đề cập bây giờ là trên github: [UKSyntaxColoredTextDocument] (https://github.com/uliwitness/UKSyntaxColoredTextDocument) – Stephan

9

Rob Keniger's answer là tốt, nhưng đối với ai đó đang tìm kiếm một ví dụ cụ thể hơn, đây là một cú pháp tô sáng cú pháp ngắn tôi đã viết nên làm nổi bật cú pháp mẫu RegEx. Tôi muốn \ có màu xám, với ký tự ngay sau chúng là màu đen. Tôi muốn $ có màu đỏ, với ký tự chữ số ngay sau $ cũng có màu đỏ. Mọi thứ khác phải là màu đen. Đây là giải pháp của tôi:

tôi đã thực hiện một lớp mẫu highlighter, với một tiêu đề mà trông như thế này:

@interface RMETemplateHighlighter : NSObject <NSTextStorageDelegate> 

@end 

tôi khởi tạo nó trong tập tin nib như một đối tượng và móc nó lên để điều khiển quan điểm của tôi với một đầu ra.Trong awakeFromNib của bộ điều khiển xem, tôi có điều này (nơi replacer là ổ cắm NSTextView tôi và templateHighlighter là lối thoát cho các lớp trên):

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

Và thực hiện của tôi trông như thế này:

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

Vì vậy, có bạn đi, một ví dụ hoàn toàn làm việc. Có một vài chi tiết mà tôi đã vấp phải trong ~ 10 phút, giống như việc bạn phải lấy chuỗi ra khỏi textStorage để truy cập các ký tự riêng lẻ ... có thể điều này sẽ cứu người khác vài phút.

+0

Cảm ơn, hoạt động như quảng cáo và đã tiết kiệm cho tôi khá lâu. –

+0

Điều này làm việc tuyệt vời để làm nổi bật cú pháp, nhưng trong trường hợp của tôi cũng có vẻ như phá vỡ 'contentSize' của UITextView của tôi. Cụ thể hơn, 'contentSize' dường như luôn là chiều rộng của UITextView x chiều cao của một dòng đơn. – carloe

+0

@carloe: Đây là giải pháp OS X ... bạn đang đề cập đến 'UITextView' (không ** NS **' TextView') nên tôi cho rằng bạn đang làm việc với iOS. Có thể có sự khác biệt nhỏ giữa các API ... những gì tốt nhất trên OS X có thể không tốt nhất trên iOS. – ArtOfWarfare

Các vấn đề liên quan