Full Code of questbeat/Lin-Xcode5 for AI

master ca499ac6d375 cached
78 files
188.7 KB
51.4k tokens
11 symbols
1 requests
Download .txt
Showing preview only (207K chars total). Download the full file or copy to clipboard to get everything.
Repository: questbeat/Lin-Xcode5
Branch: master
Commit: ca499ac6d375
Files: 78
Total size: 188.7 KB

Directory structure:
gitextract_srotazw1/

├── .gitignore
├── .travis.yml
├── LICENSE.txt
├── Lin/
│   ├── DVTDualProxyWindow.h
│   ├── DVTFilePath.h
│   ├── DVTSourceTextView.h
│   ├── IDEEditorDocument.h
│   ├── IDEIndex+Lin.h
│   ├── IDEIndex+Lin.m
│   ├── IDEIndex.h
│   ├── IDEIndexCollection.h
│   ├── IDEWorkspace.h
│   ├── IDEWorkspaceWindow.h
│   ├── LNAlertAccessoryView.h
│   ├── LNAlertAccessoryView.m
│   ├── LNAlertAccessoryView.xib
│   ├── LNButtonCell.h
│   ├── LNButtonCell.m
│   ├── LNDetector.h
│   ├── LNDetector.m
│   ├── LNEntity.h
│   ├── LNEntity.m
│   ├── LNHorizontalLine.h
│   ├── LNHorizontalLine.m
│   ├── LNImageButtonCell.h
│   ├── LNImageButtonCell.m
│   ├── LNLocalization.h
│   ├── LNLocalization.m
│   ├── LNLocalizationCollection.h
│   ├── LNLocalizationCollection.m
│   ├── LNLocalizedStringCollectionOperation.h
│   ├── LNLocalizedStringCollectionOperation.m
│   ├── LNPopoverContentView.h
│   ├── LNPopoverContentView.m
│   ├── LNPopoverContentView.xib
│   ├── LNPopoverWindow.h
│   ├── LNPopoverWindow.m
│   ├── LNPopoverWindowController.h
│   ├── LNPopoverWindowController.m
│   ├── LNRegularExpressionPattern+type.h
│   ├── LNRegularExpressionPattern+type.m
│   ├── LNRegularExpressionPattern.h
│   ├── LNRegularExpressionPattern.m
│   ├── LNTableCornerView.h
│   ├── LNTableCornerView.m
│   ├── LNTableHeaderCell.h
│   ├── LNTableHeaderCell.m
│   ├── LNTableView.h
│   ├── LNTableView.m
│   ├── LNUserDefaultsManager.h
│   ├── LNUserDefaultsManager.m
│   ├── Lin-Info.plist
│   ├── Lin-Prefix.pch
│   ├── Lin.h
│   ├── Lin.m
│   ├── MethodSwizzle.h
│   ├── MethodSwizzle.m
│   ├── NSBundle+versions.h
│   ├── NSBundle+versions.m
│   ├── NSPopoverFrame+Lin.h
│   ├── NSPopoverFrame+Lin.m
│   ├── NSPopoverFrame.h
│   ├── NSTableView+editedColumnIdentifier.h
│   ├── NSTableView+editedColumnIdentifier.m
│   └── en.lproj/
│       └── InfoPlist.strings
├── Lin.xcodeproj/
│   ├── project.pbxproj
│   └── xcshareddata/
│       └── xcschemes/
│           ├── Lin.xcscheme
│           └── LinTests.xcscheme
├── LinTests/
│   ├── LNDetectorTestSet.h
│   ├── LNDetectorTestSet.m
│   ├── LNDetectorTests.m
│   ├── LNLocalizationTests.m
│   ├── LinTests-Info.plist
│   ├── LinTests-Prefix.pch
│   ├── Localizable.strings
│   └── en.lproj/
│       └── InfoPlist.strings
├── Makefile
└── README.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Generated by http://gitignore.io

### Objective-C ###
# Xcode
.DS_Store
*/build/*
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
*.xcworkspace
!default.xcworkspace
xcuserdata
profile
*.moved-aside
DerivedData
.idea/
*.hmap



================================================
FILE: .travis.yml
================================================
language: objective-c
script: make clean test



================================================
FILE: LICENSE.txt
================================================
Copyright (c) 2013 Katsuma Tanaka
 
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

================================================
FILE: Lin/DVTDualProxyWindow.h
================================================
//
//  DVTDualProxyWindow.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/26.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface DVTDualProxyWindow : NSWindow

@end


================================================
FILE: Lin/DVTFilePath.h
================================================
//
//  DVTFilePath.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/23.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface DVTFilePath : NSObject

@property (readonly) NSString *fileName;
@property (readonly) NSURL *fileURL;
@property (readonly) NSArray *pathComponents;
@property (readonly) NSString *pathString;

@end


================================================
FILE: Lin/DVTSourceTextView.h
================================================
//
//  DVTSourceTextView.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/26.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface DVTSourceTextView : NSTextView

@end


================================================
FILE: Lin/IDEEditorDocument.h
================================================
//
//  IDEEditorDocument.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/24.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@class DVTFilePath;

@interface IDEEditorDocument : NSDocument

@property (retain) DVTFilePath *filePath;

@end


================================================
FILE: Lin/IDEIndex+Lin.h
================================================
//
//  IDEIndex+Lin.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/24.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "IDEIndex.h"

@interface IDEIndex (Lin)

@end


================================================
FILE: Lin/IDEIndex+Lin.m
================================================
//
//  IDEIndex+Lin.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/24.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "IDEIndex+Lin.h"

#import "MethodSwizzle.h"
#import "Lin.h"

@implementation IDEIndex (Lin)

+ (void)load
{
    MethodSwizzle(self, @selector(close), @selector(jp_questbeat_lin_close));
}

- (void)jp_questbeat_lin_close
{
    [[Lin sharedPlugIn] removeLocalizationsForIndex:self];
    
    [self jp_questbeat_lin_close];
}

@end


================================================
FILE: Lin/IDEIndex.h
================================================
//
//  IDEIndex.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/23.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@class DVTFilePath;

@interface IDEIndex : NSObject

@property (readonly, nonatomic) DVTFilePath *workspaceFile;
@property (readonly, nonatomic) NSString *workspaceName;

- (void)close;
- (id)filesContaining:(id)arg1 anchorStart:(BOOL)arg2 anchorEnd:(BOOL)arg3 subsequence:(BOOL)arg4 ignoreCase:(BOOL)arg5 cancelWhen:(id)arg6;

@end


================================================
FILE: Lin/IDEIndexCollection.h
================================================
//
//  IDEIndexCollection.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/23.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface IDEIndexCollection : NSObject <NSFastEnumeration>

@end


================================================
FILE: Lin/IDEWorkspace.h
================================================
//
//  IDEWorkspace.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@class IDEIndex;
@class DVTFilePath;

@interface IDEWorkspace : NSObject

@property (retain) IDEIndex *index;
@property (readonly) DVTFilePath *representingFilePath;

- (void)_updateIndexableFiles:(id)arg1;

@end


================================================
FILE: Lin/IDEWorkspaceWindow.h
================================================
//
//  IDEWorkspaceWindow.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/26.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "DVTDualProxyWindow.h"

@interface IDEWorkspaceWindow : DVTDualProxyWindow

@end


================================================
FILE: Lin/LNAlertAccessoryView.h
================================================
//
//  LNAlertAccessoryView.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/22.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@class LNLocalizationCollection;

@interface LNAlertAccessoryView : NSView <NSTextFieldDelegate>

@property (nonatomic, copy) NSArray *collections;
@property (nonatomic, weak) NSButton *button;

@property (nonatomic, copy, readonly) LNLocalizationCollection *selectedCollection;
@property (nonatomic, copy, readonly) NSString *inputtedKey;
@property (nonatomic, copy, readonly) NSString *inputtedValue;

@end


================================================
FILE: Lin/LNAlertAccessoryView.m
================================================
//
//  LNAlertAccessoryView.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/22.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNAlertAccessoryView.h"

// Models
#import "LNLocalizationCollection.h"

@interface LNAlertAccessoryView ()

@property (weak) IBOutlet NSPopUpButton *tableButton;
@property (weak) IBOutlet NSPopUpButton *languageButton;
@property (weak) IBOutlet NSTextField *keyTextField;
@property (weak) IBOutlet NSTextField *valueTextField;

@end

@implementation LNAlertAccessoryView

- (void)awakeFromNib
{
    [super awakeFromNib];
}


#pragma mark - Accessors

- (void)setCollections:(NSArray *)collections
{
    _collections = collections;
    
    // Update
    [self configureView];
}

- (void)setButton:(NSButton *)button
{
    _button = button;
    
    // Update
    [self configureButton];
}

- (LNLocalizationCollection *)selectedCollection
{
    NSString *selectedFileName = [self.tableButton titleOfSelectedItem];
    NSString *selectedLanguageDesignations = [self.languageButton titleOfSelectedItem];
    
    for (LNLocalizationCollection *collection in self.collections) {
        if ([collection.fileName isEqualToString:selectedFileName]
            && [collection.languageDesignation isEqualToString:selectedLanguageDesignations]) {
            return collection;
        }
    }
    
    return nil;
}

- (NSString *)inputtedKey
{
    return self.keyTextField.stringValue;
}

- (NSString *)inputtedValue
{
    return self.valueTextField.stringValue;
}


#pragma mark - Actions

- (IBAction)tableDidChange:(id)sender
{
    // Update
    [self updateLanguages];
}


#pragma mark - Updating the Views

- (void)updateTables
{
    [self.tableButton removeAllItems];
    
    NSMutableSet *tableFileNames = [NSMutableSet set];
    for (LNLocalizationCollection *collection in self.collections) {
        [tableFileNames addObject:collection.fileName];
    }
    
    [self.tableButton addItemsWithTitles:[tableFileNames allObjects]];
}

- (void)updateLanguages
{
    [self.languageButton removeAllItems];
    
    NSString *titleOfSelectedItem = [self.tableButton titleOfSelectedItem];
    
    NSMutableSet *languageDesignations = [NSMutableSet set];
    for (LNLocalizationCollection *collection in self.collections) {
        if ([titleOfSelectedItem isEqualToString:collection.fileName]) {
            [languageDesignations addObject:collection.languageDesignation];
        }
    }
    
    [self.languageButton addItemsWithTitles:[languageDesignations allObjects]];
}

- (void)configureView
{
    [self updateTables];
    [self updateLanguages];
    
    [self configureButton];
}

- (void)configureButton
{
    NSString *key = self.keyTextField.stringValue;
    NSString *value = self.valueTextField.stringValue;
    
    [self.button setEnabled:(self.collections.count > 0 && key.length > 0 && value.length > 0)];
}


#pragma mark - NSTextFieldDelegate

- (void)controlTextDidChange:(NSNotification *)obj
{
    [self configureButton];
}

@end


================================================
FILE: Lin/LNAlertAccessoryView.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4510" systemVersion="12F37" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
    <dependencies>
        <deployment defaultVersion="1080" identifier="macosx"/>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4510"/>
    </dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner" customClass="NSViewController">
            <connections>
                <outlet property="view" destination="1" id="ApE-I1-pgP"/>
            </connections>
        </customObject>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <customObject id="-3" userLabel="Application"/>
        <customView id="1" customClass="LNAlertAccessoryView">
            <rect key="frame" x="0.0" y="0.0" width="276" height="126"/>
            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
            <subviews>
                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="g8L-IS-4Xk">
                    <rect key="frame" x="-3" y="105" width="74" height="18"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Table:" id="jNJ-it-poE">
                        <font key="font" size="11" name="LucidaGrande"/>
                        <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="c83-4U-gPj">
                    <rect key="frame" x="-3" y="74" width="74" height="18"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Language:" id="kRy-xH-jEz">
                        <font key="font" size="11" name="LucidaGrande"/>
                        <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eXz-ob-H9h">
                    <rect key="frame" x="-3" y="38" width="74" height="18"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Key:" id="aF0-zx-EL7">
                        <font key="font" size="11" name="LucidaGrande"/>
                        <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RCM-7S-qgd">
                    <rect key="frame" x="-3" y="2" width="74" height="18"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="Value:" id="oqq-yX-bGL">
                        <font key="font" size="11" name="LucidaGrande"/>
                        <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                </textField>
                <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ffd-kG-7Ps">
                    <rect key="frame" x="84" y="101" width="175" height="26"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="Bnc-Jb-pk1" id="f33-uO-Fvh">
                        <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
                        <font key="font" metaFont="menu"/>
                        <menu key="menu" title="OtherViews" id="OjL-b2-nb9">
                            <items>
                                <menuItem title="Item 1" state="on" id="Bnc-Jb-pk1"/>
                                <menuItem title="Item 2" id="v2K-y3-Q4d"/>
                                <menuItem title="Item 3" id="j9O-iS-YPm"/>
                            </items>
                        </menu>
                    </popUpButtonCell>
                    <connections>
                        <action selector="tableDidChange:" target="1" id="7TQ-0w-o4K"/>
                    </connections>
                </popUpButton>
                <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8bv-Xr-gdv">
                    <rect key="frame" x="84" y="70" width="175" height="26"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <popUpButtonCell key="cell" type="push" title="Item 1" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="in5-1O-5XW" id="Dtc-dm-ra0">
                        <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
                        <font key="font" metaFont="menu"/>
                        <menu key="menu" title="OtherViews" id="BIV-qg-Oc4">
                            <items>
                                <menuItem title="Item 1" state="on" id="in5-1O-5XW"/>
                                <menuItem title="Item 2" id="ICT-Lj-Z8X"/>
                                <menuItem title="Item 3" id="pA4-SI-bOd"/>
                            </items>
                        </menu>
                    </popUpButtonCell>
                </popUpButton>
                <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Qol-ST-d7x">
                    <rect key="frame" x="86" y="36" width="170" height="22"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="eux-4V-Yap">
                        <font key="font" metaFont="system"/>
                        <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                    <connections>
                        <outlet property="delegate" destination="1" id="sAt-3w-AaA"/>
                    </connections>
                </textField>
                <textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2iU-j0-HKh">
                    <rect key="frame" x="86" y="0.0" width="170" height="22"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="6k4-Zy-TKZ">
                        <font key="font" metaFont="system"/>
                        <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </textFieldCell>
                    <connections>
                        <outlet property="delegate" destination="1" id="bbF-ov-OoT"/>
                    </connections>
                </textField>
            </subviews>
            <connections>
                <outlet property="keyTextField" destination="Qol-ST-d7x" id="TpR-9R-1mv"/>
                <outlet property="languageButton" destination="8bv-Xr-gdv" id="fP1-93-XWJ"/>
                <outlet property="tableButton" destination="Ffd-kG-7Ps" id="742-rf-D76"/>
                <outlet property="valueTextField" destination="2iU-j0-HKh" id="Bap-fJ-DcY"/>
            </connections>
        </customView>
    </objects>
</document>

================================================
FILE: Lin/LNButtonCell.h
================================================
//
//  LNButtonCell.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface LNButtonCell : NSButtonCell

@end


================================================
FILE: Lin/LNButtonCell.m
================================================
//
//  LNButtonCell.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNButtonCell.h"

@implementation LNButtonCell

- (void)drawImage:(NSImage *)image withFrame:(NSRect)frame inView:(NSView *)controlView
{
    // Adjustment
    frame.origin.y += 3;
    
    [super drawImage:image withFrame:frame inView:controlView];
}

@end


================================================
FILE: Lin/LNDetector.h
================================================
//
//  LNDetector.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface LNDetector : NSObject

@property (nonatomic, copy, readonly) NSArray *regularExpressionPatterns;

+ (instancetype)detector;

- (NSArray *)entitiesInString:(NSString *)string;

@end


================================================
FILE: Lin/LNDetector.m
================================================
//
//  LNDetector.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNDetector.h"

// Models
#import "LNEntity.h"
#import "LNRegularExpressionPattern.h"
#import "LNRegularExpressionPattern+type.h"

@interface LNDetector ()

@property (nonatomic, copy, readwrite) NSArray *regularExpressionPatterns;

@end

@implementation LNDetector

+ (instancetype)detector
{
    return [[self alloc] init];
}

- (instancetype)init
{
    self = [super init];
    
    if (self) {
        self.regularExpressionPatterns = @[
                                           [LNRegularExpressionPattern patternWithType:LNEntityTypeLocalizedString],
                                           [LNRegularExpressionPattern patternWithType:LNEntityTypeLocalizedStringForKey],
                                           [LNRegularExpressionPattern patternWithType:LNEntityTypeLocalizedStringFromTable],
                                           [LNRegularExpressionPattern patternWithType:LNEntityTypeLocalizedStringFromTableInBundle],
                                           [LNRegularExpressionPattern patternWithType:LNEntityTypeLocalizedStringWithDefaultValue]
                                           ];
    }
    
    return self;
}


#pragma mark - Finding Entities

- (NSArray *)entitiesInString:(NSString *)string
{
    NSMutableArray *entities = [NSMutableArray array];
    
    for (LNRegularExpressionPattern *regularExpressionPattern in self.regularExpressionPatterns) {
        NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:regularExpressionPattern.pattern options:0 error:NULL];
        
        __block NSRange entityRange;
        __block NSRange keyRange;
        
        [regularExpression enumerateMatchesInString:string
                                            options:0
                                              range:NSMakeRange(0, string.length)
                                         usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
                                             if (result.numberOfRanges == regularExpressionPattern.numberOfRanges) {
                                                 entityRange = [result rangeAtIndex:regularExpressionPattern.entityRangeIndex];
                                                 keyRange = [result rangeAtIndex:regularExpressionPattern.keyRangeIndex];
                                                 
                                                 LNEntity *entity = [LNEntity entityWithType:regularExpressionPattern.type
                                                                                 entityRange:entityRange
                                                                                    keyRange:keyRange];
                                                 
                                                 [entities addObject:entity];
                                             }
                                         }];
    }
    
    return [entities copy];
}

@end


================================================
FILE: Lin/LNEntity.h
================================================
//
//  LNEntity.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSUInteger, LNEntityType) {
    LNEntityTypeLocalizedString = 0,
    LNEntityTypeLocalizedStringForKey,
    LNEntityTypeLocalizedStringFromTable,
    LNEntityTypeLocalizedStringFromTableInBundle,
    LNEntityTypeLocalizedStringWithDefaultValue
};

NS_INLINE NSString * NSStringFromEntityType(LNEntityType type) {
    NSString *string = nil;
    
    switch (type) {
        case LNEntityTypeLocalizedString:
            string = @"LNEntityTypeLocalizedString";
            break;
        case LNEntityTypeLocalizedStringForKey:
            string = @"LNEntityTypeLocalizedStringForKey";
            break;
        case LNEntityTypeLocalizedStringFromTable:
            string = @"LNEntityTypeLocalizedStringFromTable";
            break;
        case LNEntityTypeLocalizedStringFromTableInBundle:
            string = @"LNEntityTypeLocalizedStringFromTableInBundle";
            break;
        case LNEntityTypeLocalizedStringWithDefaultValue:
            string = @"LNEntityTypeLocalizedStringWithDefaultValue";
            break;
    }
    
    return string;
}

@interface LNEntity : NSObject

@property (nonatomic, assign, readonly) LNEntityType type;
@property (nonatomic, assign, readonly) NSRange entityRange;
@property (nonatomic, assign, readonly) NSRange keyRange;

+ (instancetype)entityWithType:(LNEntityType)type entityRange:(NSRange)entityRange keyRange:(NSRange)keyRange;

- (instancetype)initWithType:(LNEntityType)type entityRange:(NSRange)entityRange keyRange:(NSRange)keyRange;

@end


================================================
FILE: Lin/LNEntity.m
================================================
//
//  LNEntity.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNEntity.h"

@interface LNEntity ()

@property (nonatomic, assign, readwrite) LNEntityType type;
@property (nonatomic, assign, readwrite) NSRange entityRange;
@property (nonatomic, assign, readwrite) NSRange keyRange;

@end

@implementation LNEntity

+ (instancetype)entityWithType:(LNEntityType)type entityRange:(NSRange)entityRange keyRange:(NSRange)keyRange
{
    return [[self alloc] initWithType:type entityRange:entityRange keyRange:keyRange];
}

- (instancetype)initWithType:(LNEntityType)type entityRange:(NSRange)entityRange keyRange:(NSRange)keyRange
{
    self = [super init];
    
    if (self) {
        self.type = type;
        self.entityRange = entityRange;
        self.keyRange = keyRange;
    }
    
    return self;
}

- (BOOL)isEqual:(id)object
{
    if (object == self)
        return YES;
    if (!object || ![[object class] isEqual:[self class]])
        return NO;
    if (!NSEqualRanges([self entityRange], [object entityRange]))
        return NO;
    
    return YES;
}

- (NSString *)description
{
    return [NSString stringWithFormat:
            @"<%@: %p; type = %@; range = %@; key = %@>",
            NSStringFromClass([self class]),
            self,
            NSStringFromEntityType(self.type),
            NSStringFromRange(self.entityRange),
            NSStringFromRange(self.keyRange)
            ];
}

@end


================================================
FILE: Lin/LNHorizontalLine.h
================================================
//
//  LNHorizontalLine.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface LNHorizontalLine : NSBox

@end


================================================
FILE: Lin/LNHorizontalLine.m
================================================
//
//  LNHorizontalLine.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNHorizontalLine.h"

@implementation LNHorizontalLine

- (void)drawRect:(NSRect)dirtyRect
{
    [[NSColor colorWithDeviceWhite:204.0/255.0 alpha:1.0] set];
    [NSBezierPath strokeLineFromPoint:NSMakePoint(dirtyRect.origin.x, 2.5)
                              toPoint:NSMakePoint(dirtyRect.origin.x + dirtyRect.size.width, 2.5)];
}

@end


================================================
FILE: Lin/LNImageButtonCell.h
================================================
//
//  LNImageButtonCell.h
//  Lin
//
//  Created by Tanaka Katsuma on 2014/03/04.
//  Copyright (c) 2014年 Tanaka Katsuma. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface LNImageButtonCell : NSButtonCell

@end


================================================
FILE: Lin/LNImageButtonCell.m
================================================
//
//  LNImageButtonCell.m
//  Lin
//
//  Created by Tanaka Katsuma on 2014/03/04.
//  Copyright (c) 2014年 Tanaka Katsuma. All rights reserved.
//

#import "LNImageButtonCell.h"

@implementation LNImageButtonCell

- (void)drawImage:(NSImage *)image withFrame:(NSRect)frame inView:(NSView *)controlView
{
    // Adjustment
    frame.origin.y += 2;
    
    [super drawImage:image withFrame:frame inView:controlView];
}

@end


================================================
FILE: Lin/LNLocalization.h
================================================
//
//  LNLocalization.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/23.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@class LNLocalizationCollection;

@interface LNLocalization : NSObject

@property (nonatomic, copy, readonly) NSString *key;
@property (nonatomic, copy, readonly) NSString *value;

@property (nonatomic, assign, readonly) NSRange entityRange;
@property (nonatomic, assign, readonly) NSRange keyRange;
@property (nonatomic, assign, readonly) NSRange valueRange;

@property (nonatomic, weak, readonly) LNLocalizationCollection *collection;

+ (instancetype)localizationWithKey:(NSString *)key value:(NSString *)value entityRange:(NSRange)entityRange keyRange:(NSRange)keyRange valueRange:(NSRange)valueRange collection:(LNLocalizationCollection *)collection;

- (instancetype)initWithKey:(NSString *)key value:(NSString *)value entityRange:(NSRange)entityRange keyRange:(NSRange)keyRange valueRange:(NSRange)valueRange collection:(LNLocalizationCollection *)collection;

@end


================================================
FILE: Lin/LNLocalization.m
================================================
//
//  LNLocalization.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/23.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNLocalization.h"

@interface LNLocalization ()

@property (nonatomic, copy, readwrite) NSString *key;
@property (nonatomic, copy, readwrite) NSString *value;

@property (nonatomic, assign, readwrite) NSRange entityRange;
@property (nonatomic, assign, readwrite) NSRange keyRange;
@property (nonatomic, assign, readwrite) NSRange valueRange;

@property (nonatomic, weak, readwrite) LNLocalizationCollection *collection;

@end

@implementation LNLocalization

+ (instancetype)localizationWithKey:(NSString *)key value:(NSString *)value entityRange:(NSRange)entityRange keyRange:(NSRange)keyRange valueRange:(NSRange)valueRange collection:(LNLocalizationCollection *)collection
{
    return [[self alloc] initWithKey:key value:value entityRange:(NSRange)entityRange keyRange:keyRange valueRange:valueRange collection:collection];
}

- (instancetype)initWithKey:(NSString *)key value:(NSString *)value entityRange:(NSRange)entityRange keyRange:(NSRange)keyRange valueRange:(NSRange)valueRange collection:(LNLocalizationCollection *)collection
{
    self = [super init];
    
    if (self) {
        self.key = key;
        self.value = value;
        
        self.entityRange = entityRange;
        self.keyRange = keyRange;
        self.valueRange = valueRange;
        
        self.collection = collection;
    }
    
    return self;
}

- (BOOL)isEqual:(id)object
{
    if (object == self)
        return YES;
    if (!object || ![[object class] isEqual:[self class]])
        return NO;
    if (![[self key] isEqualToString:[object key]])
        return NO;
    
    return YES;
}

- (NSUInteger)hash
{
    return [self.key hash];
}

- (NSString *)description
{
    return [NSString stringWithFormat:
            @"<%@: %p; key = %@; value = %@; entityRange = %@; keyRange = %@; valueRange = %@; collection = %p>",
            NSStringFromClass([self class]),
            self,
            self.key,
            self.value,
            NSStringFromRange(self.entityRange),
            NSStringFromRange(self.keyRange),
            NSStringFromRange(self.valueRange),
            self.collection
            ];
}

@end


================================================
FILE: Lin/LNLocalizationCollection.h
================================================
//
//  LNLocalizationCollection.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/23.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@class LNLocalization;

@interface LNLocalizationCollection : NSObject

@property (nonatomic, copy, readonly) NSString *filePath;
@property (nonatomic, copy, readonly) NSString *languageDesignation;

@property (nonatomic, strong, readonly) NSMutableSet *localizations;

+ (instancetype)localizationCollectionWithContentsOfFile:(NSString *)filePath;

- (instancetype)initWithContentsOfFile:(NSString *)filePath;

- (NSString *)fileName;

- (void)reloadLocalizations;
- (void)addLocalization:(LNLocalization *)localization;
- (void)deleteLocalization:(LNLocalization *)localization;
- (void)replaceLocalization:(LNLocalization *)localization withLocalization:(LNLocalization *)newLocalization;

@end


================================================
FILE: Lin/LNLocalizationCollection.m
================================================
//
//  LNLocalizationCollection.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/23.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNLocalizationCollection.h"

// Models
#import "LNLocalization.h"

@interface LNLocalizationCollection ()

@property (nonatomic, copy, readwrite) NSString *filePath;
@property (nonatomic, copy, readwrite) NSString *languageDesignation;

@property (nonatomic, strong, readwrite) NSMutableSet *localizations;

@end

@implementation LNLocalizationCollection

+ (instancetype)localizationCollectionWithContentsOfFile:(NSString *)filePath
{
    return [[self alloc] initWithContentsOfFile:filePath];
}

- (instancetype)initWithContentsOfFile:(NSString *)filePath
{
    self = [super init];
    
    if (self) {
        self.filePath = filePath;
        
        // Extract language designation
        NSArray *pathComponents = [filePath pathComponents];
        self.languageDesignation = [[pathComponents objectAtIndex:pathComponents.count - 2] stringByDeletingPathExtension];
        
        // Update
        [self reloadLocalizations];
    }
    
    return self;
}

- (NSString *)description
{
    return [NSString stringWithFormat:
            @"<%@: %p; filePath = %@; languageDesignation = %@; localizations = %@>",
            NSStringFromClass([self class]),
            self,
            self.filePath,
            self.languageDesignation,
            self.localizations
            ];
}


#pragma mark - Accessors

- (NSString *)fileName
{
    return [self.filePath lastPathComponent];
}


#pragma mark - Managing Localizations

- (NSString *)loadContentsOfFile:(NSString *)filePath
{
	NSError *error = nil;
    NSStringEncoding encoding = NSUTF8StringEncoding;
    NSString *contents = [NSString stringWithContentsOfURL:[NSURL fileURLWithPath:self.filePath]
                                              usedEncoding:&encoding
                                                     error:&error];
    
    if (error) {
        NSLog(@"Error: %@", [error localizedDescription]);
        
        return nil;
    }
    
    return contents;
}

- (void)reloadLocalizations
{
    // Load contents
    NSString *contents = [self loadContentsOfFile:self.filePath];
    
    if (contents) {
        NSMutableSet *localizations = [NSMutableSet set];
        
        // Parse
        __block NSInteger lineOffset = 0;
        __block NSString *key;
        __block NSString *value;
        __block NSRange entityRange;
        __block NSRange keyRange;
        __block NSRange valueRange;
        
        NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:@"(\"(\\S+.*\\S+)\"|(\\S+.*\\S+))\\s*=\\s*\"(.*)\";$"
                                                                                           options:0
                                                                                             error:NULL];
        
        [contents enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
            key = nil;
            value = nil;
            keyRange = NSMakeRange(NSNotFound, 0);
            valueRange = NSMakeRange(NSNotFound, 0);
            
            NSTextCheckingResult *result = [regularExpression firstMatchInString:line
                                                                         options:0
                                                                           range:NSMakeRange(0, line.length)];
            
            if (result.range.location != NSNotFound && result.numberOfRanges == 5) {
                entityRange = [result rangeAtIndex:0];
                entityRange.location += lineOffset;
                
                keyRange = [result rangeAtIndex:2];
                if (keyRange.location == NSNotFound) keyRange = [result rangeAtIndex:3];
                
                valueRange = [result rangeAtIndex:4];
                
                key = [line substringWithRange:keyRange];
                value = [line substringWithRange:valueRange];
                
                keyRange.location += lineOffset;
                valueRange.location += lineOffset;
            }
            
            // Create localization
            if (key != nil && value != nil) {
                LNLocalization *localization = [LNLocalization localizationWithKey:key
                                                                             value:value
                                                                       entityRange:entityRange
                                                                          keyRange:keyRange
                                                                        valueRange:valueRange
                                                                        collection:self];
                
                [localizations addObject:localization];
            }
            
            // Move offset
            NSRange lineRange = [contents lineRangeForRange:NSMakeRange(lineOffset, 0)];
            lineOffset += lineRange.length;
        }];
        
        self.localizations = localizations;
    } else {
        self.localizations = nil;
    }
}

- (void)addLocalization:(LNLocalization *)localization
{
    // Load contents
    NSString *contents = [self loadContentsOfFile:self.filePath];
    
    // Add
    if (![contents hasSuffix:@"\n"]) {
        contents = [contents stringByAppendingString:@"\n"];
    }
    
    contents = [contents stringByAppendingFormat:@"\"%@\" = \"%@\";\n", localization.key, localization.value];
    
    // Override
    NSError *error = nil;
    [contents writeToFile:self.filePath atomically:NO encoding:NSUTF8StringEncoding error:&error];
    
    if (error) {
        NSLog(@"Error: %@", [error localizedDescription]);
    }
    
    // Reload
    [self reloadLocalizations];
}

- (void)deleteLocalization:(LNLocalization *)localization
{
    // Load contents
    NSString *contents = [self loadContentsOfFile:self.filePath];
    
    // Delete line
    NSRange lineRange = [contents lineRangeForRange:localization.entityRange];
    contents = [contents stringByReplacingCharactersInRange:lineRange withString:@""];
    
    // Override
    NSError *error = nil;
    [contents writeToFile:self.filePath atomically:NO encoding:NSUTF8StringEncoding error:&error];
    
    if (error) {
        NSLog(@"Error: %@", [error localizedDescription]);
    }
    
    // Reload
    [self reloadLocalizations];
}

- (void)replaceLocalization:(LNLocalization *)localization withLocalization:(LNLocalization *)newLocalization
{
    // Load contents
    NSString *contents = [self loadContentsOfFile:self.filePath];
    
    // Replace
    NSString *newEntity = [NSString stringWithFormat:@"\"%@\" = \"%@\";", newLocalization.key, newLocalization.value];
    contents = [contents stringByReplacingCharactersInRange:localization.entityRange withString:newEntity];
    
    // Override
    NSError *error = nil;
    [contents writeToFile:self.filePath atomically:NO encoding:NSUTF8StringEncoding error:&error];
    
    if (error) {
        NSLog(@"Error: %@", [error localizedDescription]);
    }
    
    // Reload
    [self reloadLocalizations];
}

@end


================================================
FILE: Lin/LNLocalizedStringCollectionOperation.h
================================================
//
//  LNLocalizedStringCollectionOperation.h
//  Lin
//
//  Created by Wenbin Zhang on 3/7/14.
//  Copyright (c) 2014 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@class IDEIndex;

typedef void(^LNLocalizedStringCollectionCompletionBlock)(NSString *workspacePath, NSArray *collections);

@interface LNLocalizedStringCollectionOperation : NSOperation

@property (nonatomic, strong) IDEIndex *index;
@property (nonatomic, copy) LNLocalizedStringCollectionCompletionBlock collectionCompletedBlock;

- (instancetype)initWithIndex:(IDEIndex *)index;
@end


================================================
FILE: Lin/LNLocalizedStringCollectionOperation.m
================================================
//
//  LNLocalizedStringCollectionOperation.m
//  Lin
//
//  Created by Wenbin Zhang on 3/7/14.
//  Copyright (c) 2014 Tanaka Katsuma. All rights reserved.
//

#import "LNLocalizedStringCollectionOperation.h"
#import "IDEIndex.h"
#import "IDEWorkspace.h"
#import "IDEIndexCollection.h"
#import "DVTFilePath.h"
#import "LNLocalizationCollection.h"

@interface LNLocalizedStringCollectionOperation ()

@property (nonatomic, strong) NSArray *collections;
@property (nonatomic, strong) NSString *workspaceFilePath;
@end

@implementation LNLocalizedStringCollectionOperation

- (instancetype)initWithIndex:(IDEIndex *)index
{
    self = [super init];
    if (self) {
        self.index = index;
    }
    return self;
}

- (void)main
{
    @autoreleasepool {
        if (self.isCancelled) {
            return;
        }
        
        if (!self.index) {
            return;
        }
        [self processLocalizedString];
        
        if (self.isCancelled) {
            return;
        }
        
        if (self.collectionCompletedBlock) {
            dispatch_async(dispatch_get_main_queue(), ^{
                self.collectionCompletedBlock(self.workspaceFilePath, self.collections);
            });
        }
        
        [self cleanup];
    }
}

- (void)processLocalizedString
{
    IDEWorkspace *workspace = [self.index valueForKey:@"_workspace"];
    DVTFilePath *representingFilePath = workspace.representingFilePath;
    self.workspaceFilePath = representingFilePath.pathString;
    NSMutableArray *mutableCollections = [[NSMutableArray alloc] init];
    
    if (self.workspaceFilePath) {
        NSString *projectRootPath = [[self.workspaceFilePath stringByDeletingLastPathComponent] stringByDeletingLastPathComponent];
        
        // Find .strings files
        IDEIndexCollection *indexCollection = [self.index filesContaining:@".strings" anchorStart:NO anchorEnd:NO subsequence:NO ignoreCase:YES cancelWhen:nil];
        
        for (DVTFilePath *filePath in indexCollection) {
            if (self.isCancelled) {
                return;
            }
            NSString *pathString = filePath.pathString;
            
            BOOL parseStringsFilesOutsideWorkspaceProject = YES;
            if (parseStringsFilesOutsideWorkspaceProject ||
                (!parseStringsFilesOutsideWorkspaceProject && [pathString rangeOfString:projectRootPath].location != NSNotFound)) {
                // Create localization collection
                LNLocalizationCollection *collection = [LNLocalizationCollection localizationCollectionWithContentsOfFile:pathString];
                [mutableCollections addObject:collection];
            }
        }
        self.collections = [mutableCollections copy];
    }
}

- (void)cleanup
{
    self.index = nil;
}

@end


================================================
FILE: Lin/LNPopoverContentView.h
================================================
//
//  LNPopoverContentView.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/06.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Cocoa/Cocoa.h>

extern NSString * const LNPopoverContentViewLocalizationKey;

extern NSString * const LNPopoverContentViewLocalizationDidSelectNotification;
extern NSString * const LNPopoverContentViewAlertDidDismissNotification;
extern NSString * const LNPopoverContentViewDetachButtonDidClickNotification;

@interface LNPopoverContentView : NSView <NSTableViewDataSource, NSTableViewDelegate>

@property (nonatomic, weak, readonly) NSTableView *tableView;
@property (nonatomic, weak, readonly) NSButton *detachButton;
@property (nonatomic, copy) NSArray *collections;
@property (nonatomic, copy) NSString *searchString;

@end


================================================
FILE: Lin/LNPopoverContentView.m
================================================
//
//  LNPopoverContentView.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/06.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNPopoverContentView.h"

// Categories
#import "NSTableView+editedColumnIdentifier.h"

// Models
#import "LNLocalizationCollection.h"
#import "LNLocalization.h"

// Views
#import "LNTableHeaderCell.h"
#import "LNAlertAccessoryView.h"

NSString * const LNPopoverContentViewLocalizationKey = @"LNPopoverContentViewLocalizationKey";

NSString * const LNPopoverContentViewLocalizationDidSelectNotification = @"LNPopoverContentViewRowDidDoubleClickNotification";
NSString * const LNPopoverContentViewAlertDidDismissNotification = @"LNPopoverContentViewAlertDidDismissNotification";
NSString * const LNPopoverContentViewDetachButtonDidClickNotification = @"LNPopoverContentViewDetachButtonDidClickNotification";

@interface LNPopoverContentView ()

@property (nonatomic, weak, readwrite) IBOutlet NSTableView *tableView;
@property (nonatomic, weak, readwrite) IBOutlet NSButton *detachButton;

@property (nonatomic, strong) NSMutableArray *localizations;
@property (nonatomic, strong) NSMutableArray *sortedLocalizations;

- (IBAction)addLocalization:(id)sender;
- (IBAction)deleteLocalization:(id)sender;
- (IBAction)detachPopover:(id)sender;

@end

@implementation LNPopoverContentView

- (void)awakeFromNib
{
    [super awakeFromNib];
    
    // Set default sort order
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"key"
                                                                     ascending:YES
                                                                      selector:@selector(compare:)];
    [self.tableView setSortDescriptors:@[sortDescriptor]];
    
    // Register to notification center
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(textDidEndEditing:)
                                                 name:NSControlTextDidEndEditingNotification
                                               object:nil];
}

- (void)dealloc
{
    // Remove from notification center
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:NSControlTextDidEndEditingNotification
                                                  object:nil];
}


#pragma mark - Accessors

- (void)setTableView:(NSTableView *)tableView
{
    _tableView = tableView;
    
    // Set double click action
    [_tableView setTarget:self];
    [_tableView setDoubleAction:@selector(tableViewDidDoubleClick:)];
}

- (void)setCollections:(NSArray *)collections
{
    _collections = collections;
    
    // Update
    [self configureView];
}

- (void)setSearchString:(NSString *)searchString
{
    _searchString = searchString;
    
    // Update
    [self configureView];
}


#pragma mark - Notifications

- (void)textDidEndEditing:(NSNotification *)notification
{
    NSInteger editedRow = [self.tableView editedRow];
    NSInteger editedColumn = [self.tableView editedColumn];
    
    if (editedRow >= 0 && editedColumn >= 0) {
        NSTextView *textView = (NSTextView *)[notification.userInfo objectForKey:@"NSFieldEditor"];
        
        // Create a new localization
        LNLocalization *localization = [self.sortedLocalizations objectAtIndex:editedRow];
        
        NSString *key = localization.key;
        NSString *value = localization.value;
        
        NSString *columnIdentifier = [self.tableView editedColumnIdentifier];
        
        if ([columnIdentifier isEqualToString:@"key"]) {
            key = textView.textStorage.string;
        } else if ([columnIdentifier isEqualToString:@"value"]) {
            value = textView.textStorage.string;
        }
        
        LNLocalization *newLocalization = [LNLocalization localizationWithKey:key
                                                                        value:value
                                                                  entityRange:localization.entityRange
                                                                     keyRange:localization.keyRange
                                                                   valueRange:localization.valueRange
                                                                   collection:localization.collection];
        
        // Replace in file
        [localization.collection replaceLocalization:localization withLocalization:newLocalization];
        
        // Update
        [self configureView];
    }
}


#pragma mark - Actions

- (void)tableViewDidDoubleClick:(id)sender
{
    NSInteger clickedRow = [self.tableView clickedRow];
    
    if (clickedRow >= 0) {
        LNLocalization *localization = [self.sortedLocalizations objectAtIndex:clickedRow];
        
        // Post notification
        [[NSNotificationCenter defaultCenter] postNotificationName:LNPopoverContentViewLocalizationDidSelectNotification
                                                            object:self
                                                          userInfo:@{LNPopoverContentViewLocalizationKey: localization}];
    }
}

- (IBAction)addLocalization:(id)sender
{
    // Create alert
    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    NSViewController *viewController = [[NSViewController alloc] initWithNibName:@"LNAlertAccessoryView" bundle:bundle];
    LNAlertAccessoryView *accessoryView = (LNAlertAccessoryView *)viewController.view;
    accessoryView.collections = self.collections;
    
    NSAlert *alert = [NSAlert alertWithMessageText:@"Lin"
                                     defaultButton:@"OK"
                                   alternateButton:@"Cancel"
                                       otherButton:nil
                         informativeTextWithFormat:@"Input a key/value for a new localization."];
    alert.accessoryView = accessoryView;
    
    NSButton *button = [[alert buttons] objectAtIndex:0];
    accessoryView.button = button;
    
    // Set icon
    NSString *filePath = [bundle pathForResource:@"icon120" ofType:@"tiff"];
    NSImage *icon = [[NSImage alloc] initWithContentsOfFile:filePath];
    [alert setIcon:icon];
    
    // Show alert
    switch ([alert runModal]) {
        case NSAlertDefaultReturn:
        {
            // Create a new localization
            LNAlertAccessoryView *accessoryView = (LNAlertAccessoryView *)alert.accessoryView;
            
            LNLocalizationCollection *collection = accessoryView.selectedCollection;
            NSString *key = accessoryView.inputtedKey;
            NSString *value = accessoryView.inputtedValue;
            
            LNLocalization *localization = [LNLocalization localizationWithKey:key
                                                                         value:value
                                                                   entityRange:NSMakeRange(NSNotFound, 0)
                                                                      keyRange:NSMakeRange(NSNotFound, 0)
                                                                    valueRange:NSMakeRange(NSNotFound, 0)
                                                                    collection:collection];
            
            // Add localization to file
            [collection addLocalization:localization];
            
            // Update
            [self configureView];
        }
            
        default:
        {
            // Post notification
            [[NSNotificationCenter defaultCenter] postNotificationName:LNPopoverContentViewAlertDidDismissNotification
                                                                object:self
                                                              userInfo:nil];
        }
            break;
    }
}

- (IBAction)deleteLocalization:(id)sender
{
    NSInteger selectedRow = [self.tableView selectedRow];
    
    if (selectedRow >= 0) {
        [self.tableView beginUpdates];
        
        // Delete localization from array
        LNLocalization *localization = [self.sortedLocalizations objectAtIndex:selectedRow];
        NSInteger index = [self.localizations indexOfObject:localization];
        [self.localizations removeObjectAtIndex:index];
        
        // Filter localizations
        [self filterLocalizations];
        
        // Delete localization from file
        LNLocalizationCollection *collection = localization.collection;
        [collection deleteLocalization:localization];
        
        // Delete localization from table view
        [self.tableView removeRowsAtIndexes:[NSIndexSet indexSetWithIndex:selectedRow]
                              withAnimation:NSTableViewAnimationEffectFade];
        
        [self.tableView endUpdates];
    }
}

- (IBAction)detachPopover:(id)sender
{
    // Post notification
    [[NSNotificationCenter defaultCenter] postNotificationName:LNPopoverContentViewDetachButtonDidClickNotification
                                                        object:self
                                                      userInfo:nil];
}


#pragma mark - Updating and Drawing the View

- (void)reloadLocalizations
{
    NSMutableArray *localizations = [NSMutableArray array];
    
    for (LNLocalizationCollection *collection in self.collections) {
        [localizations addObjectsFromArray:[collection.localizations allObjects]];
    }
    
    self.localizations = localizations;
}

- (void)filterLocalizations
{
    // Filter localizations
    NSArray *filteredLocalizations = self.localizations;
    
    if (self.searchString.length > 0) {
        filteredLocalizations = [filteredLocalizations filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"key contains[c] %@", self.searchString]];
    }
    
    // Sort localizations
    self.sortedLocalizations = [[filteredLocalizations sortedArrayUsingDescriptors:self.tableView.sortDescriptors] mutableCopy];
}

- (void)configureView
{
    // Reload localizations
    [self reloadLocalizations];
    
    // Filter localizations
    [self filterLocalizations];
    
    // Update table view
    [self.tableView reloadData];
}


#pragma mark - NSTableViewDataSource

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
    return self.sortedLocalizations.count;
}

- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
    LNLocalization *localization = [self.sortedLocalizations objectAtIndex:row];
    NSString *identifier = tableColumn.identifier;
    
    if([identifier isEqualToString:@"table"]) {
        return [localization.collection.filePath lastPathComponent];
    }
    else if ([identifier isEqualToString:@"language"]) {
        return localization.collection.languageDesignation;
    }
    else if ([identifier isEqualToString:@"key"]) {
        return localization.key;
    }
    else if ([identifier isEqualToString:@"value"]) {
        return localization.value;
    }
    
    return nil;
}

- (void)tableView:(NSTableView *)tableView sortDescriptorsDidChange:(NSArray *)oldDescriptors
{
    // Update
    [self configureView];
}


#pragma mark - NSTableViewDelegate

- (void)tableView:(NSTableView *)tableView didClickTableColumn:(NSTableColumn *)clickedTableColumn
{
    for (NSTableColumn *tableColumn in [tableView tableColumns]) {
        LNTableHeaderCell *headerCell = (LNTableHeaderCell*)[tableColumn headerCell];
        
        if (tableColumn == clickedTableColumn) {
            [headerCell setSortAscending:[[[tableView sortDescriptors] objectAtIndex:0] ascending]
                                priority:0];
        } else {
            [headerCell setSortAscending:NO
                                priority:1];
        }
    }
}

@end


================================================
FILE: Lin/LNPopoverContentView.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4514" systemVersion="13C64" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
    <dependencies>
        <deployment defaultVersion="1070" identifier="macosx"/>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4514"/>
    </dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner" customClass="NSViewController">
            <connections>
                <outlet property="view" destination="JhI-Tt-sI6" id="ShO-KJ-h53"/>
            </connections>
        </customObject>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <customObject id="-3" userLabel="Application"/>
        <customView id="JhI-Tt-sI6" customClass="LNPopoverContentView">
            <rect key="frame" x="0.0" y="0.0" width="500" height="200"/>
            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
            <subviews>
                <scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="22" horizontalPageScroll="10" verticalLineScroll="22" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3v3-Ru-fHe">
                    <rect key="frame" x="0.0" y="26" width="500" height="165"/>
                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                    <clipView key="contentView" id="4Zc-RR-q53">
                        <rect key="frame" x="0.0" y="17" width="500" height="148"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" autosaveColumns="NO" rowHeight="20" headerView="PhJ-5j-No2" id="Bwg-zH-Dly" customClass="LNTableView">
                                <rect key="frame" x="0.0" y="0.0" width="500" height="148"/>
                                <autoresizingMask key="autoresizingMask"/>
                                <size key="intercellSpacing" width="3" height="2"/>
                                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                                <tableViewGridLines key="gridStyleMask" horizontal="YES"/>
                                <color key="gridColor" red="0.92156862745098034" green="0.92156862745098034" blue="0.92156862745098034" alpha="1" colorSpace="calibratedRGB"/>
                                <tableColumns>
                                    <tableColumn identifier="table" editable="NO" width="120" minWidth="40" maxWidth="1000" id="YXl-vg-Qqt">
                                        <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Table">
                                            <font key="font" metaFont="smallSystem"/>
                                            <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
                                            <color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
                                        </tableHeaderCell>
                                        <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="zoX-Td-qdB">
                                            <font key="font" metaFont="cellTitle"/>
                                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                                            <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
                                        </textFieldCell>
                                        <sortDescriptor key="sortDescriptorPrototype" selector="compare:" sortKey="collection.fileName"/>
                                        <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
                                    </tableColumn>
                                    <tableColumn identifier="language" editable="NO" width="80" minWidth="40" maxWidth="1000" id="5SM-c2-cfJ">
                                        <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Language">
                                            <font key="font" metaFont="smallSystem"/>
                                            <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
                                            <color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
                                        </tableHeaderCell>
                                        <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="Ira-n7-x81">
                                            <font key="font" metaFont="cellTitle"/>
                                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                                            <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
                                        </textFieldCell>
                                        <sortDescriptor key="sortDescriptorPrototype" selector="compare:" sortKey="collection.languageDesignation"/>
                                        <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
                                    </tableColumn>
                                    <tableColumn identifier="key" width="100" minWidth="40" maxWidth="1000" id="UTY-KW-1GJ">
                                        <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Key">
                                            <font key="font" metaFont="smallSystem"/>
                                            <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
                                            <color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
                                        </tableHeaderCell>
                                        <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="VEM-Lk-Orp">
                                            <font key="font" metaFont="cellTitle"/>
                                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                                            <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
                                        </textFieldCell>
                                        <sortDescriptor key="sortDescriptorPrototype" selector="compare:" sortKey="key"/>
                                        <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
                                    </tableColumn>
                                    <tableColumn identifier="value" width="188" minWidth="40" maxWidth="1000" id="puj-ZH-fjz">
                                        <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Value">
                                            <font key="font" metaFont="smallSystem"/>
                                            <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
                                            <color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
                                        </tableHeaderCell>
                                        <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="KsI-QU-sXD">
                                            <font key="font" metaFont="cellTitle"/>
                                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                                            <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
                                        </textFieldCell>
                                        <sortDescriptor key="sortDescriptorPrototype" selector="compare:" sortKey="value"/>
                                        <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
                                    </tableColumn>
                                </tableColumns>
                                <connections>
                                    <outlet property="dataSource" destination="JhI-Tt-sI6" id="rzs-bS-zvN"/>
                                    <outlet property="delegate" destination="JhI-Tt-sI6" id="qbi-dH-oJW"/>
                                </connections>
                            </tableView>
                        </subviews>
                        <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
                    </clipView>
                    <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="kwl-10-84v">
                        <rect key="frame" x="0.0" y="149" width="485" height="16"/>
                        <autoresizingMask key="autoresizingMask"/>
                    </scroller>
                    <scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="9DO-ip-b6D">
                        <rect key="frame" x="485" y="17" width="15" height="132"/>
                        <autoresizingMask key="autoresizingMask"/>
                    </scroller>
                    <tableHeaderView key="headerView" id="PhJ-5j-No2">
                        <rect key="frame" x="0.0" y="0.0" width="500" height="17"/>
                        <autoresizingMask key="autoresizingMask"/>
                    </tableHeaderView>
                </scrollView>
                <box autoresizesSubviews="NO" verticalHuggingPriority="750" title="Box" boxType="separator" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="M5Y-vQ-slM" customClass="LNHorizontalLine">
                    <rect key="frame" x="0.0" y="23" width="500" height="5"/>
                    <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
                    <color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
                    <color key="fillColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
                    <font key="titleFont" metaFont="system"/>
                </box>
                <box autoresizesSubviews="NO" boxType="custom" borderType="none" titlePosition="noTitle" translatesAutoresizingMaskIntoConstraints="NO" id="cAa-PZ-3Fm">
                    <rect key="frame" x="0.0" y="0.0" width="500" height="25"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <view key="contentView">
                        <rect key="frame" x="0.0" y="0.0" width="500" height="25"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <button translatesAutoresizingMaskIntoConstraints="NO" id="WtB-AR-lfY">
                                <rect key="frame" x="4" y="1" width="23" height="23"/>
                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="23" id="VSY-Ea-som"/>
                                    <constraint firstAttribute="width" constant="23" id="vGo-Tv-NV0"/>
                                </constraints>
                                <buttonCell key="cell" type="bevel" bezelStyle="rounded" image="icon_plus" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" inset="2" id="Vfs-qd-LwL" customClass="LNImageButtonCell">
                                    <behavior key="behavior" lightByContents="YES"/>
                                    <font key="font" metaFont="system"/>
                                </buttonCell>
                                <connections>
                                    <action selector="addLocalization:" target="JhI-Tt-sI6" id="dgA-Bo-Yol"/>
                                </connections>
                            </button>
                            <button translatesAutoresizingMaskIntoConstraints="NO" id="Xwg-el-W0l">
                                <rect key="frame" x="27" y="1" width="23" height="23"/>
                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                <constraints>
                                    <constraint firstAttribute="width" constant="23" id="0kD-WZ-161"/>
                                    <constraint firstAttribute="height" constant="23" id="D5h-qU-aRQ"/>
                                </constraints>
                                <buttonCell key="cell" type="bevel" bezelStyle="rounded" image="icon_minus" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" inset="2" id="jgd-uF-zMf" customClass="LNImageButtonCell">
                                    <behavior key="behavior" lightByContents="YES"/>
                                    <font key="font" metaFont="system"/>
                                </buttonCell>
                                <connections>
                                    <action selector="deleteLocalization:" target="JhI-Tt-sI6" id="tFN-bB-EZ9"/>
                                </connections>
                            </button>
                            <button translatesAutoresizingMaskIntoConstraints="NO" id="X12-7a-tbY">
                                <rect key="frame" x="473" y="1" width="23" height="23"/>
                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                <constraints>
                                    <constraint firstAttribute="height" constant="23" id="Fjw-Dz-IYH"/>
                                    <constraint firstAttribute="width" constant="23" id="PsO-Ia-HA2"/>
                                </constraints>
                                <buttonCell key="cell" type="bevel" bezelStyle="rounded" image="icon_detach" imagePosition="overlaps" alignment="center" imageScaling="proportionallyDown" inset="2" id="VUs-dt-MMw" customClass="LNImageButtonCell">
                                    <behavior key="behavior" lightByContents="YES"/>
                                    <font key="font" metaFont="system"/>
                                </buttonCell>
                                <connections>
                                    <action selector="detachPopover:" target="JhI-Tt-sI6" id="uOQ-V9-dBd"/>
                                </connections>
                            </button>
                        </subviews>
                    </view>
                    <constraints>
                        <constraint firstItem="Xwg-el-W0l" firstAttribute="leading" secondItem="WtB-AR-lfY" secondAttribute="trailing" id="5pw-fJ-d8R"/>
                        <constraint firstAttribute="trailing" secondItem="X12-7a-tbY" secondAttribute="trailing" constant="4" id="6xU-Pd-Agd"/>
                        <constraint firstItem="WtB-AR-lfY" firstAttribute="leading" secondItem="cAa-PZ-3Fm" secondAttribute="leading" constant="4" id="Kry-Fq-New"/>
                        <constraint firstAttribute="centerY" secondItem="X12-7a-tbY" secondAttribute="centerY" id="oUR-CY-xSP"/>
                        <constraint firstAttribute="centerY" secondItem="Xwg-el-W0l" secondAttribute="centerY" id="omo-Dh-2fO"/>
                        <constraint firstAttribute="height" constant="25" id="qFh-OU-mVW"/>
                        <constraint firstAttribute="centerY" secondItem="WtB-AR-lfY" secondAttribute="centerY" id="ucy-2R-CBm"/>
                    </constraints>
                    <color key="borderColor" white="0.0" alpha="0.41999999999999998" colorSpace="calibratedWhite"/>
                    <color key="fillColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="calibratedRGB"/>
                </box>
            </subviews>
            <constraints>
                <constraint firstAttribute="trailing" secondItem="3v3-Ru-fHe" secondAttribute="trailing" id="0L7-81-bdN"/>
                <constraint firstItem="M5Y-vQ-slM" firstAttribute="top" secondItem="3v3-Ru-fHe" secondAttribute="bottom" id="1WQ-Ef-TZV"/>
                <constraint firstAttribute="trailing" secondItem="M5Y-vQ-slM" secondAttribute="trailing" id="5Yh-4m-jQy"/>
                <constraint firstItem="cAa-PZ-3Fm" firstAttribute="top" secondItem="M5Y-vQ-slM" secondAttribute="bottom" id="Fna-Xj-XEe"/>
                <constraint firstItem="cAa-PZ-3Fm" firstAttribute="leading" secondItem="JhI-Tt-sI6" secondAttribute="leading" id="Kgt-Ih-fU7"/>
                <constraint firstAttribute="trailing" secondItem="cAa-PZ-3Fm" secondAttribute="trailing" id="NNz-sZ-Vbd"/>
                <constraint firstItem="3v3-Ru-fHe" firstAttribute="top" secondItem="JhI-Tt-sI6" secondAttribute="top" constant="9" id="cCW-AF-6OE"/>
                <constraint firstAttribute="bottom" secondItem="cAa-PZ-3Fm" secondAttribute="bottom" id="feW-oG-u69"/>
                <constraint firstItem="3v3-Ru-fHe" firstAttribute="leading" secondItem="JhI-Tt-sI6" secondAttribute="leading" id="frT-O8-fDd"/>
                <constraint firstItem="M5Y-vQ-slM" firstAttribute="leading" secondItem="JhI-Tt-sI6" secondAttribute="leading" id="gtc-0Y-ztA"/>
                <constraint firstItem="M5Y-vQ-slM" firstAttribute="top" secondItem="3v3-Ru-fHe" secondAttribute="bottom" id="ibB-DG-WcF"/>
                <constraint firstItem="cAa-PZ-3Fm" firstAttribute="top" secondItem="M5Y-vQ-slM" secondAttribute="bottom" id="ruW-IO-Hhr"/>
            </constraints>
            <connections>
                <outlet property="detachButton" destination="X12-7a-tbY" id="BqK-21-FHB"/>
                <outlet property="tableView" destination="Bwg-zH-Dly" id="KYr-er-9ip"/>
            </connections>
        </customView>
    </objects>
    <resources>
        <image name="icon_detach" width="12" height="12"/>
        <image name="icon_minus" width="8" height="8"/>
        <image name="icon_plus" width="8" height="8"/>
    </resources>
</document>

================================================
FILE: Lin/LNPopoverWindow.h
================================================
//
//  LNPopoverWindow.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface LNPopoverWindow : NSWindow <NSToolbarDelegate, NSTextFieldDelegate>

+ (instancetype)popoverWindow;

@end


================================================
FILE: Lin/LNPopoverWindow.m
================================================
//
//  LNPopoverWindow.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNPopoverWindow.h"

// Views
#import "LNPopoverContentView.h"

// Controllers
#import "LNPopoverWindowController.h"

static NSString * const kLNPopoverWindowToolbarSearchFieldIdentifier = @"Search";

@interface LNPopoverWindow ()

@property (nonatomic, strong) NSSearchField *searchField;

@end

@implementation LNPopoverWindow

+ (instancetype)popoverWindow
{
    LNPopoverWindow *popoverWindow = [[LNPopoverWindow alloc] initWithContentRect:NSZeroRect
                                                                        styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask)
                                                                          backing:NSBackingStoreBuffered
                                                                            defer:NO];
    popoverWindow.title = @"Lin";
    popoverWindow.level = NSFloatingWindowLevel;
    popoverWindow.backgroundColor = [NSColor whiteColor];
    [popoverWindow.contentView setAutoresizesSubviews:YES];
    
    return popoverWindow;
}

- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag
{
    self = [super initWithContentRect:contentRect styleMask:aStyle backing:bufferingType defer:flag];
    
    if (self) {
        // Create toolbar
        NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"Toolbar"];
        toolbar.delegate = self;
        toolbar.displayMode = NSToolbarDisplayModeIconOnly;
        
        [self setToolbar:toolbar];
    }
    
    return self;
}


#pragma mark - Actions

- (void)textFieldDidReturn:(id)sender
{
    [self controlTextDidChange:nil];
}


#pragma mark - NSToolbarDelegate

- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar
{
    return @[NSToolbarFlexibleSpaceItemIdentifier, kLNPopoverWindowToolbarSearchFieldIdentifier];
}

- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
{
    return @[NSToolbarFlexibleSpaceItemIdentifier, kLNPopoverWindowToolbarSearchFieldIdentifier];
}

- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
{
    NSToolbarItem *toolbarItem = nil;
    
    if ([itemIdentifier isEqualToString:kLNPopoverWindowToolbarSearchFieldIdentifier]) {
        toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
        
        NSSearchField *searchField = [[NSSearchField alloc] init];
        [searchField setDelegate:self];
        [searchField setTarget:self];
        [searchField setAction:@selector(textFieldDidReturn:)];
        
        [toolbarItem setView:searchField];
        self.searchField = searchField;
    }
    
    return toolbarItem;
}


#pragma mark - NSTextFieldDelegate

- (void)controlTextDidChange:(NSNotification *)obj
{
    LNPopoverWindowController *popoverWindowController = (LNPopoverWindowController *)self.windowController;
    LNPopoverContentView *contentView = (LNPopoverContentView *)popoverWindowController.popoverContentViewController.view;
    
    contentView.searchString = self.searchField.stringValue;
}

@end


================================================
FILE: Lin/LNPopoverWindowController.h
================================================
//
//  LNPopoverWindowController.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/20.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@class LNPopoverContentViewController;

extern NSString * const LNPopoverWindowControllerWindowWillCloseNotification;

@interface LNPopoverWindowController : NSWindowController <NSWindowDelegate, NSToolbarDelegate, NSTextFieldDelegate>

@property (nonatomic, strong) NSViewController *popoverContentViewController;

- (instancetype)initWithPopoverContentViewController:(NSViewController *)popoverContentViewController;

@end


================================================
FILE: Lin/LNPopoverWindowController.m
================================================
//
//  LNPopoverWindowController.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/20.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNPopoverWindowController.h"

// Views
#import "LNPopoverWindow.h"

NSString * const LNPopoverWindowControllerWindowWillCloseNotification = @"LNPopoverWindowControllerWindowWillCloseNotification";

@implementation LNPopoverWindowController

- (instancetype)initWithPopoverContentViewController:(NSViewController *)popoverContentViewController
{
    LNPopoverWindow *popoverWindow = [LNPopoverWindow popoverWindow];
    popoverWindow.delegate = self;
    
    self = [super initWithWindow:popoverWindow];
    
    if (self) {
        self.popoverContentViewController = popoverContentViewController;
    }
    
    return self;
}


#pragma mark - Accessors

- (void)setPopoverContentViewController:(NSViewController *)popoverContentViewController
{
    // Remove previous content view
    if (self.popoverContentViewController) {
        [self.popoverContentViewController.view removeFromSuperview];
    }
    
    _popoverContentViewController = popoverContentViewController;
    
    // Set content view of the window
    self.popoverContentViewController.view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
    [self.window.contentView setFrame:self.popoverContentViewController.view.bounds];
    [self.window.contentView addSubview:self.popoverContentViewController.view];
}


#pragma mark - NSWindowDelegate

- (void)windowWillClose:(NSNotification *)notification
{
    // Post notification
    [[NSNotificationCenter defaultCenter] postNotificationName:LNPopoverWindowControllerWindowWillCloseNotification
                                                        object:self
                                                      userInfo:nil];
}

@end


================================================
FILE: Lin/LNRegularExpressionPattern+type.h
================================================
//
//  LNRegularExpressionPattern+type.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNRegularExpressionPattern.h"

// Models
#import "LNEntity.h"

@interface LNRegularExpressionPattern (type)

@property (nonatomic, assign, readonly) LNEntityType type;

+ (instancetype)patternWithType:(LNEntityType)type;

@end


================================================
FILE: Lin/LNRegularExpressionPattern+type.m
================================================
//
//  LNRegularExpressionPattern+type.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNRegularExpressionPattern+type.h"
#import <objc/runtime.h>

static NSString * const LNRegularExpressionPatternTypePropertyKey = @"type";

@implementation LNRegularExpressionPattern (type)

- (LNEntityType)type
{
    return [objc_getAssociatedObject(self, (__bridge const void *)(LNRegularExpressionPatternTypePropertyKey)) unsignedIntegerValue];
}

- (void)setType:(LNEntityType)type
{
    objc_setAssociatedObject(self, (__bridge const void *)(LNRegularExpressionPatternTypePropertyKey), @(type), OBJC_ASSOCIATION_ASSIGN);
}

+ (instancetype)patternWithType:(LNEntityType)type
{
    LNRegularExpressionPattern *regularExpression = nil;
    
    NSString *pettern = nil;
    NSUInteger numberOfRanges = 0;
    NSUInteger entityRangeIndex = 0;
    NSUInteger keyRangeIndex = 1;
    
    switch (type) {
        case LNEntityTypeLocalizedString:
        {
            pettern = @"NSLocalizedString\\s*\\(\\s*@\"(.*?)\"\\s*,\\s*(.*?)\\s*\\)";
            numberOfRanges = 3;
        }
            break;
        case LNEntityTypeLocalizedStringForKey:
        {
            pettern = @"localizedStringForKey:\\s*@\"(.*?)\"\\s*value:\\s*(.*?)\\s*table:\\s*(.*?)";
            numberOfRanges = 4;
        }
            break;
        case LNEntityTypeLocalizedStringFromTable:
        {
            pettern = @"NSLocalizedStringFromTable\\s*\\(\\s*@\"(.*?)\"\\s*,\\s*(.*?)\\s*,\\s*(.*?)\\s*\\)";
            numberOfRanges = 4;
        }
            break;
        case LNEntityTypeLocalizedStringFromTableInBundle:
        {
            pettern = @"NSLocalizedStringFromTableInBundle\\s*\\(\\s*@\"(.*?)\"\\s*,\\s*(.*?)\\s*,\\s*(.*?)\\s*,\\s*(.*?)\\s*\\)";
            numberOfRanges = 5;
        }
            break;
        case LNEntityTypeLocalizedStringWithDefaultValue:
        {
            pettern = @"NSLocalizedStringWithDefaultValue\\s*\\(\\s*@\"(.*?)\"\\s*,\\s*(.*?)\\s*,\\s*(.*?)\\s*,\\s*(.*?)\\s*,\\s*(.*?)\\s*\\)";
            numberOfRanges = 6;
        }
            break;
    }
    
    if (pettern) {
        regularExpression = [LNRegularExpressionPattern patternWithString:pettern
                                                           numberOfRanges:numberOfRanges
                                                         entityRangeIndex:entityRangeIndex
                                                            keyRangeIndex:keyRangeIndex];
        regularExpression.type = type;
    }
    
    return regularExpression;
}

@end


================================================
FILE: Lin/LNRegularExpressionPattern.h
================================================
//
//  LNRegularExpressionPattern.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface LNRegularExpressionPattern : NSObject

@property (nonatomic, copy, readonly) NSString *pattern;
@property (nonatomic, assign, readonly) NSUInteger numberOfRanges;
@property (nonatomic, assign, readonly) NSUInteger entityRangeIndex;
@property (nonatomic, assign, readonly) NSUInteger keyRangeIndex;

+ (instancetype)patternWithString:(NSString *)string numberOfRanges:(NSUInteger)numberOfRanges entityRangeIndex:(NSUInteger)entityRangeIndex keyRangeIndex:(NSUInteger)keyRangeIndex;

- (instancetype)initWithString:(NSString *)string numberOfRanges:(NSUInteger)numberOfRanges entityRangeIndex:(NSUInteger)entityRangeIndex keyRangeIndex:(NSUInteger)keyRangeIndex;

@end


================================================
FILE: Lin/LNRegularExpressionPattern.m
================================================
//
//  LNRegularExpressionPattern.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNRegularExpressionPattern.h"

@interface LNRegularExpressionPattern ()

@property (nonatomic, copy, readwrite) NSString *pattern;
@property (nonatomic, assign, readwrite) NSUInteger numberOfRanges;
@property (nonatomic, assign, readwrite) NSUInteger entityRangeIndex;
@property (nonatomic, assign, readwrite) NSUInteger keyRangeIndex;

@end

@implementation LNRegularExpressionPattern

+ (instancetype)patternWithString:(NSString *)string numberOfRanges:(NSUInteger)numberOfRanges entityRangeIndex:(NSUInteger)entityRangeIndex keyRangeIndex:(NSUInteger)keyRangeIndex
{
    return [[self alloc] initWithString:string
                         numberOfRanges:numberOfRanges
                       entityRangeIndex:entityRangeIndex
                          keyRangeIndex:keyRangeIndex];
}

- (instancetype)initWithString:(NSString *)string numberOfRanges:(NSUInteger)numberOfRanges entityRangeIndex:(NSUInteger)entityRangeIndex keyRangeIndex:(NSUInteger)keyRangeIndex
{
    self = [super init];
    
    if (self) {
        self.pattern = string;
        self.numberOfRanges = numberOfRanges;
        self.entityRangeIndex = entityRangeIndex;
        self.keyRangeIndex = keyRangeIndex;
    }
    
    return self;
}

@end


================================================
FILE: Lin/LNTableCornerView.h
================================================
//
//  LNTableCornerView.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface LNTableCornerView : NSView

@end


================================================
FILE: Lin/LNTableCornerView.m
================================================
//
//  LNTableCornerView.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNTableCornerView.h"

@implementation LNTableCornerView

- (void)drawRect:(NSRect)dirtyRect
{
	[super drawRect:dirtyRect];
	
    // Background
    [[NSColor whiteColor] setFill];
    NSRectFill(dirtyRect);
    
    // Draw separator
    [[NSColor colorWithDeviceWhite:204.0/255.0 alpha:1.0] setStroke];
    [NSBezierPath strokeLineFromPoint:NSMakePoint(dirtyRect.origin.x, 0.5)
                              toPoint:NSMakePoint(dirtyRect.origin.x + dirtyRect.size.width, 0.5)];
}

@end


================================================
FILE: Lin/LNTableHeaderCell.h
================================================
//
//  LNTableHeaderCell.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface LNTableHeaderCell : NSTableHeaderCell

@property (nonatomic, weak) NSTableView *tableView;

- (void)setSortAscending:(BOOL)ascending priority:(NSInteger)priority;

@end


================================================
FILE: Lin/LNTableHeaderCell.m
================================================
//
//  LNTableHeaderCell.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNTableHeaderCell.h"

static const NSInteger kLNTableHeaderCellSortIndicatorWidth = 8;
static const NSInteger kLNTableHeaderCellSortIndicatorHeight = 7;
static const NSInteger kLNTableHeaderCellSortIndicatorMarginX = 4;
static const NSInteger kLNTableHeaderCellSortIndicatorMarginY = 6;

@interface LNTableHeaderCell ()

@property (nonatomic, assign) BOOL ascending;
@property (nonatomic, assign) NSInteger priority;

- (void)drawContentInRect:(NSRect)rect highlighted:(BOOL)highlighted;

@end

@implementation LNTableHeaderCell

- (instancetype)init
{
    self = [super init];
    
    if (self) {
        self.priority = 1;
    }
    
    return self;
}


#pragma mark - Accessors

- (void)setSortAscending:(BOOL)ascending priority:(NSInteger)priority
{
    self.ascending = ascending;
    self.priority = priority;
}


#pragma mark - Drawing the View

- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
    [self drawContentInRect:cellFrame highlighted:NO];
    [self drawSortIndicatorWithFrame:cellFrame inView:controlView ascending:self.ascending priority:self.priority];
}

- (void)highlight:(BOOL)flag withFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
    [self drawContentInRect:cellFrame highlighted:YES];
    [self drawSortIndicatorWithFrame:cellFrame inView:controlView ascending:self.ascending priority:self.priority];
}

- (void)drawContentInRect:(NSRect)rect highlighted:(BOOL)highlighted
{
    // Draw background
    NSRect backgroundRect = rect;
    backgroundRect.size.width -= 1;
    
    if (highlighted) {
        [[NSColor colorWithDeviceWhite:153.0/255.0 alpha:1.0] set];
    } else {
        [[NSColor whiteColor] set];
    }
    
    NSRectFill(backgroundRect);
    
    // Draw separator
    [[NSColor colorWithDeviceWhite:204.0/255.0 alpha:1.0] setStroke];
    [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x, rect.size.height - 0.5)
                              toPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.size.height - 0.5)];
    
    // Draw title
    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:[self attributedStringValue]];
    
    NSDictionary *attributes;
    if (highlighted) {
        attributes = @{
                       NSForegroundColorAttributeName: [NSColor whiteColor],
                       NSFontAttributeName: [NSFont systemFontOfSize:12.0]
                       };
    } else {
        attributes = @{
                       NSForegroundColorAttributeName: [NSColor colorWithDeviceWhite:153.0/255.0 alpha:1.0],
                       NSFontAttributeName: [NSFont systemFontOfSize:12.0]
                       };
    }
    
    [attributedString addAttributes:attributes range:NSMakeRange(0, [attributedString length])];
    
    NSRect titleRect = rect;
    titleRect.origin.x += 3;
    titleRect.origin.y += 0;
    
    [attributedString drawInRect:titleRect];
}

- (void)drawSortIndicatorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView ascending:(BOOL)ascending priority:(NSInteger)priority
{
    NSBezierPath *path = [NSBezierPath bezierPath];
    
    if (ascending) {
        NSPoint p = NSMakePoint(cellFrame.origin.x + cellFrame.size.width - kLNTableHeaderCellSortIndicatorWidth - kLNTableHeaderCellSortIndicatorMarginX,
                                cellFrame.origin.y + cellFrame.size.height - kLNTableHeaderCellSortIndicatorMarginY);
        [path moveToPoint:p];
        
        p.x += kLNTableHeaderCellSortIndicatorWidth / 2.0;
        p.y -= kLNTableHeaderCellSortIndicatorHeight;
        [path lineToPoint:p];
        
        p.x += kLNTableHeaderCellSortIndicatorWidth / 2.0;
        p.y += kLNTableHeaderCellSortIndicatorHeight;
        [path lineToPoint:p];
    } else {
        NSPoint p = NSMakePoint(cellFrame.origin.x + cellFrame.size.width - kLNTableHeaderCellSortIndicatorWidth - kLNTableHeaderCellSortIndicatorMarginX,
                                cellFrame.origin.y + cellFrame.size.height - kLNTableHeaderCellSortIndicatorHeight - kLNTableHeaderCellSortIndicatorMarginY);
        [path moveToPoint:p];
        
        p.x += kLNTableHeaderCellSortIndicatorWidth / 2.0;
        p.y += kLNTableHeaderCellSortIndicatorHeight;
        [path lineToPoint:p];
        
        p.x += kLNTableHeaderCellSortIndicatorWidth / 2.0;
        p.y -= kLNTableHeaderCellSortIndicatorHeight;
        [path lineToPoint:p];
    }
    
    [path closePath];
    
    if (priority == 0) {
        [[NSColor colorWithDeviceWhite:153.0/255.0 alpha:1.0] set];
    } else {
        [[NSColor clearColor] set];
    }
    
    [path fill];
}

@end


================================================
FILE: Lin/LNTableView.h
================================================
//
//  LNTableView.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface LNTableView : NSTableView

@end


================================================
FILE: Lin/LNTableView.m
================================================
//
//  LNTableView.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNTableView.h"

// Views
#import "LNTableCornerView.h"
#import "LNTableHeaderCell.h"

@implementation LNTableView

- (void)awakeFromNib
{
    [super awakeFromNib];
    
    // Set corner view
    NSView *cornerView = [self cornerView];
    LNTableCornerView *newCornerView = [[LNTableCornerView alloc] initWithFrame:cornerView.frame];
    [self setCornerView:newCornerView];
    
    // Change header cell
    for (NSTableColumn *tableColumn in [self tableColumns]) {
        NSTableHeaderCell *headerCell = [tableColumn headerCell];
        
        LNTableHeaderCell *newHeaderCell = [[LNTableHeaderCell alloc] init];
        newHeaderCell.tableView = self;
        [newHeaderCell setAttributedStringValue:[headerCell attributedStringValue]];
        
        [tableColumn setHeaderCell:newHeaderCell];
    }
}

@end


================================================
FILE: Lin/LNUserDefaultsManager.h
================================================
//
//  LNUserDefaultsManager.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/22.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface LNUserDefaultsManager : NSObject

@property (nonatomic, assign, getter = isEnabled) BOOL enabled;

+ (instancetype)sharedManager;

@end


================================================
FILE: Lin/LNUserDefaultsManager.m
================================================
//
//  LNUserDefaultsManager.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/22.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNUserDefaultsManager.h"

static NSString * const LNUserDefaultManagerEnabledKey = @"jp.questbeat.Lin.enabled";

@implementation LNUserDefaultsManager

+ (instancetype)sharedManager
{
    static id _sharedManager;
	static dispatch_once_t _onceToken;
    
	dispatch_once(&_onceToken, ^{
		_sharedManager = [[self alloc] init];
	});
    
    return _sharedManager;
}

- (instancetype)init
{
    self = [super init];
    
    if (self) {
        // Register defaults
        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
        [userDefaults registerDefaults:@{LNUserDefaultManagerEnabledKey: @(YES)}];
        [userDefaults synchronize];
    }
    
    return self;
}


#pragma mark - Accessors

- (void)setEnabled:(BOOL)enabled
{
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    [userDefaults setBool:enabled forKey:LNUserDefaultManagerEnabledKey];
    [userDefaults synchronize];
}

- (BOOL)isEnabled
{
    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    return [userDefaults boolForKey:LNUserDefaultManagerEnabledKey];
}

@end


================================================
FILE: Lin/Lin-Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>English</string>
	<key>CFBundleExecutable</key>
	<string>${EXECUTABLE_NAME}</string>
	<key>CFBundleIconFile</key>
	<string></string>
	<key>CFBundleIdentifier</key>
	<string>jp.questbeat.${PRODUCT_NAME:rfc1034identifier}</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>${PRODUCT_NAME}</string>
	<key>CFBundlePackageType</key>
	<string>BNDL</string>
	<key>CFBundleShortVersionString</key>
	<string>2.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>DVTPlugInCompatibilityUUIDs</key>
	<array>
		<string>37B30044-3B14-46BA-ABAA-F01000C27B63</string>
		<string>640F884E-CE55-4B40-87C0-8869546CAB7A</string>
		<string>A2E4D43F-41F4-4FB9-BB94-7177011C9AED</string>
	</array>
	<key>LSApplicationCategoryType</key>
	<string></string>
	<key>NSHumanReadableCopyright</key>
	<string>Copyright © 2013年 Tanaka Katsuma. All rights reserved.</string>
	<key>NSPrincipalClass</key>
	<string>Lin</string>
	<key>XC4Compatible</key>
	<true/>
	<key>XC5Compatible</key>
	<true/>
	<key>XCGCReady</key>
	<true/>
	<key>XCPluginHasUI</key>
	<false/>
</dict>
</plist>


================================================
FILE: Lin/Lin-Prefix.pch
================================================
//
//  Prefix header
//
//  The contents of this file are implicitly included at the beginning of every source file.
//

#ifdef __OBJC__
    #import <Cocoa/Cocoa.h>
#endif


================================================
FILE: Lin/Lin.h
================================================
//
//  Lin.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@class IDEIndex;

@interface Lin : NSObject <NSPopoverDelegate>

+ (void)pluginDidLoad:(NSBundle *)bundle;
+ (instancetype)sharedPlugIn;

- (void)indexNeedsUpdate:(IDEIndex *)index;
- (void)removeLocalizationsForIndex:(IDEIndex *)index;

@end


================================================
FILE: Lin/Lin.m
================================================
//
//  Lin.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "Lin.h"

// Xcode
#import "IDEWorkspace.h"
#import "DVTFilePath.h"
#import "IDEIndex.h"
#import "IDEIndexCollection.h"
#import "IDEEditorDocument.h"
#import "IDEWorkspaceWindow.h"
#import "DVTSourceTextView.h"

// Categories
#import "NSBundle+versions.h"

// Shared
#import "LNUserDefaultsManager.h"

// Models
#import "LNDetector.h"
#import "LNEntity.h"
#import "LNLocalizationCollection.h"
#import "LNLocalization.h"

// Views
#import "LNPopoverContentView.h"

// Controllers
#import "LNPopoverWindowController.h"
#import "LNLocalizedStringCollectionOperation.h"

static Lin *_sharedPlugin = nil;

@interface NSPopover ()

- (id)_popoverWindow;

@end

@interface Lin ()

@property (nonatomic, strong) NSPopover *popover;
@property (nonatomic, strong) LNPopoverWindowController *popoverWindowController;

@property (nonatomic, strong) NSTextView *textView;

@property (nonatomic, strong) LNDetector *detector;
@property (nonatomic, strong) NSMutableDictionary *workspaceLocalizations;
@property (nonatomic, copy) NSString *currentWorkspaceFilePath;
@property (nonatomic, unsafe_unretained) NSResponder *previousFirstResponder;
@property (nonatomic, assign, getter = isActivated) BOOL activated;

@property (nonatomic, strong) NSMenuItem *enableMenuItem;
@property (nonatomic, strong) NSMenuItem *showWindowMenuItem;
@property (nonatomic, strong) NSOperationQueue *collectionProcessQueue;

@end

@implementation Lin

+ (void)pluginDidLoad:(NSBundle *)bundle
{
    static dispatch_once_t _onceToken;
    dispatch_once(&_onceToken, ^{
        _sharedPlugin = [[self alloc] init];
    });
}

+ (instancetype)sharedPlugIn
{
    return _sharedPlugin;
}

- (instancetype)init
{
    self = [super init];
    
    if (self) {
        // Initialization
        self.detector = [LNDetector detector];
        self.workspaceLocalizations = [NSMutableDictionary dictionary];
        
        // Create menu
        [self createMenuItem];
        
        // Load views
        [self instantiatePopover];
        [self instantiatePopoverWindowController];
        
        // Register to notification center
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(workspaceWindowDidBecomeMain:)
                                                     name:NSWindowDidBecomeMainNotification
                                                   object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(indexDidIndexWorkspace:)
                                                     name:@"IDEIndexDidIndexWorkspaceNotification"
                                                   object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(editorDocumentDidSave:)
                                                     name:@"IDEEditorDocumentDidSaveNotification"
                                                   object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(popoverWindowControllerWindowWillClose:)
                                                     name:LNPopoverWindowControllerWindowWillCloseNotification
                                                   object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(popoverContentViewLocalizationDidSelect:)
                                                     name:LNPopoverContentViewLocalizationDidSelectNotification
                                                   object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(popoverContentViewAlertDidDismiss:)
                                                     name:LNPopoverContentViewAlertDidDismissNotification
                                                   object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(popoverContentViewDetachButtonDidClick:)
                                                     name:LNPopoverContentViewDetachButtonDidClickNotification
                                                   object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(menuDidChange:)
                                                     name:NSMenuDidChangeItemNotification
                                                   object:nil];
        
        // Activate if enabled
        if ([[LNUserDefaultsManager sharedManager] isEnabled]) {
            [self activate];
        }
        
        self.collectionProcessQueue = [[NSOperationQueue alloc] init];
        self.collectionProcessQueue.maxConcurrentOperationCount = 1;
    }
    
    return self;
}

- (void)instantiatePopover
{
    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    NSViewController *contentViewController = [[NSViewController alloc] initWithNibName:@"LNPopoverContentView" bundle:bundle];
    
    NSPopover *popover = [[NSPopover alloc] init];
    popover.delegate = self;
    popover.behavior = NSPopoverBehaviorTransient;
    popover.appearance = NSPopoverAppearanceMinimal;
    popover.animates = NO;
    popover.contentViewController = contentViewController;
    
    self.popover = popover;
}

- (void)instantiatePopoverWindowController
{
    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    NSViewController *contentViewController = [[NSViewController alloc] initWithNibName:@"LNPopoverContentView" bundle:bundle];
    LNPopoverContentView *contentView = (LNPopoverContentView *)contentViewController.view;
    [contentView.detachButton setHidden:YES];
    
    LNPopoverWindowController *popoverWindowController = [[LNPopoverWindowController alloc] initWithPopoverContentViewController:contentViewController];
    
    self.popoverWindowController = popoverWindowController;
}

- (void)dealloc
{
    // Deactivate
    [self deactivate];
    
    // Remove from notification center
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:NSWindowDidBecomeMainNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:@"IDEIndexDidIndexWorkspaceNotification"
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:@"IDEEditorDocumentDidSaveNotification"
                                                  object:nil];
    
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:LNPopoverWindowControllerWindowWillCloseNotification
                                                  object:nil];
    
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:LNPopoverContentViewLocalizationDidSelectNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:LNPopoverContentViewAlertDidDismissNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:LNPopoverContentViewDetachButtonDidClickNotification
                                                  object:nil];
    
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:NSMenuDidChangeItemNotification
                                                  object:nil];
}


#pragma mark - Managing Application State

- (void)activate
{
    if (!self.activated) {
        self.activated = YES;
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(textDidChange:)
                                                     name:NSTextDidChangeNotification
                                                   object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(textViewDidChangeSelection:)
                                                     name:NSTextViewDidChangeSelectionNotification
                                                   object:nil];
    }
}

- (void)deactivate
{
    if (self.activated) {
        self.activated = NO;
        
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:NSTextDidChangeNotification
                                                      object:nil];
        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:NSTextViewDidChangeSelectionNotification
                                                      object:nil];
    }
}


#pragma mark - Notifications

- (void)textDidChange:(NSNotification *)notification
{
	if ([[notification object] isKindOfClass:[DVTSourceTextView class]]) {
        NSTextView *textView = (NSTextView *)[notification object];
        self.textView = textView;
        
        // Find entity
        LNEntity *entity = [self selectedEntityInTextView:textView];
        
        if (entity) {
            [self presentPopoverInTextView:textView entity:entity];
        } else {
            [self dismissPopover];
        }
	}
}

- (void)textViewDidChangeSelection:(NSNotification *)notification
{
	if ([[notification object] isKindOfClass:[DVTSourceTextView class]]) {
        NSTextView *textView = (NSTextView *)[notification object];
        self.textView = textView;
        
        // Find entity
        LNEntity *entity = [self selectedEntityInTextView:textView];
        
        if (entity) {
            [self presentPopoverInTextView:textView entity:entity];
        } else {
            [self dismissPopover];
        }
	}
}

- (void)workspaceWindowDidBecomeMain:(NSNotification *)notification
{
    if ([[notification object] isKindOfClass:[IDEWorkspaceWindow class]]) {
        NSWindow *workspaceWindow = (NSWindow *)[notification object];
        NSWindowController *workspaceWindowController = (NSWindowController *)workspaceWindow.windowController;
        
        IDEWorkspace *workspace = (IDEWorkspace *)[workspaceWindowController valueForKey:@"_workspace"];
        DVTFilePath *representingFilePath = workspace.representingFilePath;
        NSString *pathString = representingFilePath.pathString;
        
        self.currentWorkspaceFilePath = pathString;
    }
}

- (void)indexDidIndexWorkspace:(NSNotification *)notification
{
    IDEIndex *index = (IDEIndex *)[notification object];
    [self indexNeedsUpdate:index];
}

- (void)editorDocumentDidSave:(NSNotification *)notification
{
    IDEEditorDocument *editorDocument = (IDEEditorDocument *)[notification object];
    DVTFilePath *filePath = editorDocument.filePath;
    NSString *pathString = filePath.pathString;
    
    // Check whether there are any changes to .strings
    NSArray *collections = [self.workspaceLocalizations objectForKey:self.currentWorkspaceFilePath];
    
    for (LNLocalizationCollection *collection in collections) {
        if ([collection.filePath isEqualToString:pathString]) {
            [collection reloadLocalizations];
            
            break;
        }
    }
}

- (void)popoverWindowControllerWindowWillClose:(NSNotification *)notification
{
    // Instantiate popover
    [self instantiatePopover];
}

- (void)popoverContentViewLocalizationDidSelect:(NSNotification *)notification
{
    NSTextView *textView = self.textView;
    LNEntity *entity = [self selectedEntityInTextView:textView];
    
    if (entity) {
        NSArray *selectedRanges = textView.selectedRanges;
        
        if (selectedRanges.count > 0) {
            NSRange selectedRange = [[selectedRanges objectAtIndex:0] rangeValue];
            
            // Locate the key
            NSRange lineRange = [textView.textStorage.string lineRangeForRange:selectedRange];
            NSRange keyRange = NSMakeRange(lineRange.location + entity.keyRange.location, entity.keyRange.length);
            
            // Replace
            LNLocalization *localization = [[notification userInfo] objectForKey:LNPopoverContentViewLocalizationKey];
            [textView insertText:localization.key replacementRange:keyRange];
        }
    }
}

- (void)popoverContentViewAlertDidDismiss:(NSNotification *)notification
{
    // Show popover again
    [self presentPopoverInTextView:self.textView entity:[self selectedEntityInTextView:self.textView]];
}

- (void)popoverContentViewDetachButtonDidClick:(NSNotification *)notification
{
    [self preparePopoverWindow];
    [self detachPopover];
}

- (void)menuDidChange:(NSNotification *)notification
{
    // Create menu item
    [self createMenuItem];
}


#pragma mark - Detachig Popover

- (void)preparePopoverWindow
{
    // Resize popover window
    NSWindow *popoverWindow = [self.popover _popoverWindow];
    
    [self.popoverWindowController.window setFrame:NSMakeRect(popoverWindow.frame.origin.x,
                                                             popoverWindow.frame.origin.y - (80.0 / 2.0),
                                                             self.popover.contentSize.width,
                                                             self.popover.contentSize.height + 80.0)
                                          display:NO];
    
    // Copy popover content
    LNPopoverContentView *popoverContentView = (LNPopoverContentView *)self.popover.contentViewController.view;
    LNPopoverContentView *popoverWindowContentView = (LNPopoverContentView *)self.popoverWindowController.popoverContentViewController.view;
    popoverWindowContentView.tableView.sortDescriptors = popoverContentView.tableView.sortDescriptors;
    popoverWindowContentView.collections = popoverContentView.collections;
    popoverWindowContentView.searchString = popoverContentView.searchString;
}

- (void)detachPopover
{
    [self dismissPopover];
    [self.popoverWindowController showWindow:nil];
}


#pragma mark - Entity

- (LNEntity *)selectedEntityInTextView:(NSTextView *)textView
{
    NSArray *selectedRanges = textView.selectedRanges;
    
    if (selectedRanges.count > 0) {
        NSRange selectedRange = [[selectedRanges objectAtIndex:0] rangeValue];
        
        // Locate the line containing the caret
        NSString *string = textView.textStorage.string;
        NSRange lineRange = [string lineRangeForRange:selectedRange];
        NSString *lineString = [string substringWithRange:lineRange];
        NSRange selectedRangeInLine = NSMakeRange(selectedRange.location - lineRange.location, selectedRange.length);
        
        // Search for the entities
        NSArray *entities = [self.detector entitiesInString:lineString];
        
        for (LNEntity *entity in entities) {
            if (NSLocationInRange(selectedRangeInLine.location, entity.entityRange)) {
                return entity;
            }
        }
    }
    
    return nil;
}


#pragma mark - Menu

- (void)createMenuItem
{
    NSMenuItem *editorMenuItem = [[NSApp mainMenu] itemWithTitle:@"Editor"];
    
    if (editorMenuItem && [[editorMenuItem submenu] itemWithTitle:@"Lin"] == nil) {
        // Load defaults
        BOOL enabled = [[LNUserDefaultsManager sharedManager] isEnabled];
        
        NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:@"Lin" action:NULL keyEquivalent:@""];
        
        NSMenu *submenu = [[NSMenu alloc] initWithTitle:@"Lin"];
        menuItem.submenu = submenu;
        
        // Enable Lin
        NSMenuItem *enableMenuItem = [[NSMenuItem alloc] initWithTitle:@"Enable Lin" action:@selector(toggleEnabled:) keyEquivalent:@""];
        [enableMenuItem setTarget:self];
        enableMenuItem.state = enabled ? NSOnState : NSOffState;
        
        [submenu addItem:enableMenuItem];
        self.enableMenuItem = enableMenuItem;
        
        // Show Window
        NSMenuItem *showWindowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Show Window" action:@selector(showWindow:) keyEquivalent:@""];
        [showWindowMenuItem setTarget:self];
        
        [submenu addItem:showWindowMenuItem];
        self.showWindowMenuItem = showWindowMenuItem;
        
        // Separator
        [submenu addItem:[NSMenuItem separatorItem]];
        
        // Version Info
        NSMenuItem *versionInfoMenuItem = [[NSMenuItem alloc] initWithTitle:@"Version Info" action:@selector(showVersionInfo:) keyEquivalent:@""];
        [versionInfoMenuItem setTarget:self];
        [submenu addItem:versionInfoMenuItem];
        
        [[editorMenuItem submenu] addItem:[NSMenuItem separatorItem]];
        [[editorMenuItem submenu] addItem:menuItem];
    }
}

- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
    if (menuItem == self.showWindowMenuItem) {
        return [[LNUserDefaultsManager sharedManager] isEnabled];
    }
    
    return YES;
}

- (void)toggleEnabled:(id)sender
{
    // Save defaults
    LNUserDefaultsManager *userDefaultManager = [LNUserDefaultsManager sharedManager];
    BOOL enabled = ![userDefaultManager isEnabled];
    userDefaultManager.enabled = enabled;
    
    // Update menu item
    self.enableMenuItem.state = enabled ? NSOnState : NSOffState;
    
    // Activate/Deactivate
    if (enabled) {
        [self activate];
    } else {
        [self deactivate];
    }
}

- (void)showWindow:(id)sender
{
    // Prepare window
    NSArray *collections = [self.workspaceLocalizations objectForKey:self.currentWorkspaceFilePath];
    
    LNPopoverContentView *popoverWindowContentView = (LNPopoverContentView *)self.popoverWindowController.popoverContentViewController.view;
    popoverWindowContentView.collections = collections;
    popoverWindowContentView.searchString = @"";
    
    // Show window
    [self.popoverWindowController.window setFrame:NSMakeRect(0, 0, 500, 280) display:NO];
    [self.popoverWindowController.window center];
    [self.popoverWindowController showWindow:nil];
}

- (void)showVersionInfo:(id)sender
{
    // Create alert
    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    NSAlert *alert = [NSAlert alertWithMessageText:@"Lin"
                                     defaultButton:@"OK"
                                   alternateButton:nil
                                       otherButton:@"Open Website"
                         informativeTextWithFormat:@"Version %@\n\nCopyright (c) 2013 Katsuma Tanaka\n\nEmail: questbeat@gmail.com\nTwitter: @questbeat", [bundle shortVersionString]];
    
    // Set icon
    NSString *filePath = [bundle pathForResource:@"icon120" ofType:@"tiff"];
    NSImage *icon = [[NSImage alloc] initWithContentsOfFile:filePath];
    [alert setIcon:icon];
    
    // Show alert
    if ([alert runModal] == NSAlertOtherReturn) {
        [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://questbe.at/lin"]];
    }
}


#pragma mark - Index

- (void)indexNeedsUpdate:(IDEIndex *)index
{
    DVTFilePath *workspaceFile = index.workspaceFile;
    NSString *workspaceFilePath = workspaceFile.pathString;
    
    if (workspaceFilePath) {
        [self.collectionProcessQueue cancelAllOperations];
        [self updateLocalizationsForIndex:index];
    }
}

- (void)updateLocalizationsForIndex:(IDEIndex *)index
{
    LNLocalizedStringCollectionOperation *processOperation = [[LNLocalizedStringCollectionOperation alloc] initWithIndex:index];
    processOperation.collectionCompletedBlock = ^(NSString *workspaceFilePath, NSArray *collections) {
        [self.workspaceLocalizations setObject:collections forKey:workspaceFilePath];
        if ([workspaceFilePath isEqualToString:self.currentWorkspaceFilePath]) {
            if ([self.popover isShown]) {
                LNPopoverContentView *contentView = (LNPopoverContentView *)self.popover.contentViewController.view;
                contentView.collections = collections;
            } else if ([self.popoverWindowController.window isVisible]) {
                LNPopoverContentView *contentView = (LNPopoverContentView *)self.popoverWindowController.popoverContentViewController.view;
                contentView.collections = collections;
            }
        }
    };
    
    [self.collectionProcessQueue addOperation:processOperation];
}

- (void)removeLocalizationsForIndex:(IDEIndex *)index
{
    DVTFilePath *workspaceFile = index.workspaceFile;
    NSString *workspaceFilePath = workspaceFile.pathString;
    
    if (workspaceFilePath) {
        [self.workspaceLocalizations removeObjectForKey:workspaceFilePath];
    }
}


#pragma mark - Popover

- (void)presentPopoverInTextView:(NSTextView *)textView entity:(LNEntity *)entity
{
    if (![[LNUserDefaultsManager sharedManager] isEnabled]) {
        return;
    }
    
    NSArray *selectedRanges = textView.selectedRanges;
    
    if (selectedRanges.count > 0) {
        NSRange selectedRange = [[selectedRanges objectAtIndex:0] rangeValue];
        
        // Locate the line containing the caret
        NSRange lineRange = [textView.textStorage.string lineRangeForRange:selectedRange];
        
        // Stick popover at the beginning of the key
        NSRange keyRange = NSMakeRange(lineRange.location + entity.keyRange.location, 1);
        NSRect keyRectOnScreen = [textView firstRectForCharacterRange:keyRange actualRange:NULL];
        NSRect keyRectOnWindow = [textView.window convertRectFromScreen:keyRectOnScreen];
        NSRect keyRectOnTextView = [textView convertRect:keyRectOnWindow fromView:nil];
        
        // Update or show popover
        NSArray *collections = [self.workspaceLocalizations objectForKey:self.currentWorkspaceFilePath];
        NSString *key = [textView.textStorage.string substringWithRange:NSMakeRange(lineRange.location + entity.keyRange.location, entity.keyRange.length)];
        
        if ([self.popoverWindowController.window isVisible]) {
            // Update popover content
            LNPopoverContentView *contentView = (LNPopoverContentView *)self.popoverWindowController.popoverContentViewController.view;
            contentView.collections = collections;
            contentView.searchString = key;
        } else {
            if ([self.popover isShown]) {
                // Update the position for popover when the cursor moved
                self.popover.positioningRect = keyRectOnTextView;
                
                // Update popover content
                LNPopoverContentView *contentView = (LNPopoverContentView *)self.popover.contentViewController.view;
                contentView.searchString = key;
            } else {
                // Show popover
                [self.popover showRelativeToRect:keyRectOnTextView
                                          ofView:textView
                                   preferredEdge:NSMinYEdge];
                
                // Update popover content
                LNPopoverContentView *contentView = (LNPopoverContentView *)self.popover.contentViewController.view;
                contentView.collections = collections;
                contentView.searchString = key;
            }
        }
    }
}

- (void)dismissPopover
{
    if ([self.popoverWindowController.window isVisible]) {
        // Update popover content
        NSArray *collections = [self.workspaceLocalizations objectForKey:self.currentWorkspaceFilePath];
        
        LNPopoverContentView *contentView = (LNPopoverContentView *)self.popoverWindowController.popoverContentViewController.view;
        contentView.collections = collections;
        contentView.searchString = nil;
    } else {
        // Hide popover
        if (self.popover.shown) {
            [self.popover performClose:self];
        }
    }
}


#pragma mark - NSPopoverDelegate

- (void)popoverWillShow:(NSNotification *)notification
{
    // Save first responder
    self.previousFirstResponder = [self.textView.window firstResponder];
}

- (void)popoverDidShow:(NSNotification *)notification
{
    // Reclaim key window and first responder
    [self.textView.window becomeKeyWindow];
    [self.textView.window makeFirstResponder:self.previousFirstResponder];
}

- (NSWindow *)detachableWindowForPopover:(NSPopover *)popover
{
    // Prepare for detaching
    [self preparePopoverWindow];
    
    return self.popoverWindowController.window;
}

@end


================================================
FILE: Lin/MethodSwizzle.h
================================================
//
//  MethodSwizzle.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/24.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

void MethodSwizzle(Class cls, SEL org_sel, SEL alt_sel);


================================================
FILE: Lin/MethodSwizzle.m
================================================
//
//  MethodSwizzle.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/24.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "MethodSwizzle.h"
#import <objc/objc-class.h>

void MethodSwizzle(Class cls, SEL org_sel, SEL alt_sel)
{
    Method org_method = nil, alt_method = nil;
	
    org_method = class_getInstanceMethod(cls, org_sel);
    alt_method = class_getInstanceMethod(cls, alt_sel);
	
    if (org_method != nil && alt_method != nil) {
        method_exchangeImplementations(org_method, alt_method);
	}
}



================================================
FILE: Lin/NSBundle+versions.h
================================================
//
//  NSBundle+versions.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSBundle (versions)

- (NSString *)shortVersionString;
- (NSNumber *)buildNumber;

@end


================================================
FILE: Lin/NSBundle+versions.m
================================================
//
//  NSBundle+versions.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "NSBundle+versions.h"

@implementation NSBundle (versions)

- (NSString *)shortVersionString
{
    return [self objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
}

- (NSNumber *)buildNumber
{
    return [self objectForInfoDictionaryKey:@"CFBundleVersion"];
}

@end


================================================
FILE: Lin/NSPopoverFrame+Lin.h
================================================
//
//  NSPopoverFrame+Lin.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "NSPopoverFrame.h"

@interface NSPopoverFrame (Lin)

@end


================================================
FILE: Lin/NSPopoverFrame+Lin.m
================================================
//
//  NSPopoverFrame+Lin.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "NSPopoverFrame+Lin.h"
#import <CoreServices/CoreServices.h>

#import "MethodSwizzle.h"

@implementation NSPopoverFrame (Lin)

+ (void)load
{
    MethodSwizzle(self, @selector(_drawMinimalPopoverAppearanceInRect:anchorEdge:anchorPoint:), @selector(jp_questbeat_lin_drawMinimalPopoverAppearanceInRect:anchorEdge:anchorPoint:));
}

- (void)jp_questbeat_lin_drawMinimalPopoverAppearanceInRect:(struct CGRect)arg1 anchorEdge:(unsigned long long)arg2 anchorPoint:(struct CGPoint)arg3
{
    [self jp_questbeat_lin_drawMinimalPopoverAppearanceInRect:arg1 anchorEdge:arg2 anchorPoint:arg3];
    
    // Check OS version
    SInt32 major = 0;
    SInt32 minor = 0;
    Gestalt(gestaltSystemVersionMajor, &major);
    Gestalt(gestaltSystemVersionMinor, &minor);
    
    if ((major == 10 && minor <= 8) || major <= 9) {
        // Mac OS X Mountain Lion or older
        // This code will cause a problem on Max OS X 10.9 Mavericks (or maybe later)
        [[NSColor whiteColor] setFill];
        NSRectFill(arg1);
    } else {
        // Mac OS X Mavericks or later
        CGPathRef path = [self _newMinimalAppearancePathInBounds:arg1
                                                      anchorEdge:arg2
                                                     anchorPoint:arg3
                                                      topCapOnly:NO
                                                     arrowOffset:0];
        CGImageRef maskImage = [self _imageMaskForPath:(struct CGPath *)path
                                            anchorEdge:arg2
                                           anchorPoint:arg3];
        
        NSBitmapImageRep *backgroundImageRep = [self backgroundImageRepWithSize:self.bounds.size maskImage:maskImage];
        
        CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
        CGImageRef backgroundImageRef = [backgroundImageRep CGImage];
        CGContextDrawImage(context, self.bounds, backgroundImageRef);
    }
}

- (NSBitmapImageRep *)backgroundImageRepWithSize:(NSSize)size maskImage:(CGImageRef)maskImage
{
    CGContextRef currentContext = [[NSGraphicsContext currentContext] graphicsPort];
    CGContextSaveGState(currentContext);
    
    CGFloat scale = [self convertSizeToBacking:CGSizeMake(1, 1)].width;
    size.width *= scale;
    size.height *= scale;
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL,
                                                 size.width,
                                                 size.height,
                                                 8,
                                                 4 * size.width,
                                                 colorSpace,
                                                 (CGBitmapInfo)kCGImageAlphaPremultipliedLast);
    
    CGContextClipToMask(context, CGRectMake(0, 0, size.width, size.height), maskImage);
    
    CGContextSetFillColorWithColor(context, [[NSColor whiteColor] CGColor]);
    CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));
    
    CGImageRef backgroundImageRef = CGBitmapContextCreateImage(context);
    NSBitmapImageRep *backgroundImageRep = [[NSBitmapImageRep alloc] initWithCGImage:backgroundImageRef];
    CGImageRelease(backgroundImageRef);
    
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    
    CGContextRestoreGState(currentContext);
    
    return backgroundImageRep;
}

@end


================================================
FILE: Lin/NSPopoverFrame.h
================================================
/*
 *     Generated by class-dump 3.4 (64 bit).
 *
 *     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2012 by Steve Nygard.
 */

#import <AppKit/NSView.h>

@class NSImage;

@interface NSPopoverFrame : NSView

- (void)_drawMinimalPopoverAppearanceInRect:(struct CGRect)arg1 anchorEdge:(unsigned long long)arg2 anchorPoint:(struct CGPoint)arg3;

- (struct CGImage *)_imageMaskForPath:(struct CGPath *)arg1 anchorEdge:(unsigned long long)arg2 anchorPoint:(struct CGPoint)arg3;
- (struct CGPath *)_newMinimalAppearancePathInBounds:(struct CGRect)arg1 anchorEdge:(unsigned long long)arg2 anchorPoint:(struct CGPoint)arg3 topCapOnly:(BOOL)arg4 arrowOffset:(double)arg5;
- (struct CGPath *)_newMinimalAppearancePathInBounds:(struct CGRect)arg1 anchorEdge:(unsigned long long)arg2 arrowPosition:(double)arg3 topCapOnly:(BOOL)arg4 arrowOffset:(double)arg5;

@end



================================================
FILE: Lin/NSTableView+editedColumnIdentifier.h
================================================
//
//  NSTableView+editedColumnIdentifier.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/22.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface NSTableView (editedColumnIdentifier)

- (NSString *)editedColumnIdentifier;

@end


================================================
FILE: Lin/NSTableView+editedColumnIdentifier.m
================================================
//
//  NSTableView+editedColumnIdentifier.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/09/22.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "NSTableView+editedColumnIdentifier.h"

@implementation NSTableView (editedColumnIdentifier)

- (NSString *)editedColumnIdentifier
{
    NSInteger editedColumnIndex = [self editedColumn];
    
    NSArray *tableColumns = [self tableColumns];
    for (NSInteger i = 0; i < tableColumns.count; i++) {
        NSTableColumn *column = [tableColumns objectAtIndex:i];
        
        if (i == editedColumnIndex) {
            return column.identifier;
        }
    }
    
    return nil;
}

@end


================================================
FILE: Lin/en.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */



================================================
FILE: Lin.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		AA02CE8B17EE08240041C2BD /* LNAlertAccessoryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = AA02CE8A17EE08240041C2BD /* LNAlertAccessoryView.xib */; };
		AA02CE8E17EE083A0041C2BD /* LNAlertAccessoryView.m in Sources */ = {isa = PBXBuildFile; fileRef = AA02CE8D17EE083A0041C2BD /* LNAlertAccessoryView.m */; };
		AA1B7DA717C3C1EC00A3A6D7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA1B7DA617C3C1EC00A3A6D7 /* Cocoa.framework */; };
		AA1B7DB117C3C1EC00A3A6D7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = AA1B7DAF17C3C1EC00A3A6D7 /* InfoPlist.strings */; };
		AA1B7DBA17C3C20F00A3A6D7 /* Lin.m in Sources */ = {isa = PBXBuildFile; fileRef = AA1B7DB917C3C20F00A3A6D7 /* Lin.m */; };
		AA20D87F17ECB12A006B7CA2 /* NSPopoverFrame+Lin.m in Sources */ = {isa = PBXBuildFile; fileRef = AA20D87E17ECB12A006B7CA2 /* NSPopoverFrame+Lin.m */; };
		AA2980B417EE2C5300CF46E3 /* LNUserDefaultsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = AA2980B317EE2C5300CF46E3 /* LNUserDefaultsManager.m */; };
		AA36376617D9EF9E003C5E55 /* LNPopoverContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = AA36376517D9EF9E003C5E55 /* LNPopoverContentView.m */; };
		AA3EC36F17EB2A290003A180 /* DVTFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3EC36D17EB2A290003A180 /* DVTFoundation.framework */; };
		AA3EC37017EB2A290003A180 /* DVTKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3EC36E17EB2A290003A180 /* DVTKit.framework */; };
		AA3EC37317EB2A380003A180 /* IDEFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3EC37117EB2A380003A180 /* IDEFoundation.framework */; };
		AA3EC37417EB2A380003A180 /* IDEKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3EC37217EB2A380003A180 /* IDEKit.framework */; };
		AA470D5B17C3CFEC005CBB7F /* LNDetector.m in Sources */ = {isa = PBXBuildFile; fileRef = AA470D5A17C3CFEC005CBB7F /* LNDetector.m */; };
		AA470D5E17C3D05D005CBB7F /* LNEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = AA470D5D17C3D05D005CBB7F /* LNEntity.m */; };
		AA470D6517C3D380005CBB7F /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA470D6417C3D380005CBB7F /* XCTest.framework */; };
		AA470D6B17C3D380005CBB7F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = AA470D6917C3D380005CBB7F /* InfoPlist.strings */; };
		AA470D7D17C3DE31005CBB7F /* LNDetectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA470D7C17C3DE31005CBB7F /* LNDetectorTests.m */; };
		AA6377CE18C5CCFC005EADC7 /* LNImageButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = AA6377CD18C5CCFC005EADC7 /* LNImageButtonCell.m */; };
		AA63897918C6019A0061C2C4 /* icon_plus@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA63897118C6019A0061C2C4 /* icon_plus@2x.png */; };
		AA63897A18C6019A0061C2C4 /* icon_minus.png in Resources */ = {isa = PBXBuildFile; fileRef = AA63897218C6019A0061C2C4 /* icon_minus.png */; };
		AA63897B18C6019A0061C2C4 /* icon_minus@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA63897318C6019A0061C2C4 /* icon_minus@2x.png */; };
		AA63897C18C6019A0061C2C4 /* icon120.png in Resources */ = {isa = PBXBuildFile; fileRef = AA63897418C6019A0061C2C4 /* icon120.png */; };
		AA63897D18C6019A0061C2C4 /* icon_plus.png in Resources */ = {isa = PBXBuildFile; fileRef = AA63897518C6019A0061C2C4 /* icon_plus.png */; };
		AA63897E18C6019A0061C2C4 /* icon_detach@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA63897618C6019A0061C2C4 /* icon_detach@2x.png */; };
		AA63897F18C6019A0061C2C4 /* icon120@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = AA63897718C6019A0061C2C4 /* icon120@2x.png */; };
		AA63898018C6019A0061C2C4 /* icon_detach.png in Resources */ = {isa = PBXBuildFile; fileRef = AA63897818C6019A0061C2C4 /* icon_detach.png */; };
		AA7D4DB117C74CFE0092DF8A /* LNLocalizationCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = AA7D4DB017C74CFE0092DF8A /* LNLocalizationCollection.m */; };
		AA7D4DB417C74D0A0092DF8A /* LNLocalization.m in Sources */ = {isa = PBXBuildFile; fileRef = AA7D4DB317C74D0A0092DF8A /* LNLocalization.m */; };
		AA8F8EF017EDFC68004964FB /* NSTableView+editedColumnIdentifier.m in Sources */ = {isa = PBXBuildFile; fileRef = AA8F8EEF17EDFC68004964FB /* NSTableView+editedColumnIdentifier.m */; };
		AA95FDEC17EB48A9007D33D4 /* LNPopoverContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = AA95FDEB17EB48A9007D33D4 /* LNPopoverContentView.xib */; };
		AA95FDEF17EB4E77007D33D4 /* LNPopoverWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = AA95FDEE17EB4E77007D33D4 /* LNPopoverWindowController.m */; };
		AAAC873317ED9D4F00BF251D /* LNHorizontalLine.m in Sources */ = {isa = PBXBuildFile; fileRef = AAAC873217ED9D4F00BF251D /* LNHorizontalLine.m */; };
		AAAC873B17EDA9CF00BF251D /* LNPopoverWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = AAAC873A17EDA9CF00BF251D /* LNPopoverWindow.m */; };
		AAB0CD3117C4382D0085E913 /* LNRegularExpressionPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = AAB0CD3017C4382D0085E913 /* LNRegularExpressionPattern.m */; };
		AAB0CD3417C448200085E913 /* LNRegularExpressionPattern+type.m in Sources */ = {isa = PBXBuildFile; fileRef = AAB0CD3317C448200085E913 /* LNRegularExpressionPattern+type.m */; };
		AAB0CD3617C46A730085E913 /* LNDetector.m in Sources */ = {isa = PBXBuildFile; fileRef = AA470D5A17C3CFEC005CBB7F /* LNDetector.m */; };
		AAB0CD3717C46B070085E913 /* LNEntity.m in Sources */ = {isa = PBXBuildFile; fileRef = AA470D5D17C3D05D005CBB7F /* LNEntity.m */; };
		AAB0CD3817C46B070085E913 /* LNRegularExpressionPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = AAB0CD3017C4382D0085E913 /* LNRegularExpressionPattern.m */; };
		AAB0CD3917C46B070085E913 /* LNRegularExpressionPattern+type.m in Sources */ = {isa = PBXBuildFile; fileRef = AAB0CD3317C448200085E913 /* LNRegularExpressionPattern+type.m */; };
		AAB0CD3C17C477030085E913 /* LNDetectorTestSet.m in Sources */ = {isa = PBXBuildFile; fileRef = AAB0CD3B17C477030085E913 /* LNDetectorTestSet.m */; };
		AADDDA9417C49D4800BBA67C /* NSBundle+versions.m in Sources */ = {isa = PBXBuildFile; fileRef = AADDDA9317C49D4800BBA67C /* NSBundle+versions.m */; };
		AADEADB317C7B6D3001E0C65 /* LNLocalizationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AADEADB217C7B6D3001E0C65 /* LNLocalizationTests.m */; };
		AADEADB417C7B838001E0C65 /* LNLocalization.m in Sources */ = {isa = PBXBuildFile; fileRef = AA7D4DB317C74D0A0092DF8A /* LNLocalization.m */; };
		AADEADB717C87298001E0C65 /* IDEIndex+Lin.m in Sources */ = {isa = PBXBuildFile; fileRef = AADEADB617C87298001E0C65 /* IDEIndex+Lin.m */; };
		AADEADC017C87392001E0C65 /* MethodSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = AADEADBF17C87392001E0C65 /* MethodSwizzle.m */; };
		AAF0D6AB17ECB87100B4318B /* LNTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = AAF0D6AA17ECB87100B4318B /* LNTableView.m */; };
		AAF0D6AE17ECB89800B4318B /* LNTableHeaderCell.m in Sources */ = {isa = PBXBuildFile; fileRef = AAF0D6AD17ECB89800B4318B /* LNTableHeaderCell.m */; };
		AAF0D6B117ECC4AF00B4318B /* LNTableCornerView.m in Sources */ = {isa = PBXBuildFile; fileRef = AAF0D6B017ECC4AF00B4318B /* LNTableCornerView.m */; };
		AAF0D6B417ECD8EC00B4318B /* LNButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = AAF0D6B317ECD8EC00B4318B /* LNButtonCell.m */; };
		AAFE3C3F17EECF4A0018E478 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = AAFE3C3E17EECF4A0018E478 /* Localizable.strings */; };
		AAFE3C4117EED36C0018E478 /* LNLocalizationCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = AA7D4DB017C74CFE0092DF8A /* LNLocalizationCollection.m */; };
		F5859DBD18CABC2A009AF108 /* LNLocalizedStringCollectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F5859DBC18CABC2A009AF108 /* LNLocalizedStringCollectionOperation.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
		AA470D6F17C3D380005CBB7F /* PBXContainerItemProxy */ = {
			isa = PBXContainerItemProxy;
			containerPortal = AA1B7D9B17C3C1EC00A3A6D7 /* Project object */;
			proxyType = 1;
			remoteGlobalIDString = AA1B7DA217C3C1EC00A3A6D7;
			remoteInfo = Lin;
		};
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
		AA02CE8A17EE08240041C2BD /* LNAlertAccessoryView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LNAlertAccessoryView.xib; sourceTree = "<group>"; };
		AA02CE8C17EE083A0041C2BD /* LNAlertAccessoryView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNAlertAccessoryView.h; sourceTree = "<group>"; };
		AA02CE8D17EE083A0041C2BD /* LNAlertAccessoryView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNAlertAccessoryView.m; sourceTree = "<group>"; };
		AA11AC4017C66F0200889DFB /* DVTFilePath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVTFilePath.h; sourceTree = "<group>"; };
		AA11AC4317C6746800889DFB /* IDEIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDEIndex.h; sourceTree = "<group>"; };
		AA11AC4617C6755400889DFB /* IDEIndexCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDEIndexCollection.h; sourceTree = "<group>"; };
		AA1B7DA317C3C1EC00A3A6D7 /* Lin.xcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Lin.xcplugin; sourceTree = BUILT_PRODUCTS_DIR; };
		AA1B7DA617C3C1EC00A3A6D7 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
		AA1B7DA917C3C1EC00A3A6D7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
		AA1B7DAA17C3C1EC00A3A6D7 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
		AA1B7DAB17C3C1EC00A3A6D7 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
		AA1B7DAE17C3C1EC00A3A6D7 /* Lin-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Lin-Info.plist"; sourceTree = "<group>"; };
		AA1B7DB017C3C1EC00A3A6D7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
		AA1B7DB217C3C1EC00A3A6D7 /* Lin-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Lin-Prefix.pch"; sourceTree = "<group>"; };
		AA1B7DB817C3C20F00A3A6D7 /* Lin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Lin.h; sourceTree = "<group>"; };
		AA1B7DB917C3C20F00A3A6D7 /* Lin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Lin.m; sourceTree = "<group>"; };
		AA20D87D17ECB12A006B7CA2 /* NSPopoverFrame+Lin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPopoverFrame+Lin.h"; sourceTree = "<group>"; };
		AA20D87E17ECB12A006B7CA2 /* NSPopoverFrame+Lin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSPopoverFrame+Lin.m"; sourceTree = "<group>"; };
		AA20D88017ECB1AD006B7CA2 /* NSPopoverFrame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSPopoverFrame.h; sourceTree = "<group>"; };
		AA2980B217EE2C5300CF46E3 /* LNUserDefaultsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNUserDefaultsManager.h; sourceTree = "<group>"; };
		AA2980B317EE2C5300CF46E3 /* LNUserDefaultsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNUserDefaultsManager.m; sourceTree = "<group>"; };
		AA36376417D9EF9E003C5E55 /* LNPopoverContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNPopoverContentView.h; sourceTree = "<group>"; };
		AA36376517D9EF9E003C5E55 /* LNPopoverContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNPopoverContentView.m; sourceTree = "<group>"; };
		AA3EC36D17EB2A290003A180 /* DVTFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DVTFoundation.framework; path = ../../../../Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework; sourceTree = "<group>"; };
		AA3EC36E17EB2A290003A180 /* DVTKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DVTKit.framework; path = ../../../../Applications/Xcode.app/Contents/SharedFrameworks/DVTKit.framework; sourceTree = "<group>"; };
		AA3EC37117EB2A380003A180 /* IDEFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IDEFoundation.framework; path = ../../../../Applications/Xcode.app/Contents/Frameworks/IDEFoundation.framework; sourceTree = "<group>"; };
		AA3EC37217EB2A380003A180 /* IDEKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IDEKit.framework; path = ../../../../Applications/Xcode.app/Contents/Frameworks/IDEKit.framework; sourceTree = "<group>"; };
		AA470D5917C3CFEC005CBB7F /* LNDetector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNDetector.h; sourceTree = "<group>"; };
		AA470D5A17C3CFEC005CBB7F /* LNDetector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNDetector.m; sourceTree = "<group>"; };
		AA470D5C17C3D05D005CBB7F /* LNEntity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNEntity.h; sourceTree = "<group>"; };
		AA470D5D17C3D05D005CBB7F /* LNEntity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNEntity.m; sourceTree = "<group>"; };
		AA470D6317C3D380005CBB7F /* LinTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LinTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
		AA470D6417C3D380005CBB7F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
		AA470D6817C3D380005CBB7F /* LinTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "LinTests-Info.plist"; sourceTree = "<group>"; };
		AA470D6A17C3D380005CBB7F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
		AA470D6E17C3D380005CBB7F /* LinTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "LinTests-Prefix.pch"; sourceTree = "<group>"; };
		AA470D7C17C3DE31005CBB7F /* LNDetectorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNDetectorTests.m; sourceTree = "<group>"; };
		AA6377CC18C5CCFC005EADC7 /* LNImageButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNImageButtonCell.h; sourceTree = "<group>"; };
		AA6377CD18C5CCFC005EADC7 /* LNImageButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNImageButtonCell.m; sourceTree = "<group>"; };
		AA63897118C6019A0061C2C4 /* icon_plus@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_plus@2x.png"; sourceTree = "<group>"; };
		AA63897218C6019A0061C2C4 /* icon_minus.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_minus.png; sourceTree = "<group>"; };
		AA63897318C6019A0061C2C4 /* icon_minus@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_minus@2x.png"; sourceTree = "<group>"; };
		AA63897418C6019A0061C2C4 /* icon120.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon120.png; sourceTree = "<group>"; };
		AA63897518C6019A0061C2C4 /* icon_plus.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_plus.png; sourceTree = "<group>"; };
		AA63897618C6019A0061C2C4 /* icon_detach@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_detach@2x.png"; sourceTree = "<group>"; };
		AA63897718C6019A0061C2C4 /* icon120@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon120@2x.png"; sourceTree = "<group>"; };
		AA63897818C6019A0061C2C4 /* icon_detach.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_detach.png; sourceTree = "<group>"; };
		AA7B0CAD17F4228E0004FE3B /* DVTDualProxyWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVTDualProxyWindow.h; sourceTree = "<group>"; };
		AA7B0CB017F4229D0004FE3B /* IDEWorkspaceWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDEWorkspaceWindow.h; sourceTree = "<group>"; };
		AA7B0CB317F422BB0004FE3B /* DVTSourceTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVTSourceTextView.h; sourceTree = "<group>"; };
		AA7D4DAF17C74CFE0092DF8A /* LNLocalizationCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNLocalizationCollection.h; sourceTree = "<group>"; };
		AA7D4DB017C74CFE0092DF8A /* LNLocalizationCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNLocalizationCollection.m; sourceTree = "<group>"; };
		AA7D4DB217C74D0A0092DF8A /* LNLocalization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNLocalization.h; sourceTree = "<group>"; };
		AA7D4DB317C74D0A0092DF8A /* LNLocalization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNLocalization.m; sourceTree = "<group>"; };
		AA8F8EEE17EDFC68004964FB /* NSTableView+editedColumnIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSTableView+editedColumnIdentifier.h"; sourceTree = "<group>"; };
		AA8F8EEF17EDFC68004964FB /* NSTableView+editedColumnIdentifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSTableView+editedColumnIdentifier.m"; sourceTree = "<group>"; };
		AA93691517C4E4C000E94318 /* IDEWorkspace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDEWorkspace.h; sourceTree = "<group>"; };
		AA95FDEB17EB48A9007D33D4 /* LNPopoverContentView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LNPopoverContentView.xib; sourceTree = "<group>"; };
		AA95FDED17EB4E77007D33D4 /* LNPopoverWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNPopoverWindowController.h; sourceTree = "<group>"; };
		AA95FDEE17EB4E77007D33D4 /* LNPopoverWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNPopoverWindowController.m; sourceTree = "<group>"; };
		AAAC873117ED9D4F00BF251D /* LNHorizontalLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNHorizontalLine.h; sourceTree = "<group>"; };
		AAAC873217ED9D4F00BF251D /* LNHorizontalLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNHorizontalLine.m; sourceTree = "<group>"; };
		AAAC873917EDA9CF00BF251D /* LNPopoverWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNPopoverWindow.h; sourceTree = "<group>"; };
		AAAC873A17EDA9CF00BF251D /* LNPopoverWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNPopoverWindow.m; sourceTree = "<group>"; };
		AAB0CD2F17C4382D0085E913 /* LNRegularExpressionPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNRegularExpressionPattern.h; sourceTree = "<group>"; };
		AAB0CD3017C4382D0085E913 /* LNRegularExpressionPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNRegularExpressionPattern.m; sourceTree = "<group>"; };
		AAB0CD3217C448200085E913 /* LNRegularExpressionPattern+type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "LNRegularExpressionPattern+type.h"; sourceTree = "<group>"; };
		AAB0CD3317C448200085E913 /* LNRegularExpressionPattern+type.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "LNRegularExpressionPattern+type.m"; sourceTree = "<group>"; };
		AAB0CD3A17C477030085E913 /* LNDetectorTestSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNDetectorTestSet.h; sourceTree = "<group>"; };
		AAB0CD3B17C477030085E913 /* LNDetectorTestSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNDetectorTestSet.m; sourceTree = "<group>"; };
		AADDDA9217C49D4800BBA67C /* NSBundle+versions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSBundle+versions.h"; sourceTree = "<group>"; };
		AADDDA9317C49D4800BBA67C /* NSBundle+versions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+versions.m"; sourceTree = "<group>"; };
		AADEADB217C7B6D3001E0C65 /* LNLocalizationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNLocalizationTests.m; sourceTree = "<group>"; };
		AADEADB517C87298001E0C65 /* IDEIndex+Lin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IDEIndex+Lin.h"; sourceTree = "<group>"; };
		AADEADB617C87298001E0C65 /* IDEIndex+Lin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "IDEIndex+Lin.m"; sourceTree = "<group>"; };
		AADEADBB17C872EB001E0C65 /* IDEEditorDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDEEditorDocument.h; sourceTree = "<group>"; };
		AADEADBE17C87392001E0C65 /* MethodSwizzle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodSwizzle.h; sourceTree = "<group>"; };
		AADEADBF17C87392001E0C65 /* MethodSwizzle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MethodSwizzle.m; sourceTree = "<group>"; };
		AAF0D6A917ECB87100B4318B /* LNTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNTableView.h; sourceTree = "<group>"; };
		AAF0D6AA17ECB87100B4318B /* LNTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNTableView.m; sourceTree = "<group>"; };
		AAF0D6AC17ECB89800B4318B /* LNTableHeaderCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNTableHeaderCell.h; sourceTree = "<group>"; };
		AAF0D6AD17ECB89800B4318B /* LNTableHeaderCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNTableHeaderCell.m; sourceTree = "<group>"; };
		AAF0D6AF17ECC4AF00B4318B /* LNTableCornerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNTableCornerView.h; sourceTree = "<group>"; };
		AAF0D6B017ECC4AF00B4318B /* LNTableCornerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNTableCornerView.m; sourceTree = "<group>"; };
		AAF0D6B217ECD8EC00B4318B /* LNButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNButtonCell.h; sourceTree = "<group>"; };
		AAF0D6B317ECD8EC00B4318B /* LNButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNButtonCell.m; sourceTree = "<group>"; };
		AAFE3C3E17EECF4A0018E478 /* Localizable.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = "<group>"; };
		F5859DBB18CABC2A009AF108 /* LNLocalizedStringCollectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LNLocalizedStringCollectionOperation.h; sourceTree = "<group>"; };
		F5859DBC18CABC2A009AF108 /* LNLocalizedStringCollectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LNLocalizedStringCollectionOperation.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
		AA1B7DA017C3C1EC00A3A6D7 /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				AA3EC37317EB2A380003A180 /* IDEFoundation.framework in Frameworks */,
				AA3EC37417EB2A380003A180 /* IDEKit.framework in Frameworks */,
				AA3EC36F17EB2A290003A180 /* DVTFoundation.framework in Frameworks */,
				AA3EC37017EB2A290003A180 /* DVTKit.framework in Frameworks */,
				AA1B7DA717C3C1EC00A3A6D7 /* Cocoa.framework in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		AA470D6017C3D380005CBB7F /* Frameworks */ = {
			isa = PBXFrameworksBuildPhase;
			buildActionMask = 2147483647;
			files = (
				AA470D6517C3D380005CBB7F /* XCTest.framework in Frameworks */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
		AA1B7D9A17C3C1EC00A3A6D7 = {
			isa = PBXGroup;
			children = (
				AA1B7DAC17C3C1EC00A3A6D7 /* Lin */,
				AA470D6617C3D380005CBB7F /* LinTests */,
				AA1B7DA517C3C1EC00A3A6D7 /* Frameworks */,
				AA1B7DA417C3C1EC00A3A6D7 /* Products */,
			);
			sourceTree = "<group>";
		};
		AA1B7DA417C3C1EC00A3A6D7 /* Products */ = {
			isa = PBXGroup;
			children = (
				AA1B7DA317C3C1EC00A3A6D7 /* Lin.xcplugin */,
				AA470D6317C3D380005CBB7F /* LinTests.xctest */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		AA1B7DA517C3C1EC00A3A6D7 /* Frameworks */ = {
			isa = PBXGroup;
			children = (
				AA3EC37117EB2A380003A180 /* IDEFoundation.framework */,
				AA3EC37217EB2A380003A180 /* IDEKit.framework */,
				AA3EC36D17EB2A290003A180 /* DVTFoundation.framework */,
				AA3EC36E17EB2A290003A180 /* DVTKit.framework */,
				AA1B7DA617C3C1EC00A3A6D7 /* Cocoa.framework */,
				AA470D6417C3D380005CBB7F /* XCTest.framework */,
				AA1B7DA817C3C1EC00A3A6D7 /* Other Frameworks */,
			);
			name = Frameworks;
			sourceTree = "<group>";
		};
		AA1B7DA817C3C1EC00A3A6D7 /* Other Frameworks */ = {
			isa = PBXGroup;
			children = (
				AA1B7DA917C3C1EC00A3A6D7 /* Foundation.framework */,
				AA1B7DAA17C3C1EC00A3A6D7 /* CoreData.framework */,
				AA1B7DAB17C3C1EC00A3A6D7 /* AppKit.framework */,
			);
			name = "Other Frameworks";
			sourceTree = "<group>";
		};
		AA1B7DAC17C3C1EC00A3A6D7 /* Lin */ = {
			isa = PBXGroup;
			children = (
				AA93691817C4E4C700E94318 /* Xcode-Private-Classes */,
				AA20D88117ECB467006B7CA2 /* AppKit-Private-Classes */,
				AADDDA9517C49D4D00BBA67C /* Categories */,
				AA2980B517EE2CF600CF46E3 /* Shared */,
				AA470D7817C3DD42005CBB7F /* Models */,
				AADDDAA017C4A3BA00BBA67C /* Views */,
				AADDDA9C17C4A0E200BBA67C /* Controllers */,
				AA1B7DB817C3C20F00A3A6D7 /* Lin.h */,
				AA1B7DB917C3C20F00A3A6D7 /* Lin.m */,
				AADDDA9B17C4A0DA00BBA67C /* Resources */,
				AA1B7DAD17C3C1EC00A3A6D7 /* Supporting Files */,
			);
			path = Lin;
			sourceTree = "<group>";
		};
		AA1B7DAD17C3C1EC00A3A6D7 /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				AA1B7DAE17C3C1EC00A3A6D7 /* Lin-Info.plist */,
				AA1B7DAF17C3C1EC00A3A6D7 /* InfoPlist.strings */,
				AA1B7DB217C3C1EC00A3A6D7 /* Lin-Prefix.pch */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
		AA20D88117ECB467006B7CA2 /* AppKit-Private-Classes */ = {
			isa = PBXGroup;
			children = (
				AA20D88017ECB1AD006B7CA2 /* NSPopoverFrame.h */,
			);
			name = "AppKit-Private-Classes";
			sourceTree = "<group>";
		};
		AA2980B517EE2CF600CF46E3 /* Shared */ = {
			isa = PBXGroup;
			children = (
				AA2980B217EE2C5300CF46E3 /* LNUserDefaultsManager.h */,
				AA2980B317EE2C5300CF46E3 /* LNUserDefaultsManager.m */,
				F5859DBB18CABC2A009AF108 /* LNLocalizedStringCollectionOperation.h */,
				F5859DBC18CABC2A009AF108 /* LNLocalizedStringCollectionOperation.m */,
			);
			name = Shared;
			sourceTree = "<group>";
		};
		AA470D6617C3D380005CBB7F /* LinTests */ = {
			isa = PBXGroup;
			children = (
				AAB0CD3D17C478EF0085E913 /* Models */,
				AA470D7C17C3DE31005CBB7F /* LNDetectorTests.m */,
				AADEADB217C7B6D3001E0C65 /* LNLocalizationTests.m */,
				AAFE3C4017EED0950018E478 /* Resources */,
				AA470D6717C3D380005CBB7F /* Supporting Files */,
			);
			path = LinTests;
			sourceTree = "<group>";
		};
		AA470D6717C3D380005CBB7F /* Supporting Files */ = {
			isa = PBXGroup;
			children = (
				AA470D6817C3D380005CBB7F /* LinTests-Info.plist */,
				AA470D6917C3D380005CBB7F /* InfoPlist.strings */,
				AA470D6E17C3D380005CBB7F /* LinTests-Prefix.pch */,
			);
			name = "Supporting Files";
			sourceTree = "<group>";
		};
		AA470D7817C3DD42005CBB7F /* Models */ = {
			isa = PBXGroup;
			children = (
				AA470D5917C3CFEC005CBB7F /* LNDetector.h */,
				AA470D5A17C3CFEC005CBB7F /* LNDetector.m */,
				AA470D5C17C3D05D005CBB7F /* LNEntity.h */,
				AA470D5D17C3D05D005CBB7F /* LNEntity.m */,
				AAB0CD2F17C4382D0085E913 /* LNRegularExpressionPattern.h */,
				AAB0CD3017C4382D0085E913 /* LNRegularExpressionPattern.m */,
				AAB0CD3217C448200085E913 /* LNRegularExpressionPattern+type.h */,
				AAB0CD3317C448200085E913 /* LNRegularExpressionPattern+type.m */,
				AA7D4DAF17C74CFE0092DF8A /* LNLocalizationCollection.h */,
				AA7D4DB017C74CFE0092DF8A /* LNLocalizationCollection.m */,
				AA7D4DB217C74D0A0092DF8A /* LNLocalization.h */,
				AA7D4DB317C74D0A0092DF8A /* LNLocalization.m */,
			);
			name = Models;
			sourceTree = "<group>";
		};
		AA63898118C6019F0061C2C4 /* Images */ = {
			isa = PBXGroup;
			children = (
				AA63897118C6019A0061C2C4 /* icon_plus@2x.png */,
				AA63897518C6019A0061C2C4 /* icon_plus.png */,
				AA63897218C6019A0061C2C4 /* icon_minus.png */,
				AA63897318C6019A0061C2C4 /* icon_minus@2x.png */,
				AA63897618C6019A0061C2C4 /* icon_detach@2x.png */,
				AA63897818C6019A0061C2C4 /* icon_detach.png */,
				AA63897718C6019A0061C2C4 /* icon120@2x.png */,
				AA63897418C6019A0061C2C4 /* icon120.png */,
			);
			name = Images;
			sourceTree = "<group>";
		};
		AA93691817C4E4C700E94318 /* Xcode-Private-Classes */ = {
			isa = PBXGroup;
			children = (
				AA93691517C4E4C000E94318 /* IDEWorkspace.h */,
				AA11AC4017C66F0200889DFB /* DVTFilePath.h */,
				AA11AC4317C6746800889DFB /* IDEIndex.h */,
				AA11AC4617C6755400889DFB /* IDEIndexCollection.h */,
				AADEADBB17C872EB001E0C65 /* IDEEditorDocument.h */,
				AA7B0CAD17F4228E0004FE3B /* DVTDualProxyWindow.h */,
				AA7B0CB017F4229D0004FE3B /* IDEWorkspaceWindow.h */,
				AA7B0CB317F422BB0004FE3B /* DVTSourceTextView.h */,
			);
			name = "Xcode-Private-Classes";
			sourceTree = "<group>";
		};
		AAB0CD3D17C478EF0085E913 /* Models */ = {
			isa = PBXGroup;
			children = (
				AAB0CD3A17C477030085E913 /* LNDetectorTestSet.h */,
				AAB0CD3B17C477030085E913 /* LNDetectorTestSet.m */,
			);
			name = Models;
			sourceTree = "<group>";
		};
		AADDDA9517C49D4D00BBA67C /* Categories */ = {
			isa = PBXGroup;
			children = (
				AADEADBE17C87392001E0C65 /* MethodSwizzle.h */,
				AADEADBF17C87392001E0C65 /* MethodSwizzle.m */,
				AADDDA9217C49D4800BBA67C /* NSBundle+versions.h */,
				AADDDA9317C49D4800BBA67C /* NSBundle+versions.m */,
				AADEADB517C87298001E0C65 /* IDEIndex+Lin.h */,
				AADEADB617C87298001E0C65 /* IDEIndex+Lin.m */,
				AA20D87D17ECB12A006B7CA2 /* NSPopoverFrame+Lin.h */,
				AA20D87E17ECB12A006B7CA2 /* NSPopoverFrame+Lin.m */,
				AA8F8EEE17EDFC68004964FB /* NSTableView+editedColumnIdentifier.h */,
				AA8F8EEF17EDFC68004964FB /* NSTableView+editedColumnIdentifier.m */,
			);
			name = Categories;
			sourceTree = "<group>";
		};
		AADDDA9B17C4A0DA00BBA67C /* Resources */ = {
			isa = PBXGroup;
			children = (
				AA95FDEB17EB48A9007D33D4 /* LNPopoverContentView.xib */,
				AA02CE8A17EE08240041C2BD /* LNAlertAccessoryView.xib */,
				AA63898118C6019F0061C2C4 /* Images */,
			);
			name = Resources;
			sourceTree = "<group>";
		};
		AADDDA9C17C4A0E200BBA67C /* Controllers */ = {
			isa = PBXGroup;
			children = (
				AA95FDED17EB4E77007D33D4 /* LNPopoverWindowController.h */,
				AA95FDEE17EB4E77007D33D4 /* LNPopoverWindowController.m */,
			);
			name = Controllers;
			sourceTree = "<group>";
		};
		AADDDAA017C4A3BA00BBA67C /* Views */ = {
			isa = PBXGroup;
			children = (
				AAAC873917EDA9CF00BF251D /* LNPopoverWindow.h */,
				AAAC873A17EDA9CF00BF251D /* LNPopoverWindow.m */,
				AA36376417D9EF9E003C5E55 /* LNPopoverContentView.h */,
				AA36376517D9EF9E003C5E55 /* LNPopoverContentView.m */,
				AAF0D6A917ECB87100B4318B /* LNTableView.h */,
				AAF0D6AA17ECB87100B4318B /* LNTableView.m */,
				AAF0D6AF17ECC4AF00B4318B /* LNTableCornerView.h */,
				AAF0D6B017ECC4AF00B4318B /* LNTableCornerView.m */,
				AAF0D6AC17ECB89800B4318B /* LNTableHeaderCell.h */,
				AAF0D6AD17ECB89800B4318B /* LNTableHeaderCell.m */,
				AAF0D6B217ECD8EC00B4318B /* LNButtonCell.h */,
				AAF0D6B317ECD8EC00B4318B /* LNButtonCell.m */,
				AAAC873117ED9D4F00BF251D /* LNHorizontalLine.h */,
				AAAC873217ED9D4F00BF251D /* LNHorizontalLine.m */,
				AA02CE8C17EE083A0041C2BD /* LNAlertAccessoryView.h */,
				AA02CE8D17EE083A0041C2BD /* LNAlertAccessoryView.m */,
				AA6377CC18C5CCFC005EADC7 /* LNImageButtonCell.h */,
				AA6377CD18C5CCFC005EADC7 /* LNImageButtonCell.m */,
			);
			name = Views;
			sourceTree = "<group>";
		};
		AAFE3C4017EED0950018E478 /* Resources */ = {
			isa = PBXGroup;
			children = (
				AAFE3C3E17EECF4A0018E478 /* Localizable.strings */,
			);
			name = Resources;
			sourceTree = "<group>";
		};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
		AA1B7DA217C3C1EC00A3A6D7 /* Lin */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = AA1B7DB517C3C1EC00A3A6D7 /* Build configuration list for PBXNativeTarget "Lin" */;
			buildPhases = (
				AA1B7D9F17C3C1EC00A3A6D7 /* Sources */,
				AA1B7DA017C3C1EC00A3A6D7 /* Frameworks */,
				AA1B7DA117C3C1EC00A3A6D7 /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
			);
			name = Lin;
			productName = Lin;
			productReference = AA1B7DA317C3C1EC00A3A6D7 /* Lin.xcplugin */;
			productType = "com.apple.product-type.bundle";
		};
		AA470D6217C3D380005CBB7F /* LinTests */ = {
			isa = PBXNativeTarget;
			buildConfigurationList = AA470D7117C3D380005CBB7F /* Build configuration list for PBXNativeTarget "LinTests" */;
			buildPhases = (
				AA470D5F17C3D380005CBB7F /* Sources */,
				AA470D6017C3D380005CBB7F /* Frameworks */,
				AA470D6117C3D380005CBB7F /* Resources */,
			);
			buildRules = (
			);
			dependencies = (
				AA470D7017C3D380005CBB7F /* PBXTargetDependency */,
			);
			name = LinTests;
			productName = LinTests;
			productReference = AA470D6317C3D380005CBB7F /* LinTests.xctest */;
			productType = "com.apple.product-type.bundle.unit-test";
		};
/* End PBXNativeTarget section */

/* Begin PBXProject section */
		AA1B7D9B17C3C1EC00A3A6D7 /* Project object */ = {
			isa = PBXProject;
			attributes = {
				LastUpgradeCheck = 0610;
				ORGANIZATIONNAME = "Tanaka Katsuma";
				TargetAttributes = {
					AA470D6217C3D380005CBB7F = {
						TestTargetID = AA1B7DA217C3C1EC00A3A6D7;
					};
				};
			};
			buildConfigurationList = AA1B7D9E17C3C1EC00A3A6D7 /* Build configuration list for PBXProject "Lin" */;
			compatibilityVersion = "Xcode 3.2";
			developmentRegion = English;
			hasScannedForEncodings = 0;
			knownRegions = (
				en,
			);
			mainGroup = AA1B7D9A17C3C1EC00A3A6D7;
			productRefGroup = AA1B7DA417C3C1EC00A3A6D7 /* Products */;
			projectDirPath = "";
			projectRoot = "";
			targets = (
				AA1B7DA217C3C1EC00A3A6D7 /* Lin */,
				AA470D6217C3D380005CBB7F /* LinTests */,
			);
		};
/* End PBXProject section */

/* Begin PBXResourcesBuildPhase section */
		AA1B7DA117C3C1EC00A3A6D7 /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				AA63897B18C6019A0061C2C4 /* icon_minus@2x.png in Resources */,
				AA63897F18C6019A0061C2C4 /* icon120@2x.png in Resources */,
				AA63898018C6019A0061C2C4 /* icon_detach.png in Resources */,
				AA63897A18C6019A0061C2C4 /* icon_minus.png in Resources */,
				AA95FDEC17EB48A9007D33D4 /* LNPopoverContentView.xib in Resources */,
				AA63897C18C6019A0061C2C4 /* icon120.png in Resources */,
				AA63897D18C6019A0061C2C4 /* icon_plus.png in Resources */,
				AA63897E18C6019A0061C2C4 /* icon_detach@2x.png in Resources */,
				AA63897918C6019A0061C2C4 /* icon_plus@2x.png in Resources */,
				AA02CE8B17EE08240041C2BD /* LNAlertAccessoryView.xib in Resources */,
				AA1B7DB117C3C1EC00A3A6D7 /* InfoPlist.strings in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		AA470D6117C3D380005CBB7F /* Resources */ = {
			isa = PBXResourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				AA470D6B17C3D380005CBB7F /* InfoPlist.strings in Resources */,
				AAFE3C3F17EECF4A0018E478 /* Localizable.strings in Resources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXResourcesBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
		AA1B7D9F17C3C1EC00A3A6D7 /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				AA7D4DB117C74CFE0092DF8A /* LNLocalizationCollection.m in Sources */,
				AAF0D6B417ECD8EC00B4318B /* LNButtonCell.m in Sources */,
				AAF0D6B117ECC4AF00B4318B /* LNTableCornerView.m in Sources */,
				AAB0CD3417C448200085E913 /* LNRegularExpressionPattern+type.m in Sources */,
				AADDDA9417C49D4800BBA67C /* NSBundle+versions.m in Sources */,
				AAAC873B17EDA9CF00BF251D /* LNPopoverWindow.m in Sources */,
				AA8F8EF017EDFC68004964FB /* NSTableView+editedColumnIdentifier.m in Sources */,
				AA6377CE18C5CCFC005EADC7 /* LNImageButtonCell.m in Sources */,
				AA20D87F17ECB12A006B7CA2 /* NSPopoverFrame+Lin.m in Sources */,
				AA02CE8E17EE083A0041C2BD /* LNAlertAccessoryView.m in Sources */,
				AA36376617D9EF9E003C5E55 /* LNPopoverContentView.m in Sources */,
				AA470D5E17C3D05D005CBB7F /* LNEntity.m in Sources */,
				AA7D4DB417C74D0A0092DF8A /* LNLocalization.m in Sources */,
				AAB0CD3117C4382D0085E913 /* LNRegularExpressionPattern.m in Sources */,
				AA1B7DBA17C3C20F00A3A6D7 /* Lin.m in Sources */,
				AAF0D6AE17ECB89800B4318B /* LNTableHeaderCell.m in Sources */,
				AAAC873317ED9D4F00BF251D /* LNHorizontalLine.m in Sources */,
				AADEADB717C87298001E0C65 /* IDEIndex+Lin.m in Sources */,
				AAF0D6AB17ECB87100B4318B /* LNTableView.m in Sources */,
				AA2980B417EE2C5300CF46E3 /* LNUserDefaultsManager.m in Sources */,
				AA95FDEF17EB4E77007D33D4 /* LNPopoverWindowController.m in Sources */,
				AADEADC017C87392001E0C65 /* MethodSwizzle.m in Sources */,
				F5859DBD18CABC2A009AF108 /* LNLocalizedStringCollectionOperation.m in Sources */,
				AA470D5B17C3CFEC005CBB7F /* LNDetector.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
		AA470D5F17C3D380005CBB7F /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				AAFE3C4117EED36C0018E478 /* LNLocalizationCollection.m in Sources */,
				AADEADB417C7B838001E0C65 /* LNLocalization.m in Sources */,
				AAB0CD3C17C477030085E913 /* LNDetectorTestSet.m in Sources */,
				AAB0CD3717C46B070085E913 /* LNEntity.m in Sources */,
				AAB0CD3817C46B070085E913 /* LNRegularExpressionPattern.m in Sources */,
				AAB0CD3917C46B070085E913 /* LNRegularExpressionPattern+type.m in Sources */,
				AAB0CD3617C46A730085E913 /* LNDetector.m in Sources */,
				AA470D7D17C3DE31005CBB7F /* LNDetectorTests.m in Sources */,
				AADEADB317C7B6D3001E0C65 /* LNLocalizationTests.m in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
		AA470D7017C3D380005CBB7F /* PBXTargetDependency */ = {
			isa = PBXTargetDependency;
			target = AA1B7DA217C3C1EC00A3A6D7 /* Lin */;
			targetProxy = AA470D6F17C3D380005CBB7F /* PBXContainerItemProxy */;
		};
/* End PBXTargetDependency section */

/* Begin PBXVariantGroup section */
		AA1B7DAF17C3C1EC00A3A6D7 /* InfoPlist.strings */ = {
			isa = PBXVariantGroup;
			children = (
				AA1B7DB017C3C1EC00A3A6D7 /* en */,
			);
			name = InfoPlist.strings;
			sourceTree = "<group>";
		};
		AA470D6917C3D380005CBB7F /* InfoPlist.strings */ = {
			isa = PBXVariantGroup;
			children = (
				AA470D6A17C3D380005CBB7F /* en */,
			);
			name = InfoPlist.strings;
			sourceTree = "<group>";
		};
/* End PBXVariantGroup section */

/* Begin XCBuildConfiguration section */
		AA1B7DB317C3C1EC00A3A6D7 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COPY_PHASE_STRIP = NO;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_DYNAMIC_NO_PIC = NO;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_OPTIMIZATION_LEVEL = 0;
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				MACOSX_DEPLOYMENT_TARGET = 10.7;
				ONLY_ACTIVE_ARCH = YES;
				SDKROOT = macosx;
			};
			name = Debug;
		};
		AA1B7DB417C3C1EC00A3A6D7 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				ALWAYS_SEARCH_USER_PATHS = NO;
				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
				CLANG_CXX_LIBRARY = "libc++";
				CLANG_ENABLE_MODULES = YES;
				CLANG_ENABLE_OBJC_ARC = YES;
				CLANG_WARN_BOOL_CONVERSION = YES;
				CLANG_WARN_CONSTANT_CONVERSION = YES;
				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
				CLANG_WARN_EMPTY_BODY = YES;
				CLANG_WARN_ENUM_CONVERSION = YES;
				CLANG_WARN_INT_CONVERSION = YES;
				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
				COPY_PHASE_STRIP = YES;
				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
				ENABLE_NS_ASSERTIONS = NO;
				GCC_C_LANGUAGE_STANDARD = gnu99;
				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
				GCC_WARN_UNDECLARED_SELECTOR = YES;
				GCC_WARN_UNINITIALIZED_AUTOS = YES;
				GCC_WARN_UNUSED_FUNCTION = YES;
				GCC_WARN_UNUSED_VARIABLE = YES;
				MACOSX_DEPLOYMENT_TARGET = 10.7;
				SDKROOT = macosx;
			};
			name = Release;
		};
		AA1B7DB617C3C1EC00A3A6D7 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				COMBINE_HIDPI_IMAGES = YES;
				DEPLOYMENT_LOCATION = YES;
				DSTROOT = "$(HOME)";
				FRAMEWORK_SEARCH_PATHS = (
					"$(inherited)",
					"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/SharedFrameworks",
					"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Frameworks",
				);
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = "Lin/Lin-Prefix.pch";
				INFOPLIST_FILE = "Lin/Lin-Info.plist";
				INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins";
				PRODUCT_NAME = "$(TARGET_NAME)";
				WRAPPER_EXTENSION = xcplugin;
			};
			name = Debug;
		};
		AA1B7DB717C3C1EC00A3A6D7 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				COMBINE_HIDPI_IMAGES = YES;
				DEPLOYMENT_LOCATION = YES;
				DSTROOT = "$(HOME)";
				FRAMEWORK_SEARCH_PATHS = (
					"$(inherited)",
					"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/SharedFrameworks",
					"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Frameworks",
				);
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = "Lin/Lin-Prefix.pch";
				INFOPLIST_FILE = "Lin/Lin-Info.plist";
				INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins";
				PRODUCT_NAME = "$(TARGET_NAME)";
				WRAPPER_EXTENSION = xcplugin;
			};
			name = Release;
		};
		AA470D7217C3D380005CBB7F /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				COMBINE_HIDPI_IMAGES = YES;
				FRAMEWORK_SEARCH_PATHS = (
					"$(DEVELOPER_FRAMEWORKS_DIR)",
					"$(inherited)",
				);
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = "LinTests/LinTests-Prefix.pch";
				GCC_PREPROCESSOR_DEFINITIONS = (
					"DEBUG=1",
					"$(inherited)",
				);
				INFOPLIST_FILE = "LinTests/LinTests-Info.plist";
				PRODUCT_NAME = "$(TARGET_NAME)";
				WRAPPER_EXTENSION = xctest;
			};
			name = Debug;
		};
		AA470D7317C3D380005CBB7F /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				COMBINE_HIDPI_IMAGES = YES;
				FRAMEWORK_SEARCH_PATHS = (
					"$(DEVELOPER_FRAMEWORKS_DIR)",
					"$(inherited)",
				);
				GCC_PRECOMPILE_PREFIX_HEADER = YES;
				GCC_PREFIX_HEADER = "LinTests/LinTests-Prefix.pch";
				INFOPLIST_FILE = "LinTests/LinTests-Info.plist";
				PRODUCT_NAME = "$(TARGET_NAME)";
				WRAPPER_EXTENSION = xctest;
			};
			name = Release;
		};
/* End XCBuildConfiguration section */

/* Begin XCConfigurationList section */
		AA1B7D9E17C3C1EC00A3A6D7 /* Build configuration list for PBXProject "Lin" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				AA1B7DB317C3C1EC00A3A6D7 /* Debug */,
				AA1B7DB417C3C1EC00A3A6D7 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		AA1B7DB517C3C1EC00A3A6D7 /* Build configuration list for PBXNativeTarget "Lin" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				AA1B7DB617C3C1EC00A3A6D7 /* Debug */,
				AA1B7DB717C3C1EC00A3A6D7 /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
		AA470D7117C3D380005CBB7F /* Build configuration list for PBXNativeTarget "LinTests" */ = {
			isa = XCConfigurationList;
			buildConfigurations = (
				AA470D7217C3D380005CBB7F /* Debug */,
				AA470D7317C3D380005CBB7F /* Release */,
			);
			defaultConfigurationIsVisible = 0;
			defaultConfigurationName = Release;
		};
/* End XCConfigurationList section */
	};
	rootObject = AA1B7D9B17C3C1EC00A3A6D7 /* Project object */;
}


================================================
FILE: Lin.xcodeproj/xcshareddata/xcschemes/Lin.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "0610"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "AA1B7DA217C3C1EC00A3A6D7"
               BuildableName = "Lin.xcplugin"
               BlueprintName = "Lin"
               ReferencedContainer = "container:Lin.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES"
      buildConfiguration = "Debug">
      <Testables>
         <TestableReference
            skipped = "NO">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "AA470D6217C3D380005CBB7F"
               BuildableName = "LinTests.xctest"
               BlueprintName = "LinTests"
               ReferencedContainer = "container:Lin.xcodeproj">
            </BuildableReference>
         </TestableReference>
      </Testables>
   </TestAction>
   <LaunchAction
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      buildConfiguration = "Debug"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      allowLocationSimulation = "YES">
      <PathRunnable
         FilePath = "/Applications/Xcode.app">
      </PathRunnable>
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "AA1B7DA217C3C1EC00A3A6D7"
            BuildableName = "Lin.xcplugin"
            BlueprintName = "Lin"
            ReferencedContainer = "container:Lin.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <AdditionalOptions>
         <AdditionalOption
            key = "NSZombieEnabled"
            value = "YES"
            isEnabled = "YES">
         </AdditionalOption>
      </AdditionalOptions>
   </LaunchAction>
   <ProfileAction
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      buildConfiguration = "Release"
      debugDocumentVersioning = "YES">
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: Lin.xcodeproj/xcshareddata/xcschemes/LinTests.xcscheme
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "0610"
   version = "1.3">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "NO"
            buildForArchiving = "NO"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "AA470D6217C3D380005CBB7F"
               BuildableName = "LinTests.xctest"
               BlueprintName = "LinTests"
               ReferencedContainer = "container:Lin.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES"
      buildConfiguration = "Debug">
      <Testables>
         <TestableReference
            skipped = "NO">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "AA470D6217C3D380005CBB7F"
               BuildableName = "LinTests.xctest"
               BlueprintName = "LinTests"
               ReferencedContainer = "container:Lin.xcodeproj">
            </BuildableReference>
         </TestableReference>
      </Testables>
   </TestAction>
   <LaunchAction
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      buildConfiguration = "Debug"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      allowLocationSimulation = "YES">
      <MacroExpansion>
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "AA470D6217C3D380005CBB7F"
            BuildableName = "LinTests.xctest"
            BlueprintName = "LinTests"
            ReferencedContainer = "container:Lin.xcodeproj">
         </BuildableReference>
      </MacroExpansion>
      <AdditionalOptions>
      </AdditionalOptions>
   </LaunchAction>
   <ProfileAction
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      buildConfiguration = "Release"
      debugDocumentVersioning = "YES">
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>


================================================
FILE: LinTests/LNDetectorTestSet.h
================================================
//
//  LNDetectorTestSet.h
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface LNDetectorTestSet : NSObject

@property (nonatomic, copy, readonly) NSString *string;
@property (nonatomic, copy, readonly) NSArray *keys;

- (instancetype)initWithString:(NSString *)string keys:(NSString *)keyValue, ... NS_REQUIRES_NIL_TERMINATION;

@end


================================================
FILE: LinTests/LNDetectorTestSet.m
================================================
//
//  LNDetectorTestSet.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import "LNDetectorTestSet.h"

@interface LNDetectorTestSet ()

@property (nonatomic, copy, readwrite) NSString *string;
@property (nonatomic, copy, readwrite) NSArray *keys;

@end

@implementation LNDetectorTestSet

- (instancetype)initWithString:(NSString *)string keys:(NSString *)keyValue, ...
{
    self = [super init];
    
    if (self) {
        self.string = string;
        
        va_list arguments;
        va_start(arguments, keyValue);
        
        NSString *key = keyValue;
        NSMutableArray *keys = [NSMutableArray array];
        
        while (key) {
            [keys addObject:key];
            
            key = va_arg(arguments, typeof(NSString *));
        }
        
        self.keys = [keys copy];
        
        va_end(arguments);
    }
    
    return self;
}

@end


================================================
FILE: LinTests/LNDetectorTests.m
================================================
//
//  LNDetectorTests.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/21.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <XCTest/XCTest.h>

// Models
#import "LNDetector.h"
#import "LNEntity.h"
#import "LNDetectorTestSet.h"

@interface LNDetectorTests : XCTestCase

@property (nonatomic, strong) LNDetector *detector;

- (void)performTests:(LNDetectorTestSet *)testSetValue, ... NS_REQUIRES_NIL_TERMINATION;

@end

@implementation LNDetectorTests

- (void)setUp
{
    [super setUp];
    
    LNDetector *detector = [LNDetector detector];
    self.detector = detector;
}

- (void)tearDown
{
    [super tearDown];
}

- (void)testLocalizedString
{
    [self performTests:
     [[LNDetectorTestSet alloc] initWithString:@"NSLocalizedString(@\"key\", nil);"
                                          keys:@"key", nil],
     
     [[LNDetectorTestSet alloc] initWithString:@"NSLocalizedString ( @\"key\" , nil );"
                                          keys:@"key", nil],
     [[LNDetectorTestSet alloc] initWithString:@"NSString *value = NSLocalizedString(@\"key\", nil);"
                                          keys:@"key", nil],
     [[LNDetectorTestSet alloc] initWithString:@"NSLog(@\"value1 = %@, value2 = %@\", NSLocalizedString(@\"key1\", nil), NSLocalizedString(@\"key2\", nil));"
                                          keys:@"key1", @"key2", nil],
     nil];
}

- (void)testLocalizedStringForKey
{
    [self performTests:
     [[LNDetectorTestSet alloc] initWithString:@"[[NSBundle mainBundle] localizedStringForKey:@\"key\" value:@\"default_value\" table:@\"table_name\"];"
                                          keys:@"key", nil],
     nil];
}

- (void)testLocalizedStringFromTable
{
    [self performTests:
     [[LNDetectorTestSet alloc] initWithString:@"NSLocalizedStringFromTable(@\"key\", @\"table_name\", @\"comment\");"
                                          keys:@"key", nil],
     nil];
}

- (void)testLocalizedStringFromTableInBundle
{
    [self performTests:
     [[LNDetectorTestSet alloc] initWithString:@"NSLocalizedStringFromTableInBundle(@\"key\", @\"table_name\", [NSBundle mainBundle], @\"comment\");"
                                          keys:@"key", nil],
     nil];
}

- (void)testLocalizedStringWithDefaultValue
{
    [self performTests:
     [[LNDetectorTestSet alloc] initWithString:@"NSLocalizedStringWithDefaultValue(@\"key\", @\"table_name\", [NSBundle mainBundle], @\"default_value\", @\"comment\");"
                                          keys:@"key", nil],
     nil];
}

- (void)performTests:(LNDetectorTestSet *)testSetValue, ...
{
    // Parse arguments
    va_list arguments;
    va_start(arguments, testSetValue);
    
    LNDetectorTestSet *testSet = testSetValue;
    NSMutableArray *testSets = [NSMutableArray array];
    
    while (testSet) {
        [testSets addObject:testSet];
        
        testSet = va_arg(arguments, typeof(LNDetectorTestSet *));
    }
    
    va_end(arguments);
    
    // Do tests
    for (LNDetectorTestSet *testSet in testSets) {
        NSArray *entities = [self.detector entitiesInString:testSet.string];
        XCTAssertTrue(entities.count == testSet.keys.count); // Number of detected entities and expected keys are equal.
        
        for (LNEntity *entity in entities) {
            NSUInteger indexOfEntity = [entities indexOfObject:entity];
            NSString *keyString = [testSet.string substringWithRange:entity.keyRange];
            XCTAssertEqualObjects(keyString, testSet.keys[indexOfEntity]); // Extracted key is equal to expected key.
        }
    }
}

@end


================================================
FILE: LinTests/LNLocalizationTests.m
================================================
//
//  LNLocalizationTests.m
//  Lin
//
//  Created by Tanaka Katsuma on 2013/08/24.
//  Copyright (c) 2013年 Tanaka Katsuma. All rights reserved.
//

#import <XCTest/XCTest.h>

// Models
#import "LNLocalizationCollection.h"
#import "LNLocalization.h"

@interface LNLocalizationTests : XCTestCase

@end

@implementation LNLocalizationTests

- (NSBundle *)testBundle
{
    for (NSBundle *bundle in [NSBundle allBundles]) {
        if ([[bundle bundleIdentifier] isEqualToString:@"jp.questbeat.LinTests"]) {
            return bundle;
        }
    }
    
    return nil;
}

- (void)testParsingPatterns
{
    NSString *filePath = [[self testBundle] pathForResource:@"Localizable" ofType:@"strings"];
    LNLocalizationCollection *collection = [LNLocalizationCollection localizationCollectionWithContentsOfFile:filePath];
    
    struct LNLocalizationTestSet {
        __unsafe_unretained NSString *key;
        __unsafe_unretained NSString *value;
    } testSets[] = {
        {@"key0",   @"value0"},
        {@"key1",   @"value1"},
        {@"key2",   @"value2"},
        {@"key3",   @"value3"},
        {@"key4",   @"value4"},
        {@"key5",   @"value5"},
        {@"key6",   @"value6"},
        {@"key7",   @"value7"},
        {@"key8",   @"value8"},
        {@"key 9",  @"value9"},
        {@"key 10", @"value10"},
        {@"key 11", @"value11"},
        {@"key 12", @"value12"},
        {@"key 13", @"value13"},
        {@"key 14", @"value14"},
        {@"key 15", @"value15"},
        {@"key 16", @"value16"},
        {@"key.17", @"value17"},
        {@"key.18", @"value18"},
        {@"key.19", @"value19"},
        {@"key.20", @"value20"},
        {@"key.21", @"value21"}
    };
    
    NSInteger numberOfTestSets = sizeof(testSets) / sizeof(struct LNLocalizationTestSet);
    
    for (NSInteger i = 0; i < numberOfTestSets; i++) {
        LNLocalization *localization = [LNLocalization localizationWithKey:testSets[i].key
                                                                     value:testSets[i].value
                                                               entityRange:NSMakeRange(0, 0)
                                                                  keyRange:NSMakeRange(0, 0)
                                                                valueRange:NSMakeRange(0, 0)
                                                                collection:nil];
        
        XCTAssertTrue([collection.localizations containsObject:localization]);
    }
}

@end


================================================
FILE: LinTests/LinTests-Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>${EXECUTABLE_NAME}</string>
	<key>CFBundleIdentifier</key>
	<string>jp.questbeat.${PRODUCT_NAME:rfc1034identifier}</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundlePackageType</key>
	<string>BNDL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
</dict>
</plist>


================================================
FILE: LinTests/LinTests-Prefix.pch
================================================
//
//  Prefix header
//
//  The contents of this file are implicitly included at the beginning of every source file.
//

#ifdef __OBJC__
    #import <Cocoa/Cocoa.h>
#endif

// Fix Xcode 5 confusion about #defines
#undef NULL
#define NULL ((void*)0)


================================================
FILE: LinTests/Localizable.strings
================================================
/* 
  Localizable.strings
Download .txt
gitextract_srotazw1/

├── .gitignore
├── .travis.yml
├── LICENSE.txt
├── Lin/
│   ├── DVTDualProxyWindow.h
│   ├── DVTFilePath.h
│   ├── DVTSourceTextView.h
│   ├── IDEEditorDocument.h
│   ├── IDEIndex+Lin.h
│   ├── IDEIndex+Lin.m
│   ├── IDEIndex.h
│   ├── IDEIndexCollection.h
│   ├── IDEWorkspace.h
│   ├── IDEWorkspaceWindow.h
│   ├── LNAlertAccessoryView.h
│   ├── LNAlertAccessoryView.m
│   ├── LNAlertAccessoryView.xib
│   ├── LNButtonCell.h
│   ├── LNButtonCell.m
│   ├── LNDetector.h
│   ├── LNDetector.m
│   ├── LNEntity.h
│   ├── LNEntity.m
│   ├── LNHorizontalLine.h
│   ├── LNHorizontalLine.m
│   ├── LNImageButtonCell.h
│   ├── LNImageButtonCell.m
│   ├── LNLocalization.h
│   ├── LNLocalization.m
│   ├── LNLocalizationCollection.h
│   ├── LNLocalizationCollection.m
│   ├── LNLocalizedStringCollectionOperation.h
│   ├── LNLocalizedStringCollectionOperation.m
│   ├── LNPopoverContentView.h
│   ├── LNPopoverContentView.m
│   ├── LNPopoverContentView.xib
│   ├── LNPopoverWindow.h
│   ├── LNPopoverWindow.m
│   ├── LNPopoverWindowController.h
│   ├── LNPopoverWindowController.m
│   ├── LNRegularExpressionPattern+type.h
│   ├── LNRegularExpressionPattern+type.m
│   ├── LNRegularExpressionPattern.h
│   ├── LNRegularExpressionPattern.m
│   ├── LNTableCornerView.h
│   ├── LNTableCornerView.m
│   ├── LNTableHeaderCell.h
│   ├── LNTableHeaderCell.m
│   ├── LNTableView.h
│   ├── LNTableView.m
│   ├── LNUserDefaultsManager.h
│   ├── LNUserDefaultsManager.m
│   ├── Lin-Info.plist
│   ├── Lin-Prefix.pch
│   ├── Lin.h
│   ├── Lin.m
│   ├── MethodSwizzle.h
│   ├── MethodSwizzle.m
│   ├── NSBundle+versions.h
│   ├── NSBundle+versions.m
│   ├── NSPopoverFrame+Lin.h
│   ├── NSPopoverFrame+Lin.m
│   ├── NSPopoverFrame.h
│   ├── NSTableView+editedColumnIdentifier.h
│   ├── NSTableView+editedColumnIdentifier.m
│   └── en.lproj/
│       └── InfoPlist.strings
├── Lin.xcodeproj/
│   ├── project.pbxproj
│   └── xcshareddata/
│       └── xcschemes/
│           ├── Lin.xcscheme
│           └── LinTests.xcscheme
├── LinTests/
│   ├── LNDetectorTestSet.h
│   ├── LNDetectorTestSet.m
│   ├── LNDetectorTests.m
│   ├── LNLocalizationTests.m
│   ├── LinTests-Info.plist
│   ├── LinTests-Prefix.pch
│   ├── Localizable.strings
│   └── en.lproj/
│       └── InfoPlist.strings
├── Makefile
└── README.md
Download .txt
SYMBOL INDEX (11 symbols across 2 files)

FILE: Lin/LNEntity.h
  function NS_INLINE (line 19) | NS_INLINE NSString * NSStringFromEntityType(LNEntityType type) {

FILE: Lin/NSPopoverFrame.h
  type CGRect (line 13) | struct CGRect
  type CGPoint (line 13) | struct CGPoint
  type CGImage (line 15) | struct CGImage
  type CGPath (line 15) | struct CGPath
  type CGPoint (line 15) | struct CGPoint
  type CGPath (line 16) | struct CGPath
  type CGRect (line 16) | struct CGRect
  type CGPoint (line 16) | struct CGPoint
  type CGPath (line 17) | struct CGPath
  type CGRect (line 17) | struct CGRect
Condensed preview — 78 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (208K chars).
[
  {
    "path": ".gitignore",
    "chars": 299,
    "preview": "# Generated by http://gitignore.io\n\n### Objective-C ###\n# Xcode\n.DS_Store\n*/build/*\n*.pbxuser\n!default.pbxuser\n*.mode1v3"
  },
  {
    "path": ".travis.yml",
    "chars": 47,
    "preview": "language: objective-c\nscript: make clean test\n\n"
  },
  {
    "path": "LICENSE.txt",
    "chars": 1060,
    "preview": "Copyright (c) 2013 Katsuma Tanaka\n \nPermission is hereby granted, free of charge, to any person obtaining a copy of this"
  },
  {
    "path": "Lin/DVTDualProxyWindow.h",
    "chars": 231,
    "preview": "//\n//  DVTDualProxyWindow.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/26.\n//  Copyright (c) 2013年 Tanaka Katsu"
  },
  {
    "path": "Lin/DVTFilePath.h",
    "chars": 385,
    "preview": "//\n//  DVTFilePath.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/23.\n//  Copyright (c) 2013年 Tanaka Katsuma. All"
  },
  {
    "path": "Lin/DVTSourceTextView.h",
    "chars": 231,
    "preview": "//\n//  DVTSourceTextView.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/26.\n//  Copyright (c) 2013年 Tanaka Katsum"
  },
  {
    "path": "Lin/IDEEditorDocument.h",
    "chars": 295,
    "preview": "//\n//  IDEEditorDocument.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/24.\n//  Copyright (c) 2013年 Tanaka Katsum"
  },
  {
    "path": "Lin/IDEIndex+Lin.h",
    "chars": 197,
    "preview": "//\n//  IDEIndex+Lin.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/24.\n//  Copyright (c) 2013年 Tanaka Katsuma. Al"
  },
  {
    "path": "Lin/IDEIndex+Lin.m",
    "chars": 480,
    "preview": "//\n//  IDEIndex+Lin.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/24.\n//  Copyright (c) 2013年 Tanaka Katsuma. Al"
  },
  {
    "path": "Lin/IDEIndex.h",
    "chars": 507,
    "preview": "//\n//  IDEIndex.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/23.\n//  Copyright (c) 2013年 Tanaka Katsuma. All ri"
  },
  {
    "path": "Lin/IDEIndexCollection.h",
    "chars": 251,
    "preview": "//\n//  IDEIndexCollection.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/23.\n//  Copyright (c) 2013年 Tanaka Katsu"
  },
  {
    "path": "Lin/IDEWorkspace.h",
    "chars": 391,
    "preview": "//\n//  IDEWorkspace.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsuma. Al"
  },
  {
    "path": "Lin/IDEWorkspaceWindow.h",
    "chars": 238,
    "preview": "//\n//  IDEWorkspaceWindow.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/26.\n//  Copyright (c) 2013年 Tanaka Katsu"
  },
  {
    "path": "Lin/LNAlertAccessoryView.h",
    "chars": 585,
    "preview": "//\n//  LNAlertAccessoryView.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/22.\n//  Copyright (c) 2013年 Tanaka Kat"
  },
  {
    "path": "Lin/LNAlertAccessoryView.m",
    "chars": 3013,
    "preview": "//\n//  LNAlertAccessoryView.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/22.\n//  Copyright (c) 2013年 Tanaka Kat"
  },
  {
    "path": "Lin/LNAlertAccessoryView.xib",
    "chars": 9796,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3"
  },
  {
    "path": "Lin/LNButtonCell.h",
    "chars": 213,
    "preview": "//\n//  LNButtonCell.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsuma. Al"
  },
  {
    "path": "Lin/LNButtonCell.m",
    "chars": 409,
    "preview": "//\n//  LNButtonCell.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsuma. Al"
  },
  {
    "path": "Lin/LNDetector.h",
    "chars": 368,
    "preview": "//\n//  LNDetector.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsuma. All "
  },
  {
    "path": "Lin/LNDetector.m",
    "chars": 3120,
    "preview": "//\n//  LNDetector.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsuma. All "
  },
  {
    "path": "Lin/LNEntity.h",
    "chars": 1693,
    "preview": "//\n//  LNEntity.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsuma. All ri"
  },
  {
    "path": "Lin/LNEntity.m",
    "chars": 1500,
    "preview": "//\n//  LNEntity.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsuma. All ri"
  },
  {
    "path": "Lin/LNHorizontalLine.h",
    "chars": 214,
    "preview": "//\n//  LNHorizontalLine.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsuma"
  },
  {
    "path": "Lin/LNHorizontalLine.m",
    "chars": 495,
    "preview": "//\n//  LNHorizontalLine.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsuma"
  },
  {
    "path": "Lin/LNImageButtonCell.h",
    "chars": 223,
    "preview": "//\n//  LNImageButtonCell.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2014/03/04.\n//  Copyright (c) 2014年 Tanaka Katsum"
  },
  {
    "path": "Lin/LNImageButtonCell.m",
    "chars": 424,
    "preview": "//\n//  LNImageButtonCell.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2014/03/04.\n//  Copyright (c) 2014年 Tanaka Katsum"
  },
  {
    "path": "Lin/LNLocalization.h",
    "chars": 1053,
    "preview": "//\n//  LNLocalization.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/23.\n//  Copyright (c) 2013年 Tanaka Katsuma. "
  },
  {
    "path": "Lin/LNLocalization.m",
    "chars": 2275,
    "preview": "//\n//  LNLocalization.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/23.\n//  Copyright (c) 2013年 Tanaka Katsuma. "
  },
  {
    "path": "Lin/LNLocalizationCollection.h",
    "chars": 888,
    "preview": "//\n//  LNLocalizationCollection.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/23.\n//  Copyright (c) 2013年 Tanaka"
  },
  {
    "path": "Lin/LNLocalizationCollection.m",
    "chars": 7207,
    "preview": "//\n//  LNLocalizationCollection.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/23.\n//  Copyright (c) 2013年 Tanaka"
  },
  {
    "path": "Lin/LNLocalizedStringCollectionOperation.h",
    "chars": 582,
    "preview": "//\n//  LNLocalizedStringCollectionOperation.h\n//  Lin\n//\n//  Created by Wenbin Zhang on 3/7/14.\n//  Copyright (c) 2014 T"
  },
  {
    "path": "Lin/LNLocalizedStringCollectionOperation.m",
    "chars": 2786,
    "preview": "//\n//  LNLocalizedStringCollectionOperation.m\n//  Lin\n//\n//  Created by Wenbin Zhang on 3/7/14.\n//  Copyright (c) 2014 T"
  },
  {
    "path": "Lin/LNPopoverContentView.h",
    "chars": 788,
    "preview": "//\n//  LNPopoverContentView.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/06.\n//  Copyright (c) 2013年 Tanaka Kat"
  },
  {
    "path": "Lin/LNPopoverContentView.m",
    "chars": 11829,
    "preview": "//\n//  LNPopoverContentView.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/06.\n//  Copyright (c) 2013年 Tanaka Kat"
  },
  {
    "path": "Lin/LNPopoverContentView.xib",
    "chars": 19490,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3"
  },
  {
    "path": "Lin/LNPopoverWindow.h",
    "chars": 288,
    "preview": "//\n//  LNPopoverWindow.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsuma."
  },
  {
    "path": "Lin/LNPopoverWindow.m",
    "chars": 3300,
    "preview": "//\n//  LNPopoverWindow.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsuma."
  },
  {
    "path": "Lin/LNPopoverWindowController.h",
    "chars": 606,
    "preview": "//\n//  LNPopoverWindowController.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/20.\n//  Copyright (c) 2013年 Tanak"
  },
  {
    "path": "Lin/LNPopoverWindowController.m",
    "chars": 1835,
    "preview": "//\n//  LNPopoverWindowController.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/20.\n//  Copyright (c) 2013年 Tanak"
  },
  {
    "path": "Lin/LNRegularExpressionPattern+type.h",
    "chars": 398,
    "preview": "//\n//  LNRegularExpressionPattern+type.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年"
  },
  {
    "path": "Lin/LNRegularExpressionPattern+type.m",
    "chars": 2628,
    "preview": "//\n//  LNRegularExpressionPattern+type.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年"
  },
  {
    "path": "Lin/LNRegularExpressionPattern.h",
    "chars": 870,
    "preview": "//\n//  LNRegularExpressionPattern.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tana"
  },
  {
    "path": "Lin/LNRegularExpressionPattern.m",
    "chars": 1387,
    "preview": "//\n//  LNRegularExpressionPattern.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tana"
  },
  {
    "path": "Lin/LNTableCornerView.h",
    "chars": 217,
    "preview": "//\n//  LNTableCornerView.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsum"
  },
  {
    "path": "Lin/LNTableCornerView.m",
    "chars": 643,
    "preview": "//\n//  LNTableCornerView.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsum"
  },
  {
    "path": "Lin/LNTableHeaderCell.h",
    "chars": 353,
    "preview": "//\n//  LNTableHeaderCell.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsum"
  },
  {
    "path": "Lin/LNTableHeaderCell.m",
    "chars": 4791,
    "preview": "//\n//  LNTableHeaderCell.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsum"
  },
  {
    "path": "Lin/LNTableView.h",
    "chars": 210,
    "preview": "//\n//  LNTableView.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsuma. All"
  },
  {
    "path": "Lin/LNTableView.m",
    "chars": 970,
    "preview": "//\n//  LNTableView.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsuma. All"
  },
  {
    "path": "Lin/LNUserDefaultsManager.h",
    "chars": 334,
    "preview": "//\n//  LNUserDefaultsManager.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/22.\n//  Copyright (c) 2013年 Tanaka Ka"
  },
  {
    "path": "Lin/LNUserDefaultsManager.m",
    "chars": 1269,
    "preview": "//\n//  LNUserDefaultsManager.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/22.\n//  Copyright (c) 2013年 Tanaka Ka"
  },
  {
    "path": "Lin/Lin-Info.plist",
    "chars": 1386,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Lin/Lin-Prefix.pch",
    "chars": 172,
    "preview": "//\n//  Prefix header\n//\n//  The contents of this file are implicitly included at the beginning of every source file.\n//\n"
  },
  {
    "path": "Lin/Lin.h",
    "chars": 412,
    "preview": "//\n//  Lin.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsuma. All rights "
  },
  {
    "path": "Lin/Lin.m",
    "chars": 25171,
    "preview": "//\n//  Lin.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsuma. All rights "
  },
  {
    "path": "Lin/MethodSwizzle.h",
    "chars": 236,
    "preview": "//\n//  MethodSwizzle.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/24.\n//  Copyright (c) 2013年 Tanaka Katsuma. A"
  },
  {
    "path": "Lin/MethodSwizzle.m",
    "chars": 540,
    "preview": "//\n//  MethodSwizzle.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/24.\n//  Copyright (c) 2013年 Tanaka Katsuma. A"
  },
  {
    "path": "Lin/NSBundle+versions.h",
    "chars": 282,
    "preview": "//\n//  NSBundle+versions.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsum"
  },
  {
    "path": "Lin/NSBundle+versions.m",
    "chars": 431,
    "preview": "//\n//  NSBundle+versions.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsum"
  },
  {
    "path": "Lin/NSPopoverFrame+Lin.h",
    "chars": 215,
    "preview": "//\n//  NSPopoverFrame+Lin.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsu"
  },
  {
    "path": "Lin/NSPopoverFrame+Lin.m",
    "chars": 3639,
    "preview": "//\n//  NSPopoverFrame+Lin.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/21.\n//  Copyright (c) 2013年 Tanaka Katsu"
  },
  {
    "path": "Lin/NSPopoverFrame.h",
    "chars": 866,
    "preview": "/*\n *     Generated by class-dump 3.4 (64 bit).\n *\n *     class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2012 by"
  },
  {
    "path": "Lin/NSTableView+editedColumnIdentifier.h",
    "chars": 283,
    "preview": "//\n//  NSTableView+editedColumnIdentifier.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/22.\n//  Copyright (c) 20"
  },
  {
    "path": "Lin/NSTableView+editedColumnIdentifier.m",
    "chars": 666,
    "preview": "//\n//  NSTableView+editedColumnIdentifier.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/09/22.\n//  Copyright (c) 20"
  },
  {
    "path": "Lin/en.lproj/InfoPlist.strings",
    "chars": 45,
    "preview": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "Lin.xcodeproj/project.pbxproj",
    "chars": 47839,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "Lin.xcodeproj/xcshareddata/xcschemes/Lin.xcscheme",
    "chars": 3023,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0610\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "Lin.xcodeproj/xcshareddata/xcschemes/LinTests.xcscheme",
    "chars": 2799,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0610\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "LinTests/LNDetectorTestSet.h",
    "chars": 450,
    "preview": "//\n//  LNDetectorTestSet.h\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsum"
  },
  {
    "path": "LinTests/LNDetectorTestSet.m",
    "chars": 956,
    "preview": "//\n//  LNDetectorTestSet.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsum"
  },
  {
    "path": "LinTests/LNDetectorTests.m",
    "chars": 3616,
    "preview": "//\n//  LNDetectorTests.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/21.\n//  Copyright (c) 2013年 Tanaka Katsuma."
  },
  {
    "path": "LinTests/LNLocalizationTests.m",
    "chars": 2490,
    "preview": "//\n//  LNLocalizationTests.m\n//  Lin\n//\n//  Created by Tanaka Katsuma on 2013/08/24.\n//  Copyright (c) 2013年 Tanaka Kats"
  },
  {
    "path": "LinTests/LinTests-Info.plist",
    "chars": 692,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "LinTests/LinTests-Prefix.pch",
    "chars": 249,
    "preview": "//\n//  Prefix header\n//\n//  The contents of this file are implicitly included at the beginning of every source file.\n//\n"
  },
  {
    "path": "LinTests/Localizable.strings",
    "chars": 566,
    "preview": "/* \n  Localizable.strings\n  Lin\n\n  Created by Tanaka Katsuma on 2013/09/22.\n  Copyright (c) 2013年 Tanaka Katsuma. All ri"
  },
  {
    "path": "LinTests/en.lproj/InfoPlist.strings",
    "chars": 45,
    "preview": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "Makefile",
    "chars": 158,
    "preview": "clean:\n\txcodebuild \\\n\t\t-project Lin.xcodeproj \\\n\t\tclean\n\ntest:\n\txcodebuild \\\n\t\t-project Lin.xcodeproj \\\n\t\t-scheme LinTes"
  },
  {
    "path": "README.md",
    "chars": 2322,
    "preview": "# Lin\nLin is a open source plug-in for **Xcode 5**.  \nIt lets you search/manage localizations without opening the .strin"
  }
]

About this extraction

This page contains the full source code of the questbeat/Lin-Xcode5 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 78 files (188.7 KB), approximately 51.4k tokens, and a symbol index with 11 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!