Full Code of onevcat/VVDocumenter-Xcode for AI

master 0ab09a930dbe cached
72 files
293.7 KB
79.7k tokens
1 symbols
1 requests
Download .txt
Showing preview only (315K chars total). Download the full file or copy to clipboard to get everything.
Repository: onevcat/VVDocumenter-Xcode
Branch: master
Commit: 0ab09a930dbe
Files: 72
Total size: 293.7 KB

Directory structure:
gitextract_6z6nzidj/

├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── VVDocumenter-Xcode/
│   ├── Commenter/
│   │   ├── VVArgument.h
│   │   ├── VVArgument.m
│   │   ├── VVBaseCommenter.h
│   │   ├── VVBaseCommenter.m
│   │   ├── VVCommenter.h
│   │   ├── VVEnumCommenter.h
│   │   ├── VVEnumCommenter.m
│   │   ├── VVFunctionCommenter.h
│   │   ├── VVFunctionCommenter.m
│   │   ├── VVMacroCommenter.h
│   │   ├── VVMacroCommenter.m
│   │   ├── VVMethodCommenter.h
│   │   ├── VVMethodCommenter.m
│   │   ├── VVPropertyCommenter.h
│   │   ├── VVPropertyCommenter.m
│   │   ├── VVStructCommenter.h
│   │   ├── VVStructCommenter.m
│   │   ├── VVSwiftEnumCommenter.h
│   │   ├── VVSwiftEnumCommenter.m
│   │   ├── VVSwiftExtensionCommenter.h
│   │   ├── VVSwiftExtensionCommenter.m
│   │   ├── VVSwiftFunctionCommenter.h
│   │   ├── VVSwiftFunctionCommenter.m
│   │   ├── VVSwiftPropertyCommenter.h
│   │   ├── VVSwiftPropertyCommenter.m
│   │   ├── VVVariableCommenter.h
│   │   └── VVVariableCommenter.m
│   ├── KeyboardHelper/
│   │   ├── VVKeyboardEventSender.h
│   │   └── VVKeyboardEventSender.m
│   ├── OCCategory/
│   │   ├── NSString+PDRegex/
│   │   │   ├── NSString+PDRegex.h
│   │   │   └── NSString+PDRegex.m
│   │   ├── NSString+VVSyntax/
│   │   │   ├── NSString+VVSyntax.h
│   │   │   └── NSString+VVSyntax.m
│   │   ├── NSString+VVTextGetter/
│   │   │   ├── NSString+VVTextGetter.h
│   │   │   └── NSString+VVTextGetter.m
│   │   ├── NSTextView+VVTextGetter/
│   │   │   ├── NSTextView+VVTextGetter.h
│   │   │   └── NSTextView+VVTextGetter.m
│   │   ├── VVTextResult.h
│   │   └── VVTextResult.m
│   ├── ProjectHelper/
│   │   ├── VVProject.h
│   │   ├── VVProject.m
│   │   ├── VVWorkspaceManager.h
│   │   └── VVWorkspaceManager.m
│   ├── Setting/
│   │   ├── VVDSettingPanelWindowController.h
│   │   ├── VVDSettingPanelWindowController.m
│   │   ├── VVDSettingPanelWindowController.xib
│   │   ├── VVDocumenterSetting.h
│   │   └── VVDocumenterSetting.m
│   ├── VVDocumenter-Xcode-Info.plist
│   ├── VVDocumenter-Xcode-Prefix.pch
│   ├── VVDocumenter.h
│   ├── VVDocumenter.m
│   ├── VVDocumenterManager.h
│   ├── VVDocumenterManager.m
│   └── en.lproj/
│       └── InfoPlist.strings
├── VVDocumenter-Xcode.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   └── contents.xcworkspacedata
│   └── xcshareddata/
│       └── xcschemes/
│           ├── VVDocumenter-Xcode.xcscheme
│           └── VVDocumenterTests.xcscheme
└── VVDocumenterTests/
    ├── CommenterTests/
    │   └── CommenterTests.m
    ├── DocumenterTests/
    │   └── VVMethodTestsCode.plist
    ├── SyntaxTests/
    │   └── SyntaxTests.m
    ├── VVDocumenterTests-Info.plist
    ├── VVDocumenterTests-Prefix.pch
    ├── VVDocumenterTests.m
    ├── VVTestHelper.h
    ├── VVTestHelper.m
    └── en.lproj/
        └── InfoPlist.strings

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

================================================
FILE: .gitignore
================================================
#########################
# .gitignore file for Xcode4 / OS X Source projects
#
# Version 2.1
# For latest version, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects
#
# 2013 updates:
# - fixed the broken "save personal Schemes"
# - added line-by-line explanations for EVERYTHING (some were missing)
#
# NB: if you are storing "built" products, this WILL NOT WORK,
# and you should use a different .gitignore (or none at all)
# This file is for SOURCE projects, where there are many extra
# files that we want to exclude
#
#########################

#####
# OS X temporary files that should never be committed
#
# c.f. http://www.westwind.com/reference/os-x/invisibles.html

.DS_Store

# c.f. http://www.westwind.com/reference/os-x/invisibles.html

.Trashes

# c.f. http://www.westwind.com/reference/os-x/invisibles.html

*.swp

# *.lock - this is used and abused by many editors for many different things.
#    For the main ones I use (e.g. Eclipse), it should be excluded 
#    from source-control, but YMMV

*.lock

#
# profile - REMOVED temporarily (on double-checking, this seems incorrect; I can't find it in OS X docs?)
#profile


####
# Xcode temporary files that should never be committed
# 
# NB: NIB/XIB files still exist even on Storyboard projects, so we want this...

*~.nib


####
# Xcode build files -
#
# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData"

DerivedData/

# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build"

build/


#####
# Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups)
#
# This is complicated:
#
# SOMETIMES you need to put this file in version control.
# Apple designed it poorly - if you use "custom executables", they are
#  saved in this file.
# 99% of projects do NOT use those, so they do NOT want to version control this file.
#  ..but if you're in the 1%, comment out the line "*.pbxuser"

# .pbxuser: http://lists.apple.com/archives/xcode-users/2004/Jan/msg00193.html

*.pbxuser

# .mode1v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html

*.mode1v3

# .mode2v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html

*.mode2v3

# .perspectivev3: http://stackoverflow.com/questions/5223297/xcode-projects-what-is-a-perspectivev3-file

*.perspectivev3

#    NB: also, whitelist the default ones, some projects need to use these
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3


####
# Xcode 4 - semi-personal settings
#
#
# OPTION 1: ---------------------------------
#     throw away ALL personal settings (including custom schemes!
#     - unless they are "shared")
#
# NB: this is exclusive with OPTION 2 below
xcuserdata

# OPTION 2: ---------------------------------
#     get rid of ALL personal settings, but KEEP SOME OF THEM
#     - NB: you must manually uncomment the bits you want to keep
#
# NB: this *requires* git v1.8.2 or above; you may need to upgrade to latest OS X,
#    or manually install git over the top of the OS X version
# NB: this is exclusive with OPTION 1 above
#
#xcuserdata/**/*

#     (requires option 2 above): Personal Schemes
#
#!xcuserdata/**/xcschemes/*

####
# XCode 4 workspaces - more detailed
#
# Workspaces are important! They are a core feature of Xcode - don't exclude them :)
#
# Workspace layout is quite spammy. For reference:
#
# /(root)/
#   /(project-name).xcodeproj/
#     project.pbxproj
#     /project.xcworkspace/
#       contents.xcworkspacedata
#       /xcuserdata/
#         /(your name)/xcuserdatad/
#           UserInterfaceState.xcuserstate
#     /xcsshareddata/
#       /xcschemes/
#         (shared scheme name).xcscheme
#     /xcuserdata/
#       /(your name)/xcuserdatad/
#         (private scheme).xcscheme
#         xcschememanagement.plist
#
#

####
# Xcode 4 - Deprecated classes
#
# Allegedly, if you manually "deprecate" your classes, they get moved here.
#
# We're using source-control, so this is a "feature" that we do not want!

*.moved-aside

####
# UNKNOWN: recommended by others, but I can't discover what these files are
#
# ...none. Everything is now explained.

/VVDocumenter-Xcode.xcodeproj/project.xcworkspace/xcshareddata/
.idea


================================================
FILE: .travis.yml
================================================
language: objective-c
xcode_project: VVDocumenter-Xcode.xcodeproj
xcode_scheme: VVDocumenter-Xcode


================================================
FILE: LICENSE
================================================
Copyright (c) 2015 Wei Wang <onevcat@gmail.com>

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: README.md
================================================
# VVDocumenter-Xcode [![Build Status](https://api.travis-ci.org/onevcat/VVDocumenter-Xcode.svg)](https://travis-ci.org/onevcat/VVDocumenter-Xcode) <a href="https://flattr.com/submit/auto?user_id=onevcat&url=https%3A%2F%2Fgithub.com%2Fonevcat%2FVVDocumenter-Xcode" target="_blank"><img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0"></a>
---

# Goodbye World

In Xcode 8, Apple integrated a comment documentation generator plugin, which is built on top of VVDocumenter. Now this project is proud to be a part of Apple. It means you could just use the shortcut (⌥ Option + ⌘ Command + /) to add a documentation comment to your code if you are using Xcode 8 or above!

VVDocumenter is one of my hobby projects [from 2013](https://github.com/onevcat/VVDocumenter-Xcode/commit/6a2b604713c9fb573e229daece8286dac68ac24a), back to the age of Xcode 4. It serves well for these years and I am so glad that it helps a lot of developers to improve their productivity. Since there is no need to install this plugin anymore, the development of VVDocumenter will not continue. Yes, it's time to say goodbye, with a happy ending.

Thank you all for your selfless support to this project. Let's build more great things and make the world better in future!

## What is this?

Writing documentation is so important for developing, but it is really painful with Xcode. Think about how much time you are wasting in pressing '*' or '/', and typing the parameters again and again. Now, you can find the method (or any code) you want to document to, and type in `///`, the document will be generated for you and all params and return will be extracted into a Javadoc style, which is compatible with [appledoc](https://github.com/tomaz/appledoc), [Doxygen](http://www.stack.nl/~dimitri/doxygen/) and [HeaderDoc](https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/HeaderDoc/intro/intro.html). You can just fill the inline placeholder tokens to finish your document.

Here is an image which can show what it exactly does. 

![Screenshot](https://raw.github.com/onevcat/VVDocumenter-Xcode/master/ScreenShot.gif)

> By the way, it also supports [Swift](https://developer.apple.com/swift/) now. Cheers!

![Screenshot](https://raw.github.com/onevcat/VVDocumenter-Xcode/master/vvdocumenter-swift.gif)

## How to install and use?

The best way of installing is by [Alcatraz](http://alcatraz.io). Install Alcatraz followed by the instruction, restart your Xcode and press `⇧⌘9`. You can find `VVDocumenter-Xcode` in the list and click the icon on left to install.

If you do not like the Alcatraz way, you can also clone the repo. Then build the `VVDocumenter-Xcode` target in the Xcode project and the plug-in will automatically be installed in `~/Library/Application Support/Developer/Shared/Xcode/Plug-ins`. Relaunch Xcode and type in `///` above any code you want to write a document to.

If you want to use other text beside of `///` to trigger the document insertion, you can find a setting panel by clicking `VVDocument` in the Window menu of Xcode. You can also find some other useful options there, including setting using spaces instead of tab in the panel or changing the format of generated documentation.

## Xcode version?

This plug-in is supported in Xcode 5, 6 and 7. From Xcode 5, Apple added a UUID-verification to all plugins to ensure the stability when Xcode gets updated. The value of `DVTPlugInCompatibilityUUIDs` in project plist should contains current UUID of Xcode version, or the plugin does not work. And from Xcode 6.3, you will be prompt to "Load third party bundle" if you are using a plugin. You should always select "Load bundles" to enable this plugin.

All plugins will be disabled once you update your Xcode, since the supported UUIDs in the plugins do not contain the one. You should try to clean your plugins folder (`~/Library/Application Support/Developer/Shared/Xcode/Plug-ins` by default) and clone/build the latest version from master branch. If you happened to skip the bundle loading, you can use this to reset the prompt:

```bash
defaults delete com.apple.dt.Xcode DVTPlugInManagerNonApplePlugIns-Xcode-{your_xcode_version}
```

**Please do not open an issue if this plugin not work in your newly updated Xcode.** Pull request for new `DVTPlugInCompatibilityUUIDs` is welcome, and if UUID of your Xcode version is already there, please try to reinstall the plugin from a clean state.

The default deployment target is 10.8. If you want to use it in a earlier OS version, you should change OS X Deployment Target (in project info setting) to your system version.

## Swift Support

Yes, this plugin supports documentation for Swift 2 now. Check [this post](http://ericasadun.com/2015/06/14/swift-header-documentation-in-xcode-7/) to see how to write the documentation for swift. By using `VVDocumenter-Xcode`, you can just type `///` to make the magic happen.

The documentation format changed from Swift 1.x to 2. If you are using Swift 1.x, you could build from branch [Xcode6](https://github.com/onevcat/VVDocumenter-Xcode/tree/Xcode6) to get the support for the earlier format.

## Limitations and Future

The plugin is using simulation of keyboard event to insert the doc comments for you. So it is depending the keyboard shortcut of Xcode. These two kinds of operation are being used:

* Delete to Beginning of the Line (⌘⌫)
* Paste (⌘V)

If you have modified these two shortcuts in your Xcode, the newset version of the plugin would not work correctly. Instead, you can use a earlier version such as [this one(commit 03c4169ff7)](https://github.com/onevcat/VVDocumenter-Xcode/tree/03c4169ff79b618b9fd3db93dd96652a522ad3e0). Be causion you may suffer an [undo and redo issue ](https://github.com/onevcat/VVDocumenter-Xcode/issues/3).

`VVDocumenter-Xcode` is now using regular expression to extract things needed, which is not the best way to do such thing. A better approach could be using the AST, and I also have a plan to do it later if I have some more time :)

## License

VVDocumenter is published under MIT License. See the LICENSE file for more.




================================================
FILE: VVDocumenter-Xcode/Commenter/VVArgument.h
================================================
//
//  Argument.h
//  VVDocumenter-Xcode

//
//  Created by 王 巍 on 13-7-19.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Foundation/Foundation.h>

@interface VVArgument : NSObject
@property (nonatomic, copy) NSString *type;
@property (nonatomic, copy) NSString *name;
@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVArgument.m
================================================
//
//  Argument.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-19.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVArgument.h"

@implementation VVArgument

-(void)setType:(NSString *)type
{
    if (type != _type) {
       _type = [[[type vv_stringByReplacingRegexPattern:@"&$" withString:@""]
                       vv_stringByReplacingRegexPattern:@"\\s*\\*$" withString:@""]
                     stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    }
}

-(void)setName:(NSString *)name
{
    if (name != _name) {
        _name = [[[[[[[name vv_stringByReplacingRegexPattern:@"\\(|\\)" withString:@""]
                            vv_stringByReplacingRegexPattern:@"^&" withString:@""]
                            vv_stringByReplacingRegexPattern:@"^\\*+" withString:@""]
                            vv_stringByReplacingRegexPattern:@"\\[.*$" withString:@""]
                            vv_stringByReplacingRegexPattern:@",$" withString:@""]
                            vv_stringByReplacingRegexPattern:@";$" withString:@""]
                          stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    }
}

- (NSString *)description {
    return [NSString stringWithFormat:@"%@< type: %@, name: %@>", self.class, self.type, self.name];
}

- (BOOL)isEqual:(id)other {
    if (other == self) {
        return YES;
    }
    if ([other isKindOfClass:self.class]) {
        return [((VVArgument *)other).type isEqualToString:self.type]
            && [((VVArgument *)other).name isEqualToString:self.name];
    }
    return NO;
}

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVBaseCommenter.h
================================================
//
//  VVBaseCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Foundation/Foundation.h>

@interface VVBaseCommenter : NSObject

@property (nonatomic, copy) NSString *indent;
@property (nonatomic, copy) NSString *code;
@property (nonatomic, strong) NSMutableArray *arguments;
@property (nonatomic, assign) BOOL hasReturn;
@property (nonatomic, assign) BOOL hasThrows;

-(instancetype) initWithIndentString:(NSString *)indent codeString:(NSString *)code;

-(NSString *) document;

-(NSString *) documentForC;
-(NSString *) documentForSwift;
-(NSString *) documentForSwiftEnum;

-(void) parseArgumentsInputArgs:(NSString *)rawArgsCode;

-(BOOL) shouldComment;

// Comment methods
-(NSString *) startComment;
-(NSString *) startCommentWithDescriptionTag:(NSString *)tag;
-(NSString *) argumentsComment;
-(NSString *) endComment;
-(NSString *) returnComment;
-(NSString *) sinceComment;

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVBaseCommenter.m
================================================
//
//  VVBaseCommenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"
#import "VVArgument.h"
#import "VVDocumenterSetting.h"
#import "NSString+VVSyntax.h"
#import "VVProject.h"

@interface VVBaseCommenter()
@property (nonatomic, copy) NSString *space;
@property (nonatomic, assign) BOOL forSwift;
@property (nonatomic, assign) BOOL forSwiftEnum;
@end

@implementation VVBaseCommenter
-(instancetype) initWithIndentString:(NSString *)indent codeString:(NSString *)code
{
    self = [super init];
    if (self) {
        _indent = indent;
        _code = code;
        _arguments = [NSMutableArray array];
        _space = [[VVDocumenterSetting defaultSetting] spacesString];
        _forSwift = NO;
        _forSwiftEnum = NO;
    }
    return self;
}

-(NSString *) paramSymbol {
    return self.forSwift ? @"- parameter" : @"@param";
}

-(NSString *) returnSymbol {
    return self.forSwift ? @"- returns:" : @"@return";
}

-(NSString *) throwsSymbol {
    return @"- throws:";
}


-(NSString *) startCommentWithDescriptionTag:(NSString *)tag {
    NSString *authorInfo = @"";
    NSString *dateInfo = @"";
    
    if ([[VVDocumenterSetting defaultSetting] useAuthorInformation]) {
        NSMutableString *authorCotent = @"".mutableCopy;
        
        if ([[VVDocumenterSetting defaultSetting] authorInformation].length > 0) {
            [authorCotent appendString:[[VVDocumenterSetting defaultSetting] authorInformation]];
        }
        
        if ([[VVDocumenterSetting defaultSetting] useDateInformation]) {
            NSString *formatString = [[VVDocumenterSetting defaultSetting] dateInformationFormat];
            if ([formatString length] <= 0) {
                formatString = @"MM-dd-YYYY HH:MM:ss";
            }
            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
            [formatter setDateFormat:formatString];
            
            dateInfo = [formatter stringFromDate:[NSDate date]];
            
            if (self.forSwift) {
                [authorCotent appendString: [NSString stringWithFormat:@"\n%@- date: %@", self.prefixString, dateInfo]];
            } else {
                
                if (authorCotent.length > 0) {
                    [authorCotent appendString:@", "];
                }
                
                [authorCotent appendString: dateInfo];
            }
            
        }
        
        if (self.forSwift) {
            authorInfo = [NSString stringWithFormat:@"\n%@- author: %@\n", self.prefixString, authorCotent];
        } else {
            authorInfo = [NSString stringWithFormat:@"%@@author %@\n%@\n", self.prefixString, authorCotent, self.prefixString];
        }
        
    }
    
    if ([[VVDocumenterSetting defaultSetting] useHeaderDoc]) {
        return [NSString stringWithFormat:@"%@/*!\n%@%@%@<#Description#>\n", self.indent, authorInfo, self.prefixString, tag];
    } else if ([[VVDocumenterSetting defaultSetting] prefixWithSlashes]) {
        return [NSString stringWithFormat:@"%@%@%@<#Description#>\n", self.prefixString, authorInfo, tag];
    } else {
        
        if (self.forSwift){
            return [NSString stringWithFormat:@"%@/**\n%@%@<#Description#>\n%@", self.indent, self.prefixString, tag, authorInfo];
        } else {
            return [NSString stringWithFormat:@"%@/**\n%@%@%@<#Description#>\n", self.indent, authorInfo, self.prefixString, tag];
        }
        
    }
}

-(NSString *) startComment
{
    NSString *descriptionTag =
    [[VVDocumenterSetting defaultSetting] briefDescription] && !self.forSwift ? @"@brief " : @"";
    return [self startCommentWithDescriptionTag:descriptionTag];
}

-(NSString *) argumentsComment
{
    if (self.arguments.count == 0)
        return @"";

    // start off with an empty line
    NSMutableString *result = [NSMutableString stringWithFormat:@"%@", self.emptyLine];

    int longestNameLength = [[self.arguments valueForKeyPath:@"@max.name.length"] intValue];
    BOOL useSpace = [[VVDocumenterSetting defaultSetting] useSpaces];
    
    for (VVArgument *arg in self.arguments) {
        NSString *name = arg.name;

        if ([[VVDocumenterSetting defaultSetting] alignArgumentComments]) {
            if (self.forSwiftEnum) {
                if (useSpace) {
                    name = [[name stringByAppendingString:@":"] stringByPaddingToLength:longestNameLength + 1 withString:@" " startingAtIndex:0];
                } else {
                    NSInteger tabSpaceRateCount = [[VVDocumenterSetting defaultSetting] spaceCount];
                    NSInteger neededTabCount = (longestNameLength + tabSpaceRateCount - name.length) / tabSpaceRateCount - 1;
                    name = [[name stringByAppendingString:@":"] stringByPaddingToLength:(name.length + 1 + neededTabCount) withString:@"\t" startingAtIndex:0];
                }
            } else {
                if (self.forSwift) {
                    name = [name stringByAppendingString:@":"];
                    if (useSpace) {
                        name = [name stringByPaddingToLength:longestNameLength + 1 withString:@" " startingAtIndex:0];
                    } else {
                        NSInteger tabSpaceRateCount = [[VVDocumenterSetting defaultSetting] spaceCount];
                        NSInteger neededTabCount = (longestNameLength + 1 + tabSpaceRateCount - name.length) / tabSpaceRateCount - 1;
                        name = [name stringByPaddingToLength:(name.length + neededTabCount) withString:@"\t" startingAtIndex:0];
                    }
                } else {
                    if (useSpace) {
                        name = [name stringByPaddingToLength:longestNameLength withString:@" " startingAtIndex:0];
                    } else {
                        NSInteger tabSpaceRateCount = [[VVDocumenterSetting defaultSetting] spaceCount];
                        NSInteger neededTabCount = (longestNameLength + tabSpaceRateCount - name.length) / tabSpaceRateCount - 1;
                        name = [name stringByPaddingToLength:(name.length + neededTabCount) withString:@"\t" startingAtIndex:0];
                    }
                }
            }
        }
        else {
            if (self.forSwiftEnum || self.forSwift) {
                name = [name stringByAppendingString:@":"];
            }
        }

        NSString *indentString = useSpace ? @" " : @"\t";
        if (self.forSwiftEnum) {
            [result appendFormat:@"%@- %@%@<#%@ description#>\n", self.prefixString, name, indentString, arg.name];
        } else {
            [result appendFormat:@"%@%@ %@%@<#%@ description#>\n", self.prefixString, [self paramSymbol], name, indentString, arg.name];
        }

    }
    return result;
}

-(NSString *) returnComment
{
    if (!self.hasReturn) {
        return @"";
    } else {
        return [NSString stringWithFormat:@"%@%@%@ <#return value description#>\n", self.emptyLine, self.prefixString, [self returnSymbol]];
    }
}

-(NSString *) throwsComment
{
    if (!self.hasThrows) {
        return @"";
    } else {
        return [NSString stringWithFormat:@"%@%@%@ <#throws value description#>\n", self.emptyLine, self.prefixString, [self throwsSymbol]];
    }
}

-(NSString *) sinceComment
{
    //It seems no since attribute for swift? Maybe I am wrong.
    VVProject *project = [VVProject projectForKeyWindow];
    
    if (!self.forSwift && [[VVDocumenterSetting defaultSetting] addSinceToComments]) {

        VVDSinceOption sinceOption = [[VVDocumenterSetting defaultSetting] sinceOption];

        switch (sinceOption) {
            case VVDSinceOptionPlaceholder: {

                return [NSString stringWithFormat:@"%@%@@since <#version number#>\n", self.emptyLine, self.prefixString];
                break;
            }
            case VVDSinceOptionProjectVersion: {

                if (project.projectVersion && project.projectVersion.length>0) {

                    return [NSString stringWithFormat:@"%@%@@since <#%@#>\n", self.emptyLine, self.prefixString,project.projectVersion];
                }else{
                    // Fall back onto default placeholder if no project version can be obtained.
                    return [NSString stringWithFormat:@"%@%@@since <#version number#>\n", self.emptyLine, self.prefixString];
                }

                break;
            }
            case VVDSinceOptionSpecificVersion: {

                NSString *version = [[VVDocumenterSetting defaultSetting] sinceVersion];
                if (version && version.length>0) {

                    return [NSString stringWithFormat:@"%@%@@since <#%@#>\n", self.emptyLine, self.prefixString, version];
                }else{
                    // Fall back onto default placeholder if no version can be obtained.
                    return [NSString stringWithFormat:@"%@%@@since <#version number#>\n", self.emptyLine, self.prefixString];
                }
                break;
            }
        }
    } else {
        return @"";
    }
}

-(NSString *) endComment
{
    if ([[VVDocumenterSetting defaultSetting] prefixWithSlashes]) {
        return @"";
    } else {
        return [NSString stringWithFormat:@"%@ */",self.indent];
    }
}

-(NSString *) documentForSwift
{
    self.forSwift = YES;
    return [self __document];
}

-(NSString *) documentForSwiftEnum
{
    self.forSwiftEnum = YES;
    self.forSwift = YES;
    return [self __document];
}

-(NSString *) documentForC
{
    self.forSwift = NO;
    return [self __document];
}

-(NSString *) __document
{
    NSString * comment = [NSString stringWithFormat:@"%@%@%@%@%@%@",
                          [self startComment],
                          [self argumentsComment],
                          [self throwsComment],
                          [self returnComment],
                          [self sinceComment],
                          [self endComment]];
    
    // The last line of the comment should be adjacent to the next line of code,
    // back off the newline from the last comment component.
    if ([[VVDocumenterSetting defaultSetting] prefixWithSlashes]) {
        return [comment stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    } else {
        return comment;
    }
}

-(NSString *) document
{
    //This is the default action
    return [self documentForC];
}

-(NSString *) emptyLine
{
    if ([[VVDocumenterSetting defaultSetting] blankLinesBetweenSections]) {
        return [[NSString stringWithFormat:@"%@\n", self.prefixString] vv_stringByTrimEndSpaces];
    } else {
        return @"";
    }
}

-(NSString *) prefixString
{
    if ([[VVDocumenterSetting defaultSetting] prefixWithStar] && !self.forSwift) {
        return [NSString stringWithFormat:@"%@ *%@", self.indent, self.space];
    } else if ([[VVDocumenterSetting defaultSetting] prefixWithSlashes]) {
        return [NSString stringWithFormat:@"%@///%@", self.indent, self.space];
    } else {
        return [NSString stringWithFormat:@"%@ ", self.indent];
    }
}

-(void) parseArgumentsInputArgs:(NSString *)rawArgsCode
{
    [self.arguments removeAllObjects];
    if (rawArgsCode.length == 0) {
        return;
    }

    NSArray *argumentStrings = [rawArgsCode componentsSeparatedByString:@","];
    for (__strong NSString *argumentString in argumentStrings) {
        VVArgument *arg = [[VVArgument alloc] init];
        argumentString = [argumentString vv_stringByReplacingRegexPattern:@"=\\s*\\w*" withString:@""];
        argumentString = [argumentString vv_stringByReplacingRegexPattern:@"\\(" withString:@" "];
        argumentString = [argumentString vv_stringByReplacingRegexPattern:@"\\*" withString:@" "];
        argumentString = [argumentString vv_stringByReplacingRegexPattern:@"\\s+$" withString:@""];
        argumentString = [argumentString vv_stringByReplacingRegexPattern:@"\\s+" withString:@" "];
        NSMutableArray *tempArgs = [[argumentString componentsSeparatedByString:@" "] mutableCopy];
        while ([[tempArgs lastObject] isEqualToString:@" "]) {
            [tempArgs removeLastObject];
        }

        arg.name = [tempArgs lastObject];

        [tempArgs removeLastObject];
        arg.type = [tempArgs componentsJoinedByString:@" "];

        VVLog(@"arg type: %@", arg.type);
        VVLog(@"arg name: %@", arg.name);

        [self.arguments addObject:arg];
    }
}

-(BOOL) shouldComment
{
    return YES;
}

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVCommenter.h
================================================
//
//  VVCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-18.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#ifndef CommentTest_Commenter_h
#define CommentTest_Commenter_h

#import "VVBaseCommenter.h"
#import "VVMethodCommenter.h"
#import "VVPropertyCommenter.h"
#import "VVFunctionCommenter.h"
#import "VVMacroCommenter.h"
#import "VVEnumCommenter.h"
#import "VVStructCommenter.h"
#import "VVVariableCommenter.h"
#import "VVArgument.h"
#import "VVSwiftFunctionCommenter.h"
#import "VVSwiftEnumCommenter.h"
#import "VVSwiftPropertyCommenter.h"
#import "VVSwiftExtensionCommenter.h"

#endif


================================================
FILE: VVDocumenter-Xcode/Commenter/VVEnumCommenter.h
================================================
//
//  VVEnumCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"

@interface VVEnumCommenter : VVBaseCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVEnumCommenter.m
================================================
//
//  VVEnumCommenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVEnumCommenter.h"

@implementation VVEnumCommenter

- (NSString *)document {
    //Regular comment documentation
    NSString *finalString = [NSString stringWithFormat:@"%@%@%@", [self startComment],
                                                                  [self sinceComment],
                                                                  [self endComment]];

    if (![finalString hasSuffix:@"\n"]) {
        finalString = [finalString stringByAppendingString:@"\n"];
    }

    // Grab everything from the start of the line to the opening brace, which
    // may be on a different line.
    NSString *enumDefinePattern = @"^\\s*(\\w+\\s+)?NS_(ENUM|OPTIONS)[\\s\\S]*?\\{";
    
    NSRegularExpression *enumDefineExpression = [NSRegularExpression regularExpressionWithPattern:enumDefinePattern options:0 error:nil];
    NSTextCheckingResult *enumDefineResult = [enumDefineExpression firstMatchInString:self.code options:0 range:NSMakeRange(0, self.code.length)];
    
    finalString = [finalString stringByAppendingString:[self.code substringWithRange:[enumDefineResult rangeAtIndex:0]]];
    finalString = [finalString substringToIndex:finalString.length - 1];
    finalString = [finalString stringByAppendingString:@" {\n"];
    
    NSString *endPattern = @"\\}\\s*;";
    NSString *enumPartsString = [[self.code vv_stringByReplacingRegexPattern:enumDefinePattern withString:@""]
                                            vv_stringByReplacingRegexPattern:endPattern        withString:@""];
    NSArray *enumParts = [enumPartsString componentsSeparatedByString:@","];
    
    for (NSString *part in enumParts) {
        NSString *trimmedPart = [part stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        //Only append when there is a enum define. (In case of the last comma, followed no define)
        if (trimmedPart.length != 0) {
            NSString *temp = [NSString stringWithFormat:@"%@%@%@", [self startCommentWithDescriptionTag:@""],
                              [self sinceComment],
                              [self endComment]];

            if ([temp hasSuffix:@"\n"]) {
                // comment has a newline suffix, so trimmedPart will go on
                // the next line
                temp = [temp stringByAppendingString:trimmedPart];
            } else {
                // comment does not have a newline suffix, so trimmedPart
                // needs to be moved to the next line
                temp = [temp stringByAppendingFormat:@"\n%@", trimmedPart];
            }

            if (part != [enumParts lastObject]) {
                temp = [temp stringByAppendingString:@",\n"];
            } else {
                // since trimmedPart was used there is no trailing newline
                temp = [temp stringByAppendingString:@"\n"];
            }
            finalString = [finalString stringByAppendingString:temp];
        }
    }

    return [finalString stringByAppendingString:@"};"];
}

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVFunctionCommenter.h
================================================
//
//  VVFunctionCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"

@interface VVFunctionCommenter : VVBaseCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVFunctionCommenter.m
================================================
//
//  VVFunctionCommenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVFunctionCommenter.h"
#import "VVArgument.h"

@implementation VVFunctionCommenter

-(void) captureReturnType
{
    NSArray *arr = [self.code componentsSeparatedByString:@"("];
    if (arr.count > 0 && (![arr[0] vv_matchesPatternRegexPattern:@"^\\s*void\\s*[^*]*\\s*\\w+$"] &&
                          ![arr[0] vv_matchesPatternRegexPattern:@"^\\w+\\svoid"])) {
        self.hasReturn = YES;
    }
}

-(void) captureParameters
{
    NSArray * braceGroups = [self.code vv_stringsByExtractingGroupsUsingRegexPattern:@"\\(([^\\^].*?)\\)(?:__attribute__\\(\\(.*\\)\\))?"];
    if (braceGroups.count > 0) {
        [self parseArgumentsInputArgs:braceGroups[0]];
    }
    
    //Remove void arg in block
    NSArray *tempArray = [NSArray arrayWithArray:self.arguments];
    [tempArray enumerateObjectsUsingBlock:^(VVArgument *arg, NSUInteger idx, BOOL *stop) {
        if ([arg.type isEqualToString:@""] && [arg.name isEqualToString:@"void"]) {
            [self.arguments removeObject:arg];
        }
    }];
}

-(NSString *) document
{
    [self captureReturnType];
    [self captureParameters];
    
    return [super documentForC];
}

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVMacroCommenter.h
================================================
//
//  VVMacroCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"

@interface VVMacroCommenter : VVBaseCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVMacroCommenter.m
================================================
//
//  VVMacroCommenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVMacroCommenter.h"

@implementation VVMacroCommenter

-(void) captureReturnType
{
    self.hasReturn = YES;
}

-(void) captureParameters
{
    NSArray * braceGroups = [self.code vv_stringsByExtractingGroupsUsingRegexPattern:@"\\(([^\\^][^\\(\\)]*)\\)"];
    if (braceGroups.count > 0) {
        [self parseArgumentsInputArgs:braceGroups[0]];
    }
}

-(NSString *) document
{
    [self captureReturnType];
    [self captureParameters];
    
    return [super documentForC];
}

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVMethodCommenter.h
================================================
//
//  VVMethodCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"

@interface VVMethodCommenter : VVBaseCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVMethodCommenter.m
================================================
//
//  VVMethodCommenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVMethodCommenter.h"
#import "VVArgument.h"

@implementation VVMethodCommenter

-(void) captureReturnType
{
    NSArray * matchedTypes = [self.code vv_stringsByExtractingGroupsUsingRegexPattern:@"^\\s*[+-]\\s*\\(([^\\(\\)]*)\\)"];

    if (matchedTypes.count == 1) {
        if (![matchedTypes[0] vv_matchesPatternRegexPattern:@"^\\s*void\\s*[^*]*\\s*$"] &&
            ![matchedTypes[0] vv_matchesPatternRegexPattern:@"^\\s*IBAction\\s*$"]) {
            self.hasReturn = YES;
        }
    }
}

-(void) captureParameters
{
    NSArray * matchedParams = [self.code vv_stringsByExtractingGroupsUsingRegexPattern:@"\\:\\(([^:]+)\\)(\\w+)"];
    VVLog(@"matchedParams: %@",matchedParams);
    for (int i = 0; i < (int)matchedParams.count - 1; i = i + 2) {
        VVArgument *arg = [[VVArgument alloc] init];
        arg.type = [matchedParams[i] vv_stringByReplacingRegexPattern:@"[\\s*;.*]" withString:@""];
        arg.name = [matchedParams[i + 1] vv_stringByReplacingRegexPattern:@"[\\s*;.*]" withString:@""];
        [self.arguments addObject:arg];
    }
}

-(NSString *) document
{
    [self captureReturnType];
    [self captureParameters];
    
    return [super documentForC];
}

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVPropertyCommenter.h
================================================
//
//  VVPropertyCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"

@interface VVPropertyCommenter : VVBaseCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVPropertyCommenter.m
================================================
//
//  VVPropertyCommenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVPropertyCommenter.h"

@implementation VVPropertyCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVStructCommenter.h
================================================
//
//  VVStructCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"

@interface VVStructCommenter : VVBaseCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVStructCommenter.m
================================================
//
//  VVStructCommenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVStructCommenter.h"

@implementation VVStructCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVSwiftEnumCommenter.h
================================================
//
//  VVSwiftEnumCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 14-7-30.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"

@interface VVSwiftEnumCommenter : VVBaseCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVSwiftEnumCommenter.m
================================================
//
//  VVSwiftEnumCommenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 14-7-30.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVSwiftEnumCommenter.h"
#import "VVArgument.h"

@implementation VVSwiftEnumCommenter

-(void) captureParameters
{
    NSString *normalizedCode = [self.code vv_stringByReplacingRegexPattern:@"\\s*\\n\\s*" withString:@"\n"];
    NSArray *lines = [normalizedCode componentsSeparatedByString:@"\n"];
    [lines enumerateObjectsUsingBlock:^(NSString *line, NSUInteger idx, BOOL *stop) {
        if ([line vv_matchesPatternRegexPattern:@"^case\\s+"]) {
            NSString * plainCase = [line vv_stringByReplacingRegexPattern:@"\\(.*?\\)" withString:@""];
            plainCase = [[plainCase vv_stringByReplacingRegexPattern:@"^case\\s+" withString:@""] vv_stringByReplacingRegexPattern:@"\\s+" withString:@""];
            NSArray *cases = [plainCase componentsSeparatedByString:@","];
            [cases enumerateObjectsUsingBlock:^(NSString *name, NSUInteger idx, BOOL *stop) {
                NSString *plainName = [name vv_stringByReplacingRegexPattern:@"=\\s*.*$" withString:@""];
                if ([plainName hasPrefix:@"."]) {
                    return;
                }
                VVArgument *arg = [[VVArgument alloc] init];
                arg.name = plainName;
                [self.arguments addObject:arg];
            }];
        }
    }];
}

-(NSString *) document
{
    [self captureParameters];
    return [super documentForSwiftEnum];
}

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVSwiftExtensionCommenter.h
================================================
//
//  VVSwiftExtensionCommenter.h
//  VVDocumenter-Xcode
//
//  Created by WANG WEI on 2015/06/17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"

@interface VVSwiftExtensionCommenter : VVBaseCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVSwiftExtensionCommenter.m
================================================
//
//  VVSwiftExtensionCommenter.m
//  VVDocumenter-Xcode
//
//  Created by WANG WEI on 2015/06/17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVSwiftExtensionCommenter.h"

@implementation VVSwiftExtensionCommenter
-(NSString *) document
{
    NSArray *component = [[self.code stringByReplacingOccurrencesOfString:@"{" withString:@""] componentsSeparatedByString:@":"];
    NSString *description = @"Description";
    if (component.count == 2) {
        description = [component.lastObject stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    }
    
    return [NSString stringWithFormat:@"// MARK: - <#%@#>", description];
}
@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVSwiftFunctionCommenter.h
================================================
//
//  VVSwiftFunctionCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 14-7-30.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"

@interface VVSwiftFunctionCommenter : VVBaseCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVSwiftFunctionCommenter.m
================================================
//
//  VVSwiftFunctionCommenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 14-7-30.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVSwiftFunctionCommenter.h"
#import "VVArgument.h"
#import "NSString+VVTextGetter.h"
#import "VVTextResult.h"

@implementation VVSwiftFunctionCommenter
-(void) captureReturnType
{
    VVTextResult *funcParenthesesResult = [self.code vv_textResultMatchPartWithPairOpenString:@"(" closeString:@")" currentLocation:0];
    NSString * funcSignatureWithoutParams = [self.code stringByReplacingCharactersInRange:funcParenthesesResult.range withString:@" "];
    
    if ([funcSignatureWithoutParams vv_matchesPatternRegexPattern:@"\\s+(throws|rethrows)\\s+"]) {
        self.hasThrows = YES;
    }
    
    if ([funcSignatureWithoutParams vv_matchesPatternRegexPattern:@"\\s*->\\s*\\(?(\\Void?|\\(\\s*\\))\\)?\\s*[{]"]) {
        self.hasReturn = NO;
    } else if ([funcSignatureWithoutParams vv_matchesPatternRegexPattern:@"s*->\\s*"]) {
        self.hasReturn = YES;
    } else if ([funcSignatureWithoutParams vv_matchesPatternRegexPattern:@"^\\s*(.*\\s+)?(init|subscript)\\s*"]) {
        self.hasReturn = YES;
    } else {
        self.hasReturn = NO;
    }
}

-(void) captureParameters
{
    VVTextResult *funcParenthesesResult = [self.code vv_textResultMatchPartWithPairOpenString:@"(" closeString:@")" currentLocation:0];
    NSArray * braceGroups = [funcParenthesesResult.string vv_stringsByExtractingGroupsUsingRegexPattern:@"\\((.*)\\)"];
    if (braceGroups.count > 0) {
        NSString *content = braceGroups[0];
        NSString *trimmed = [content stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        if (trimmed.length != 0) {
            [self parseSwiftArgumentsInputArgs:trimmed];
        }
    }
}

-(void) parseSwiftArgumentsInputArgs:(NSString *)rawArgsCode
{
    [self.arguments removeAllObjects];
    if (rawArgsCode.length == 0) {
        return;
    }
    
    NSString *removedUnwantComma = [rawArgsCode vv_stringByReplacingRegexPattern:@"[{].*?[^}],.*?[)}]" withString:@""];
    NSString *removedUnwantParentheses = [removedUnwantComma copy];
    
    VVTextResult *parenthesesInParam = [removedUnwantComma vv_textResultMatchPartWithPairOpenString:@"(" closeString:@")" currentLocation:0];
    while (parenthesesInParam.string) {
        removedUnwantParentheses = [removedUnwantParentheses stringByReplacingOccurrencesOfString:parenthesesInParam.string withString:@""];
        parenthesesInParam = [removedUnwantParentheses vv_textResultMatchPartWithPairOpenString:@"(" closeString:@")" currentLocation:0];
    }
    
    NSArray *argumentStrings = [removedUnwantParentheses componentsSeparatedByString:@","];
    for (__strong NSString *argumentString in argumentStrings) {
        VVArgument *arg = [[VVArgument alloc] init];
        argumentString = [argumentString vv_stringByReplacingRegexPattern:@"=\\s*\\w*" withString:@""];
        argumentString = [argumentString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        argumentString = [argumentString vv_stringByReplacingRegexPattern:@"\\s+" withString:@" "];
        NSMutableArray *tempArgs = [[argumentString componentsSeparatedByString:@":"] mutableCopy];
        if (tempArgs.count == 1) { //There is no ":", it is not a arg
            continue;
        }
        
        NSString *firstPart = [[tempArgs firstObject] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
        if ([firstPart rangeOfString:@" "].location != NSNotFound) {
            arg.name = [[[firstPart componentsSeparatedByString:@" "] lastObject] vv_stringByReplacingRegexPattern:@"#" withString:@""];
        } else {
            arg.name = [firstPart vv_stringByReplacingRegexPattern:@"#" withString:@""];
        }
        
        VVLog(@"arg name: %@", arg.name);
        
        [self.arguments addObject:arg];
    }
}

-(NSString *) document
{
    [self captureReturnType];
    [self captureParameters];
    
    return [super documentForSwift];
}
@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVSwiftPropertyCommenter.h
================================================
//
//  VVSwiftPropertyCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 14-7-31.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"

@interface VVSwiftPropertyCommenter : VVBaseCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVSwiftPropertyCommenter.m
================================================
//
//  VVSwiftPropertyCommenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 14-7-31.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVSwiftPropertyCommenter.h"

@implementation VVSwiftPropertyCommenter

-(NSString *) document
{
    return [NSString stringWithFormat:@"/// <#Description#>"];
}

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVVariableCommenter.h
================================================
//
//  VVVariableCommenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVBaseCommenter.h"

@interface VVVariableCommenter : VVBaseCommenter

@end


================================================
FILE: VVDocumenter-Xcode/Commenter/VVVariableCommenter.m
================================================
//
//  VVVariableCommenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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./

#import "VVVariableCommenter.h"

@implementation VVVariableCommenter

@end


================================================
FILE: VVDocumenter-Xcode/KeyboardHelper/VVKeyboardEventSender.h
================================================
//
//  VVKeyboardEventSender.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-26.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Foundation/Foundation.h>
#import <Carbon/Carbon.h>


@interface VVKeyboardEventSender : NSObject
-(void) beginKeyBoradEvents;
-(void) sendKeyCode:(NSInteger)keyCode;
-(void) sendKeyCode:(NSInteger)keyCode withModifierCommand:(BOOL)command
                                                       alt:(BOOL)alt
                                                     shift:(BOOL)shift
                                                   control:(BOOL)control;
-(void) sendKeyCode:(NSInteger)keyCode withModifier:(NSInteger)modifierMask;
-(void) endKeyBoradEvents;
@end


================================================
FILE: VVDocumenter-Xcode/KeyboardHelper/VVKeyboardEventSender.m
================================================
//
//  VVKeyboardEventSender.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-26.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVKeyboardEventSender.h"

@interface VVKeyboardEventSender()
{
    CGEventSourceRef _source;
    CGEventTapLocation _location;
}
@end

@implementation VVKeyboardEventSender
-(void) beginKeyBoradEvents
{
    _source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
    _location = kCGHIDEventTap;
}

-(void) sendKeyCode:(NSInteger)keyCode
{
    [self sendKeyCode:keyCode withModifier:0];
}

-(void) sendKeyCode:(NSInteger)keyCode withModifierCommand:(BOOL)command
                alt:(BOOL)alt
              shift:(BOOL)shift
            control:(BOOL)control
{
    NSInteger modifier = 0;
    if (command) {
        modifier = modifier ^ kCGEventFlagMaskCommand;
    }
    if (alt) {
        modifier = modifier ^ kCGEventFlagMaskAlternate;
    }
    if (shift) {
        modifier = modifier ^ kCGEventFlagMaskShift;
    }
    if (control) {
        modifier = modifier ^ kCGEventFlagMaskControl;
    }

    [self sendKeyCode:keyCode withModifier:modifier];
}

-(void) sendKeyCode:(NSInteger)keyCode withModifier:(NSInteger)modifierMask
{
    NSAssert(_source != NULL, @"You should call -beginKeyBoradEvents before sending a key event");
    CGEventRef event;
    event = CGEventCreateKeyboardEvent(_source, keyCode, true);
    CGEventSetFlags(event, modifierMask);
    CGEventPost(_location, event);
    CFRelease(event);
    
    event = CGEventCreateKeyboardEvent(_source, keyCode, false);
    CGEventSetFlags(event, modifierMask);
    CGEventPost(_location, event);
    CFRelease(event);
}

-(void) endKeyBoradEvents
{
    NSAssert(_source != NULL, @"You should call -beginKeyBoradEvents before end current keyborad event");
    CFRelease(_source);
    _source = nil;
}
@end


================================================
FILE: VVDocumenter-Xcode/OCCategory/NSString+PDRegex/NSString+PDRegex.h
================================================
//
//  NSString+PDRegex.h
//  RegexOnNSString
//
//  Created by Carl Brown on 10/3/11.
//  Copyright 2011 PDAgent, LLC. Released under MIT License.
//

#import <Foundation/Foundation.h>

@interface NSString (PDRegex)

-(NSString *) vv_stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *) replacement;
-(NSString *) vv_stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *) replacement caseInsensitive:(BOOL) ignoreCase;
-(NSString *) vv_stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *) replacement caseInsensitive:(BOOL) ignoreCase treatAsOneLine:(BOOL) assumeMultiLine;
-(NSArray *) vv_stringsByExtractingGroupsUsingRegexPattern:(NSString *)regex;
-(NSArray *) vv_stringsByExtractingGroupsUsingRegexPattern:(NSString *)regex caseInsensitive:(BOOL) ignoreCase treatAsOneLine:(BOOL) assumeMultiLine;
-(BOOL) vv_matchesPatternRegexPattern:(NSString *)regex;
-(BOOL) vv_matchesPatternRegexPattern:(NSString *)regex caseInsensitive:(BOOL) ignoreCase treatAsOneLine:(BOOL) assumeMultiLine;

@end


================================================
FILE: VVDocumenter-Xcode/OCCategory/NSString+PDRegex/NSString+PDRegex.m
================================================
//
//  NSString+PDRegex.m
//  RegexOnNSString
//
//  Created by Carl Brown on 10/3/11.
//  Copyright 2011 PDAgent, LLC. Released under MIT License.
//

#import "NSString+PDRegex.h"

@implementation NSString (PDRegex)

-(NSString *) vv_stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *) replacement caseInsensitive:(BOOL)ignoreCase {
    return [self vv_stringByReplacingRegexPattern:regex withString:replacement caseInsensitive:ignoreCase treatAsOneLine:NO];
}

-(NSString *) vv_stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *) replacement caseInsensitive:(BOOL) ignoreCase treatAsOneLine:(BOOL) assumeMultiLine {
    
    NSUInteger options=0;
    if (ignoreCase) {
        options = options | NSRegularExpressionCaseInsensitive;
    }
    if (assumeMultiLine) {
        options = options | NSRegularExpressionDotMatchesLineSeparators;
    }

    NSError *error=nil;
    NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:regex options:options error:&error];
    if (error) {
        NSLog(@"Error creating Regex: %@",[error description]);
        return nil;
    }
    
    NSString *retVal= [pattern stringByReplacingMatchesInString:self options:0 range:NSMakeRange(0, [self length]) withTemplate:replacement];
    return retVal;
}

-(NSString *) vv_stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *) replacement {
    return [self vv_stringByReplacingRegexPattern:regex withString:replacement caseInsensitive:NO treatAsOneLine:NO];
}

-(NSArray *) vv_stringsByExtractingGroupsUsingRegexPattern:(NSString *)regex caseInsensitive:(BOOL) ignoreCase treatAsOneLine:(BOOL) assumeMultiLine {
    NSUInteger options=0;
    if (ignoreCase) {
        options = options | NSRegularExpressionCaseInsensitive;
    }
    if (assumeMultiLine) {
        options = options | NSRegularExpressionDotMatchesLineSeparators;
    }
    
    NSError *error=nil;
    NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:regex options:options error:&error];
    if (error) {
        NSLog(@"Error creating Regex: %@",[error description]);
        return nil;
    }

    __block NSMutableArray *retVal = [NSMutableArray array];
    [pattern enumerateMatchesInString:self options:0 range:NSMakeRange(0, [self length]) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
        //Note, we only want to return the things in parens, so we're skipping index 0 intentionally
        for (int i=1; i<[result numberOfRanges]; i++) {
            NSString *matchedString=[self substringWithRange:[result rangeAtIndex:i]];
            [retVal addObject:matchedString];
        }
    }];
    return retVal;
}

-(NSArray *) vv_stringsByExtractingGroupsUsingRegexPattern:(NSString *)regex {
    return [self vv_stringsByExtractingGroupsUsingRegexPattern:regex caseInsensitive:NO treatAsOneLine:NO];
}

-(BOOL) vv_matchesPatternRegexPattern:(NSString *)regex caseInsensitive:(BOOL) ignoreCase treatAsOneLine:(BOOL) assumeMultiLine {
    NSUInteger options=0;
    if (ignoreCase) {
        options = options | NSRegularExpressionCaseInsensitive;
    }
    if (assumeMultiLine) {
        options = options | NSRegularExpressionDotMatchesLineSeparators;
    }
    
    NSError *error=nil;
    NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:regex options:options error:&error];
    if (error) {
        NSLog(@"Error creating Regex: %@",[error description]);
        return NO;  //Can't possibly match an invalid Regex
    }

    return ([pattern numberOfMatchesInString:self options:0 range:NSMakeRange(0, [self length])] > 0);
}

-(BOOL) vv_matchesPatternRegexPattern:(NSString *)regex {
    return [self vv_matchesPatternRegexPattern:regex caseInsensitive:NO treatAsOneLine:NO];
}

@end


================================================
FILE: VVDocumenter-Xcode/OCCategory/NSString+VVSyntax/NSString+VVSyntax.h
================================================
//
//  NSString+VVSyntax.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-18.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Foundation/Foundation.h>

@interface NSString (VVSyntax)
-(NSString *) vv_stringByConvertingToUniform;
-(NSString *) vv_stringByTrimEndSpaces;

-(BOOL) vv_isObjCMethod;
-(BOOL) vv_isProperty;
-(BOOL) vv_isCFunction;
-(BOOL) vv_isMacro;
-(BOOL) vv_isEnum;
-(BOOL) vv_isStruct;
-(BOOL) vv_isUnion;
-(BOOL) vv_isComplieKeyword;
-(BOOL) vv_isSwiftFunction;
-(BOOL) vv_isSwiftEnum;
-(BOOL) vv_isSwiftProperty;
-(BOOL) vv_isSwiftExtension;

@end

================================================
FILE: VVDocumenter-Xcode/OCCategory/NSString+VVSyntax/NSString+VVSyntax.m
================================================
//
//  NSString+VVSyntax.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-18.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "NSString+VVSyntax.h"

@implementation NSString (VVSyntax)
-(NSString *) vv_stringByConvertingToUniform
{
    return [[[self vv_stringByReplacingRegexPattern:@"\\s*\\("    withString:@"("]
                   vv_stringByReplacingRegexPattern:@"\\)\\s*"    withString:@")"]
                   vv_stringByReplacingRegexPattern:@"\\s*\n\\s*" withString:@" "];
}

-(NSString *) vv_stringByTrimEndSpaces
{
    return [self vv_stringByReplacingRegexPattern:@"\\s*\n" withString:@"\n"];
}

-(BOOL) vv_isObjCMethod
{
    return [self vv_matchesPatternRegexPattern:@"^\\s*[+-]"];
}

-(BOOL) vv_isCFunction
{
    return ![self vv_isEnum] &&
           ![self vv_isMacro] &&
           ![self vv_isObjCMethod] &&
           ![self vv_isProperty] &&
           ![self vv_isComplieKeyword] &&
           ![self vv_isSwiftFunction] &&
           ![self vv_isSwiftEnum] &&
           ![self vv_isSwiftProperty] &&
           [self vv_matchesPatternRegexPattern:@".+\\s+.+\\("];
}

-(BOOL) vv_isProperty
{
	return [self vv_matchesPatternRegexPattern:@"^\\s*\\@property"];
}

-(BOOL) vv_isMacro
{
    return [self vv_matchesPatternRegexPattern:@"^\\s*\\#define"];
}

-(BOOL) vv_isStruct
{
    return [self vv_matchesPatternRegexPattern:@"^\\s*(\\w+\\s)?struct.*\\{"];
}

-(BOOL) vv_isEnum
{
    return [self vv_matchesPatternRegexPattern:@"^\\s*(\\w+\\s+)?NS_(ENUM|OPTIONS)\\b"];
}

-(BOOL) vv_isUnion
{
    return [self vv_matchesPatternRegexPattern:@"^\\s*(\\w+\\s)?union.*\\{"];
}

-(BOOL) vv_isComplieKeyword
{
    return ![self vv_isProperty] && [self vv_matchesPatternRegexPattern:@"^\\s*\\@"];
}

-(BOOL) vv_isSwiftFunction
{
    return ![self vv_isObjCMethod] && ![self vv_isSwiftProperty] && [self vv_matchesPatternRegexPattern:@"^\\s*(.*\\s+)?(func\\s+)|(init|deinit|subscript)"];
}

-(BOOL) vv_isSwiftEnum
{
    return ![self vv_isSwiftProperty] && [self vv_matchesPatternRegexPattern:@"^\\s*(.*\\s+)?enum\\s+"];
}

-(BOOL) vv_isSwiftProperty
{
    // Opt out the situation of `class func`
    if ([self vv_matchesPatternRegexPattern:@"class func"]) {
        return NO;
    }
    
    // `let`/`var` can be in swift func, but `(` appear before `let`/`var` only
    // happens when `private(set)` or `internal(set)` is used
    // typealias is considered to share the same comment as property.
    return [self vv_matchesPatternRegexPattern:@"^\\s*([^(]*?)(((\\s*let|var|typealias|class\\s*)\\s+)|(\\(\\s*set\\s*\\)))"];
}

-(BOOL) vv_isSwiftExtension
{
    return [self vv_matchesPatternRegexPattern:@"^\\s*(.*\\s+)?extension\\s+"];
}

@end


================================================
FILE: VVDocumenter-Xcode/OCCategory/NSString+VVTextGetter/NSString+VVTextGetter.h
================================================
//
//  NSString+VVTextGetter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 14-7-31.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Foundation/Foundation.h>

@class VVTextResult;

@interface NSString (VVTextGetter)

-(VVTextResult *) vv_textResultOfCurrentLineCurrentLocation:(NSInteger)location;

-(VVTextResult *) vv_textResultOfPreviousLineCurrentLocation:(NSInteger)location;

-(VVTextResult *) vv_textResultOfNextLineCurrentLocation:(NSInteger)location;

-(VVTextResult *) vv_textResultUntilNextString:(NSString *)findString currentLocation:(NSInteger)location;

-(VVTextResult *) vv_textResultWithPairOpenString:(NSString *)open
                                      closeString:(NSString *)close
                                  currentLocation:(NSInteger)location;

-(VVTextResult *) vv_textResultMatchPartWithPairOpenString:(NSString *)open
                                            closeString:(NSString *)close
                                        currentLocation:(NSInteger)location;

-(VVTextResult *) vv_textResultToEndOfFileCurrentLocation:(NSInteger)location;
@end


================================================
FILE: VVDocumenter-Xcode/OCCategory/NSString+VVTextGetter/NSString+VVTextGetter.m
================================================
//
//  NSString+VVTextGetter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 14-7-31.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "NSString+VVTextGetter.h"
#import "VVTextResult.h"

@implementation NSString (VVTextGetter)

-(VVTextResult *) vv_textResultOfCurrentLineCurrentLocation:(NSInteger)location
{
    NSInteger curseLocation = location;
    NSRange range = NSMakeRange(0, curseLocation);
    NSRange thisLineRange = [self rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch range:range];
    
    NSString *line = nil;
    if (thisLineRange.location != NSNotFound) {
        NSRange lineRange = NSMakeRange(thisLineRange.location + 1, curseLocation - thisLineRange.location - 1);
        if (lineRange.location < [self length] && NSMaxRange(lineRange) < [self length]) {
            line = [self substringWithRange:lineRange];
            return [[VVTextResult alloc] initWithRange:lineRange string:line];
        } else {
            return nil;
        }
    } else {
        return nil;
    }
}


-(VVTextResult *) vv_textResultOfPreviousLineCurrentLocation:(NSInteger)location
{
    NSInteger curseLocation = location;
    NSRange range = NSMakeRange(0, curseLocation);
    NSRange thisLineRange = [self rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch range:range];
    
    NSString *line = nil;
    if (thisLineRange.location != NSNotFound) {
        range = NSMakeRange(0, thisLineRange.location);
        NSRange previousLineRange = [self rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch range:range];
        
        if (previousLineRange.location != NSNotFound) {
            NSRange lineRange = NSMakeRange(previousLineRange.location + 1, thisLineRange.location - previousLineRange.location);
            if (lineRange.location < [self length] && NSMaxRange(lineRange) < [self length]) {
                line = [self substringWithRange:lineRange];
                return [[VVTextResult alloc] initWithRange:lineRange string:line];
            } else {
                return nil;
            }
        } else {
            return nil;
        }
    } else {
        return nil;
    }
}

-(VVTextResult *) vv_textResultOfNextLineCurrentLocation:(NSInteger)location
{
    NSInteger curseLocation = location;
    NSRange range = NSMakeRange(curseLocation, self.length - curseLocation);
    NSRange thisLineRange = [self rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:0 range:range];
    
    NSString *line = nil;
    if (thisLineRange.location != NSNotFound) {
        range = NSMakeRange(thisLineRange.location + 1, self.length - thisLineRange.location - 1);
        NSRange nextLineRange = [self rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:0 range:range];
        
        if (nextLineRange.location != NSNotFound) {
            NSRange lineRange = NSMakeRange(thisLineRange.location + 1, NSMaxRange(nextLineRange) - NSMaxRange(thisLineRange));
            if (lineRange.location < [self length] && NSMaxRange(lineRange) < [self length]) {
                line = [self substringWithRange:lineRange];
                return [[VVTextResult alloc] initWithRange:lineRange string:line];
            } else {
                return nil;
            }
        } else {
            return nil;
        }
    } else {
        return nil;
    }
}

-(VVTextResult *) vv_textResultUntilNextString:(NSString *)findString currentLocation:(NSInteger)location
{
    NSInteger curseLocation = location;
    
    NSRange range = NSMakeRange(curseLocation, self.length - curseLocation);
    NSRange nextLineRange = [self rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:0 range:range];
    NSRange rangeToString = [self rangeOfString:findString options:0 range:range];
    
    NSString *line = nil;
    if (nextLineRange.location != NSNotFound && rangeToString.location != NSNotFound && nextLineRange.location <= rangeToString.location) {
        NSRange lineRange = NSMakeRange(nextLineRange.location + 1, rangeToString.location - nextLineRange.location);
        if (lineRange.location < [self length] && NSMaxRange(lineRange) <= [self length]) {
            line = [self substringWithRange:lineRange];
            return [[VVTextResult alloc] initWithRange:lineRange string:line];
        } else {
            return nil;
        }
    } else {
        return nil;
    }
}

-(VVTextResult *) vv_textResultMatchPartWithPairOpenString:(NSString *)open
                                            closeString:(NSString *)close
                                        currentLocation:(NSInteger)location
{
    return [self textResultWithPairOpenString:open closeString:close currentLocation:location extractMatch:YES];
}

-(VVTextResult *) vv_textResultWithPairOpenString:(NSString *)open
                                   closeString:(NSString *)close
                               currentLocation:(NSInteger)location
{
    return [self textResultWithPairOpenString:open closeString:close currentLocation:location extractMatch:NO];
}

-(VVTextResult *) vv_textResultToEndOfFileCurrentLocation:(NSInteger)location
{
    NSRange range = NSMakeRange(location, self.length - location);
    VVTextResult *result = [[VVTextResult alloc] initWithRange:range string:[self substringWithRange:range]];
    return result;
}

-(VVTextResult *) textResultWithPairOpenString:(NSString *)open
                                   closeString:(NSString *)close
                               currentLocation:(NSInteger)location
                                  extractMatch:(BOOL)extract
{
    // Find all content from current positon to the last paired scope. Useful when pairing `{}` or `()`
    NSInteger curseLocation = location;
    
    NSRange range = NSMakeRange(curseLocation, self.length - curseLocation);
    
    // searchRange will be updated to new range later, for search the next open/close token.
    NSRange searchRange = range;
    VVLog(@"Begin Search Range: %lu, %lu", (unsigned long)searchRange.location, (unsigned long)searchRange.length);
    
    NSInteger openCount = 0;
    NSInteger closeCount = 0;
    
    NSRange nextOpenRange = [self rangeOfString:open options:0 range:searchRange];
    NSRange nextCloseRange = [self rangeOfString:close options:0 range:searchRange];
    
    NSRange firstOpenRange = nextOpenRange;
    
    // Not even open. Early return
    if (nextOpenRange.location == NSNotFound || nextCloseRange.location == NSNotFound || nextCloseRange.location < nextOpenRange.location) {
        return nil;
    }
    
    openCount++;
    
    // Update the search range: from current token to the end.
    searchRange = NSMakeRange(nextOpenRange.location + 1, self.length - nextOpenRange.location - 1);
    VVLog(@"Update Search Range: %lu, %lu", (unsigned long)searchRange.location, (unsigned long)searchRange.length);
    
    // Try to find the scope by pairing open and close count
    NSRange targetRange = NSMakeRange(0,0);
    while (openCount != closeCount) {
        // Get next open and close token location
        nextOpenRange = [self rangeOfString:open options:0 range:searchRange];
        nextCloseRange = [self rangeOfString:close options:0 range:searchRange];
        
        // No new close token. This scope will not close.
        if (nextCloseRange.location == NSNotFound) {
            return nil;
        }
        
        if (nextOpenRange.location < nextCloseRange.location) {
            targetRange = nextOpenRange;
            openCount++;
        } else {
            targetRange = nextCloseRange;
            closeCount++;
        }
        
        VVLog(@"Open:%ld, Close:%ld",(long)openCount,(long)closeCount);
        // Update the search range: from current token to the end.
        searchRange = NSMakeRange(targetRange.location + 1, self.length - targetRange.location - 1);
        VVLog(@"Target Range: %lu, %lu",targetRange.location,targetRange.length);
        VVLog(@"Update Search Range: %lu, %lu", (unsigned long)searchRange.location, (unsigned long)searchRange.length);
    }
    
    NSRange resultRange;
    if (extract) {
        resultRange = NSMakeRange(firstOpenRange.location, targetRange.location - firstOpenRange.location + 1);
    } else {
        // Extract the code need to be documented. From next line to the matched scope end.
        NSRange nextLineRange = [self rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:0 range:range];
        resultRange = NSMakeRange(nextLineRange.location + 1, targetRange.location - nextLineRange.location);
    }
    
    if (resultRange.location < [self length] && NSMaxRange(resultRange) <= [self length]) {
        NSString *result = [self substringWithRange:resultRange];
        return [[VVTextResult alloc] initWithRange:resultRange string:result];
    } else {
        return nil;
    }
    
}
@end


================================================
FILE: VVDocumenter-Xcode/OCCategory/NSTextView+VVTextGetter/NSTextView+VVTextGetter.h
================================================
//
//  NSTextView+VVTextGetter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Cocoa/Cocoa.h>

@class VVTextResult;

@interface NSTextView (VVTextGetter)
-(NSInteger) vv_currentCurseLocation;

-(VVTextResult *) vv_textResultOfCurrentLine;

-(VVTextResult *) vv_textResultOfPreviousLine;

-(VVTextResult *) vv_textResultOfNextLine;

-(VVTextResult *) vv_textResultUntilNextString:(NSString *)findString;

-(VVTextResult *) vv_textResultWithPairOpenString:(NSString *)open closeString:(NSString *)close;

-(VVTextResult *) vv_textResultToEndOfFile;
@end


================================================
FILE: VVDocumenter-Xcode/OCCategory/NSTextView+VVTextGetter/NSTextView+VVTextGetter.m
================================================
//
//  NSTextView+VVTextGetter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "NSTextView+VVTextGetter.h"
#import "VVTextResult.h"
#import "NSString+VVTextGetter.h"

@implementation NSTextView (VVTextGetter)
-(NSInteger) vv_currentCurseLocation
{
    return [[[self selectedRanges] objectAtIndex:0] rangeValue].location;
}

-(VVTextResult *) vv_textResultOfCurrentLine
{
    return [self.textStorage.string vv_textResultOfCurrentLineCurrentLocation:[self vv_currentCurseLocation]];
}

-(VVTextResult *) vv_textResultOfPreviousLine
{
    return [self.textStorage.string vv_textResultOfPreviousLineCurrentLocation:[self vv_currentCurseLocation]];
}

-(VVTextResult *) vv_textResultOfNextLine
{
    return [self.textStorage.string vv_textResultOfNextLineCurrentLocation:[self vv_currentCurseLocation]];
}

-(VVTextResult *) vv_textResultUntilNextString:(NSString *)findString
{
    return [self.textStorage.string vv_textResultUntilNextString:findString currentLocation:[self vv_currentCurseLocation]];
}

-(VVTextResult *) vv_textResultWithPairOpenString:(NSString *)open closeString:(NSString *)close
{
    return [self.textStorage.string vv_textResultWithPairOpenString:open closeString:close currentLocation:[self vv_currentCurseLocation]];
}

-(VVTextResult *) vv_textResultToEndOfFile
{
    return [self.textStorage.string vv_textResultToEndOfFileCurrentLocation:[self vv_currentCurseLocation]];
}

@end


================================================
FILE: VVDocumenter-Xcode/OCCategory/VVTextResult.h
================================================
//
//  VVTextResult.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 14-7-31.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Foundation/Foundation.h>

@interface VVTextResult : NSObject

@property (nonatomic, assign) NSRange range;
@property (nonatomic, copy) NSString *string;

-(instancetype) initWithRange:(NSRange)aRange string:(NSString *)aString;

@end


================================================
FILE: VVDocumenter-Xcode/OCCategory/VVTextResult.m
================================================
//
//  VVTextResult.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 14-7-31.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVTextResult.h"

@implementation VVTextResult

-(instancetype) initWithRange:(NSRange)aRange string:(NSString *)aString

{
    self = [super init];
    if (self) {
        _range = aRange;
        _string = aString;
    }
    return self;
}

-(NSString *)description
{
    return [NSString stringWithFormat:@"Location:%ld, Length:%ld, String:%@",self.range.location,self.range.length,self.string];
}

@end

================================================
FILE: VVDocumenter-Xcode/ProjectHelper/VVProject.h
================================================
//
//  VVProject.h
//  VVDocumenter-Xcode
//
//  Created by 夏天味道 on 15/6/25.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Foundation/Foundation.h>

@interface VVProject : NSObject

@property (nonatomic, copy) NSString     *directoryPath;

@property (nonatomic,copy,readonly) NSString     *workspacePath;

@property (nonatomic, copy) NSString     *projectName;

@property (nonatomic, copy) NSDictionary *infoDictionary;

@property (nonatomic, copy) NSString     *projectVersion;

@property (nonatomic,copy) NSDictionary *pbxprojDictionary;

@property (nonatomic,copy) NSString     *organizeationName;


+ (instancetype)projectForKeyWindow;

@end


================================================
FILE: VVDocumenter-Xcode/ProjectHelper/VVProject.m
================================================
//
//  VVProject.m
//  VVDocumenter-Xcode
//
//  Created by 夏天味道 on 15/6/25.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVProject.h"
#import "VVWorkspaceManager.h"

@implementation VVProject

+ (instancetype)projectForKeyWindow
{
    id workspace = [VVWorkspaceManager workspaceForKeyWindow];
    
    id contextManager = [workspace valueForKey:@"_runContextManager"];
    
    for (id scheme in[contextManager valueForKey:@"runContexts"]) {
        NSString *schemeName = [scheme valueForKey:@"name"];
        if (![schemeName hasPrefix:@"Pods-"]) {
            NSString *path = [VVWorkspaceManager directoryPathForWorkspace:workspace];
            return [[VVProject alloc] initWithName:schemeName path:path];
        }
    }
    
    return nil;
}

- (id)initWithName:(NSString *)name
              path:(NSString *)path
{
    if (self = [self init]) {
        _projectName = name;
        _directoryPath = path;
        
        
        NSString *pbxprojPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.xcodeproj/project.pbxproj",name]];
        _pbxprojDictionary = [NSDictionary dictionaryWithContentsOfFile:pbxprojPath];
        
        
        
        _organizeationName = [self getOrganizeationName];
        NSString *infoplistName = [self infoplistNameWithAtScheme:name];
        
        NSString *infoPath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@", infoplistName]];
        
        
        _infoDictionary = [NSDictionary dictionaryWithContentsOfFile:infoPath];
        
        _projectVersion = self.infoDictionary[@"CFBundleShortVersionString"];
    }
    
    return self;
}

-(NSString *)getOrganizeationName{
    NSDictionary *objects = [_pbxprojDictionary objectForKey:@"objects"];
    NSString *rootObjectId = [_pbxprojDictionary objectForKey:@"rootObject"];
    
    NSDictionary *pbxProjectDic = [objects objectForKey:rootObjectId];
    NSDictionary *attributes = [pbxProjectDic objectForKey:@"attributes"];
    NSString *organizeationName = [attributes objectForKey:@"ORGANIZATIONNAME"];
    return organizeationName;
}

-(NSString *)infoplistNameWithAtScheme:(NSString *)currentSchemeName{
    NSDictionary *objects = [_pbxprojDictionary objectForKey:@"objects"];
    NSString *rootObjectId = [_pbxprojDictionary objectForKey:@"rootObject"];
    
    NSDictionary *pbxProjectDic = [objects objectForKey:rootObjectId];
    NSArray *targetIds = [pbxProjectDic objectForKey:@"targets"];
    NSString *currentTargetId;
    for (NSString *targetId in targetIds) {
        NSDictionary *targetDic = [objects objectForKey:targetId];
        NSString *targetName = [targetDic objectForKey:@"name"];
        if ([targetName isEqualToString:currentSchemeName]) {
            currentTargetId = targetId;
            break;
        }
    }
    if (!currentTargetId) {
        currentTargetId = [targetIds firstObject];
    }
    
    NSDictionary *targetDic = [objects objectForKey:currentTargetId];
    NSString *buildConfigurationListId = [targetDic objectForKey:@"buildConfigurationList"];
    
    NSDictionary *buildConfigurationListDic = [objects objectForKey:buildConfigurationListId];
    NSArray *buildConfigurationIds = [buildConfigurationListDic objectForKey:@"buildConfigurations"];
    
    NSString *debugBuildConfigurationId;
    for (NSString *buildConfigurationId in buildConfigurationIds) {
        NSDictionary *buildConfigurationDic = [objects objectForKey:buildConfigurationId];
        NSString *name = [buildConfigurationDic objectForKey:@"name"];
        if ([name isEqualToString:@"Debug"]) {
            debugBuildConfigurationId = buildConfigurationId;
            break;
        }
    }
    if (!debugBuildConfigurationId) {
        debugBuildConfigurationId = [buildConfigurationIds firstObject];
    }
    
    NSDictionary *buildConfigurationDic = [objects objectForKey:debugBuildConfigurationId];
    NSDictionary *buildSettings = [buildConfigurationDic objectForKey:@"buildSettings"];
    NSString *infoplistName = [buildSettings objectForKey:@"INFOPLIST_FILE"];
    return infoplistName;
}

@end


================================================
FILE: VVDocumenter-Xcode/ProjectHelper/VVWorkspaceManager.h
================================================
//
//  VVWorkspaceManager.h
//  VVDocumenter-Xcode
//
//  Created by 夏天味道 on 15/6/25.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Foundation/Foundation.h>

@interface VVWorkspaceManager : NSObject

+ (id)workspaceForKeyWindow;

+ (NSString *)currentWorkspaceDirectoryPath;
+ (NSString *)directoryPathForWorkspace:(id)workspace;

@end


================================================
FILE: VVDocumenter-Xcode/ProjectHelper/VVWorkspaceManager.m
================================================
//
//  VVWorkspaceManager.m
//  VVDocumenter-Xcode
//
//  Created by 夏天味道 on 15/6/25.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVWorkspaceManager.h"

@implementation VVWorkspaceManager

+ (NSString *)currentWorkspaceDirectoryPath
{
    return [self directoryPathForWorkspace:[self workspaceForKeyWindow]];
}

+ (NSString *)directoryPathForWorkspace:(id)workspace
{
    NSString *workspacePath = [[workspace valueForKey:@"representingFilePath"] valueForKey:@"_pathString"];
    return [workspacePath stringByDeletingLastPathComponent];
}

#pragma mark - Private

+ (id)workspaceForKeyWindow
{
    return [self workspaceForWindow:[NSApp keyWindow]];
}

+ (id)workspaceForWindow:(NSWindow *)window
{
    NSArray *workspaceWindowControllers = [NSClassFromString(@"IDEWorkspaceWindowController") valueForKey:@"workspaceWindowControllers"];
    
    for (id controller in workspaceWindowControllers) {
        if ([[controller valueForKey:@"window"] isEqual:window]) {
            return [controller valueForKey:@"_workspace"];
        }
    }
    return nil;
}

@end


================================================
FILE: VVDocumenter-Xcode/Setting/VVDSettingPanelWindowController.h
================================================
//
//  VVDSettingPanelWindowController.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-8-3.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Cocoa/Cocoa.h>

@interface VVDSettingPanelWindowController : NSWindowController

@end


================================================
FILE: VVDocumenter-Xcode/Setting/VVDSettingPanelWindowController.m
================================================
//
//  VVDSettingPanelWindowController.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-8-3.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVDSettingPanelWindowController.h"
#import "VVDocumenterSetting.h"

@interface VVDSettingPanelWindowController ()<NSTextFieldDelegate>
@property (weak) IBOutlet NSTextField *tfTrigger;
@property (weak) IBOutlet NSButton *btnUseSpaces;
@property (weak) IBOutlet NSTextField *tfSpaceCount;
@property (weak) IBOutlet NSTextField *tfSpaceLabel;

@property (weak) IBOutlet NSStepper *stepperCount;

@property (weak) IBOutlet NSMatrix *mtxSinceOptions;
@property (weak) IBOutlet NSMatrix *mtxPrefixOptions;
@property (weak) IBOutlet NSButtonCell *btnPrefixWithWhitespace;
@property (weak) IBOutlet NSButtonCell *btnPrefixWithStar;
@property (weak) IBOutlet NSButtonCell *btnPrefixWithSlashes;
@property (weak) IBOutlet NSButton *btnAddSinceToComment;
@property (weak) IBOutlet NSButton *btnBriefDescription;
@property (weak) IBOutlet NSButton *btnUseHeaderDoc;
@property (weak) IBOutlet NSButton *btnBlankLinesBetweenSections;
@property (weak) IBOutlet NSButton *btnAlightArgumentComments;
@property (weak) IBOutlet NSButton *btnUseAuthorInformation;
@property (weak) IBOutlet NSButton *btnUseDateInformation;
@property (weak) IBOutlet NSTextField *tfAuthoInformation;
@property (weak) IBOutlet NSTextField *tfDateInformaitonFormat;
@property (weak) IBOutlet NSTextField *tfSinceVersion;

@end

@implementation VVDSettingPanelWindowController

- (instancetype)initWithWindow:(NSWindow *)window
{
    self = [super initWithWindow:window];
    if (self) {
        // Initialization code here.
    }

    return self;
}

- (void)windowDidLoad
{
    [super windowDidLoad];

    // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
    [self.tfTrigger setStringValue:[[VVDocumenterSetting defaultSetting] triggerString]];
    self.btnUseSpaces.state = (NSCellStateValue)[[VVDocumenterSetting defaultSetting] useSpaces];

    self.btnAddSinceToComment.state = (NSCellStateValue)[[VVDocumenterSetting defaultSetting] addSinceToComments];
    self.mtxSinceOptions.enabled = [[VVDocumenterSetting defaultSetting] addSinceToComments];
    [self.mtxSinceOptions selectCellAtRow:(NSInteger)[[VVDocumenterSetting defaultSetting] sinceOption] column:0];
    self.tfSinceVersion.enabled = [[VVDocumenterSetting defaultSetting] addSinceToComments];
    self.tfSinceVersion.stringValue = [[VVDocumenterSetting defaultSetting] sinceVersion];

    self.btnBriefDescription.state = (NSCellStateValue)[[VVDocumenterSetting defaultSetting] briefDescription];
    self.btnUseHeaderDoc.state = (NSCellStateValue)[[VVDocumenterSetting defaultSetting] useHeaderDoc];
    self.btnBlankLinesBetweenSections.state = (NSCellStateValue)[[VVDocumenterSetting defaultSetting] blankLinesBetweenSections];
    self.btnAlightArgumentComments.state = (NSCellStateValue)[[VVDocumenterSetting defaultSetting] alignArgumentComments];
    self.btnUseAuthorInformation.state = (NSCellStateValue)[[VVDocumenterSetting defaultSetting] useAuthorInformation];
    self.tfAuthoInformation.stringValue = [[VVDocumenterSetting defaultSetting] authorInformation];
    self.btnUseDateInformation.state = (NSCellStateValue)[[VVDocumenterSetting defaultSetting] useDateInformation];
    self.tfDateInformaitonFormat.stringValue = [[VVDocumenterSetting defaultSetting] dateInformationFormat];
    
    if ([[VVDocumenterSetting defaultSetting] prefixWithStar]) {
        [self.mtxPrefixOptions selectCell:self.btnPrefixWithStar];
    } else if ([[VVDocumenterSetting defaultSetting] prefixWithSlashes]) {
        [self.mtxPrefixOptions selectCell:self.btnPrefixWithSlashes];
    } else {
        [self.mtxPrefixOptions selectCell:self.btnPrefixWithWhitespace];
    }

    // Disable the slashes prefix option for HeaderDoc comments
    if (self.btnUseHeaderDoc.state == NSOnState) {
        self.btnPrefixWithSlashes.enabled = NO;
    }

    [self updateUseSpace:self.btnUseSpaces.state];
    [self syncSpaceCount];

    self.tfTrigger.delegate = self;
    self.tfDateInformaitonFormat.delegate = self;
    self.tfAuthoInformation.delegate = self;
    self.tfSinceVersion.delegate = self;
}

- (IBAction)stepperPressed:(id)sender {
    [[VVDocumenterSetting defaultSetting] setSpaceCount:self.stepperCount.integerValue];
    [self syncSpaceCount];
}

- (IBAction)btnResetPressed:(id)sender {
    [[VVDocumenterSetting defaultSetting] setUseSpaces:YES];
    [[VVDocumenterSetting defaultSetting] setTriggerString:VVDDefaultTriggerString];
    [[VVDocumenterSetting defaultSetting] setSpaceCount:2];
    [[VVDocumenterSetting defaultSetting] setPrefixWithStar:YES];
    [[VVDocumenterSetting defaultSetting] setPrefixWithSlashes:NO];
    [[VVDocumenterSetting defaultSetting] setAddSinceToComments:NO];
    [[VVDocumenterSetting defaultSetting] setSinceVersion:@""];
    [[VVDocumenterSetting defaultSetting] setBriefDescription:NO];
    [[VVDocumenterSetting defaultSetting] setUseHeaderDoc:NO];
    [[VVDocumenterSetting defaultSetting] setBlankLinesBetweenSections:YES];
    [[VVDocumenterSetting defaultSetting] setAlignArgumentComments:YES];
    [[VVDocumenterSetting defaultSetting] setUseAuthorInformation:NO];
    [[VVDocumenterSetting defaultSetting] setAuthorInformation:VVDDefaultAuthorString];
    [[VVDocumenterSetting defaultSetting] setUseDateInformation:NO];
    [[VVDocumenterSetting defaultSetting] setDateInformationFormat:VVDDefaultDateInfomationFormat];
    
    self.btnUseSpaces.state = NSOnState;
    [self updateUseSpace:self.btnUseSpaces.state];
    self.btnPrefixWithWhitespace.state = NSOffState;
    self.btnPrefixWithStar.state = NSOnState;
    self.btnPrefixWithSlashes.state = NSOffState;
    self.btnAddSinceToComment.state = NSOffState;
    self.tfSinceVersion.enabled = NO;
    self.mtxSinceOptions.enabled = NO;
    self.btnBriefDescription.state = NSOffState;
    [self.tfTrigger setStringValue:VVDDefaultTriggerString];
    self.btnUseHeaderDoc.state = NSOffState;
    self.btnBlankLinesBetweenSections.state = NSOnState;
    self.btnAlightArgumentComments.state = NSOnState;
    self.btnUseAuthorInformation.state = NSOffState;
    self.tfAuthoInformation.stringValue = VVDDefaultAuthorString;
    self.btnUseDateInformation.state = NSOffState;
    self.tfDateInformaitonFormat.stringValue = VVDDefaultDateInfomationFormat;
    
    self.btnPrefixWithSlashes.enabled = YES;

    [self syncSpaceCount];

}

- (IBAction)mtxSinceOptionPressed:(id)sender {
    VVDSinceOption option = self.mtxSinceOptions.selectedRow;
    [[VVDocumenterSetting defaultSetting] setSinceOption:option];
}

- (IBAction)btnUseSpacesPressed:(id)sender {
    [[VVDocumenterSetting defaultSetting] setUseSpaces:self.btnUseSpaces.state];
    [self updateUseSpace:self.btnUseSpaces.state];
}

- (IBAction)mtxPrefixSettingPressed:(id)sender {
    id selectedCell = self.mtxPrefixOptions.selectedCell;

    [[VVDocumenterSetting defaultSetting] setPrefixWithStar:[selectedCell isEqual:self.btnPrefixWithStar]];
    [[VVDocumenterSetting defaultSetting] setPrefixWithSlashes:[selectedCell isEqual:self.btnPrefixWithSlashes]];
}

- (IBAction)btnAddSinceToCommentsPressed:(id)sender {
    BOOL enableSince = self.btnAddSinceToComment.state;
    [[VVDocumenterSetting defaultSetting] setAddSinceToComments:enableSince];
    self.tfSinceVersion.enabled = enableSince;
    self.mtxSinceOptions.enabled = enableSince;
}

- (IBAction)btnBriefDescriptionPressed:(id)sender {
    [[VVDocumenterSetting defaultSetting] setBriefDescription:self.btnBriefDescription.state];
}

- (IBAction)btnUseAuthorInformationPressed:(id)sender {
    [[VVDocumenterSetting defaultSetting] setUseAuthorInformation:self.btnUseAuthorInformation.state];
}

- (IBAction)btnUseDateInformationPressed:(id)sender {
    [[VVDocumenterSetting defaultSetting] setUseDateInformation:self.btnUseDateInformation.state];
}

-(void) syncSpaceCount
{
    NSInteger spaceCount = [[VVDocumenterSetting defaultSetting] spaceCount];
    [self.tfSpaceCount setIntegerValue:spaceCount];
    [self.stepperCount setIntegerValue:spaceCount];
}

-(void) updateUseSpace:(BOOL)useSpace
{
    [self.tfSpaceCount setEnabled:useSpace];
    [self.stepperCount setEnabled:useSpace];
    self.tfSpaceLabel.textColor = useSpace ? [NSColor blackColor] : [NSColor grayColor];
}

- (void)controlTextDidChange:(NSNotification *)notification
{
    if([notification object] == self.tfTrigger) {
        [[VVDocumenterSetting defaultSetting] setTriggerString:self.tfTrigger.stringValue];
    }
    if([notification object] == self.tfAuthoInformation) {
        [[VVDocumenterSetting defaultSetting] setAuthorInformation:self.tfAuthoInformation.stringValue];
    }
    if([notification object] == self.tfDateInformaitonFormat) {
        [[VVDocumenterSetting defaultSetting] setDateInformationFormat:self.tfDateInformaitonFormat.stringValue];
    }
    if ([notification object] == self.tfSinceVersion) {
        [[VVDocumenterSetting defaultSetting] setSinceVersion:self.tfSinceVersion.stringValue];
    }
}

- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
{
    if (control == self.tfTrigger) {
        if (self.tfTrigger.stringValue.length == 0) {
            [self.tfTrigger setStringValue:VVDDefaultTriggerString];
        }
    }
    return YES;
}

- (IBAction)useHeaderDoc:(id)sender {
    [[VVDocumenterSetting defaultSetting] setUseHeaderDoc:self.btnUseHeaderDoc.state];

    if (self.btnUseHeaderDoc.state == NSOnState) {
        self.btnPrefixWithSlashes.enabled = NO;

        // If the slashes option was selected, change to the default stars
        if ([self.mtxPrefixOptions.selectedCell isEqual:self.btnPrefixWithSlashes]) {
            [self.mtxPrefixOptions selectCell:self.btnPrefixWithStar];

            // Update the settings in addition to the display
            [self.mtxPrefixOptions sendAction];
        }
    } else {
        self.btnPrefixWithSlashes.enabled = YES;
    }
}
- (IBAction)blankLinesBetweenSections:(id)sender {
    [[VVDocumenterSetting defaultSetting] setBlankLinesBetweenSections:self.btnBlankLinesBetweenSections.state];
}

- (IBAction)alignArgumentComments:(id)sender {
    [[VVDocumenterSetting defaultSetting] setAlignArgumentComments:self.btnAlightArgumentComments.state];
}

@end


================================================
FILE: VVDocumenter-Xcode/Setting/VVDSettingPanelWindowController.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
    <dependencies>
        <deployment identifier="macosx"/>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
    </dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner" customClass="VVDSettingPanelWindowController">
            <connections>
                <outlet property="btnAddSinceToComment" destination="ERW-1g-i3X" id="1ef-Mr-TVa"/>
                <outlet property="btnAlightArgumentComments" destination="g3M-cK-u5v" id="l9g-ge-CwY"/>
                <outlet property="btnBlankLinesBetweenSections" destination="6ax-Nw-Bq5" id="vCY-7n-Xqh"/>
                <outlet property="btnBriefDescription" destination="gfy-6Z-t8f" id="oHc-uk-ERk"/>
                <outlet property="btnDefaultPlaceholder" destination="3Uj-1c-BzU" id="TeO-Jj-IsJ"/>
                <outlet property="btnPrefixWithSlashes" destination="IVu-o3-DBW" id="GJD-9u-PLJ"/>
                <outlet property="btnPrefixWithStar" destination="vMT-lx-3Ep" id="JBV-hz-QfR"/>
                <outlet property="btnPrefixWithWhitespace" destination="mxJ-X3-ycD" id="oIB-Va-SeQ"/>
                <outlet property="btnProjectVersion" destination="pSZ-Vj-hkT" id="OIF-HV-I6g"/>
                <outlet property="btnSpecificVersion" destination="PbN-ts-AYz" id="21F-j3-SGO"/>
                <outlet property="btnUseAuthorInformation" destination="yp5-mf-NgJ" id="Pqf-GX-Avo"/>
                <outlet property="btnUseDateInformation" destination="b6P-6I-DiH" id="s02-Tx-jGJ"/>
                <outlet property="btnUseHeaderDoc" destination="bgb-aQ-BAa" id="wor-rz-Ijg"/>
                <outlet property="btnUseSpaces" destination="9" id="37"/>
                <outlet property="mtxPrefixOptions" destination="9MP-VX-rsW" id="pMl-hs-b8d"/>
                <outlet property="mtxSinceOptions" destination="F04-TF-nUJ" id="uSS-BQ-O3Z"/>
                <outlet property="stepperCount" destination="54" id="57"/>
                <outlet property="tfAuthoInformation" destination="zua-Qs-tG6" id="as9-qR-Eq1"/>
                <outlet property="tfDateInformaitonFormat" destination="L0g-BX-Fh0" id="df2-hk-v5B"/>
                <outlet property="tfSinceVersion" destination="lQp-YM-3hX" id="Xj0-Zg-bCx"/>
                <outlet property="tfSpaceCount" destination="30" id="38"/>
                <outlet property="tfSpaceLabel" destination="16" id="53"/>
                <outlet property="tfTrigger" destination="26" id="36"/>
                <outlet property="window" destination="1" id="3"/>
            </connections>
        </customObject>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <customObject id="-3" userLabel="Application"/>
        <window title="VVDocumenter Setting" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" animationBehavior="default" id="1">
            <windowStyleMask key="styleMask" titled="YES" closable="YES"/>
            <rect key="contentRect" x="20" y="40" width="463" height="586"/>
            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
            <view key="contentView" id="2">
                <rect key="frame" x="0.0" y="0.0" width="463" height="586"/>
                <autoresizingMask key="autoresizingMask"/>
                <subviews>
                    <button id="9">
                        <rect key="frame" x="67" y="460" width="212" height="35"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <buttonCell key="cell" type="check" title="Use spaces instead of tabs" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="10">
                            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                            <font key="font" metaFont="system"/>
                        </buttonCell>
                        <connections>
                            <action selector="btnUseSpacesPressed:" target="-2" id="51"/>
                        </connections>
                    </button>
                    <textField verticalHuggingPriority="750" id="16">
                        <rect key="frame" x="329" y="469" width="60" height="17"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="spaces" id="17">
                            <font key="font" metaFont="system"/>
                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                        </textFieldCell>
                    </textField>
                    <textField verticalHuggingPriority="750" id="30">
                        <rect key="frame" x="279" y="466" width="37" height="22"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" allowsUndo="NO" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="center" title="123" drawsBackground="YES" id="31">
                            <font key="font" metaFont="system"/>
                            <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                        </textFieldCell>
                    </textField>
                    <button verticalHuggingPriority="750" id="22">
                        <rect key="frame" x="11" y="13" width="113" height="32"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <buttonCell key="cell" type="push" title="Reset Default" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="23">
                            <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
                            <font key="font" metaFont="system"/>
                        </buttonCell>
                        <connections>
                            <action selector="btnResetPressed:" target="-2" id="33"/>
                        </connections>
                    </button>
                    <textField verticalHuggingPriority="750" id="24">
                        <rect key="frame" x="66" y="547" width="107" height="17"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Trigger Input" id="25">
                            <font key="font" metaFont="system"/>
                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                        </textFieldCell>
                    </textField>
                    <textField verticalHuggingPriority="750" id="26">
                        <rect key="frame" x="279" y="544" width="96" 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" alignment="right" drawsBackground="YES" id="27">
                            <font key="font" metaFont="system"/>
                            <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                        </textFieldCell>
                    </textField>
                    <textField verticalHuggingPriority="750" id="zua-Qs-tG6">
                        <rect key="frame" x="149" y="192" width="241" 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" alignment="right" drawsBackground="YES" id="3w5-ev-VuS">
                            <font key="font" metaFont="system"/>
                            <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                        </textFieldCell>
                    </textField>
                    <textField verticalHuggingPriority="750" id="28">
                        <rect key="frame" x="78" y="501" width="295" height="38"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="VVDocumenter will inspect the input and insert document comment when it matches this." id="29">
                            <font key="font" metaFont="titleBar" size="12"/>
                            <color key="textColor" name="controlShadowColor" catalog="System" colorSpace="catalog"/>
                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                        </textFieldCell>
                    </textField>
                    <stepper horizontalHuggingPriority="750" verticalHuggingPriority="750" id="54">
                        <rect key="frame" x="312" y="463" width="19" height="27"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <stepperCell key="cell" continuous="YES" alignment="left" maxValue="100" id="55"/>
                        <connections>
                            <action selector="stepperPressed:" target="-2" id="58"/>
                        </connections>
                    </stepper>
                    <button id="ERW-1g-i3X">
                        <rect key="frame" x="67" y="439" width="201" height="18"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <buttonCell key="cell" type="check" title="Use @since to all comments" bezelStyle="regularSquare" imagePosition="left" inset="2" id="eH9-9F-VR9">
                            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                            <font key="font" metaFont="system"/>
                        </buttonCell>
                        <connections>
                            <action selector="btnAddSinceToCommentsPressed:" target="-2" id="mx1-gQ-vXj"/>
                        </connections>
                    </button>
                    <button id="gfy-6Z-t8f">
                        <rect key="frame" x="67" y="342" width="187" height="18"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <buttonCell key="cell" type="check" title="Use @brief for description" bezelStyle="regularSquare" imagePosition="left" inset="2" id="wKY-lg-WfF">
                            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                            <font key="font" metaFont="system"/>
                        </buttonCell>
                        <connections>
                            <action selector="btnBriefDescriptionPressed:" target="-2" id="UE3-ix-FCS"/>
                        </connections>
                    </button>
                    <button id="bgb-aQ-BAa">
                        <rect key="frame" x="67" y="312" width="272" height="18"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <buttonCell key="cell" type="check" title="Use /*! (HeaderDoc style) instead of /**" bezelStyle="regularSquare" imagePosition="left" inset="2" id="C3y-LS-75k">
                            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                            <font key="font" metaFont="system"/>
                        </buttonCell>
                        <connections>
                            <action selector="useHeaderDoc:" target="-2" id="1Wy-E1-jLv"/>
                        </connections>
                    </button>
                    <button id="6ax-Nw-Bq5">
                        <rect key="frame" x="67" y="284" width="272" height="18"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <buttonCell key="cell" type="check" title="Add blank lines between sections" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="YoT-Nd-Bhd">
                            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                            <font key="font" metaFont="system"/>
                        </buttonCell>
                        <connections>
                            <action selector="blankLinesBetweenSections:" target="-2" id="Ut9-U7-XdV"/>
                        </connections>
                    </button>
                    <matrix verticalHuggingPriority="750" allowsEmptySelection="NO" autosizesCells="NO" id="9MP-VX-rsW">
                        <rect key="frame" x="65" y="61" width="325" height="85"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                        <size key="cellSize" width="325" height="28"/>
                        <size key="intercellSpacing" width="4" height="2"/>
                        <buttonCell key="prototype" type="radio" title="Prefix each comment line with three slashes" bezelStyle="regularSquare" imagePosition="left" alignment="left" inset="2" id="wZv-eZ-WK7">
                            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                            <font key="font" metaFont="system"/>
                        </buttonCell>
                        <cells>
                            <column>
                                <buttonCell type="radio" title="Prefix each comment line with whitespace only" imagePosition="left" alignment="left" tag="1" inset="2" id="mxJ-X3-ycD">
                                    <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                                    <font key="font" metaFont="system"/>
                                </buttonCell>
                                <buttonCell type="radio" title="Prefix each comment line with a star (objc only)" imagePosition="left" alignment="left" state="on" tag="2" inset="2" id="vMT-lx-3Ep">
                                    <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                                    <font key="font" metaFont="system"/>
                                </buttonCell>
                                <buttonCell type="radio" title="Prefix each comment line with three slashes" bezelStyle="regularSquare" imagePosition="left" alignment="left" tag="3" inset="2" id="IVu-o3-DBW">
                                    <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                                    <font key="font" metaFont="system"/>
                                </buttonCell>
                            </column>
                        </cells>
                        <connections>
                            <action selector="mtxPrefixSettingPressed:" target="-2" id="lCp-Ch-TTG"/>
                        </connections>
                    </matrix>
                    <box verticalHuggingPriority="750" title="Box" boxType="separator" titlePosition="noTitle" id="Qwl-tK-TKG">
                        <rect key="frame" x="67" y="152" width="323" height="5"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="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>
                    <button id="g3M-cK-u5v">
                        <rect key="frame" x="67" y="252" width="272" height="18"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <buttonCell key="cell" type="check" title="Align argument comments" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="5tp-ni-55q">
                            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                            <font key="font" metaFont="system"/>
                        </buttonCell>
                        <connections>
                            <action selector="alignArgumentComments:" target="-2" id="o62-1G-Tta"/>
                        </connections>
                    </button>
                    <button id="yp5-mf-NgJ">
                        <rect key="frame" x="66" y="217" width="326" height="24"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <buttonCell key="cell" type="check" title="Add Default User Information" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="7e3-kk-v20">
                            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                            <font key="font" metaFont="system"/>
                        </buttonCell>
                        <connections>
                            <action selector="btnUseAuthorInformationPressed:" target="-2" id="cAF-1d-3Wh"/>
                        </connections>
                    </button>
                    <textField verticalHuggingPriority="750" id="Haw-5R-IXR">
                        <rect key="frame" x="83" y="194" width="60" height="17"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Author:" id="s2i-JB-wgP">
                            <font key="font" metaFont="system"/>
                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                        </textFieldCell>
                    </textField>
                    <textField verticalHuggingPriority="750" id="L0g-BX-Fh0">
                        <rect key="frame" x="225" y="167" width="165" 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" alignment="left" title="MM-dd-YYYY, HH:MM:ss" drawsBackground="YES" id="Krc-dg-Cog">
                            <font key="font" metaFont="system"/>
                            <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                        </textFieldCell>
                    </textField>
                    <button id="b6P-6I-DiH">
                        <rect key="frame" x="83" y="168" width="90" height="18"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <buttonCell key="cell" type="check" title="Add Date" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="y0w-1Y-908">
                            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                            <font key="font" metaFont="system"/>
                        </buttonCell>
                        <connections>
                            <action selector="btnUseDateInformationPressed:" target="-2" id="bKa-IH-b3m"/>
                        </connections>
                    </button>
                    <textField verticalHuggingPriority="750" id="whT-H5-Xdo">
                        <rect key="frame" x="172" y="169" width="59" height="17"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Format:" id="To6-Zf-QbE">
                            <font key="font" metaFont="system"/>
                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                        </textFieldCell>
                    </textField>
                    <matrix verticalHuggingPriority="750" allowsEmptySelection="NO" autorecalculatesCellSize="YES" id="F04-TF-nUJ">
                        <rect key="frame" x="85" y="366" width="167" height="67"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                        <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                        <size key="cellSize" width="167" height="18"/>
                        <size key="intercellSpacing" width="4" height="2"/>
                        <buttonCell key="prototype" type="radio" title="Radio" imagePosition="left" alignment="left" inset="2" id="SMy-aZ-Tel">
                            <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                            <font key="font" metaFont="system"/>
                        </buttonCell>
                        <cells>
                            <column>
                                <buttonCell type="radio" title="Use default placeholder" imagePosition="left" alignment="left" state="on" tag="1" inset="2" id="3Uj-1c-BzU">
                                    <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                                    <font key="font" metaFont="system"/>
                                </buttonCell>
                                <buttonCell type="radio" title="Use project version" imagePosition="left" alignment="left" inset="2" id="pSZ-Vj-hkT">
                                    <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                                    <font key="font" metaFont="system"/>
                                </buttonCell>
                                <buttonCell type="radio" title="Use specific version" imagePosition="left" alignment="left" inset="2" id="PbN-ts-AYz">
                                    <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
                                    <font key="font" metaFont="system"/>
                                </buttonCell>
                            </column>
                        </cells>
                        <connections>
                            <action selector="mtxSinceOptionPressed:" target="-2" id="fFz-uM-7g0"/>
                        </connections>
                    </matrix>
                    <textField verticalHuggingPriority="750" id="lQp-YM-3hX">
                        <rect key="frame" x="279" y="373" width="96" 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" placeholderString="Version" drawsBackground="YES" id="OAk-cF-UEV">
                            <font key="font" metaFont="system"/>
                            <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                        </textFieldCell>
                    </textField>
                </subviews>
            </view>
            <connections>
                <outlet property="delegate" destination="-2" id="4"/>
            </connections>
            <point key="canvasLocation" x="424.5" y="496"/>
        </window>
    </objects>
</document>


================================================
FILE: VVDocumenter-Xcode/Setting/VVDocumenterSetting.h
================================================
//
//  VVDocumenterSetting.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-8-3.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, VVDSinceOption) {
    VVDSinceOptionPlaceholder,
    VVDSinceOptionProjectVersion,
    VVDSinceOptionSpecificVersion,
};

extern NSString *const VVDDefaultTriggerString;
extern NSString *const VVDDefaultAuthorString;
extern NSString *const VVDDefaultDateInfomationFormat;

@interface VVDocumenterSetting : NSObject
+ (VVDocumenterSetting *)defaultSetting;

@property (readonly) NSInteger keyVCode;
@property BOOL useSpaces;
@property NSInteger spaceCount;
@property NSString *triggerString;
@property VVDSinceOption sinceOption;
@property BOOL prefixWithStar;
@property BOOL prefixWithSlashes;
@property BOOL addSinceToComments;
@property NSString *sinceVersion;
@property BOOL briefDescription;
@property BOOL useHeaderDoc;
@property BOOL blankLinesBetweenSections;
@property BOOL alignArgumentComments;
@property BOOL useAuthorInformation;
@property NSString *authorInformation;
@property BOOL useDateInformation;
@property NSString *dateInformationFormat;
@property (readonly) NSString *spacesString;
@end


================================================
FILE: VVDocumenter-Xcode/Setting/VVDocumenterSetting.m
================================================
//
//  VVDocumenterSetting.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-8-3.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVDocumenterSetting.h"
#import <Carbon/Carbon.h>
#import "VVProject.h"

NSString *const VVDDefaultTriggerString = @"///";
NSString *const VVDDefaultAuthorString = @"";
NSString *const VVDDefaultDateInfomationFormat = @"YY-MM-dd HH:MM:ss";

NSString *const kVVDUseSpaces = @"com.onevcat.VVDocumenter.useSpaces";
NSString *const kVVDSpaceCount = @"com.onevcat.VVDocumenter.spaceCount";
NSString *const kVVDTriggerString = @"com.onevcat.VVDocumenter.triggerString";
NSString *const kVVDPrefixWithStar = @"com.onevcat.VVDocumenter.prefixWithStar";
NSString *const kVVDPrefixWithSlashes = @"com.onevcat.VVDocumenter.prefixWithSlashes";
NSString *const kVVDAddSinceToComments = @"com.onevcat.VVDocumenter.addSinceToComments";
NSString *const kVVDSinceVersion = @"com.onevcat.VVDocumenter.sinceVersion";
NSString *const kVVDSinceOption = @"com.onevcat.VVDocumenter.sinceOption";
NSString *const kVVDBriefDescription = @"com.onevcat.VVDocumenter.briefDescription";
NSString *const kVVDUserHeaderDoc = @"com.onevcat.VVDocumenter.useHeaderDoc";
NSString *const kVVDNoBlankLinesBetweenFields = @"com.onevcat.VVDocumenter.noBlankLinesBetweenFields";
NSString *const kVVDNoArgumentPadding = @"com.onevcat.VVDocumenter.noArgumentPadding";
NSString *const kVVDUseAuthorInformation = @"com.onevcat.VVDocumenter.useAuthorInformation";
NSString *const kVVDAuthorInfomation = @"com.onevcat.VVDocumenter.authorInfomation";
NSString *const kVVDUseDateInformation = @"com.onevcat.VVDocumenter.useDateInformation";
NSString *const kVVDDateInformationFormat = @"com.onevcat.VVDocumenter.dateInformationFomat";
@implementation VVDocumenterSetting

+ (VVDocumenterSetting *)defaultSetting
{
    static dispatch_once_t once;
    static VVDocumenterSetting *defaultSetting;
    dispatch_once(&once, ^ {
        defaultSetting = [[VVDocumenterSetting alloc] init];
        
        NSDictionary *defaults = @{kVVDPrefixWithStar: @YES,
                                   kVVDUseSpaces: @YES};
        [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
    });
    return defaultSetting;
}

-(BOOL) useSpaces
{
    return [[NSUserDefaults standardUserDefaults] boolForKey:kVVDUseSpaces];
}

-(void) setUseSpaces:(BOOL)useSpace
{
    [[NSUserDefaults standardUserDefaults] setBool:useSpace forKey:kVVDUseSpaces];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(NSInteger) keyVCode
{
    TISInputSourceRef inputSource = TISCopyCurrentKeyboardLayoutInputSource();
    NSString *layoutID = (__bridge NSString *)TISGetInputSourceProperty(inputSource, kTISPropertyInputSourceID);
    CFRelease(inputSource);

    // Possible dvorak layout SourceIDs:
    //    com.apple.keylayout.Dvorak (System Qwerty)
    // But exclude:
    //    com.apple.keylayout.DVORAK-QWERTYCMD (System Qwerty ⌘)
    //    org.unknown.keylayout.DvorakImproved-Qwerty⌘ (http://www.macupdate.com/app/mac/24137/dvorak-improved-keyboard-layout)
    if ([layoutID localizedCaseInsensitiveContainsString:@"dvorak"] && ![layoutID localizedCaseInsensitiveContainsString: @"qwerty"]) {
        return kVK_ANSI_Period;
    }

    // Possible workman layout SourceIDs (https://github.com/ojbucao/Workman):
    //    org.sil.ukelele.keyboardlayout.workman.workman
    //    org.sil.ukelele.keyboardlayout.workman.workmanextended
    //    org.sil.ukelele.keyboardlayout.workman.workman-io
    //    org.sil.ukelele.keyboardlayout.workman.workman-p
    //    org.sil.ukelele.keyboardlayout.workman.workman-pextended
    //    org.sil.ukelele.keyboardlayout.workman.workman-dead
    if ([layoutID localizedCaseInsensitiveContainsString:@"workman"]) {
        return kVK_ANSI_B;
    }

    return kVK_ANSI_V;
}


-(NSInteger) spaceCount
{
    NSInteger count = [[NSUserDefaults standardUserDefaults] integerForKey:kVVDSpaceCount];
    return (count <= 0) ? 2 : count;
}

-(void) setSpaceCount:(NSInteger)spaceCount
{
    if (spaceCount < 1) {
        spaceCount = 1;
    } else if (spaceCount > 10) {
        spaceCount = 10;
    }
    
    [[NSUserDefaults standardUserDefaults] setInteger:spaceCount forKey:kVVDSpaceCount];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(NSString *) triggerString
{
    NSString *s = [[NSUserDefaults standardUserDefaults] stringForKey:kVVDTriggerString];
    if (s.length == 0) {
        s = VVDDefaultTriggerString;
    }
    return s;
}

-(void) setTriggerString:(NSString *)triggerString
{
    if (triggerString.length == 0) {
        [[NSUserDefaults standardUserDefaults] setObject:VVDDefaultTriggerString forKey:kVVDTriggerString];
    } else {
        [[NSUserDefaults standardUserDefaults] setObject:triggerString forKey:kVVDTriggerString];
    }

    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(VVDSinceOption) sinceOption
{
    return (VVDSinceOption)[[NSUserDefaults standardUserDefaults] integerForKey:kVVDSinceOption];
}

- (void)setSinceOption:(VVDSinceOption)sinceOption
{
    [[NSUserDefaults standardUserDefaults] setInteger:sinceOption forKey:kVVDSinceOption];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(BOOL) prefixWithStar
{
    return [[NSUserDefaults standardUserDefaults] boolForKey:kVVDPrefixWithStar];
}

-(void) setPrefixWithStar:(BOOL)prefix
{
    [[NSUserDefaults standardUserDefaults] setBool:prefix forKey:kVVDPrefixWithStar];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(BOOL) prefixWithSlashes
{
    return [[NSUserDefaults standardUserDefaults] boolForKey:kVVDPrefixWithSlashes];
}

-(void) setPrefixWithSlashes:(BOOL)prefix
{
    [[NSUserDefaults standardUserDefaults] setBool:prefix forKey:kVVDPrefixWithSlashes];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(BOOL) addSinceToComments
{
    return [[NSUserDefaults standardUserDefaults] boolForKey:kVVDAddSinceToComments];
}

-(void) setAddSinceToComments:(BOOL)add
{
    [[NSUserDefaults standardUserDefaults] setBool:add forKey:kVVDAddSinceToComments];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

- (NSString *)sinceVersion
{
    NSString *sinceVersion = [[NSUserDefaults standardUserDefaults] objectForKey:kVVDSinceVersion];

    if ( ! sinceVersion ) {
        sinceVersion = @"";
    }

    return sinceVersion;
}

- (void)setSinceVersion:(NSString *)sinceVersion
{
    [[NSUserDefaults standardUserDefaults] setObject:sinceVersion forKey:kVVDSinceVersion];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(BOOL) briefDescription
{
    return [[NSUserDefaults standardUserDefaults] boolForKey:kVVDBriefDescription];
}

-(void) setBriefDescription:(BOOL)brief
{
    [[NSUserDefaults standardUserDefaults] setBool:brief forKey:kVVDBriefDescription];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(BOOL) useHeaderDoc
{
    return [[NSUserDefaults standardUserDefaults] boolForKey:kVVDUserHeaderDoc];
}
-(void) setUseHeaderDoc:(BOOL)use
{
    [[NSUserDefaults standardUserDefaults] setBool:use forKey:kVVDUserHeaderDoc];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(BOOL) blankLinesBetweenSections
{
    return ![[NSUserDefaults standardUserDefaults] boolForKey:kVVDNoBlankLinesBetweenFields];
}
-(void) setBlankLinesBetweenSections:(BOOL)blankLinesBetweenFields
{
    [[NSUserDefaults standardUserDefaults] setBool:!blankLinesBetweenFields forKey:kVVDNoBlankLinesBetweenFields];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(BOOL) alignArgumentComments
{
    return ![[NSUserDefaults standardUserDefaults] boolForKey:kVVDNoArgumentPadding];
}
-(void) setAlignArgumentComments:(BOOL)alignArgumentComments
{
    [[NSUserDefaults standardUserDefaults] setBool:!alignArgumentComments forKey:kVVDNoArgumentPadding];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(BOOL)useAuthorInformation
{
    return [[NSUserDefaults standardUserDefaults] boolForKey:kVVDUseAuthorInformation];
}
-(void) setUseAuthorInformation:(BOOL)useAuthorInformation
{
    [[NSUserDefaults standardUserDefaults] setBool:useAuthorInformation forKey:kVVDUseAuthorInformation];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(NSString *)authorInformation {
    NSString *authorInformation = [[NSUserDefaults standardUserDefaults] objectForKey:kVVDAuthorInfomation];
    if (authorInformation.length <= 0 ) {
        NSString *name = [[VVProject projectForKeyWindow] organizeationName];
        if (name.length <= 0) {
            NSDictionary *environment = [[NSProcessInfo processInfo] environment];
            name = [environment objectForKey:@"LOGNAME"];
        }
        
        if (name.length > 0) {
            authorInformation = name;
        }else{
            authorInformation = VVDDefaultAuthorString;
        }
    }
    return authorInformation;
}
-(void)setAuthorInformation:(NSString *)authorInformation {
    [[NSUserDefaults standardUserDefaults] setObject:authorInformation forKey:kVVDAuthorInfomation];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(BOOL)useDateInformation
{
    return [[NSUserDefaults standardUserDefaults] boolForKey:kVVDUseDateInformation];
}
-(void) setUseDateInformation:(BOOL)useDateInformation
{
    [[NSUserDefaults standardUserDefaults] setBool:useDateInformation forKey:kVVDUseDateInformation];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(NSString *)dateInformationFormat {
    NSString *formatString = [[NSUserDefaults standardUserDefaults] objectForKey:kVVDDateInformationFormat];
    if (formatString == nil || formatString.length <= 0) {
        formatString = VVDDefaultDateInfomationFormat;
    }
    return formatString;
}
-(void)setDateInformationFormat:(NSString *)dateInformationFormat {
    [[NSUserDefaults standardUserDefaults] setObject:dateInformationFormat forKey:kVVDDateInformationFormat];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

-(NSString *) spacesString
{
    if ([self useSpaces]) {
        return [@"" stringByPaddingToLength:[self spaceCount] withString:@" " startingAtIndex:0];
    } else {
        return @"\t";
    }
}

@end


================================================
FILE: VVDocumenter-Xcode/VVDocumenter-Xcode-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>$(PRODUCT_BUNDLE_IDENTIFIER)</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>1.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1</string>
	<key>DVTPlugInCompatibilityUUIDs</key>
	<array>
		<string>9AFF134A-08DC-4096-8CEE-62A4BB123046</string>
		<string>63FC1C47-140D-42B0-BB4D-A10B2D225574</string>
		<string>37B30044-3B14-46BA-ABAA-F01000C27B63</string>
		<string>640F884E-CE55-4B40-87C0-8869546CAB7A</string>
		<string>A2E4D43F-41F4-4FB9-BB94-7177011C9AED</string>
		<string>AD68E85B-441B-4301-B564-A45E4919A6AD</string>
		<string>C4A681B0-4A26-480E-93EC-1218098B9AA0</string>
		<string>FEC992CC-CA4A-4CFD-8881-77300FCB848A</string>
		<string>992275C1-432A-4CF7-B659-D84ED6D42D3F</string>
		<string>A16FF353-8441-459E-A50C-B071F53F51B7</string>
		<string>9F75337B-21B4-4ADC-B558-F9CADF7073A7</string>
		<string>992275C1-432A-4CF7-B659-D84ED6D42D3F</string>
		<string>8DC44374-2B35-4C57-A6FE-2AD66A36AAD9</string>
		<string>E969541F-E6F9-4D25-8158-72DC3545A6C6</string>
		<string>AABB7188-E14E-4433-AD3B-5CD791EAD9A3</string>
		<string>7FDF5C7A-131F-4ABB-9EDC-8C5F8F0B8A90</string>
		<string>0420B86A-AA43-4792-9ED0-6FE0F2B16A13</string>
		<string>CC0D0F4F-05B3-431A-8F33-F84AFCB2C651</string>
		<string>7265231C-39B4-402C-89E1-16167C4CC990</string>
		<string>F41BD31E-2683-44B8-AE7F-5F09E919790E</string>
		<string>E71C2CFE-BFD8-4044-8F06-00AE685A406C</string>
		<string>ACA8656B-FEA8-4B6D-8E4A-93F4C95C362C</string>
		<string>E0A62D1F-3C18-4D74-BFE5-A4167D643966</string>
	</array>
	<key>NSHumanReadableCopyright</key>
	<string>Copyright © 2013年 OneV's Den. All rights reserved.</string>
	<key>NSPrincipalClass</key>
	<string></string>
	<key>XC4Compatible</key>
	<true/>
	<key>XC5Compatible</key>
	<true/>
	<key>XCGCReady</key>
	<true/>
	<key>XCPluginHasUI</key>
	<false/>
</dict>
</plist>


================================================
FILE: VVDocumenter-Xcode/VVDocumenter-Xcode-Prefix.pch
================================================
//
// Prefix header for all source files of the 'VVDocumenter-Xcode' target in the 'VVDocumenter-Xcode' project
//

#ifdef __OBJC__
    #import <Cocoa/Cocoa.h>
    #import "NSString+PDRegex.h"
#endif

//#define __DEBUG__ 1
#ifdef __DEBUG__
#define VVLog(...) NSLog(__VA_ARGS__)
#else
#define VVLog(...) do{} while(0)
#endif

================================================
FILE: VVDocumenter-Xcode/VVDocumenter.h
================================================
//
//  VVDocumenter.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Foundation/Foundation.h>

@interface VVDocumenter : NSObject
-(instancetype) initWithCode:(NSString *)code;
-(NSString *) baseIndentation;
-(NSString *) document;
@end


================================================
FILE: VVDocumenter-Xcode/VVDocumenter.m
================================================
//
//  VVDocumenter.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-17.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVDocumenter.h"
#import "NSString+VVSyntax.h"
#import "VVCommenter.h"

@interface VVDocumenter()

@property (nonatomic, copy) NSString *code;
@property (nonatomic, assign) BOOL isEnum;
@property (nonatomic, assign) BOOL isSwiftEnum;

@end

@implementation VVDocumenter

-(instancetype) initWithCode:(NSString *)code
{
    self = [super init];
    if (self) {
        NSString *trimmed = [[code vv_stringByReplacingRegexPattern:@"\\s*(\\(.*\?\\))\\s*" withString:@"$1"]
                             vv_stringByReplacingRegexPattern:@"\\s*\n\\s*"           withString:@" "];
        _isEnum = [trimmed vv_isEnum];
        _isSwiftEnum = [trimmed vv_isSwiftEnum];
        if (_isEnum || _isSwiftEnum) {
            _code = code;
        } else {
            //Trim the space around the braces
            //Then trim the new line character
            _code = trimmed;
        }
    }
    return self;
}

-(NSString *) baseIndentation
{
    NSArray *matchedSpaces = [self.code vv_stringsByExtractingGroupsUsingRegexPattern:@"^(\\s*)"];
    if (matchedSpaces.count > 0) {
        return matchedSpaces[0];
    } else {
        return @"";
    }
}

-(NSString *) document
{
    NSString *trimCode = [self.code stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    NSString *baseIndent = [self baseIndentation];
    
    VVBaseCommenter *commenter = nil;
    
    if (self.isEnum) {    
        commenter = [[VVEnumCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    } else if (self.isSwiftEnum) {
        commenter = [[VVSwiftEnumCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    } else if ([trimCode vv_isProperty]) {
        commenter = [[VVPropertyCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    } else if ([trimCode vv_isCFunction]) {
        commenter = [[VVFunctionCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    } else if ([trimCode vv_isMacro]) {
        commenter = [[VVMacroCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    } else if ([trimCode vv_isStruct]) {
        commenter = [[VVStructCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    } else if ([trimCode vv_isUnion]) {
        commenter = [[VVStructCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    } else if ([trimCode vv_isObjCMethod]) {
        commenter = [[VVMethodCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    } else if ([trimCode vv_isSwiftFunction]) {
        commenter = [[VVSwiftFunctionCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    } else if ([trimCode vv_isSwiftProperty]) {
        commenter = [[VVSwiftPropertyCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    } else if ([trimCode vv_isSwiftExtension]) {
        commenter = [[VVSwiftExtensionCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    } else {
        commenter = [[VVVariableCommenter alloc] initWithIndentString:baseIndent codeString:trimCode];
    }

    if ([commenter shouldComment]) {
        return [commenter document];
    } else {
        return nil;
    }
}



@end


================================================
FILE: VVDocumenter-Xcode/VVDocumenterManager.h
================================================
//
//  VVDocumenterManager.h
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-16.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import <Foundation/Foundation.h>

@interface VVDocumenterManager : NSObject

@end


================================================
FILE: VVDocumenter-Xcode/VVDocumenterManager.m
================================================
//
//  VVDocumenterManager.m
//  VVDocumenter-Xcode
//
//  Created by 王 巍 on 13-7-16.
//
//  Copyright (c) 2015 Wei Wang <onevcat@gmail.com>
//
//  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.

#import "VVDocumenterManager.h"
#import "NSTextView+VVTextGetter.h"
#import "NSString+VVSyntax.h"
#import "VVDocumenter.h"
#import "VVKeyboardEventSender.h"
#import "VVDSettingPanelWindowController.h"
#import "VVDocumenterSetting.h"
#import "VVTextResult.h"

@interface VVDocumenterManager()
@property (nonatomic, strong) id eventMonitor;
@property (nonatomic, assign) BOOL prefixTyped;
@property (nonatomic, strong) VVDSettingPanelWindowController *settingPanel;
@end

@implementation VVDocumenterManager
+(void)pluginDidLoad:(NSBundle *)plugin {
    VVLog(@"VVDocumenter: Plugin loaded successfully");
    [self shared];
}

+(instancetype) shared {
    static dispatch_once_t once;
    static id instance = nil;
    dispatch_once(&once, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (instancetype)init {
    if (self = [super init]) {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(applicationDidFinishLaunching:)
                                                     name:NSApplicationDidFinishLaunchingNotification
                                                   object:nil];
    }
    return self;
}

- (void) applicationDidFinishLaunching: (NSNotification*) noti {
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(textStorageDidChange:)
                                                 name:NSTextDidChangeNotification
                                               object:nil];
    [self addSettingMenu];
}

-(void) addSettingMenu
{
    NSMenuItem *editMenuItem = [[NSApp mainMenu] itemWithTitle:@"Window"];
    if (editMenuItem) {
        [[editMenuItem submenu] addItem:[NSMenuItem separatorItem]];
        
        NSMenuItem *newMenuItem = [[NSMenuItem alloc] initWithTitle:@"VVDocumenter" action:@selector(showSettingPanel:) keyEquivalent:@""];
        
        [newMenuItem setTarget:self];
        [[editMenuItem submenu] addItem:newMenuItem];
    }
}

-(void) showSettingPanel:(NSNotification *)noti {
    self.settingPanel = [[VVDSettingPanelWindowController alloc] initWithWindowNibName:@"VVDSettingPanelWindowController"];
    [self.settingPanel showWindow:self.settingPanel];
}

- (void) textStorageDidChange:(NSNotification *)noti {

    if ([[noti object] isKindOfClass:[NSTextView class]]) {
        NSTextView *textView = (NSTextView *)[noti object];
        VVTextResult *currentLineResult = [textView vv_textResultOfCurrentLine];
        if (currentLineResult) {

            //Check if there is a "//" already typed in. We do this to solve the undo issue
            //Otherwise when you press Cmd+Z, "///" will be recognized and trigger the doc inserting, so you can not perform an undo.
            NSString *triggerString = [[VVDocumenterSetting defaultSetting] triggerString];
            
            if (triggerString.length > 1) {
                NSString *preTypeString = [triggerString substringToIndex:triggerString.length - 2];
                self.prefixTyped = [currentLineResult.string vv_matchesPatternRegexPattern:[NSString stringWithFormat:@"^\\s*%@$",[NSRegularExpression escapedPatternForString:preTypeString]]] | self.prefixTyped;
            } else {
                self.prefixTyped = YES;
            }
            
            if ([currentLineResult.string vv_matchesPatternRegexPattern:[NSString stringWithFormat:@"^\\s*%@$",[NSRegularExpression escapedPatternForString:triggerString]]] && self.prefixTyped) {
                VVTextResult *previousLineResult = [textView vv_textResultOfPreviousLine];

                // Previous line is a documentation comment, so ignore this
                if ([previousLineResult.string vv_matchesPatternRegexPattern:@"^\\s*///"]) {
                    return;
                }

                VVTextResult *nextLineResult = [textView vv_textResultOfNextLine];

                // Next line is a documentation comment, so ignore this
                if ([nextLineResult.string vv_matchesPatternRegexPattern:@"^\\s*///"]) {
                    return;
                }
                
                //Get a @"///" (triggerString) typed in by user. Do work!
                self.prefixTyped = NO;

                __block BOOL shouldReplace = NO;
                
                //Decide which is closer to the cursor. A semicolon or a half brace.
                //We just want to document the next valid line.
                VVTextResult *resultUntilSemiColon = [textView vv_textResultUntilNextString:@";"];
                VVTextResult *resultUntilBrace = [textView vv_textResultUntilNextString:@"{"];
                VVTextResult *resultUntilFileEnd = [textView vv_textResultToEndOfFile];
                
                VVTextResult *resultToDocument = nil;
                
                if (resultUntilSemiColon && resultUntilBrace) {
                    resultToDocument = (resultUntilSemiColon.range.length < resultUntilBrace.range.length) ? resultUntilSemiColon : resultUntilBrace;
                } else if (resultUntilBrace) {
                    resultToDocument = resultUntilBrace;
                } else if (resultUntilSemiColon) {
                    resultToDocument = resultUntilSemiColon;
                } else {
                    resultToDocument = resultUntilFileEnd;
                }
                
                //We always write document until semicolon for enum. (Maybe struct later)
                if ([resultToDocument.string vv_isEnum]) {
                    resultToDocument = resultUntilSemiColon;
                    shouldReplace = YES;
                }
                
                NSString *inputCode = nil;
                if ([resultToDocument.string vv_isSwiftEnum]) {
                    inputCode = [textView vv_textResultWithPairOpenString:@"{" closeString:@"}"].string;
                } else {
                    inputCode = [resultToDocument.string vv_stringByConvertingToUniform];
                }
                
                VVDocumenter *doc = [[VVDocumenter alloc] initWithCode:inputCode];
                NSString *documentationString = [doc document];
                
                if (!documentationString) {
                    //Leave the user's input there.
                    //It might be no need to parse doc or something wrong.
                    return;
                }
                
                //Now we are using a simulation of keyboard event to insert the docs, instead of using the IDE's private method.
                //See more at https://github.com/onevcat/VVDocumenter-Xcode/issues/3

                //Save current content in paste board
                NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
                NSString *originPBString = [pasteBoard stringForType:NSPasteboardTypeString];

                //Set the doc comments in it
                [pasteBoard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
                [pasteBoard setString:documentationString forType:NSStringPboardType];
                
                //Begin to simulate keyborad pressing
                VVKeyboardEventSender *kes = [[VVKeyboardEventSender alloc] init];
                [kes beginKeyBoradEvents];
                //Cmd+delete Delete current line
                [kes sendKeyCode:kVK_Delete withModifierCommand:YES alt:NO shift:NO control:NO];
                //if (shouldReplace) [textView setSelectedRange:resultToDocument.range];
                //Cmd+V, paste (which key to actually use is based on the current keyboard layout)
                NSInteger kKeyVCode = [[VVDocumenterSetting defaultSetting] keyVCode];
                [kes sendKeyCode:kKeyVCode withModifierCommand:YES alt:NO shift:NO control:NO];
                
                //The key down is just a defined finish signal by me. When we receive this key, we know operation above is finished.
                [kes sendKeyCode:kVK_F20];

                self.eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:^NSEvent *(NSEvent *incomingEvent) {
                    if ([incomingEvent type] == NSKeyDown && [incomingEvent keyCode] == kVK_F20) {
                        //Finish signal arrived, no need to observe the event
                        [NSEvent removeMonitor:self.eventMonitor];
                        self.eventMonitor = nil;
                        
                        //Restore previois patse board content
                        [pasteBoard setString:originPBString forType:NSStringPboardType];
                        
                        //Set cursor before the inserted documentation. So we can use tab to begi
Download .txt
gitextract_6z6nzidj/

├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── VVDocumenter-Xcode/
│   ├── Commenter/
│   │   ├── VVArgument.h
│   │   ├── VVArgument.m
│   │   ├── VVBaseCommenter.h
│   │   ├── VVBaseCommenter.m
│   │   ├── VVCommenter.h
│   │   ├── VVEnumCommenter.h
│   │   ├── VVEnumCommenter.m
│   │   ├── VVFunctionCommenter.h
│   │   ├── VVFunctionCommenter.m
│   │   ├── VVMacroCommenter.h
│   │   ├── VVMacroCommenter.m
│   │   ├── VVMethodCommenter.h
│   │   ├── VVMethodCommenter.m
│   │   ├── VVPropertyCommenter.h
│   │   ├── VVPropertyCommenter.m
│   │   ├── VVStructCommenter.h
│   │   ├── VVStructCommenter.m
│   │   ├── VVSwiftEnumCommenter.h
│   │   ├── VVSwiftEnumCommenter.m
│   │   ├── VVSwiftExtensionCommenter.h
│   │   ├── VVSwiftExtensionCommenter.m
│   │   ├── VVSwiftFunctionCommenter.h
│   │   ├── VVSwiftFunctionCommenter.m
│   │   ├── VVSwiftPropertyCommenter.h
│   │   ├── VVSwiftPropertyCommenter.m
│   │   ├── VVVariableCommenter.h
│   │   └── VVVariableCommenter.m
│   ├── KeyboardHelper/
│   │   ├── VVKeyboardEventSender.h
│   │   └── VVKeyboardEventSender.m
│   ├── OCCategory/
│   │   ├── NSString+PDRegex/
│   │   │   ├── NSString+PDRegex.h
│   │   │   └── NSString+PDRegex.m
│   │   ├── NSString+VVSyntax/
│   │   │   ├── NSString+VVSyntax.h
│   │   │   └── NSString+VVSyntax.m
│   │   ├── NSString+VVTextGetter/
│   │   │   ├── NSString+VVTextGetter.h
│   │   │   └── NSString+VVTextGetter.m
│   │   ├── NSTextView+VVTextGetter/
│   │   │   ├── NSTextView+VVTextGetter.h
│   │   │   └── NSTextView+VVTextGetter.m
│   │   ├── VVTextResult.h
│   │   └── VVTextResult.m
│   ├── ProjectHelper/
│   │   ├── VVProject.h
│   │   ├── VVProject.m
│   │   ├── VVWorkspaceManager.h
│   │   └── VVWorkspaceManager.m
│   ├── Setting/
│   │   ├── VVDSettingPanelWindowController.h
│   │   ├── VVDSettingPanelWindowController.m
│   │   ├── VVDSettingPanelWindowController.xib
│   │   ├── VVDocumenterSetting.h
│   │   └── VVDocumenterSetting.m
│   ├── VVDocumenter-Xcode-Info.plist
│   ├── VVDocumenter-Xcode-Prefix.pch
│   ├── VVDocumenter.h
│   ├── VVDocumenter.m
│   ├── VVDocumenterManager.h
│   ├── VVDocumenterManager.m
│   └── en.lproj/
│       └── InfoPlist.strings
├── VVDocumenter-Xcode.xcodeproj/
│   ├── project.pbxproj
│   ├── project.xcworkspace/
│   │   └── contents.xcworkspacedata
│   └── xcshareddata/
│       └── xcschemes/
│           ├── VVDocumenter-Xcode.xcscheme
│           └── VVDocumenterTests.xcscheme
└── VVDocumenterTests/
    ├── CommenterTests/
    │   └── CommenterTests.m
    ├── DocumenterTests/
    │   └── VVMethodTestsCode.plist
    ├── SyntaxTests/
    │   └── SyntaxTests.m
    ├── VVDocumenterTests-Info.plist
    ├── VVDocumenterTests-Prefix.pch
    ├── VVDocumenterTests.m
    ├── VVTestHelper.h
    ├── VVTestHelper.m
    └── en.lproj/
        └── InfoPlist.strings
Download .txt
SYMBOL INDEX (1 symbols across 1 files)

FILE: VVDocumenter-Xcode/Setting/VVDocumenterSetting.h
  type VVDSinceOptionPlaceholder (line 29) | typedef NS_ENUM(NSInteger, VVDSinceOption) {
Condensed preview — 72 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (321K chars).
[
  {
    "path": ".gitignore",
    "chars": 4292,
    "preview": "#########################\n# .gitignore file for Xcode4 / OS X Source projects\n#\n# Version 2.1\n# For latest version, see:"
  },
  {
    "path": ".travis.yml",
    "chars": 99,
    "preview": "language: objective-c\nxcode_project: VVDocumenter-Xcode.xcodeproj\nxcode_scheme: VVDocumenter-Xcode\n"
  },
  {
    "path": "LICENSE",
    "chars": 1072,
    "preview": "Copyright (c) 2015 Wei Wang <onevcat@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a"
  },
  {
    "path": "README.md",
    "chars": 6166,
    "preview": "# VVDocumenter-Xcode [![Build Status](https://api.travis-ci.org/onevcat/VVDocumenter-Xcode.svg)](https://travis-ci.org/o"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVArgument.h",
    "chars": 1383,
    "preview": "//\n//  Argument.h\n//  VVDocumenter-Xcode\n\n//\n//  Created by 王 巍 on 13-7-19.\n//\n//  Copyright (c) 2015 Wei Wang <onevcat@"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVArgument.m",
    "chars": 2701,
    "preview": "//\n//  Argument.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-19.\n//\n//  Copyright (c) 2015 Wei Wang <onevcat@g"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVBaseCommenter.h",
    "chars": 2062,
    "preview": "//\n//  VVBaseCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <on"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVBaseCommenter.m",
    "chars": 13601,
    "preview": "//\n//  VVBaseCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <on"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVCommenter.h",
    "chars": 1706,
    "preview": "//\n//  VVCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-18.\n//\n//  Copyright (c) 2015 Wei Wang <onevca"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVEnumCommenter.h",
    "chars": 1308,
    "preview": "//\n//  VVEnumCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <on"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVEnumCommenter.m",
    "chars": 4234,
    "preview": "//\n//  VVEnumCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <on"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVFunctionCommenter.h",
    "chars": 1316,
    "preview": "//\n//  VVFunctionCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVFunctionCommenter.m",
    "chars": 2381,
    "preview": "//\n//  VVFunctionCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVMacroCommenter.h",
    "chars": 1310,
    "preview": "//\n//  VVMacroCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <o"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVMacroCommenter.m",
    "chars": 1721,
    "preview": "//\n//  VVMacroCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <o"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVMethodCommenter.h",
    "chars": 1312,
    "preview": "//\n//  VVMethodCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVMethodCommenter.m",
    "chars": 2430,
    "preview": "//\n//  VVMethodCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVPropertyCommenter.h",
    "chars": 1316,
    "preview": "//\n//  VVPropertyCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVPropertyCommenter.m",
    "chars": 1307,
    "preview": "//\n//  VVPropertyCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVStructCommenter.h",
    "chars": 1312,
    "preview": "//\n//  VVStructCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVStructCommenter.m",
    "chars": 1301,
    "preview": "//\n//  VVStructCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVSwiftEnumCommenter.h",
    "chars": 1318,
    "preview": "//\n//  VVSwiftEnumCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 14-7-30.\n//\n//  Copyright (c) 2015 Wei Wan"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVSwiftEnumCommenter.m",
    "chars": 2608,
    "preview": "//\n//  VVSwiftEnumCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 14-7-30.\n//\n//  Copyright (c) 2015 Wei Wan"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVSwiftExtensionCommenter.h",
    "chars": 1336,
    "preview": "//\n//  VVSwiftExtensionCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by WANG WEI on 2015/06/17.\n//\n//  Copyright (c)"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVSwiftExtensionCommenter.m",
    "chars": 1768,
    "preview": "//\n//  VVSwiftExtensionCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by WANG WEI on 2015/06/17.\n//\n//  Copyright (c)"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVSwiftFunctionCommenter.h",
    "chars": 1326,
    "preview": "//\n//  VVSwiftFunctionCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 14-7-30.\n//\n//  Copyright (c) 2015 Wei"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVSwiftFunctionCommenter.m",
    "chars": 5151,
    "preview": "//\n//  VVSwiftFunctionCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 14-7-30.\n//\n//  Copyright (c) 2015 Wei"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVSwiftPropertyCommenter.h",
    "chars": 1326,
    "preview": "//\n//  VVSwiftPropertyCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 14-7-31.\n//\n//  Copyright (c) 2015 Wei"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVSwiftPropertyCommenter.m",
    "chars": 1413,
    "preview": "//\n//  VVSwiftPropertyCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 14-7-31.\n//\n//  Copyright (c) 2015 Wei"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVVariableCommenter.h",
    "chars": 1316,
    "preview": "//\n//  VVVariableCommenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang"
  },
  {
    "path": "VVDocumenter-Xcode/Commenter/VVVariableCommenter.m",
    "chars": 1308,
    "preview": "//\n//  VVVariableCommenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang"
  },
  {
    "path": "VVDocumenter-Xcode/KeyboardHelper/VVKeyboardEventSender.h",
    "chars": 1805,
    "preview": "//\n//  VVKeyboardEventSender.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-26.\n//\n//  Copyright (c) 2015 Wei Wa"
  },
  {
    "path": "VVDocumenter-Xcode/KeyboardHelper/VVKeyboardEventSender.m",
    "chars": 2937,
    "preview": "//\n//  VVKeyboardEventSender.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-26.\n//\n//  Copyright (c) 2015 Wei Wa"
  },
  {
    "path": "VVDocumenter-Xcode/OCCategory/NSString+PDRegex/NSString+PDRegex.h",
    "chars": 1050,
    "preview": "//\n//  NSString+PDRegex.h\n//  RegexOnNSString\n//\n//  Created by Carl Brown on 10/3/11.\n//  Copyright 2011 PDAgent, LLC. "
  },
  {
    "path": "VVDocumenter-Xcode/OCCategory/NSString+PDRegex/NSString+PDRegex.m",
    "chars": 3835,
    "preview": "//\n//  NSString+PDRegex.m\n//  RegexOnNSString\n//\n//  Created by Carl Brown on 10/3/11.\n//  Copyright 2011 PDAgent, LLC. "
  },
  {
    "path": "VVDocumenter-Xcode/OCCategory/NSString+VVSyntax/NSString+VVSyntax.h",
    "chars": 1678,
    "preview": "//\n//  NSString+VVSyntax.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-18.\n//\n//  Copyright (c) 2015 Wei Wang <"
  },
  {
    "path": "VVDocumenter-Xcode/OCCategory/NSString+VVSyntax/NSString+VVSyntax.m",
    "chars": 3773,
    "preview": "//\n//  NSString+VVSyntax.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-18.\n//\n//  Copyright (c) 2015 Wei Wang <"
  },
  {
    "path": "VVDocumenter-Xcode/OCCategory/NSString+VVTextGetter/NSString+VVTextGetter.h",
    "chars": 2198,
    "preview": "//\n//  NSString+VVTextGetter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 14-7-31.\n//\n//  Copyright (c) 2015 Wei Wa"
  },
  {
    "path": "VVDocumenter-Xcode/OCCategory/NSString+VVTextGetter/NSString+VVTextGetter.m",
    "chars": 10045,
    "preview": "//\n//  NSString+VVTextGetter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 14-7-31.\n//\n//  Copyright (c) 2015 Wei Wa"
  },
  {
    "path": "VVDocumenter-Xcode/OCCategory/NSTextView+VVTextGetter/NSTextView+VVTextGetter.h",
    "chars": 1718,
    "preview": "//\n//  NSTextView+VVTextGetter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei "
  },
  {
    "path": "VVDocumenter-Xcode/OCCategory/NSTextView+VVTextGetter/NSTextView+VVTextGetter.m",
    "chars": 2573,
    "preview": "//\n//  NSTextView+VVTextGetter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei "
  },
  {
    "path": "VVDocumenter-Xcode/OCCategory/VVTextResult.h",
    "chars": 1468,
    "preview": "//\n//  VVTextResult.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 14-7-31.\n//\n//  Copyright (c) 2015 Wei Wang <onevc"
  },
  {
    "path": "VVDocumenter-Xcode/OCCategory/VVTextResult.m",
    "chars": 1639,
    "preview": "//\n//  VVTextResult.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 14-7-31.\n//\n//  Copyright (c) 2015 Wei Wang <onevc"
  },
  {
    "path": "VVDocumenter-Xcode/ProjectHelper/VVProject.h",
    "chars": 1755,
    "preview": "//\n//  VVProject.h\n//  VVDocumenter-Xcode\n//\n//  Created by 夏天味道 on 15/6/25.\n//\n//  Copyright (c) 2015 Wei Wang <onevcat"
  },
  {
    "path": "VVDocumenter-Xcode/ProjectHelper/VVProject.m",
    "chars": 5218,
    "preview": "//\n//  VVProject.m\n//  VVDocumenter-Xcode\n//\n//  Created by 夏天味道 on 15/6/25.\n//\n//  Copyright (c) 2015 Wei Wang <onevcat"
  },
  {
    "path": "VVDocumenter-Xcode/ProjectHelper/VVWorkspaceManager.h",
    "chars": 1445,
    "preview": "//\n//  VVWorkspaceManager.h\n//  VVDocumenter-Xcode\n//\n//  Created by 夏天味道 on 15/6/25.\n//\n//  Copyright (c) 2015 Wei Wang"
  },
  {
    "path": "VVDocumenter-Xcode/ProjectHelper/VVWorkspaceManager.m",
    "chars": 2176,
    "preview": "//\n//  VVWorkspaceManager.m\n//  VVDocumenter-Xcode\n//\n//  Created by 夏天味道 on 15/6/25.\n//\n//  Copyright (c) 2015 Wei Wang"
  },
  {
    "path": "VVDocumenter-Xcode/Setting/VVDSettingPanelWindowController.h",
    "chars": 1338,
    "preview": "//\n//  VVDSettingPanelWindowController.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-8-3.\n//\n//  Copyright (c) 20"
  },
  {
    "path": "VVDocumenter-Xcode/Setting/VVDSettingPanelWindowController.m",
    "chars": 11465,
    "preview": "//\n//  VVDSettingPanelWindowController.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-8-3.\n//\n//  Copyright (c) 20"
  },
  {
    "path": "VVDocumenter-Xcode/Setting/VVDSettingPanelWindowController.xib",
    "chars": 26175,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3"
  },
  {
    "path": "VVDocumenter-Xcode/Setting/VVDocumenterSetting.h",
    "chars": 2302,
    "preview": "//\n//  VVDocumenterSetting.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-8-3.\n//\n//  Copyright (c) 2015 Wei Wang "
  },
  {
    "path": "VVDocumenter-Xcode/Setting/VVDocumenterSetting.m",
    "chars": 11225,
    "preview": "//\n//  VVDocumenterSetting.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-8-3.\n//\n//  Copyright (c) 2015 Wei Wang "
  },
  {
    "path": "VVDocumenter-Xcode/VVDocumenter-Xcode-Info.plist",
    "chars": 2424,
    "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": "VVDocumenter-Xcode/VVDocumenter-Xcode-Prefix.pch",
    "chars": 323,
    "preview": "//\n// Prefix header for all source files of the 'VVDocumenter-Xcode' target in the 'VVDocumenter-Xcode' project\n//\n\n#ifd"
  },
  {
    "path": "VVDocumenter-Xcode/VVDocumenter.h",
    "chars": 1402,
    "preview": "//\n//  VVDocumenter.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <onevc"
  },
  {
    "path": "VVDocumenter-Xcode/VVDocumenter.m",
    "chars": 4454,
    "preview": "//\n//  VVDocumenter.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-17.\n//\n//  Copyright (c) 2015 Wei Wang <onevc"
  },
  {
    "path": "VVDocumenter-Xcode/VVDocumenterManager.h",
    "chars": 1315,
    "preview": "//\n//  VVDocumenterManager.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-16.\n//\n//  Copyright (c) 2015 Wei Wang"
  },
  {
    "path": "VVDocumenter-Xcode/VVDocumenterManager.m",
    "chars": 11428,
    "preview": "//\n//  VVDocumenterManager.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-16.\n//\n//  Copyright (c) 2015 Wei Wang"
  },
  {
    "path": "VVDocumenter-Xcode/en.lproj/InfoPlist.strings",
    "chars": 45,
    "preview": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "VVDocumenter-Xcode.xcodeproj/project.pbxproj",
    "chars": 46911,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "VVDocumenter-Xcode.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 163,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:VVDocumenter-Xc"
  },
  {
    "path": "VVDocumenter-Xcode.xcodeproj/xcshareddata/xcschemes/VVDocumenter-Xcode.xcscheme",
    "chars": 4605,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0700\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "VVDocumenter-Xcode.xcodeproj/xcshareddata/xcschemes/VVDocumenterTests.xcscheme",
    "chars": 2994,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0700\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "VVDocumenterTests/CommenterTests/CommenterTests.m",
    "chars": 4629,
    "preview": "//\n//  CommenterTests.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-20.\n//\n//  Copyright (c) 2015 Wei Wang <one"
  },
  {
    "path": "VVDocumenterTests/DocumenterTests/VVMethodTestsCode.plist",
    "chars": 23805,
    "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": "VVDocumenterTests/SyntaxTests/SyntaxTests.m",
    "chars": 7778,
    "preview": "//\n//  SyntaxTests.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-19.\n//\n//  Copyright (c) 2015 Wei Wang <onevca"
  },
  {
    "path": "VVDocumenterTests/VVDocumenterTests-Info.plist",
    "chars": 674,
    "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": "VVDocumenterTests/VVDocumenterTests-Prefix.pch",
    "chars": 319,
    "preview": "//\n// Prefix header for all source files of the 'VVDocumenterTests' target in the 'VVDocumenterTests' project\n//\n\n#ifdef"
  },
  {
    "path": "VVDocumenterTests/VVDocumenterTests.m",
    "chars": 3583,
    "preview": "//\n//  VVDocumenterTests.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-19.\n//\n//  Copyright (c) 2015 Wei Wang <"
  },
  {
    "path": "VVDocumenterTests/VVTestHelper.h",
    "chars": 1493,
    "preview": "//\n//  VVTestHelper.h\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-19.\n//\n//  Copyright (c) 2015 Wei Wang <onevc"
  },
  {
    "path": "VVDocumenterTests/VVTestHelper.m",
    "chars": 11303,
    "preview": "//\n//  VVTestHelper.m\n//  VVDocumenter-Xcode\n//\n//  Created by 王 巍 on 13-7-19.\n//\n//  Copyright (c) 2015 Wei Wang <onevc"
  },
  {
    "path": "VVDocumenterTests/en.lproj/InfoPlist.strings",
    "chars": 45,
    "preview": "/* Localized versions of Info.plist keys */\n\n"
  }
]

About this extraction

This page contains the full source code of the onevcat/VVDocumenter-Xcode GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 72 files (293.7 KB), approximately 79.7k tokens, and a symbol index with 1 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!