<commit_before>//
//  CodeAttributedString.swift
//  Pods
//
//  Created by <NAME>. on 4/19/16.
//
//

import Foundation

public class CodeAttributedString : NSTextStorage
{
    let stringStorage = NSMutableAttributedString(string: "")

    public let highlightr = Highlightr()
    public var language : String? {
        didSet {
            highlight(NSMakeRange(0, stringStorage.length))
        }
    }

    
        /// Use this property to update the theme.
    public var theme : String? {
        didSet {
            if let theme = theme {
                highlightr?.setTheme(theme)
                highlight(NSMakeRange(0, stringStorage.length))
            }
        }
    }
    
    public override var string: String {
        get {
            return stringStorage.string
        }
    }
    
    public override func attributesAtIndex(location: Int, effectiveRange range: NSRangePointer) -> [String : AnyObject] {
        return stringStorage.attributesAtIndex(location, effectiveRange: range)
    }
    
    public override func replaceCharactersInRange(range: NSRange, withString str: String) {
        stringStorage.replaceCharactersInRange(range, withString: str)
        self.edited(NSTextStorageEditActions.EditedCharacters, range: range, changeInLength: (str as NSString).length - range.length)
    }
    
    public override func setAttributes(attrs: [String : AnyObject]?, range: NSRange) {
        stringStorage.setAttributes(attrs, range: range)
        self.edited(NSTextStorageEditActions.EditedAttributes, range: range, changeInLength: 0)
    }
    
    public override func processEditing() {
        super.processEditing()
        if language != nil {
            if self.editedMask.contains(.EditedCharacters)
            {
                let string = (self.string as NSString)
                let range = string.paragraphRangeForRange(editedRange)
                highlight(range)
            }
        }
    }

    
    func highlight(range: NSRange)
    {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            let string = (self.string as NSString)
            let line = string.substringWithRange(range)
            let tmpStrg = self.highlightr?.highlight(self.language!, code: line, fastRender: true)
            dispatch_async(dispatch_get_main_queue(), {
                self.beginEditing()
                tmpStrg?.enumerateAttributesInRange(NSMakeRange(0, (tmpStrg?.length)!), options: [], usingBlock: { (attrs, locRange, stop) in
                    var fixedRange = NSMakeRange(range.location+locRange.location, locRange.length)
                    fixedRange.length = (fixedRange.location + fixedRange.length < string.length) ? fixedRange.length : string.length-fixedRange.location
                    fixedRange.length = (fixedRange.length >= 0) ? fixedRange.length : 0
                    self.stringStorage.setAttributes(attrs, range: fixedRange)
                })
                self.endEditing()
                self.edited(NSTextStorageEditActions.EditedAttributes, range: range, changeInLength: 0)
            })
            
        }
        
    }
    
    
}<commit_msg>Added check to see if the changes pending are still valid<commit_after>//
//  CodeAttributedString.swift
//  Pods
//
//  Created by <NAME>. on 4/19/16.
//
//

import Foundation

public class CodeAttributedString : NSTextStorage
{
    let stringStorage = NSMutableAttributedString(string: "")

    public let highlightr = Highlightr()
    public var language : String? {
        didSet {
            highlight(NSMakeRange(0, stringStorage.length))
        }
    }

    
        /// Use this property to update the theme.
    public var theme : String? {
        didSet {
            if let theme = theme {
                highlightr?.setTheme(theme)
                highlight(NSMakeRange(0, stringStorage.length))
            }
        }
    }
    
    public override var string: String {
        get {
            return stringStorage.string
        }
    }
    
    public override func attributesAtIndex(location: Int, effectiveRange range: NSRangePointer) -> [String : AnyObject] {
        return stringStorage.attributesAtIndex(location, effectiveRange: range)
    }
    
    public override func replaceCharactersInRange(range: NSRange, withString str: String) {
        stringStorage.replaceCharactersInRange(range, withString: str)
        self.edited(NSTextStorageEditActions.EditedCharacters, range: range, changeInLength: (str as NSString).length - range.length)
    }
    
    public override func setAttributes(attrs: [String : AnyObject]?, range: NSRange) {
        stringStorage.setAttributes(attrs, range: range)
        self.edited(NSTextStorageEditActions.EditedAttributes, range: range, changeInLength: 0)
    }
    
    public override func processEditing() {
        super.processEditing()
        if language != nil {
            if self.editedMask.contains(.EditedCharacters)
            {
                let string = (self.string as NSString)
                let range = string.paragraphRangeForRange(editedRange)
                highlight(range)
            }
        }
    }

    
    func highlight(range: NSRange)
    {
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            let string = (self.string as NSString)
            let line = string.substringWithRange(range)
            let tmpStrg = self.highlightr?.highlight(self.language!, code: line, fastRender: true)
            dispatch_async(dispatch_get_main_queue(), {
                //Checks to see if this highlighting is still valid.
                if((range.location + range.length) > self.stringStorage.length)
                {
                    return;
                }
                
                if(tmpStrg?.string != self.stringStorage.attributedSubstringFromRange(range).string)
                {
                    return;
                }
                
                self.beginEditing()
                tmpStrg?.enumerateAttributesInRange(NSMakeRange(0, (tmpStrg?.length)!), options: [], usingBlock: { (attrs, locRange, stop) in
                    var fixedRange = NSMakeRange(range.location+locRange.location, locRange.length)
                    fixedRange.length = (fixedRange.location + fixedRange.length < string.length) ? fixedRange.length : string.length-fixedRange.location
                    fixedRange.length = (fixedRange.length >= 0) ? fixedRange.length : 0
                    self.stringStorage.setAttributes(attrs, range: fixedRange)
                })
                self.endEditing()
                self.edited(NSTextStorageEditActions.EditedAttributes, range: range, changeInLength: 0)
            })
            
        }
        
    }
    
    
}
{'fraction_non_alphanumeric': 0.08860202435088749, 'fraction_numerical': 0.0038139944257004547, 'mean_word_length': 2.073940486925158, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3503818', 'n_tokens_mistral': 1854, 'n_tokens_neox': 1749, 'n_words': 380}