diff --git a/.gitignore b/.gitignore index 89c499e..24f1210 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,4 @@ xcuserdata profile *.moved-aside DerivedData -.idea/ +.idea/ \ No newline at end of file diff --git a/Chromatism/Chromatism.xcodeproj/project.pbxproj b/Chromatism/Chromatism.xcodeproj/project.pbxproj index f65a503..4bda488 100644 --- a/Chromatism/Chromatism.xcodeproj/project.pbxproj +++ b/Chromatism/Chromatism.xcodeproj/project.pbxproj @@ -7,254 +7,209 @@ objects = { /* Begin PBXBuildFile section */ - 32102EE117A948F900CFA161 /* Chromatism+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 32102EE017A948F900CFA161 /* Chromatism+Internal.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 32102EED17A95E2900CFA161 /* demo.txt in Resources */ = {isa = PBXBuildFile; fileRef = 32102EEB17A95E2900CFA161 /* demo.txt */; }; - 32102EEE17A95E2900CFA161 /* description.txt in Resources */ = {isa = PBXBuildFile; fileRef = 32102EEC17A95E2900CFA161 /* description.txt */; }; - 3260A15417A8845F008792E6 /* Helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F3AB94E1781C1250023348A /* Helpers.m */; }; - 3260A15617A884EC008792E6 /* JLTokenizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3260A15517A884EC008792E6 /* JLTokenizerTests.m */; }; - 8F3AB92A1781C0BA0023348A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8F3AB9291781C0BA0023348A /* XCTest.framework */; }; - 8F3AB92B1781C0BB0023348A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8F3AB91B1781C0BA0023348A /* Foundation.framework */; }; - 8F3AB92D1781C0BB0023348A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8F3AB92C1781C0BB0023348A /* UIKit.framework */; }; - 8F3AB9301781C0BB0023348A /* libChromatism.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8F3AB9181781C0BA0023348A /* libChromatism.a */; }; - 8F3AB9361781C0BB0023348A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8F3AB9341781C0BB0023348A /* InfoPlist.strings */; }; - 8F3AB9381781C0BB0023348A /* ChromatismTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F3AB9371781C0BB0023348A /* ChromatismTests.m */; }; - 8F3AB9621781C26A0023348A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8F3AB9611781C26A0023348A /* UIKit.framework */; }; - 8F54EF0E1781C776008C1609 /* Chromatism.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F3AB9201781C0BA0023348A /* Chromatism.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8F54EF101781C788008C1609 /* Helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F3AB94D1781C1250023348A /* Helpers.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8F54EF111781C788008C1609 /* JLScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F3AB94F1781C1250023348A /* JLScope.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8F54EF131781C788008C1609 /* JLTextViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F3AB9531781C1250023348A /* JLTextViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8F54EF141781C788008C1609 /* JLTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F3AB9551781C1250023348A /* JLTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8F54EF151781C788008C1609 /* JLTokenPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F3AB9571781C1250023348A /* JLTokenPattern.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8F54EF1E1781CD87008C1609 /* Chromatism.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F3AB9221781C0BA0023348A /* Chromatism.m */; }; - 8F54EF1F1781CD87008C1609 /* Helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F3AB94E1781C1250023348A /* Helpers.m */; }; - 8F54EF201781CD87008C1609 /* JLScope.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F3AB9501781C1250023348A /* JLScope.m */; }; - 8F54EF221781CD87008C1609 /* JLTextViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F3AB9541781C1250023348A /* JLTextViewController.m */; }; - 8F54EF231781CD87008C1609 /* JLTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F3AB9561781C1250023348A /* JLTokenizer.m */; }; - 8F54EF241781CD87008C1609 /* JLTokenPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F3AB9581781C1250023348A /* JLTokenPattern.m */; }; - 8F9F6BC81822F09D00DE15A8 /* JLDiffTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8F9F6BC61822F09D00DE15A8 /* JLDiffTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8F9F6BC91822F09D00DE15A8 /* JLDiffTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8F9F6BC71822F09D00DE15A8 /* JLDiffTokenizer.m */; }; - 8FA0CB0F1795F41B00FF8EB1 /* JLTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 8FA0CB0D1795F41B00FF8EB1 /* JLTextView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8FA0CB101795F41B00FF8EB1 /* JLTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FA0CB0E1795F41B00FF8EB1 /* JLTextView.m */; }; - 8FE2796517C3842900DD933A /* UIColor+Chromatism.h in Headers */ = {isa = PBXBuildFile; fileRef = 8FE2796317C3842900DD933A /* UIColor+Chromatism.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8FE2796617C3842900DD933A /* UIColor+Chromatism.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FE2796417C3842900DD933A /* UIColor+Chromatism.m */; }; - 8FFEB27D183AD6740032C9FB /* JLObjectiveCTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8FFEB27B183AD6740032C9FB /* JLObjectiveCTokenizer.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8FFEB27E183AD6740032C9FB /* JLObjectiveCTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FFEB27C183AD6740032C9FB /* JLObjectiveCTokenizer.m */; }; - 8FFEB283183AD8B70032C9FB /* JLTokenizer+Additions.h in Headers */ = {isa = PBXBuildFile; fileRef = 8FFEB281183AD8B70032C9FB /* JLTokenizer+Additions.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8FFEB284183AD8B70032C9FB /* JLTokenizer+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 8FFEB282183AD8B70032C9FB /* JLTokenizer+Additions.m */; }; + 8F311E86197C8F040030B553 /* ObjectiveC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F311E85197C8F040030B553 /* ObjectiveC.swift */; }; + 8F5961FF198925D70095A8A9 /* JLTokenizingScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F9313B61986A8E900DD3993 /* JLTokenizingScope.swift */; }; + 8F596200198926660095A8A9 /* JLTextStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F9313B11984271F00DD3993 /* JLTextStorage.swift */; }; + 8F5D7ADF197D3B4900D73B8E /* JLLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCDBFF619787C7C00F4B3EC /* JLLanguage.swift */; }; + 8F7922CA197D39B900A94724 /* JLNestedScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F7922C9197D39B900A94724 /* JLNestedScope.swift */; }; + 8F9313B21984271F00DD3993 /* JLTextStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F9313B11984271F00DD3993 /* JLTextStorage.swift */; }; + 8F9313B71986A8E900DD3993 /* JLTokenizingScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F9313B61986A8E900DD3993 /* JLTokenizingScope.swift */; }; + 8F9598A2197448B4002EA4AB /* JLTokenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F9598A1197448B4002EA4AB /* JLTokenTests.swift */; }; + 8FB10D21197EF104001A83B1 /* JLScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FBFC18B19738B7900F75A76 /* JLScope.swift */; }; + 8FB10D22197EF104001A83B1 /* JLDocumentScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FE12922197B5D780084E506 /* JLDocumentScope.swift */; }; + 8FB10D24197EF104001A83B1 /* JLRegexScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F95989D197437BF002EA4AB /* JLRegexScope.swift */; }; + 8FB10D25197EF104001A83B1 /* JLNestedScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F7922C9197D39B900A94724 /* JLNestedScope.swift */; }; + 8FB10D26197EF104001A83B1 /* NSIndexSet+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FBFC18D197418E300F75A76 /* NSIndexSet+Additions.swift */; }; + 8FB10D28197EF104001A83B1 /* JLTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCDBFFC1979940200F4B3EC /* JLTextView.swift */; }; + 8FB10D29197EF104001A83B1 /* JLTextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCDBFFF19799B6700F4B3EC /* JLTextViewController.swift */; }; + 8FB10D2A197EF104001A83B1 /* JLTokenType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCDBFF81978834D00F4B3EC /* JLTokenType.swift */; }; + 8FB10D2B197EF104001A83B1 /* JLColorTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCDBFFA1979615D00F4B3EC /* JLColorTheme.swift */; }; + 8FB10D2C197EF104001A83B1 /* JLLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCDBFF619787C7C00F4B3EC /* JLLanguage.swift */; }; + 8FB10D2F197F0A10001A83B1 /* demo.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8FB10D2E197F0A10001A83B1 /* demo.txt */; }; + 8FBFC17519738B0400F75A76 /* Chromatism.h in Headers */ = {isa = PBXBuildFile; fileRef = 8FBFC17419738B0400F75A76 /* Chromatism.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8FBFC17B19738B0400F75A76 /* Chromatism.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8FBFC16F19738B0400F75A76 /* Chromatism.framework */; }; + 8FBFC18219738B0400F75A76 /* ChromatismTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FBFC18119738B0400F75A76 /* ChromatismTests.swift */; }; + 8FBFC18E197418E300F75A76 /* NSIndexSet+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FBFC18D197418E300F75A76 /* NSIndexSet+Additions.swift */; }; + 8FBFC19219741B6B00F75A76 /* JLScopeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FBFC19119741B6B00F75A76 /* JLScopeTests.swift */; }; + 8FC8F73D198C7B5A00E4ED32 /* JLKeywordScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FC8F73C198C7B5A00E4ED32 /* JLKeywordScope.swift */; }; + 8FC8F73F198C7D1B00E4ED32 /* Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FC8F73E198C7D1B00E4ED32 /* Swift.swift */; }; + 8FC8F740198C7D2400E4ED32 /* JLKeywordScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FC8F73C198C7B5A00E4ED32 /* JLKeywordScope.swift */; }; + 8FC8F742198C7D4800E4ED32 /* JLKeywordScopeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FC8F741198C7D4800E4ED32 /* JLKeywordScopeTests.swift */; }; + 8FCDBFF91978834D00F4B3EC /* JLTokenType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCDBFF81978834D00F4B3EC /* JLTokenType.swift */; }; + 8FCDBFFB1979615D00F4B3EC /* JLColorTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCDBFFA1979615D00F4B3EC /* JLColorTheme.swift */; }; + 8FE1291B197B1D5D0084E506 /* JLScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FBFC18B19738B7900F75A76 /* JLScope.swift */; }; + 8FE1291C197B21900084E506 /* JLRegexScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F95989D197437BF002EA4AB /* JLRegexScope.swift */; }; + 8FE1291E197B21900084E506 /* JLTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCDBFFC1979940200F4B3EC /* JLTextView.swift */; }; + 8FE1291F197B21900084E506 /* JLTextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCDBFFF19799B6700F4B3EC /* JLTextViewController.swift */; }; + 8FE12923197B5D780084E506 /* JLDocumentScope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FE12922197B5D780084E506 /* JLDocumentScope.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 8F3AB92E1781C0BB0023348A /* PBXContainerItemProxy */ = { + 8FBFC17C19738B0400F75A76 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; - containerPortal = 8F3AB9101781C0BA0023348A /* Project object */; + containerPortal = 8FBFC16619738B0400F75A76 /* Project object */; proxyType = 1; - remoteGlobalIDString = 8F3AB9171781C0BA0023348A; + remoteGlobalIDString = 8FBFC16E19738B0400F75A76; remoteInfo = Chromatism; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 32102EE017A948F900CFA161 /* Chromatism+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Chromatism+Internal.h"; sourceTree = ""; }; - 32102EEB17A95E2900CFA161 /* demo.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = demo.txt; path = bundle.bundle/demo.txt; sourceTree = ""; }; - 32102EEC17A95E2900CFA161 /* description.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = description.txt; path = bundle.bundle/description.txt; sourceTree = ""; }; - 3260A15517A884EC008792E6 /* JLTokenizerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JLTokenizerTests.m; sourceTree = ""; }; - 8F3AB9181781C0BA0023348A /* libChromatism.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libChromatism.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 8F3AB91B1781C0BA0023348A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 8F3AB91F1781C0BA0023348A /* Chromatism-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Chromatism-Prefix.pch"; sourceTree = ""; }; - 8F3AB9201781C0BA0023348A /* Chromatism.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Chromatism.h; sourceTree = ""; }; - 8F3AB9221781C0BA0023348A /* Chromatism.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Chromatism.m; sourceTree = ""; }; - 8F3AB9281781C0BA0023348A /* ChromatismTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ChromatismTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 8F3AB9291781C0BA0023348A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - 8F3AB92C1781C0BB0023348A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - 8F3AB9331781C0BB0023348A /* ChromatismTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ChromatismTests-Info.plist"; sourceTree = ""; }; - 8F3AB9351781C0BB0023348A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 8F3AB9371781C0BB0023348A /* ChromatismTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChromatismTests.m; sourceTree = ""; }; - 8F3AB94D1781C1250023348A /* Helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Helpers.h; sourceTree = ""; }; - 8F3AB94E1781C1250023348A /* Helpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Helpers.m; sourceTree = ""; }; - 8F3AB94F1781C1250023348A /* JLScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JLScope.h; sourceTree = ""; }; - 8F3AB9501781C1250023348A /* JLScope.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JLScope.m; sourceTree = ""; }; - 8F3AB9531781C1250023348A /* JLTextViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JLTextViewController.h; sourceTree = ""; }; - 8F3AB9541781C1250023348A /* JLTextViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JLTextViewController.m; sourceTree = ""; }; - 8F3AB9551781C1250023348A /* JLTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JLTokenizer.h; sourceTree = ""; }; - 8F3AB9561781C1250023348A /* JLTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JLTokenizer.m; sourceTree = ""; }; - 8F3AB9571781C1250023348A /* JLTokenPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JLTokenPattern.h; sourceTree = ""; }; - 8F3AB9581781C1250023348A /* JLTokenPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JLTokenPattern.m; sourceTree = ""; }; - 8F3AB95F1781C12F0023348A /* test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = test.json; sourceTree = ""; }; - 8F3AB9611781C26A0023348A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 8F9F6BC61822F09D00DE15A8 /* JLDiffTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JLDiffTokenizer.h; sourceTree = ""; }; - 8F9F6BC71822F09D00DE15A8 /* JLDiffTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JLDiffTokenizer.m; sourceTree = ""; }; - 8FA0CB0D1795F41B00FF8EB1 /* JLTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JLTextView.h; sourceTree = ""; }; - 8FA0CB0E1795F41B00FF8EB1 /* JLTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JLTextView.m; sourceTree = ""; }; - 8FE2796317C3842900DD933A /* UIColor+Chromatism.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+Chromatism.h"; sourceTree = ""; }; - 8FE2796417C3842900DD933A /* UIColor+Chromatism.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+Chromatism.m"; sourceTree = ""; }; - 8FFEB27B183AD6740032C9FB /* JLObjectiveCTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JLObjectiveCTokenizer.h; sourceTree = ""; }; - 8FFEB27C183AD6740032C9FB /* JLObjectiveCTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JLObjectiveCTokenizer.m; sourceTree = ""; }; - 8FFEB281183AD8B70032C9FB /* JLTokenizer+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JLTokenizer+Additions.h"; sourceTree = ""; }; - 8FFEB282183AD8B70032C9FB /* JLTokenizer+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "JLTokenizer+Additions.m"; sourceTree = ""; }; + 8F311E85197C8F040030B553 /* ObjectiveC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectiveC.swift; sourceTree = ""; }; + 8F7922C9197D39B900A94724 /* JLNestedScope.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLNestedScope.swift; sourceTree = ""; }; + 8F9313B11984271F00DD3993 /* JLTextStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLTextStorage.swift; sourceTree = ""; }; + 8F9313B61986A8E900DD3993 /* JLTokenizingScope.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLTokenizingScope.swift; sourceTree = ""; }; + 8F95989D197437BF002EA4AB /* JLRegexScope.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLRegexScope.swift; sourceTree = ""; }; + 8F9598A1197448B4002EA4AB /* JLTokenTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLTokenTests.swift; sourceTree = ""; }; + 8FB10D2E197F0A10001A83B1 /* demo.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = demo.txt; sourceTree = ""; }; + 8FBFC16F19738B0400F75A76 /* Chromatism.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Chromatism.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 8FBFC17319738B0400F75A76 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8FBFC17419738B0400F75A76 /* Chromatism.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Chromatism.h; sourceTree = ""; }; + 8FBFC17A19738B0400F75A76 /* ChromatismTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ChromatismTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 8FBFC18019738B0400F75A76 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8FBFC18119738B0400F75A76 /* ChromatismTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChromatismTests.swift; sourceTree = ""; }; + 8FBFC18B19738B7900F75A76 /* JLScope.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLScope.swift; sourceTree = ""; }; + 8FBFC18D197418E300F75A76 /* NSIndexSet+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSIndexSet+Additions.swift"; sourceTree = ""; }; + 8FBFC19119741B6B00F75A76 /* JLScopeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLScopeTests.swift; sourceTree = ""; }; + 8FC8F73C198C7B5A00E4ED32 /* JLKeywordScope.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLKeywordScope.swift; sourceTree = ""; }; + 8FC8F73E198C7D1B00E4ED32 /* Swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Swift.swift; sourceTree = ""; }; + 8FC8F741198C7D4800E4ED32 /* JLKeywordScopeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLKeywordScopeTests.swift; sourceTree = ""; }; + 8FCDBFF619787C7C00F4B3EC /* JLLanguage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLLanguage.swift; sourceTree = ""; }; + 8FCDBFF81978834D00F4B3EC /* JLTokenType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLTokenType.swift; sourceTree = ""; }; + 8FCDBFFA1979615D00F4B3EC /* JLColorTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLColorTheme.swift; sourceTree = ""; }; + 8FCDBFFC1979940200F4B3EC /* JLTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLTextView.swift; sourceTree = ""; }; + 8FCDBFFF19799B6700F4B3EC /* JLTextViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLTextViewController.swift; sourceTree = ""; }; + 8FE12922197B5D780084E506 /* JLDocumentScope.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JLDocumentScope.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 8F3AB9151781C0BA0023348A /* Frameworks */ = { + 8FBFC16B19738B0400F75A76 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 8F3AB9621781C26A0023348A /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8F3AB9251781C0BA0023348A /* Frameworks */ = { + 8FBFC17719738B0400F75A76 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 8F3AB9301781C0BB0023348A /* libChromatism.a in Frameworks */, - 8F3AB92A1781C0BA0023348A /* XCTest.framework in Frameworks */, - 8F3AB92D1781C0BB0023348A /* UIKit.framework in Frameworks */, - 8F3AB92B1781C0BB0023348A /* Foundation.framework in Frameworks */, + 8FBFC17B19738B0400F75A76 /* Chromatism.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 8F3AB90F1781C0BA0023348A = { + 8F049A28198C93290078063F /* Scopes */ = { isa = PBXGroup; children = ( - 8F3AB91D1781C0BA0023348A /* Chromatism */, - 8F3AB9311781C0BB0023348A /* ChromatismTests */, - 8F3AB91A1781C0BA0023348A /* Frameworks */, - 8F3AB9191781C0BA0023348A /* Products */, + 8FBFC18B19738B7900F75A76 /* JLScope.swift */, + 8F95989D197437BF002EA4AB /* JLRegexScope.swift */, + 8FE12922197B5D780084E506 /* JLDocumentScope.swift */, + 8FC8F73C198C7B5A00E4ED32 /* JLKeywordScope.swift */, + 8F9313B81986A8FE00DD3993 /* Nested Scopes */, ); + name = Scopes; sourceTree = ""; }; - 8F3AB9191781C0BA0023348A /* Products */ = { + 8F9313B81986A8FE00DD3993 /* Nested Scopes */ = { isa = PBXGroup; children = ( - 8F3AB9181781C0BA0023348A /* libChromatism.a */, - 8F3AB9281781C0BA0023348A /* ChromatismTests.xctest */, + 8F7922C9197D39B900A94724 /* JLNestedScope.swift */, + 8F9313B61986A8E900DD3993 /* JLTokenizingScope.swift */, ); - name = Products; + name = "Nested Scopes"; sourceTree = ""; }; - 8F3AB91A1781C0BA0023348A /* Frameworks */ = { + 8FBFC16519738B0400F75A76 = { isa = PBXGroup; children = ( - 8F3AB9611781C26A0023348A /* UIKit.framework */, - 8F3AB91B1781C0BA0023348A /* Foundation.framework */, - 8F3AB9291781C0BA0023348A /* XCTest.framework */, - 8F3AB92C1781C0BB0023348A /* UIKit.framework */, + 8FBFC17119738B0400F75A76 /* Chromatism */, + 8FBFC17E19738B0400F75A76 /* ChromatismTests */, + 8FBFC17019738B0400F75A76 /* Products */, ); - name = Frameworks; - sourceTree = ""; - }; - 8F3AB91D1781C0BA0023348A /* Chromatism */ = { - isa = PBXGroup; - children = ( - 8FFEB280183AD6970032C9FB /* General */, - 8FFEB27F183AD68E0032C9FB /* Tokenizers */, - 8F3AB9531781C1250023348A /* JLTextViewController.h */, - 8F3AB9541781C1250023348A /* JLTextViewController.m */, - 8FA0CB0D1795F41B00FF8EB1 /* JLTextView.h */, - 8FA0CB0E1795F41B00FF8EB1 /* JLTextView.m */, - 8F3AB94F1781C1250023348A /* JLScope.h */, - 8F3AB9501781C1250023348A /* JLScope.m */, - 8F3AB9571781C1250023348A /* JLTokenPattern.h */, - 8F3AB9581781C1250023348A /* JLTokenPattern.m */, - 8F3AB91E1781C0BA0023348A /* Supporting Files */, - ); - path = Chromatism; sourceTree = ""; }; - 8F3AB91E1781C0BA0023348A /* Supporting Files */ = { + 8FBFC17019738B0400F75A76 /* Products */ = { isa = PBXGroup; children = ( - 8F3AB95F1781C12F0023348A /* test.json */, - 8F3AB91F1781C0BA0023348A /* Chromatism-Prefix.pch */, + 8FBFC16F19738B0400F75A76 /* Chromatism.framework */, + 8FBFC17A19738B0400F75A76 /* ChromatismTests.xctest */, ); - name = "Supporting Files"; + name = Products; sourceTree = ""; }; - 8F3AB9311781C0BB0023348A /* ChromatismTests */ = { + 8FBFC17119738B0400F75A76 /* Chromatism */ = { isa = PBXGroup; children = ( - 3260A15517A884EC008792E6 /* JLTokenizerTests.m */, - 8F3AB9371781C0BB0023348A /* ChromatismTests.m */, - 8F3AB9321781C0BB0023348A /* Supporting Files */, + 8FBFC17419738B0400F75A76 /* Chromatism.h */, + 8F049A28198C93290078063F /* Scopes */, + 8F9313B11984271F00DD3993 /* JLTextStorage.swift */, + 8FBFC18D197418E300F75A76 /* NSIndexSet+Additions.swift */, + 8FCDBFFC1979940200F4B3EC /* JLTextView.swift */, + 8FCDBFFF19799B6700F4B3EC /* JLTextViewController.swift */, + 8FCDBFF81978834D00F4B3EC /* JLTokenType.swift */, + 8FCDBFFA1979615D00F4B3EC /* JLColorTheme.swift */, + 8FCDBFF619787C7C00F4B3EC /* JLLanguage.swift */, + 8FBFC17219738B0400F75A76 /* Supporting Files */, ); - path = ChromatismTests; + path = Chromatism; sourceTree = ""; }; - 8F3AB9321781C0BB0023348A /* Supporting Files */ = { + 8FBFC17219738B0400F75A76 /* Supporting Files */ = { isa = PBXGroup; children = ( - 32102EEB17A95E2900CFA161 /* demo.txt */, - 32102EEC17A95E2900CFA161 /* description.txt */, - 8F3AB9331781C0BB0023348A /* ChromatismTests-Info.plist */, - 8F3AB9341781C0BB0023348A /* InfoPlist.strings */, + 8FBFC17319738B0400F75A76 /* Info.plist */, ); name = "Supporting Files"; sourceTree = ""; }; - 8FFEB27F183AD68E0032C9FB /* Tokenizers */ = { + 8FBFC17E19738B0400F75A76 /* ChromatismTests */ = { isa = PBXGroup; children = ( - 8F3AB9551781C1250023348A /* JLTokenizer.h */, - 8F3AB9561781C1250023348A /* JLTokenizer.m */, - 8FFEB281183AD8B70032C9FB /* JLTokenizer+Additions.h */, - 8FFEB282183AD8B70032C9FB /* JLTokenizer+Additions.m */, - 8FFEB27B183AD6740032C9FB /* JLObjectiveCTokenizer.h */, - 8FFEB27C183AD6740032C9FB /* JLObjectiveCTokenizer.m */, - 8F9F6BC61822F09D00DE15A8 /* JLDiffTokenizer.h */, - 8F9F6BC71822F09D00DE15A8 /* JLDiffTokenizer.m */, + 8FC8F741198C7D4800E4ED32 /* JLKeywordScopeTests.swift */, + 8FBFC18119738B0400F75A76 /* ChromatismTests.swift */, + 8FBFC19119741B6B00F75A76 /* JLScopeTests.swift */, + 8F9598A1197448B4002EA4AB /* JLTokenTests.swift */, + 8F311E85197C8F040030B553 /* ObjectiveC.swift */, + 8FC8F73E198C7D1B00E4ED32 /* Swift.swift */, + 8FB10D2E197F0A10001A83B1 /* demo.txt */, + 8FBFC17F19738B0400F75A76 /* Supporting Files */, ); - name = Tokenizers; + path = ChromatismTests; sourceTree = ""; }; - 8FFEB280183AD6970032C9FB /* General */ = { + 8FBFC17F19738B0400F75A76 /* Supporting Files */ = { isa = PBXGroup; children = ( - 8F3AB9201781C0BA0023348A /* Chromatism.h */, - 32102EE017A948F900CFA161 /* Chromatism+Internal.h */, - 8F3AB9221781C0BA0023348A /* Chromatism.m */, - 8F3AB94D1781C1250023348A /* Helpers.h */, - 8F3AB94E1781C1250023348A /* Helpers.m */, - 8FE2796317C3842900DD933A /* UIColor+Chromatism.h */, - 8FE2796417C3842900DD933A /* UIColor+Chromatism.m */, + 8FBFC18019738B0400F75A76 /* Info.plist */, ); - name = General; + name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 8F54EF0D1781C769008C1609 /* Headers */ = { + 8FBFC16C19738B0400F75A76 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 32102EE117A948F900CFA161 /* Chromatism+Internal.h in Headers */, - 8F9F6BC81822F09D00DE15A8 /* JLDiffTokenizer.h in Headers */, - 8FA0CB0F1795F41B00FF8EB1 /* JLTextView.h in Headers */, - 8F54EF0E1781C776008C1609 /* Chromatism.h in Headers */, - 8F54EF101781C788008C1609 /* Helpers.h in Headers */, - 8FE2796517C3842900DD933A /* UIColor+Chromatism.h in Headers */, - 8F54EF111781C788008C1609 /* JLScope.h in Headers */, - 8FFEB27D183AD6740032C9FB /* JLObjectiveCTokenizer.h in Headers */, - 8F54EF131781C788008C1609 /* JLTextViewController.h in Headers */, - 8FFEB283183AD8B70032C9FB /* JLTokenizer+Additions.h in Headers */, - 8F54EF141781C788008C1609 /* JLTokenizer.h in Headers */, - 8F54EF151781C788008C1609 /* JLTokenPattern.h in Headers */, + 8FBFC17519738B0400F75A76 /* Chromatism.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 8F3AB9171781C0BA0023348A /* Chromatism */ = { + 8FBFC16E19738B0400F75A76 /* Chromatism */ = { isa = PBXNativeTarget; - buildConfigurationList = 8F3AB93B1781C0BB0023348A /* Build configuration list for PBXNativeTarget "Chromatism" */; + buildConfigurationList = 8FBFC18519738B0400F75A76 /* Build configuration list for PBXNativeTarget "Chromatism" */; buildPhases = ( - 8F3AB9141781C0BA0023348A /* Sources */, - 8F3AB9151781C0BA0023348A /* Frameworks */, - 8F54EF0D1781C769008C1609 /* Headers */, + 8FBFC16A19738B0400F75A76 /* Sources */, + 8FBFC16B19738B0400F75A76 /* Frameworks */, + 8FBFC16C19738B0400F75A76 /* Headers */, + 8FBFC16D19738B0400F75A76 /* Resources */, ); buildRules = ( ); @@ -262,119 +217,140 @@ ); name = Chromatism; productName = Chromatism; - productReference = 8F3AB9181781C0BA0023348A /* libChromatism.a */; - productType = "com.apple.product-type.library.static"; + productReference = 8FBFC16F19738B0400F75A76 /* Chromatism.framework */; + productType = "com.apple.product-type.framework"; }; - 8F3AB9271781C0BA0023348A /* ChromatismTests */ = { + 8FBFC17919738B0400F75A76 /* ChromatismTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 8F3AB93E1781C0BB0023348A /* Build configuration list for PBXNativeTarget "ChromatismTests" */; + buildConfigurationList = 8FBFC18819738B0400F75A76 /* Build configuration list for PBXNativeTarget "ChromatismTests" */; buildPhases = ( - 8F3AB9241781C0BA0023348A /* Sources */, - 8F3AB9251781C0BA0023348A /* Frameworks */, - 8F3AB9261781C0BA0023348A /* Resources */, + 8FBFC17619738B0400F75A76 /* Sources */, + 8FBFC17719738B0400F75A76 /* Frameworks */, + 8FBFC17819738B0400F75A76 /* Resources */, ); buildRules = ( ); dependencies = ( - 8F3AB92F1781C0BB0023348A /* PBXTargetDependency */, + 8FBFC17D19738B0400F75A76 /* PBXTargetDependency */, ); name = ChromatismTests; productName = ChromatismTests; - productReference = 8F3AB9281781C0BA0023348A /* ChromatismTests.xctest */; + productReference = 8FBFC17A19738B0400F75A76 /* ChromatismTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 8F3AB9101781C0BA0023348A /* Project object */ = { + 8FBFC16619738B0400F75A76 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0500; - ORGANIZATIONNAME = Anviking; + LastUpgradeCheck = 0600; + ORGANIZATIONNAME = anviking; + TargetAttributes = { + 8FBFC16E19738B0400F75A76 = { + CreatedOnToolsVersion = 6.0; + }; + 8FBFC17919738B0400F75A76 = { + CreatedOnToolsVersion = 6.0; + TestTargetID = 8FBFC16E19738B0400F75A76; + }; + }; }; - buildConfigurationList = 8F3AB9131781C0BA0023348A /* Build configuration list for PBXProject "Chromatism" */; + buildConfigurationList = 8FBFC16919738B0400F75A76 /* Build configuration list for PBXProject "Chromatism" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); - mainGroup = 8F3AB90F1781C0BA0023348A; - productRefGroup = 8F3AB9191781C0BA0023348A /* Products */; + mainGroup = 8FBFC16519738B0400F75A76; + productRefGroup = 8FBFC17019738B0400F75A76 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 8F3AB9171781C0BA0023348A /* Chromatism */, - 8F3AB9271781C0BA0023348A /* ChromatismTests */, + 8FBFC16E19738B0400F75A76 /* Chromatism */, + 8FBFC17919738B0400F75A76 /* ChromatismTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 8F3AB9261781C0BA0023348A /* Resources */ = { + 8FBFC16D19738B0400F75A76 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8FBFC17819738B0400F75A76 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8F3AB9361781C0BB0023348A /* InfoPlist.strings in Resources */, - 32102EEE17A95E2900CFA161 /* description.txt in Resources */, - 32102EED17A95E2900CFA161 /* demo.txt in Resources */, + 8FB10D2F197F0A10001A83B1 /* demo.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 8F3AB9141781C0BA0023348A /* Sources */ = { + 8FBFC16A19738B0400F75A76 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8F54EF241781CD87008C1609 /* JLTokenPattern.m in Sources */, - 8FFEB27E183AD6740032C9FB /* JLObjectiveCTokenizer.m in Sources */, - 8F9F6BC91822F09D00DE15A8 /* JLDiffTokenizer.m in Sources */, - 8FFEB284183AD8B70032C9FB /* JLTokenizer+Additions.m in Sources */, - 8F54EF201781CD87008C1609 /* JLScope.m in Sources */, - 8FE2796617C3842900DD933A /* UIColor+Chromatism.m in Sources */, - 8FA0CB101795F41B00FF8EB1 /* JLTextView.m in Sources */, - 8F54EF1F1781CD87008C1609 /* Helpers.m in Sources */, - 8F54EF221781CD87008C1609 /* JLTextViewController.m in Sources */, - 8F54EF231781CD87008C1609 /* JLTokenizer.m in Sources */, - 8F54EF1E1781CD87008C1609 /* Chromatism.m in Sources */, + 8FC8F73D198C7B5A00E4ED32 /* JLKeywordScope.swift in Sources */, + 8FE1291E197B21900084E506 /* JLTextView.swift in Sources */, + 8F7922CA197D39B900A94724 /* JLNestedScope.swift in Sources */, + 8FE1291B197B1D5D0084E506 /* JLScope.swift in Sources */, + 8FCDBFF91978834D00F4B3EC /* JLTokenType.swift in Sources */, + 8FCDBFFB1979615D00F4B3EC /* JLColorTheme.swift in Sources */, + 8F5D7ADF197D3B4900D73B8E /* JLLanguage.swift in Sources */, + 8FBFC18E197418E300F75A76 /* NSIndexSet+Additions.swift in Sources */, + 8FE1291C197B21900084E506 /* JLRegexScope.swift in Sources */, + 8FE1291F197B21900084E506 /* JLTextViewController.swift in Sources */, + 8FE12923197B5D780084E506 /* JLDocumentScope.swift in Sources */, + 8F9313B21984271F00DD3993 /* JLTextStorage.swift in Sources */, + 8F9313B71986A8E900DD3993 /* JLTokenizingScope.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8F3AB9241781C0BA0023348A /* Sources */ = { + 8FBFC17619738B0400F75A76 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8F3AB9381781C0BB0023348A /* ChromatismTests.m in Sources */, - 3260A15417A8845F008792E6 /* Helpers.m in Sources */, - 3260A15617A884EC008792E6 /* JLTokenizerTests.m in Sources */, + 8FBFC19219741B6B00F75A76 /* JLScopeTests.swift in Sources */, + 8FB10D22197EF104001A83B1 /* JLDocumentScope.swift in Sources */, + 8F9598A2197448B4002EA4AB /* JLTokenTests.swift in Sources */, + 8FB10D21197EF104001A83B1 /* JLScope.swift in Sources */, + 8F5961FF198925D70095A8A9 /* JLTokenizingScope.swift in Sources */, + 8FB10D2C197EF104001A83B1 /* JLLanguage.swift in Sources */, + 8FB10D28197EF104001A83B1 /* JLTextView.swift in Sources */, + 8FB10D2B197EF104001A83B1 /* JLColorTheme.swift in Sources */, + 8F311E86197C8F040030B553 /* ObjectiveC.swift in Sources */, + 8FBFC18219738B0400F75A76 /* ChromatismTests.swift in Sources */, + 8FC8F73F198C7D1B00E4ED32 /* Swift.swift in Sources */, + 8FB10D29197EF104001A83B1 /* JLTextViewController.swift in Sources */, + 8FC8F740198C7D2400E4ED32 /* JLKeywordScope.swift in Sources */, + 8FB10D25197EF104001A83B1 /* JLNestedScope.swift in Sources */, + 8FB10D24197EF104001A83B1 /* JLRegexScope.swift in Sources */, + 8FC8F742198C7D4800E4ED32 /* JLKeywordScopeTests.swift in Sources */, + 8FB10D2A197EF104001A83B1 /* JLTokenType.swift in Sources */, + 8F596200198926660095A8A9 /* JLTextStorage.swift in Sources */, + 8FB10D26197EF104001A83B1 /* NSIndexSet+Additions.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 8F3AB92F1781C0BB0023348A /* PBXTargetDependency */ = { + 8FBFC17D19738B0400F75A76 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 8F3AB9171781C0BA0023348A /* Chromatism */; - targetProxy = 8F3AB92E1781C0BB0023348A /* PBXContainerItemProxy */; + target = 8FBFC16E19738B0400F75A76 /* Chromatism */; + targetProxy = 8FBFC17C19738B0400F75A76 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ -/* Begin PBXVariantGroup section */ - 8F3AB9341781C0BB0023348A /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 8F3AB9351781C0BB0023348A /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ - 8F3AB9391781C0BB0023348A /* Debug */ = { + 8FBFC18319738B0400F75A76 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -389,8 +365,12 @@ CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -399,21 +379,24 @@ "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - PRIVATE_HEADERS_FOLDER_PATH = "$(PUBLIC_HEADERS_FOLDER_PATH)/Private"; - PRODUCT_NAME = Chromatism; - PUBLIC_HEADERS_FOLDER_PATH = ../../Headers/Chromatism; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Debug; }; - 8F3AB93A1781C0BB0023348A /* Release */ = { + 8FBFC18419738B0400F75A76 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -428,125 +411,124 @@ CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; + CURRENT_PROJECT_VERSION = 1; ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - PRIVATE_HEADERS_FOLDER_PATH = "$(PUBLIC_HEADERS_FOLDER_PATH)/Private"; - PRODUCT_NAME = Chromatism; - PUBLIC_HEADERS_FOLDER_PATH = ../../Headers/Chromatism; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Release; }; - 8F3AB93C1781C0BB0023348A /* Debug */ = { + 8FBFC18619738B0400F75A76 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - DSTROOT = /tmp/Chromatism.dst; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "Chromatism/Chromatism-Prefix.pch"; - OTHER_LDFLAGS = "-ObjC"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Chromatism/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; - 8F3AB93D1781C0BB0023348A /* Release */ = { + 8FBFC18719738B0400F75A76 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - DSTROOT = /tmp/Chromatism.dst; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "Chromatism/Chromatism-Prefix.pch"; - OTHER_LDFLAGS = "-ObjC"; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Chromatism/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; - 8F3AB93F1781C0BB0023348A /* Debug */ = { + 8FBFC18919738B0400F75A76 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", - "$(SYSTEM_APPS_DIR)/Xcode5-DP2.app/Contents/Developer/Library/Frameworks", ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "Chromatism/Chromatism-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - INFOPLIST_FILE = "ChromatismTests/ChromatismTests-Info.plist"; + INFOPLIST_FILE = ChromatismTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - WRAPPER_EXTENSION = xctest; }; name = Debug; }; - 8F3AB9401781C0BB0023348A /* Release */ = { + 8FBFC18A19738B0400F75A76 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CODE_SIGN_IDENTITY = "iPhone Developer"; FRAMEWORK_SEARCH_PATHS = ( "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", - "$(SYSTEM_APPS_DIR)/Xcode5-DP2.app/Contents/Developer/Library/Frameworks", ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "Chromatism/Chromatism-Prefix.pch"; - INFOPLIST_FILE = "ChromatismTests/ChromatismTests-Info.plist"; + INFOPLIST_FILE = ChromatismTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - WRAPPER_EXTENSION = xctest; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 8F3AB9131781C0BA0023348A /* Build configuration list for PBXProject "Chromatism" */ = { + 8FBFC16919738B0400F75A76 /* Build configuration list for PBXProject "Chromatism" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8F3AB9391781C0BB0023348A /* Debug */, - 8F3AB93A1781C0BB0023348A /* Release */, + 8FBFC18319738B0400F75A76 /* Debug */, + 8FBFC18419738B0400F75A76 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 8F3AB93B1781C0BB0023348A /* Build configuration list for PBXNativeTarget "Chromatism" */ = { + 8FBFC18519738B0400F75A76 /* Build configuration list for PBXNativeTarget "Chromatism" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8F3AB93C1781C0BB0023348A /* Debug */, - 8F3AB93D1781C0BB0023348A /* Release */, + 8FBFC18619738B0400F75A76 /* Debug */, + 8FBFC18719738B0400F75A76 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 8F3AB93E1781C0BB0023348A /* Build configuration list for PBXNativeTarget "ChromatismTests" */ = { + 8FBFC18819738B0400F75A76 /* Build configuration list for PBXNativeTarget "ChromatismTests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8F3AB93F1781C0BB0023348A /* Debug */, - 8F3AB9401781C0BB0023348A /* Release */, + 8FBFC18919738B0400F75A76 /* Debug */, + 8FBFC18A19738B0400F75A76 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = 8F3AB9101781C0BA0023348A /* Project object */; + rootObject = 8FBFC16619738B0400F75A76 /* Project object */; } diff --git a/Chromatism/Chromatism.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Chromatism/Chromatism.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..ce15b4f --- /dev/null +++ b/Chromatism/Chromatism.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Chromatism/Chromatism.xcodeproj/project.xcworkspace/xcuserdata/Johannes.xcuserdatad/UserInterfaceState.xcuserstate b/Chromatism/Chromatism.xcodeproj/project.xcworkspace/xcuserdata/Johannes.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..ab9f575 Binary files /dev/null and b/Chromatism/Chromatism.xcodeproj/project.xcworkspace/xcuserdata/Johannes.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Chromatism/Chromatism.xcodeproj/xcshareddata/xcbaselines/8FBFC17919738B0400F75A76.xcbaseline/E1C12967-B873-405D-A325-ACEC65C43CDC.plist b/Chromatism/Chromatism.xcodeproj/xcshareddata/xcbaselines/8FBFC17919738B0400F75A76.xcbaseline/E1C12967-B873-405D-A325-ACEC65C43CDC.plist new file mode 100644 index 0000000..2cd977b --- /dev/null +++ b/Chromatism/Chromatism.xcodeproj/xcshareddata/xcbaselines/8FBFC17919738B0400F75A76.xcbaseline/E1C12967-B873-405D-A325-ACEC65C43CDC.plist @@ -0,0 +1,224 @@ + + + + + classNames + + C + + testBlockComments() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0099999997764825821 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testEverything() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.029999999329447746 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + + JLKeywordScopeTests + + testKeywordPattern() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.029999999329447746 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testOrdinaryPattern() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0099999997764825821 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + + ObjectiveC + + testBlockComments() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0099999997764825821 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testDotNotation() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testEverything() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 1.8200000524520874 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testFunctions() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testKeywords() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.029999999329447746 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testLineComments() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testMethodCallParts() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.029999999329447746 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testMethodCalls() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.029999999329447746 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testNumbers() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testObjectiveCKeywords() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testPreprocessor() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0099999997764825821 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testSquareBrackets() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 1.1699999570846558 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + testStrings() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 10 + + + + + performanceMetricIdentifiers + + + diff --git a/Chromatism/Chromatism.xcodeproj/xcshareddata/xcbaselines/8FBFC17919738B0400F75A76.xcbaseline/Info.plist b/Chromatism/Chromatism.xcodeproj/xcshareddata/xcbaselines/8FBFC17919738B0400F75A76.xcbaseline/Info.plist new file mode 100644 index 0000000..13d3897 --- /dev/null +++ b/Chromatism/Chromatism.xcodeproj/xcshareddata/xcbaselines/8FBFC17919738B0400F75A76.xcbaseline/Info.plist @@ -0,0 +1,40 @@ + + + + + runDestinationsByUUID + + E1C12967-B873-405D-A325-ACEC65C43CDC + + localComputer + + busSpeedInMHz + 100 + cpuCount + 1 + cpuKind + Intel Core i7 + cpuSpeedInMHz + 2300 + logicalCPUCoresPerPackage + 8 + modelCode + MacBookPro10,1 + physicalCPUCoresPerPackage + 4 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + x86_64 + targetDevice + + modelCode + iPhone6,1 + platformIdentifier + com.apple.platform.iphonesimulator + + + + + diff --git a/Chromatism/Chromatism.xcodeproj/xcuserdata/Johannes.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Chromatism/Chromatism.xcodeproj/xcuserdata/Johannes.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..8f94031 --- /dev/null +++ b/Chromatism/Chromatism.xcodeproj/xcuserdata/Johannes.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/Chromatism/Chromatism.xcodeproj/xcuserdata/Johannes.xcuserdatad/xcschemes/Chromatism.xcscheme b/Chromatism/Chromatism.xcodeproj/xcuserdata/Johannes.xcuserdatad/xcschemes/Chromatism.xcscheme new file mode 100644 index 0000000..5311f63 --- /dev/null +++ b/Chromatism/Chromatism.xcodeproj/xcuserdata/Johannes.xcuserdatad/xcschemes/Chromatism.xcscheme @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Chromatism/Chromatism.xcodeproj/xcuserdata/Johannes.xcuserdatad/xcschemes/xcschememanagement.plist b/Chromatism/Chromatism.xcodeproj/xcuserdata/Johannes.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..a76e991 --- /dev/null +++ b/Chromatism/Chromatism.xcodeproj/xcuserdata/Johannes.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,27 @@ + + + + + SchemeUserState + + Chromatism.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 8FBFC16E19738B0400F75A76 + + primary + + + 8FBFC17919738B0400F75A76 + + primary + + + + + diff --git a/Chromatism/Chromatism/Chromatism+Internal.h b/Chromatism/Chromatism/Chromatism+Internal.h deleted file mode 100644 index f325da9..0000000 --- a/Chromatism/Chromatism/Chromatism+Internal.h +++ /dev/null @@ -1,68 +0,0 @@ -// -// ChromatismInternal.h -// Chromatism -// -// Created by Anviking on 2013-07-31. -// Copyright (c) 2013 Johannes Lund -// -// 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 - -typedef NS_ENUM(NSInteger, JLTokenizerTheme) { - JLTokenizerThemeDefault, - JLTokenizerThemeDusk -}; - -#ifdef DEBUG -# define ChromatismLog(...) NSLog(__VA_ARGS__) -#else -# define ChromatismLog(...) -#endif - -FOUNDATION_EXPORT NSString *const JLTokenTypeText; -FOUNDATION_EXPORT NSString *const JLTokenTypeBackground; -FOUNDATION_EXPORT NSString *const JLTokenTypeComment; -FOUNDATION_EXPORT NSString *const JLTokenTypeDocumentationComment; -FOUNDATION_EXPORT NSString *const JLTokenTypeDocumentationCommentKeyword; -FOUNDATION_EXPORT NSString *const JLTokenTypeString; -FOUNDATION_EXPORT NSString *const JLTokenTypeCharacter; -FOUNDATION_EXPORT NSString *const JLTokenTypeNumber; -FOUNDATION_EXPORT NSString *const JLTokenTypeKeyword; -FOUNDATION_EXPORT NSString *const JLTokenTypePreprocessor; -FOUNDATION_EXPORT NSString *const JLTokenTypeURL; -FOUNDATION_EXPORT NSString *const JLTokenTypeOther; -FOUNDATION_EXPORT NSString *const JLTokenTypeOtherClassNames; -FOUNDATION_EXPORT NSString *const JLTokenTypeOtherMethodNames; -FOUNDATION_EXPORT NSString *const JLTokenTypeProjectClassNames; -FOUNDATION_EXPORT NSString *const JLTokenTypeProjectMethodNames; -FOUNDATION_EXPORT NSString *const JLTokenTypeDiffAddition; -FOUNDATION_EXPORT NSString *const JLTokenTypeDiffDeletion; - -/// Used as attribute in NSAttributedStrings. You may subclass NSLayoutManager to use this attribute. -FOUNDATION_EXPORT NSString *const JLDiffColorAttributeName; - -/** - * In addition to being the name of the library, the Chromatism class handles colors and TokenTypes - */ - -@interface Chromatism : NSObject - -+ (NSDictionary *)colorsForTheme:(JLTokenizerTheme)theme; - -@end diff --git a/Chromatism/Chromatism/Chromatism-Prefix.pch b/Chromatism/Chromatism/Chromatism-Prefix.pch deleted file mode 100644 index eb2007e..0000000 --- a/Chromatism/Chromatism/Chromatism-Prefix.pch +++ /dev/null @@ -1,9 +0,0 @@ -// -// Prefix header -// -// The contents of this file are implicitly included at the beginning of every source file. -// - -#ifdef __OBJC__ - #import -#endif diff --git a/Chromatism/Chromatism/Chromatism.h b/Chromatism/Chromatism/Chromatism.h index b0dae4e..6172a04 100644 --- a/Chromatism/Chromatism/Chromatism.h +++ b/Chromatism/Chromatism/Chromatism.h @@ -2,34 +2,18 @@ // Chromatism.h // Chromatism // -// Created by Johannes Lund on 2013-07-01. -// Copyright (c) 2013 Johannes Lund +// Created by Johannes Lund on 2014-07-14. +// Copyright (c) 2014 anviking. All rights reserved. // -// 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. +#import + +//! Project version number for Chromatism. +FOUNDATION_EXPORT double ChromatismVersionNumber; + +//! Project version string for Chromatism. +FOUNDATION_EXPORT const unsigned char ChromatismVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import -// 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 -#import "JLScope.h" -#import "JLTokenizer.h" -#import "JLTextViewController.h" -#import "JLTokenPattern.h" -#import "JLTextView.h" -#import "UIColor+Chromatism.h" -#import "JLDiffTokenizer.h" -#import "JLTokenizer+Additions.h" -#import "JLObjectiveCTokenizer.h" -#import "Chromatism+Internal.h" \ No newline at end of file diff --git a/Chromatism/Chromatism/Chromatism.m b/Chromatism/Chromatism/Chromatism.m deleted file mode 100644 index 3bc78ec..0000000 --- a/Chromatism/Chromatism/Chromatism.m +++ /dev/null @@ -1,110 +0,0 @@ -// -// Chromatism.m -// Chromatism -// -// Created by Johannes Lund on 2013-07-01. -// Copyright (c) 2013 Johannes Lund -// -// 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 "Chromatism+Internal.h" -#import "Helpers.h" - -NSString *const JLTokenTypeText = @"text"; -NSString *const JLTokenTypeBackground = @"background"; -NSString *const JLTokenTypeComment = @"comment"; -NSString *const JLTokenTypeDocumentationComment = @"documentation_comment"; -NSString *const JLTokenTypeDocumentationCommentKeyword = @"documentation_comment_keyword"; -NSString *const JLTokenTypeString = @"string"; -NSString *const JLTokenTypeCharacter = @"character"; -NSString *const JLTokenTypeNumber = @"number"; -NSString *const JLTokenTypeKeyword = @"keyword"; -NSString *const JLTokenTypePreprocessor = @"preprocessor"; -NSString *const JLTokenTypeURL = @"url"; -NSString *const JLTokenTypeAttribute = @"attribute"; -NSString *const JLTokenTypeProject = @"project"; -NSString *const JLTokenTypeOther = @"other"; -NSString *const JLTokenTypeOtherMethodNames = @"other_method_names"; -NSString *const JLTokenTypeOtherClassNames = @"other_class_names"; -NSString *const JLTokenTypeProjectMethodNames = @"project_method_names"; -NSString *const JLTokenTypeProjectClassNames = @"project_class_names"; - - -NSString *const JLTokenTypeDiffAddition = @"diff_addition"; -NSString *const JLTokenTypeDiffDeletion = @"diff_deletion"; - -NSString *const JLDiffColorAttributeName = @"diff_color_attribute_name"; - - -@implementation Chromatism - -+ (NSDictionary *)colorsForTheme:(JLTokenizerTheme)theme -{ - NSDictionary* colors; - switch(theme) { - case JLTokenizerThemeDefault: - colors = @{JLTokenTypeText: [UIColor colorWithRed:0.0/255 green:0.0/255 blue:0.0/255 alpha:1], - JLTokenTypeBackground: [UIColor colorWithRed:255.0/255 green:255.0/255 blue:255.0/255 alpha:1], - JLTokenTypeComment: [UIColor colorWithRed:0.0/255 green:131.0/255 blue:39.0/255 alpha:1], - JLTokenTypeDocumentationComment: [UIColor colorWithRed:0.0/255 green:131.0/255 blue:39.0/255 alpha:1], - JLTokenTypeDocumentationCommentKeyword: [UIColor colorWithRed:0.0/255 green:76.0/255 blue:29.0/255 alpha:1], - JLTokenTypeString: [UIColor colorWithRed:211.0/255 green:45.0/255 blue:38.0/255 alpha:1], - JLTokenTypeCharacter: [UIColor colorWithRed:40.0/255 green:52.0/255 blue:206.0/255 alpha:1], - JLTokenTypeNumber: [UIColor colorWithRed:40.0/255 green:52.0/255 blue:206.0/255 alpha:1], - JLTokenTypeKeyword: [UIColor colorWithRed:188.0/255 green:49.0/255 blue:156.0/255 alpha:1], - JLTokenTypePreprocessor: [UIColor colorWithRed:120.0/255 green:72.0/255 blue:48.0/255 alpha:1], - JLTokenTypeURL: [UIColor colorWithRed:21.0/255 green:67.0/255 blue:244.0/255 alpha:1], - JLTokenTypeOther: [UIColor colorWithRed:113.0/255 green:65.0/255 blue:163.0/255 alpha:1], - JLTokenTypeOtherMethodNames : [UIColor colorWithHex:@"7040a6" alpha:1], - JLTokenTypeOtherClassNames : [UIColor colorWithHex:@"7040a6" alpha:1], - JLTokenTypeProjectClassNames : [UIColor colorWithRed:63.0/255 green:110.0/255 blue:116.0/255 alpha:1], - JLTokenTypeProjectMethodNames : [UIColor colorWithRed:38.0/255 green:71.0/255 blue:75.0/255 alpha:1], - - JLTokenTypeDiffAddition : [UIColor greenColor], - JLTokenTypeDiffDeletion : [UIColor redColor] - - }; - break; - case JLTokenizerThemeDusk: - colors = @{JLTokenTypeText: [UIColor whiteColor], - JLTokenTypeBackground: [UIColor colorWithRed:30.0/255.0 green:32.0/255.0 blue:40.0/255.0 alpha:1], - JLTokenTypeComment: [UIColor colorWithRed:72.0/255 green:190.0/255 blue:102.0/255 alpha:1], - JLTokenTypeDocumentationComment: [UIColor colorWithRed:72.0/255 green:190.0/255 blue:102.0/255 alpha:1], - JLTokenTypeDocumentationCommentKeyword: [UIColor colorWithRed:72.0/255 green:190.0/255 blue:102.0/255 alpha:1], - JLTokenTypeString: [UIColor colorWithRed:230.0/255 green:66.0/255 blue:75.0/255 alpha:1], - JLTokenTypeCharacter: [UIColor colorWithRed:139.0/255 green:134.0/255 blue:201.0/255 alpha:1], - JLTokenTypeNumber: [UIColor colorWithRed:139.0/255 green:134.0/255 blue:201.0/255 alpha:1], - JLTokenTypeKeyword: [UIColor colorWithRed:195.0/255 green:55.0/255 blue:149.0/255 alpha:1], - JLTokenTypePreprocessor: [UIColor colorWithRed:198.0/255.0 green:124.0/255.0 blue:72.0/255.0 alpha:1], - JLTokenTypeURL: [UIColor colorWithRed:35.0/255 green:63.0/255 blue:208.0/255 alpha:1], - JLTokenTypeOther: [UIColor colorWithRed:0.0/255 green:175.0/255 blue:199.0/255 alpha:1], - JLTokenTypeOtherClassNames : [UIColor colorWithHex:@"04afc8" alpha:1], - JLTokenTypeOtherMethodNames : [UIColor colorWithHex:@"04afc8" alpha:1], - JLTokenTypeProjectMethodNames : [UIColor colorWithRed:131.0/255 green:192.0/255 blue:87.0/255 alpha:1], - JLTokenTypeProjectClassNames : [UIColor colorWithRed:131.0/255 green:192.0/255 blue:87.0/255 alpha:1], - - JLTokenTypeDiffAddition : [UIColor greenColor], - JLTokenTypeDiffDeletion : [UIColor redColor] - - }; - break; - } - return colors; -} - -@end diff --git a/Chromatism/Chromatism/Helpers.h b/Chromatism/Chromatism/Helpers.h deleted file mode 100644 index 2f183bf..0000000 --- a/Chromatism/Chromatism/Helpers.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// NSString+Helper.h -// TextTest -// -// Created by Johannes Lund on 2012-07-13. -// Copyright (c) 2012 Anviking. All rights reserved. -// - -@import UIKit; - -@interface NSString (Helper) -- (BOOL)string:(NSString *)longString containsString:(NSString *)shortString; -- (NSMutableArray *)allOccurrencesOfString:(NSString *)searchString; -@end - -@interface NSArray (Helper) -- (NSArray *)uniqueArray; -@end - -@interface NSMutableArray (Helper) -- (NSMutableArray *)uniqueArray; -@end - -@interface UIColor (Helper) - -// wrapper for [UIColor colorWithRed:green:blue:alpha:] -// values must be in range 0 - 255 -+ (UIColor *)colorWith8BitRed:(NSInteger)red green:(NSInteger)green blue:(NSInteger)blue alpha:(CGFloat)alpha; - -// Creates color using hex representation -// hex - must be in format: #FF00CC -// alpha - must be in range 0.0 - 1.0 -+ (UIColor *)colorWithHex:(NSString*)hex alpha:(CGFloat)alpha; - -@end - -@interface NSValue (Helper) -- (NSComparisonResult)compareTo:(NSValue *)range; -@end - -@interface NSDate (Helper) - -- (NSString *)iso8601String; - -@end - -@interface NSIndexSet (GSIndexSetAdditions) - -- (NSMutableIndexSet *)intersectionWithSet:(NSIndexSet *)otherSet; - -@end - - - diff --git a/Chromatism/Chromatism/Helpers.m b/Chromatism/Chromatism/Helpers.m deleted file mode 100644 index 01c65f2..0000000 --- a/Chromatism/Chromatism/Helpers.m +++ /dev/null @@ -1,54 +0,0 @@ -// -// NSString+Helper.m -// TextTest -// -// Created by Johannes Lund on 2012-07-13. -// Copyright (c) 2012 Anviking. All rights reserved. -// - -#import "Helpers.h" - -@implementation UIColor (CreateMethods) - -+ (UIColor*)colorWith8BitRed:(NSInteger)red green:(NSInteger)green blue:(NSInteger)blue alpha:(CGFloat)alpha { - return [UIColor colorWithRed:(red/255.0) green:(green/255.0) blue:(blue/255.0) alpha:alpha]; -} - -+ (UIColor*)colorWithHex:(NSString*)hex alpha:(CGFloat)alpha { - - if (hex.length != 6) return nil; - - NSString *redHex = [NSString stringWithFormat:@"0x%@", [hex substringWithRange:NSMakeRange(0, 2)]]; - NSString *greenHex = [NSString stringWithFormat:@"0x%@", [hex substringWithRange:NSMakeRange(2, 2)]]; - NSString *blueHex = [NSString stringWithFormat:@"0x%@", [hex substringWithRange:NSMakeRange(4, 2)]]; - - unsigned redInt = 0; - NSScanner *rScanner = [NSScanner scannerWithString:redHex]; - [rScanner scanHexInt:&redInt]; - - unsigned greenInt = 0; - NSScanner *gScanner = [NSScanner scannerWithString:greenHex]; - [gScanner scanHexInt:&greenInt]; - - unsigned blueInt = 0; - NSScanner *bScanner = [NSScanner scannerWithString:blueHex]; - [bScanner scanHexInt:&blueInt]; - - return [UIColor colorWith8BitRed:redInt green:greenInt blue:blueInt alpha:alpha]; -} - -@end - -@implementation NSIndexSet (GSIndexSetAdditions) - -- (NSMutableIndexSet *)intersectionWithSet:(NSIndexSet *)otherSet -{ - NSMutableIndexSet *finalSet = [NSMutableIndexSet indexSet]; - [self enumerateIndexesUsingBlock:^(NSUInteger index, BOOL *stop) { - if ([otherSet containsIndex:index]) [finalSet addIndex:index]; - }]; - - return finalSet; -} - -@end diff --git a/Chromatism/Chromatism/Info.plist b/Chromatism/Chromatism/Info.plist new file mode 100644 index 0000000..09af5a8 --- /dev/null +++ b/Chromatism/Chromatism/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + anviking.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Chromatism/Chromatism/JLColorTheme.swift b/Chromatism/Chromatism/JLColorTheme.swift new file mode 100644 index 0000000..ef1a9a9 --- /dev/null +++ b/Chromatism/Chromatism/JLColorTheme.swift @@ -0,0 +1,79 @@ +// +// JLColorTheme.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-18. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +func UIColorRGB(r:Int, g:Int, b:Int) -> UIColor { + return UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: 1.0) +} + +public enum JLColorTheme { + case Default, Dusk, Other([JLTokenType: UIColor]) + + public subscript(type: JLTokenType) -> UIColor? { + return dictionary[type] + } + + private static let defaultTheme: [JLTokenType: UIColor] = [ + .Text: UIColor.blackColor(), + .Background: UIColorRGB(255, 255, 255), + .Comment: UIColorRGB(0, 131, 39), + .DocumentationComment: UIColorRGB(0, 131, 39), + .DocumentationCommentKeyword: UIColorRGB(0, 76, 29), + .String: UIColorRGB(211, 45, 38), + .Character: UIColorRGB(40, 52, 206), + .Number: UIColorRGB(40, 52, 206), + .Keyword: UIColorRGB(188, 49, 156), + .Preprocessor: UIColorRGB(120, 72, 48), + .URL: UIColorRGB(21, 67, 244), + .OtherClassNames: UIColorRGB(92, 38, 153), + .OtherProperties: UIColorRGB(92, 38, 153), + .OtherMethodNames: UIColorRGB(46, 13, 110), + .OtherConstants: UIColorRGB(46, 13, 110), + .ProjectClassNames: UIColorRGB(63, 110, 116), + .ProjectProperties: UIColorRGB(63, 110, 116), + .ProjectConstants: UIColorRGB(38, 71, 75), + .ProjectMethodNames: UIColorRGB(38, 71, 75) + ] + + private static let duskTheme: [JLTokenType: UIColor] = [ + .Text: UIColor.whiteColor(), + .Background: UIColorRGB(30, 32, 40), + .Comment: UIColorRGB(72, 190, 102), + .DocumentationComment: UIColorRGB(72, 190, 102), + .DocumentationCommentKeyword: UIColorRGB(72, 190, 102), + .String: UIColorRGB(230, 66, 75), + .Character: UIColorRGB(139, 134, 201), + .Number: UIColorRGB(139, 134, 201), + .Keyword: UIColorRGB(195, 55, 149), + .Preprocessor: UIColorRGB(198, 124, 72), + .URL: UIColorRGB(35, 63, 208), + .OtherClassNames: UIColorRGB(4, 175, 200), + .OtherMethodNames: UIColorRGB(4, 175, 200), + .OtherConstants: UIColorRGB(4, 175, 200), + .OtherProperties: UIColorRGB(4, 175, 200), + .ProjectMethodNames: UIColorRGB(131, 192, 87), + .ProjectClassNames: UIColorRGB(131, 192, 87), + .ProjectConstants: UIColorRGB(131, 192, 87), + .ProjectProperties: UIColorRGB(131, 192, 87) + + ] + + var dictionary: [JLTokenType: UIColor] { + switch self { + case .Default: + return JLColorTheme.defaultTheme + case .Dusk: + return JLColorTheme.duskTheme + case .Other(let dictionary): + return dictionary + default: + break + } + } +} diff --git a/Chromatism/Chromatism/JLDiffTokenizer.h b/Chromatism/Chromatism/JLDiffTokenizer.h deleted file mode 100644 index e98ef85..0000000 --- a/Chromatism/Chromatism/JLDiffTokenizer.h +++ /dev/null @@ -1,16 +0,0 @@ -// -// JLDiffTokenizer.h -// Chromatism -// -// Created by Johannes Lund on 2013-10-31. -// Copyright (c) 2013 Anviking. All rights reserved. -// - -#import - -/// Very unsure about the idea of this class -@interface JLDiffTokenizer : NSObject - -+ (NSMutableAttributedString *)tokenizeString:(NSString *)string withDefaultAttributes:(NSDictionary *)attributes; - -@end diff --git a/Chromatism/Chromatism/JLDiffTokenizer.m b/Chromatism/Chromatism/JLDiffTokenizer.m deleted file mode 100644 index 716772a..0000000 --- a/Chromatism/Chromatism/JLDiffTokenizer.m +++ /dev/null @@ -1,47 +0,0 @@ -// -// JLDiffTokenizer.m -// Chromatism -// -// Created by Johannes Lund on 2013-10-31. -// Copyright (c) 2013 Anviking. All rights reserved. -// - -#import "JLDiffTokenizer.h" - -@implementation JLDiffTokenizer - -+ (NSMutableAttributedString *)tokenizeString:(NSString *)string withDefaultAttributes:(NSDictionary *)attributes -{ - NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string attributes:attributes]; - - NSRegularExpression *additionExpresssion = [[NSRegularExpression alloc] initWithPattern:@"^\\+.*?\\n" options:NSRegularExpressionAnchorsMatchLines | NSRegularExpressionDotMatchesLineSeparators error:NULL]; - NSRegularExpression *deletionExpression = [[NSRegularExpression alloc] initWithPattern:@"^-.*?\\n" options:NSRegularExpressionAnchorsMatchLines | NSRegularExpressionDotMatchesLineSeparators error:NULL]; - - NSUInteger removedCharacters = 0; - - UIColor *additionColor = attributes[JLTokenTypeDiffAddition]; - UIColor *deletionColor = attributes[JLTokenTypeDiffDeletion]; - - tokenizeStringWithExpression(additionExpresssion, string, attributedString, &removedCharacters, additionColor); - tokenizeStringWithExpression(deletionExpression, string, attributedString, &removedCharacters, deletionColor); - - return attributedString; -} - -void tokenizeStringWithExpression(NSRegularExpression *expression, NSString *string, NSMutableAttributedString *attributedString, NSUInteger *removedCharacters, UIColor *color) -{ - __block NSUInteger integer = *removedCharacters; - NSRange range = NSMakeRange(0, string.length); - [expression enumerateMatchesInString:string options:0 range:range usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { - NSUInteger location = result.range.location - integer; - NSRange lineRange = NSMakeRange(location, result.range.length); - NSRange tokenRange = NSMakeRange(location, 1); - - [attributedString addAttribute:JLDiffColorAttributeName value:color range:lineRange]; - [attributedString deleteCharactersInRange:tokenRange]; - integer++; - }]; - *removedCharacters = integer; -} - -@end diff --git a/Chromatism/Chromatism/JLDocumentScope.swift b/Chromatism/Chromatism/JLDocumentScope.swift new file mode 100644 index 0000000..f1e4a3b --- /dev/null +++ b/Chromatism/Chromatism/JLDocumentScope.swift @@ -0,0 +1,51 @@ +// +// JLDocumentScope.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-20. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +public class JLDocumentScope: JLScope { + + init() { + super.init() + } + + override func perform(indexSet: NSIndexSet) { + indexSet.enumerateRangesUsingBlock({(range, stop) in + if let color = self.theme?[.Text] { + self.attributedString.addAttribute(NSForegroundColorAttributeName, value: color, range: range) + } + }) + super.perform(indexSet) + } + + func cascadeAttributedString(attributedString: NSMutableAttributedString) { + self.attributedString = attributedString + cascade { $0.attributedString = attributedString } + } + + override func invalidateAttributesInIndexes(indexSet: NSIndexSet) { + cascade { $0.invalidateAttributesInIndexes(indexSet) } + } + + override func shiftIndexesAtLoaction(location: Int, by delta: Int) { + cascade { $0.shiftIndexesAtLoaction(location, by: delta) } + } + + func cascade(block: (scope: JLScope) -> Void) { + for scope in subscopes { + cascade(block, scope: scope) + } + } + + private func cascade(block: (scope: JLScope) -> Void, scope: JLScope) { + block(scope: scope) + for subscope in scope.subscopes { + cascade(block, scope: subscope) + } + } +} \ No newline at end of file diff --git a/Chromatism/Chromatism/JLKeywordScope.swift b/Chromatism/Chromatism/JLKeywordScope.swift new file mode 100644 index 0000000..ef2f0db --- /dev/null +++ b/Chromatism/Chromatism/JLKeywordScope.swift @@ -0,0 +1,86 @@ +// +// JLKeywordScope.swift +// Chromatism +// +// Created by Johannes Lund on 2014-08-02. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +class JLKeywordScope: JLRegexScope { + init(keywords: [String], prefix: String, suffix: String, tokenType: JLTokenType) { + let pattern = prefix + Branch(character: "", array: keywords).description + suffix + let expression = NSRegularExpression(pattern: pattern, options: nil, error: nil) + super.init(regularExpression: expression, tokenTypes: [tokenType]) + } + + /// Create a JLKeywordScope with prefix and suffix of word boundaries (\\b) + convenience init (keywords: [String], tokenType: JLTokenType) { + self.init(keywords: keywords, prefix: "\\b", suffix: "\\b", tokenType: tokenType) + } + + /// Create a JLKeywordScope with a space-separated keyword string, with \\b prefix and suffix + convenience init(keywords: String, tokenType: JLTokenType) { + self.init(keywords: keywords.componentsSeparatedByString(" "), tokenType: tokenType) + } +} + +private protocol Node { + var pattern: String {get} +} + +private struct Leaf: Node { + init() {} + var pattern: String { return "" } +} + +private struct Branch: Node, Printable { + var children = [Node]() + var character: String + + func perform(string: NSString, range: Range) { + for i in range { + + } + } + + init(character: String, array: [String]) { + self.character = character + var dictionary = [String: [String]]() + for string in array { + if countElements(string) > 0 { + let firstCharacter = String(string[string.startIndex ... string.startIndex]) + let remainingString = string[string.startIndex.successor() ..< string.endIndex] + if var array = dictionary[firstCharacter] { + array += remainingString + dictionary[firstCharacter] = array + } else { + dictionary[firstCharacter] = [remainingString] + } + } else { + // This means end of a match + children += Leaf() + } + } + for (key, value) in dictionary { + children += Branch(character: key, array: value) + } + + } + + var pattern: String { + var array = children.map { $0.pattern } + array.sort { countElements($0) < countElements($1) } + + switch array.count { + case 0: return character + "" + case 1: return character + array[0] + default: return character + "(?:" + join("|", array) + ")" + } + } + + var description: String { + return pattern + } +} diff --git a/Chromatism/Chromatism/JLLanguage.swift b/Chromatism/Chromatism/JLLanguage.swift new file mode 100644 index 0000000..17eb182 --- /dev/null +++ b/Chromatism/Chromatism/JLLanguage.swift @@ -0,0 +1,154 @@ +// +// JLLanguage.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-17. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +public enum JLLanguageType { + case C, ObjectiveC, Swift, Other(JLLanguage) + + + /** + Warning: Will probably be changed in the future to take arguments + + :returns: A functional JLLanguage object. + */ + func language() -> JLLanguage { + switch self { + case C: return JLLanguage.C() + case ObjectiveC: return JLLanguage.ObjectiveC() + case Swift: return JLLanguage.Swift() + case Other(let language): return language + default: return JLLanguage() + } + } + + /* Does not appear to be working yet + var languageClass: JLLanguage.Type { + switch self { + case C: return JLLanguage.C.self + case ObjectiveC: return JLLanguage.ObjectiveC.self + case Other(let language): return language + default: return JLLanguage.self + } + } + */ +} + +public class JLLanguage { + let documentScope = JLDocumentScope() + + public required init() { + + } + + public class C: JLLanguage { + var blockComments = JLTokenizingScope(incrementingPattern: "/\\*", decrementingPattern: "\\*/", tokenType: .Comment, hollow: false) + var lineComments = JLRegexScope(pattern: "//(.*)", tokenTypes: .Comment) + var preprocessor = JLRegexScope(pattern: "^#.*+$", tokenTypes: .Preprocessor) + var strings = JLRegexScope(pattern: "(\"|@\")[^\"\\n]*(@\"|\")", tokenTypes: .String) + var angularImports = JLRegexScope(pattern: "<.*?>", tokenTypes: .String) + var numbers = JLRegexScope(pattern: "(?<=\\s)\\d+", tokenTypes: .Number) + var functions = JLRegexScope(pattern: "\\w+\\s*(?>\\(.*\\)", tokenTypes: .OtherMethodNames) + + var keywords = JLKeywordScope(keywords: "true false YES NO TRUE FALSE bool BOOL nil id void self NULL if else strong weak nonatomic atomic assign copy typedef enum auto break case const char continue do default double extern float for goto int long register return short signed sizeof static struct switch typedef union unsigned volatile while nonatomic atomic nonatomic readonly super", tokenType: .Keyword) + + public init() { + super.init() + documentScope[ + blockComments, + lineComments, + preprocessor[strings, angularImports], + strings, + numbers, + functions, + keywords + ] + } + } + + public class ObjectiveC: C { + var dotNotation = JLRegexScope(pattern: "\\.\\w+", tokenTypes: .OtherProperties) + + // Note about project class names: When symbolication is supported this pattern should be changed to .OtherClassNames + var projectClassNames = JLRegexScope(pattern: "\\b[A-Z]{3}[a-zA-Z]*\\b", tokenTypes: .ProjectClassNames) + var NSUIClassNames = JLRegexScope(pattern: "\\b(NS|UI)[A-Z][a-zA-Z]+\\b", tokenTypes: .OtherClassNames) + // http://www.learn-cocos2d.com/2011/10/complete-list-objectivec-20-compiler-directives/ + var objcKeywords = JLKeywordScope(keywords: "class defs protocol required optional interface public package protected private property end implementation synthesize dynamic end throw try catch finally synchronized autoreleasepool selector encode compatibility_alias".componentsSeparatedByString(" "), prefix:"@", suffix:"\\b", tokenType: .Keyword) + var squareBrackets: JLTokenizingScope + var dictionaryLiteral = JLTokenizingScope(incrementingPattern: "\\@\\{", decrementingPattern: "\\}", tokenType: .OtherMethodNames, hollow: true) + var methodCallArguments = JLRegexScope(pattern: "\\b\\w+(:|(?=\\]))", tokenTypes: .OtherMethodNames) + + public init() { + let openBracket = JLTokenizingScope.Token(pattern: "\\[", delta: 1) + let closeBracket = JLTokenizingScope.Token(pattern: "\\]", delta: -1) + let arrayOpen = JLTokenizingScope.Token(pattern: "\\@\\[", delta: 1) + + let method = JLNestedScope(incrementingToken: openBracket, decrementingToken: closeBracket, tokenType: .None, hollow: false) + let arrayLiteral = JLNestedScope(incrementingToken: arrayOpen, decrementingToken: closeBracket, tokenType: .OtherMethodNames, hollow: true) + squareBrackets = JLTokenizingScope(tokens: [arrayOpen, openBracket, closeBracket]) + + super.init() + + documentScope[ + blockComments, + dictionaryLiteral, + lineComments, + preprocessor[strings, angularImports], + squareBrackets[ + arrayLiteral, + method[ + strings, + numbers, + functions, + keywords, + dotNotation, + objcKeywords, + NSUIClassNames, + projectClassNames + ] + ], + strings, + numbers, + functions, + keywords, + dotNotation, + objcKeywords, + NSUIClassNames, + projectClassNames + ] + } + } + + public class Swift: JLLanguage { + var blockComments = JLTokenizingScope(incrementingPattern: "/\\*", decrementingPattern: "\\*/", tokenType: .Comment, hollow: false) + var lineComments = JLRegexScope(pattern: "//(.*)", tokenTypes: .Comment) + var keywords = JLKeywordScope(keywords: "class protocol init required public internal import private nil super", tokenType: .Keyword) + var atKeywords = JLKeywordScope(keywords: ["optional"], prefix: "@", suffix: "\\b", tokenType: .Keyword) + var projectClassNames = JLRegexScope(pattern: "\\b[A-Z]{3}[a-zA-Z]+\\b", tokenTypes: .ProjectClassNames) + var NSUIClassNames = JLRegexScope(pattern: "\\b(NS|UI)[A-Z][a-zA-Z]+\\b", tokenTypes: .OtherClassNames) + var swiftTypes = JLKeywordScope(keywords: "Array AutoreleasingUnsafePointer BidirectionalReverseView Bit Bool CFunctionPointer COpaquePointer CVaListPointer Character CollectionOfOne ConstUnsafePointer ContiguousArray Dictionary DictionaryGenerator DictionaryIndex Double EmptyCollection EmptyGenerator EnumerateGenerator FilterCollectionView FilterCollectionViewIndex FilterGenerator FilterSequenceView Float Float80 FloatingPointClassification GeneratorOf GeneratorOfOne GeneratorSequence HeapBuffer HeapBuffer HeapBufferStorage HeapBufferStorageBase ImplicitlyUnwrappedOptional IndexingGenerator Int Int16 Int32 Int64 Int8 IntEncoder LazyBidirectionalCollection LazyForwardCollection LazyRandomAccessCollection LazySequence Less MapCollectionView MapSequenceGenerator MapSequenceView MirrorDisposition ObjectIdentifier OnHeap Optional PermutationGenerator QuickLookObject RandomAccessReverseView Range RangeGenerator RawByte Repeat ReverseBidirectionalIndex ReverseRandomAccessIndex SequenceOf SinkOf Slice StaticString StrideThrough StrideThroughGenerator StrideTo StrideToGenerator String Index UTF8View Index UnicodeScalarView IndexType GeneratorType UTF16View UInt UInt16 UInt32 UInt64 UInt8 UTF16 UTF32 UTF8 UnicodeDecodingResult UnicodeScalar Unmanaged UnsafeArray UnsafeArrayGenerator UnsafeMutableArray UnsafePointer VaListBuilder Header Zip2 ZipGenerator2", tokenType: .OtherClassNames) + var dotNotation = JLRegexScope(pattern: "\\.\\w+", tokenTypes: .OtherProperties) + + public init() { + + super.init() + documentScope[ + blockComments, + lineComments, + keywords, + atKeywords, + swiftTypes, + dotNotation, + NSUIClassNames, + projectClassNames + ] + } + } +} + + diff --git a/Chromatism/Chromatism/JLNestedScope.swift b/Chromatism/Chromatism/JLNestedScope.swift new file mode 100644 index 0000000..e4c70be --- /dev/null +++ b/Chromatism/Chromatism/JLNestedScope.swift @@ -0,0 +1,108 @@ +// +// JLNestedToken.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-21. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +protocol JLNestedScopeDelegate { + func nestedScopeDidPerform(scope: JLNestedScope, additions: NSIndexSet) +} + +public class JLNestedScope: JLScope { + var incrementingToken: JLTokenizingScope.Token + var decrementingToken: JLTokenizingScope.Token + + var tokenType: JLTokenType + var hollow: Bool + + init(incrementingToken: JLTokenizingScope.Token, decrementingToken: JLTokenizingScope.Token, tokenType: JLTokenType, hollow: Bool) { + self.incrementingToken = incrementingToken + self.decrementingToken = decrementingToken + self.hollow = hollow + self.tokenType = tokenType + super.init() + multiline = true + } + + private var oldIndexSet = NSMutableIndexSet() + + func perform(indexSet: NSIndexSet, tokens: [JLTokenizingScope.TokenResult]) { + var newIndexSet = NSMutableIndexSet() + var newSubscopeIndexSet = NSMutableIndexSet() + + var incrementingTokens = Dictionary() + var depth = 0 + for result in tokens { + if result.token.delta > 0 { + incrementingTokens[depth] = result + } else if let start = incrementingTokens[depth + result.token.delta] { + let incrementingToken = start + let decrementingToken = result + if incrementingTokenIsValid(incrementingToken) && decrementingTokenIsValid(decrementingToken) { + let indexes = indexesForTokens(incrementingToken, decrementingToken: decrementingToken, hollow: hollow) + if indexes.lastIndex < attributedString.length { + newIndexSet += indexes + } + } + } + depth += result.token.delta + } + + // We only need update attributes in indexes that just was added + // And in indexes that has been reset by the document scope + var (additions, deletions) = NSIndexSetDelta(oldIndexSet, newIndexSet) + let intersection = indexSet.intersectionWithSet(newIndexSet) + setAttributesInIndexSet(intersection + additions) + + //println("\(incrementingToken.expression.pattern) - Additions: \(additions)") + + delegate?.nestedScopeDidPerform(self, additions: additions) + performSubscopes(attributedString, indexSet: intersection) + println("Intersection: \(intersection)") + + self.indexSet = newIndexSet + oldIndexSet = newIndexSet.mutableCopy() as NSMutableIndexSet + } + + func incrementingTokenIsValid(token: JLTokenizingScope.TokenResult) -> Bool { + return token.token === self.incrementingToken + } + + func decrementingTokenIsValid(token: JLTokenizingScope.TokenResult) -> Bool { + return token.token === self.decrementingToken + } + + private func setAttributesInIndexSet(indexSet: NSIndexSet) { + indexSet.enumerateRangesUsingBlock { (range, stop) in + if let color = self.theme?[self.tokenType] { + self.attributedString.addAttribute(NSForegroundColorAttributeName, value: color, range: range) + } + } + } + + override func invalidateAttributesInIndexes(indexSet: NSIndexSet) { + self.indexSet -= indexSet + } + + override func shiftIndexesAtLoaction(location: Int, by delta: Int) { + oldIndexSet.shiftIndexesStartingAtIndex(location, by: delta) + indexSet.shiftIndexesStartingAtIndex(location, by: delta) + } + + + func indexesForTokens(incrementingToken: JLTokenizingScope.TokenResult, decrementingToken: JLTokenizingScope.TokenResult, hollow: Bool) -> NSIndexSet { + var indexSet = NSMutableIndexSet() + if hollow { + indexSet += incrementingToken.range + indexSet += decrementingToken.range + } else { + indexSet += NSRange(incrementingToken.range.start ..< decrementingToken.range.end) + } + return indexSet + } +} + diff --git a/Chromatism/Chromatism/JLObjectiveCTokenizer.h b/Chromatism/Chromatism/JLObjectiveCTokenizer.h deleted file mode 100644 index 163c3cf..0000000 --- a/Chromatism/Chromatism/JLObjectiveCTokenizer.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// JLObjectiveCTokenizer.h -// Chromatism -// -// Created by Johannes Lund on 2013-11-19. -// Copyright (c) 2013 Anviking. All rights reserved. -// - -#import - -@interface JLObjectiveCTokenizer : JLTokenizer - -@end diff --git a/Chromatism/Chromatism/JLObjectiveCTokenizer.m b/Chromatism/Chromatism/JLObjectiveCTokenizer.m deleted file mode 100644 index ba7e61d..0000000 --- a/Chromatism/Chromatism/JLObjectiveCTokenizer.m +++ /dev/null @@ -1,85 +0,0 @@ -// -// JLObjectiveCTokenizer.m -// Chromatism -// -// Created by Johannes Lund on 2013-11-19. -// Copyright (c) 2013 Anviking. All rights reserved. -// - -#import "JLObjectiveCTokenizer.h" - -@implementation JLObjectiveCTokenizer - -- (void)prepareDocumentScope:(JLScope *)documentScope -{ - [super prepareDocumentScope:documentScope]; - - JLTokenPattern *blockComment = [self addToken:JLTokenTypeComment withPattern:@"" andScope:documentScope]; - blockComment.expression = [NSRegularExpression regularExpressionWithPattern:@"/\\*.*?\\*/" options:NSRegularExpressionDotMatchesLineSeparators error:nil]; -} - -- (void)prepareLineScope:(JLScope *)lineScope -{ - [super prepareLineScope:lineScope]; - - [self addToken:JLTokenTypeComment withPattern:@"//.*+$" andScope:lineScope]; - - JLTokenPattern *preprocessor = [self addToken:JLTokenTypePreprocessor withPattern:@"^#.*+$" andScope:lineScope]; - - // #import - // In xcode it only works for #import and #include, not all preprocessor statements. - [self addToken:JLTokenTypeString withPattern:@"<.*?>" andScope:preprocessor]; - - // Strings - [[self addToken:JLTokenTypeString withPattern:@"(\"|@\")[^\"\\n]*(@\"|\")" andScope:lineScope] addScope:preprocessor]; - - // Numbers - [self addToken:JLTokenTypeNumber withPattern:@"(?<=\\s)\\d+" andScope:lineScope]; - - // New literals, for example @[] - // TODO: Highlight the closing bracket too, but with some special "nested-token-pattern" - [[self addToken:JLTokenTypeNumber withPattern:@"@[\\[|\\{|\\(]" andScope:lineScope] setOpaque:NO]; - - // C function names - [[self addToken:JLTokenTypeOtherMethodNames withPattern:@"\\w+\\s*(?>\\(.*\\)" andScope:lineScope] setCaptureGroup:1]; - - // Dot notation - [[self addToken:JLTokenTypeOtherMethodNames withPattern:@"\\.(\\w+)" andScope:lineScope] setCaptureGroup:1]; - - // Method Calls - [[self addToken:JLTokenTypeOtherMethodNames withPattern:@"(\\w+)\\]" andScope:lineScope] setCaptureGroup:1]; - - // Method call parts - [[self addToken:JLTokenTypeOtherMethodNames withPattern:@"(?<=\\w+):" andScope:lineScope] setCaptureGroup:0]; - - NSString *keywords = @"true false yes no YES TRUE FALSE bool BOOL nil id void self NULL if else strong weak nonatomic atomic assign copy typedef enum auto break case const char continue do default double extern float for goto int long register return short signed sizeof static struct switch typedef union unsigned volatile while nonatomic atomic nonatomic readonly super"; - - [self addToken:JLTokenTypeKeyword withKeywords:keywords andScope:lineScope]; - [self addToken:JLTokenTypeKeyword withPattern:@"@[a-zA-Z0-9_]+" andScope:lineScope]; - - // Other Class Names - [self addToken:JLTokenTypeOtherClassNames withPattern:@"\\b[A-Z]{3}[a-zA-Z]*\\b" andScope:lineScope]; -} - -#pragma mark - Symbolication - -- (void)prepareSymbolicateScope:(JLScope *)scope -{ - //NSString *pattern = [NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@implementation (\\w+)" captureGroup:1 textStorage:scope.textStorage] componentsJoinedByString:@"|"]]; - //JLTokenizer *pattern = [JLTokenPattern tokenPatternWithRegularExpression:[NSRegularExpression regularExpressionWithPattern:pattern options:0 error:NULL]]; - -// [self.scopes[PROJECT_METHOD_NAMES] setPattern:[NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@property \\(.*?\\)\\s*\\w+[\\s*]+(\\w+);" captureGroup:1] componentsJoinedByString:@"|"]]]; - } - -- (JLTokenizerIntendtationAction)intendationActionAfterReplacingTextInRange:(NSRange)range replacementText:(NSString *)text previousCharacter:(unichar)character textView:(UITextView *)textView; -{ - if (character == '{') { - return JLTokenizerIntendtationActionIncrease; - } else if (character == '}') { - return JLTokenizerIntendtationActionDecrease; - } else { - return JLTokenizerIntendtationActionNone; - } -} - -@end diff --git a/Chromatism/Chromatism/JLRegexScope.swift b/Chromatism/Chromatism/JLRegexScope.swift new file mode 100644 index 0000000..77d1cc4 --- /dev/null +++ b/Chromatism/Chromatism/JLRegexScope.swift @@ -0,0 +1,61 @@ +// +// JLToken.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-14. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +public class JLRegexScope: JLScope { + + var regularExpression: NSRegularExpression + + /// Allows you to specify specific tokenTypes for different capture groups. Index 0 means the whole match, following indexes represent capture groups. + public var tokenTypes: [JLTokenType] + + + init(regularExpression: NSRegularExpression, tokenTypes: [JLTokenType]) { + self.regularExpression = regularExpression + self.tokenTypes = tokenTypes + super.init() + } + + convenience init(pattern: String, options: NSRegularExpressionOptions, tokenTypes: JLTokenType...) { + let expression = NSRegularExpression(pattern: pattern, options: options, error: nil) + self.init(regularExpression: expression, tokenTypes: tokenTypes) + } + + /// Creates a JLRegexScope with .AnchorsMatchLines options + convenience init(pattern: String, tokenTypes: JLTokenType...) { + let expression = NSRegularExpression(pattern: pattern, options: .AnchorsMatchLines, error: nil) + self.init(regularExpression: expression, tokenTypes: tokenTypes) + } + + override func perform(parentIndexSet: NSIndexSet) { + parentIndexSet.enumerateRangesUsingBlock({ (range, stop) in + self.regularExpression.enumerateMatchesInString(self.attributedString.string, options: nil, range: range, usingBlock: {(result, flags, stop) in + self.process(result, attributedString: self.attributedString) + }) + }) + + performSubscopes(attributedString, indexSet: indexSet.mutableCopy() as NSMutableIndexSet) + } + + private func process(result: NSTextCheckingResult, attributedString: NSMutableAttributedString) { + for (index, type) in enumerate(self.tokenTypes) { + if let color = self.theme?[type] { + if result.numberOfRanges > index { + let range = result.rangeAtIndex(index) + attributedString.addAttribute(NSForegroundColorAttributeName, value: color, range: range) + indexSet.addIndexesInRange(range) + } + } + } + } + + override public var description: String { + return "JLToken" + } +} diff --git a/Chromatism/Chromatism/JLScope.h b/Chromatism/Chromatism/JLScope.h deleted file mode 100644 index 2615624..0000000 --- a/Chromatism/Chromatism/JLScope.h +++ /dev/null @@ -1,80 +0,0 @@ -// -// JLScope.h -// iGitpad -// -// Created by Johannes Lund on 2013-06-30. -// Copyright (c) 2013 Johannes Lund -// -// 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 - -@interface JLScope : NSOperation - -// Designated initializors -+ (instancetype)scopeWithRange:(NSRange)range inTextStorage:(NSTextStorage *)textStorage; -+ (instancetype)scopeWithTextStorage:(NSTextStorage *)textStorage; - -@property (nonatomic, strong) NSMutableIndexSet *set; - -/// Used by subclasses -- (void)performInIndexSet:(NSMutableIndexSet *)set; - -- (void)addSubscope:(JLScope *)scope; -- (void)addScope:(JLScope *)scope; - -/// Returns a set of ALL subscopes recursivly. The instance-scope adds itself to the set as well. -- (NSMutableSet *)recursiveSubscopes; - -/// NSHashTable with weak references to parent scopes -@property (nonatomic, strong) NSHashTable *scopes; - -/// NSMutableArray of strong references to subscopes -@property (nonatomic, strong) NSMutableArray *subscopes; - -/** - * A weak reference to a textStorage in which the scope is operating. Will be passed down to subscopes. - */ -@property (nonatomic, weak) NSTextStorage *textStorage; - -/** - * A shared instance of the textStorage's string. - */ -@property (nonatomic, readonly, strong) NSString *string; - -/** - * Describes wether the instance removes it's indexes from the containg scope. Default is YES. - */ -@property (nonatomic, assign, getter = isOpaque) BOOL opaque; - -/** - * If TRUE, the instance will act as if its subscopes where connected directly to the instance's parent's scope. - */ -@property (nonatomic, assign, getter = isEmpty) BOOL empty; - -/** - * An unique identifier of the scope - */ -@property (nonatomic, assign) NSString *identifier; - -/** - * What kind of scope is this? - */ -@property (nonatomic, copy) NSString *type; - -@end diff --git a/Chromatism/Chromatism/JLScope.m b/Chromatism/Chromatism/JLScope.m deleted file mode 100644 index 020b35f..0000000 --- a/Chromatism/Chromatism/JLScope.m +++ /dev/null @@ -1,146 +0,0 @@ -// -// JLScope.m -// iGitpad -// -// Created by Johannes Lund on 2013-06-30. -// Copyright (c) 2013 Johannes Lund -// -// 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 "JLScope.h" -#import "Helpers.h" - -@interface JLScope () -@property (nonatomic, readwrite, strong) NSString *string; -@end - -@implementation JLScope - -#pragma mark - Initialization - -+ (instancetype)scopeWithRange:(NSRange)range inTextStorage:(NSTextStorage *)textStorage -{ - JLScope *scope = [JLScope new]; - scope.set = [NSMutableIndexSet indexSetWithIndexesInRange:range]; - scope.textStorage = textStorage; - return scope; -} - -- (instancetype)init -{ - self = [super init]; - if (self) { - self.opaque = YES; - } - return self; -} - -+ (instancetype)scopeWithTextStorage:(NSTextStorage *)textStorage -{ - return [self scopeWithRange:NSMakeRange(0, textStorage.length) inTextStorage:textStorage]; -} - -- (NSHashTable *)scopes -{ - if (!_scopes) { - self.scopes = [NSHashTable weakObjectsHashTable]; - } - return _scopes; -} - -- (NSMutableArray *)subscopes -{ - if (!_subscopes) { - self.subscopes = [NSMutableArray array]; - } - return _subscopes; -} - -#pragma mark - Perform - -- (void)main -{ - NSMutableIndexSet *set = [NSMutableIndexSet indexSet]; - for (JLScope *scope in self.scopes) { - [set addIndexes:scope.set]; - self.textStorage = scope.textStorage; - self.string = scope.string; - } - - [self performInIndexSet:set]; - - for (JLScope *scope in self.scopes) { - [scope.set removeIndexes:self.set]; - } -} - -- (void)performInIndexSet:(NSMutableIndexSet *)set -{ - self.set = (set.count > 0) ? [self.set intersectionWithSet:set] : [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.string.length)]; -} - -- (void)addSubscope:(JLScope *)scope -{ - for (JLScope *obj in self.subscopes) { - [scope addDependency:obj]; - } - - [scope addDependency:self]; - [scope.scopes addObject:self]; - [self.subscopes addObject:scope]; -} - -- (void)addScope:(JLScope *)scope -{ - [scope addSubscope:self]; -} - -- (NSMutableSet *)recursiveSubscopes -{ - NSMutableSet *recursiveSubscopes = [NSMutableSet setWithObject:self]; - for (JLScope *scope in self.subscopes) { - for (JLScope *aScope in [scope recursiveSubscopes]) { - [recursiveSubscopes addObject:aScope]; - } - } - return recursiveSubscopes; -} - -#pragma mark - Properties - -- (NSString *)string -{ - if (!_string) _string = self.textStorage.string; - return _string; -} -- (NSMutableIndexSet *)set -{ - if (!_set) _set = [NSMutableIndexSet indexSet]; - return _set; -} - -#pragma mark - Debugging - -- (NSString *)description -{ - NSString *subscopes = [[[[self.dependencies valueForKey:@"description"] componentsJoinedByString:@"\n"] componentsSeparatedByString:@"\n"] componentsJoinedByString:@"\n\t\t"]; - return [NSString stringWithFormat:@"%@, %@, nopaque: %i, nindexesSet:%@, \n subscopes, %@", NSStringFromClass(self.class), _identifier, _opaque, _set, subscopes]; -} - -@end - diff --git a/Chromatism/Chromatism/JLScope.swift b/Chromatism/Chromatism/JLScope.swift new file mode 100644 index 0000000..1c88088 --- /dev/null +++ b/Chromatism/Chromatism/JLScope.swift @@ -0,0 +1,87 @@ +// +// JLScope.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-14. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +public class JLScope: NSObject, Printable, Equatable { + init() { + super.init() + } + + subscript(scopes: JLScope...) -> JLScope { + self.subscopes = scopes + return self + } + + var attributedString: NSMutableAttributedString! + var multiline = false + var theme: JLColorTheme? + var delegate: JLNestedScopeDelegate? + + var indexSet = NSMutableIndexSet() + var subscopes = [JLScope]() + + func addSubscope(subscope: JLScope) { + self.subscopes += subscope + } + + func perform() { + perform(NSIndexSet(indexesInRange: NSMakeRange(0, attributedString.length))) + } + + func perform(indexSet: NSIndexSet) { + + // Create a copy of the indexSet and call perform to subscopes + // The results of the subscope is removed from the indexSet copy before the next subscope is performed + let indexSetCopy = indexSet.mutableCopy() as NSMutableIndexSet + performSubscopes(attributedString, indexSet: indexSetCopy) + self.indexSet = indexSet.mutableCopy() as NSMutableIndexSet + } + + // Will change indexSet + func performSubscopes(attributedString: NSMutableAttributedString, indexSet: NSMutableIndexSet) { + + var deletions = NSMutableIndexSet() + for (index, scope) in enumerate(subscopes) { + scope.theme = theme + + var oldSet = scope.indexSet + scope.invalidateAttributesInIndexes(indexSet) + scope.perform(indexSet) + var newSet = scope.indexSet + + indexSet -= newSet + if scope.multiline { + deletions += NSIndexSetDelta(oldSet, newSet).deletions + } + } + if deletions.count > 0 { + perform(deletions + indexSet) + } + } + + // MARK: + + func invalidateAttributesInIndexes(indexSet: NSIndexSet) { + + } + + func shiftIndexesAtLoaction(location: Int, by delta: Int) { + indexSet.shiftIndexesStartingAtIndex(location, by: delta) + } + + // MARK: Printable + override public var description: String { + return "JLScope" + } + +} + +public func ==(lhs: JLScope, rhs: JLScope) -> Bool { + return lhs.subscopes == rhs.subscopes && lhs.indexSet == rhs.indexSet +} diff --git a/Chromatism/Chromatism/JLTextStorage.swift b/Chromatism/Chromatism/JLTextStorage.swift new file mode 100644 index 0000000..7e35e49 --- /dev/null +++ b/Chromatism/Chromatism/JLTextStorage.swift @@ -0,0 +1,59 @@ +// +// JLTextStorage.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-26. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +public class JLTextStorage: NSTextStorage { + + public var documentScope: JLDocumentScope + + init(documentScope: JLDocumentScope) { + self.documentScope = documentScope + super.init() + self.documentScope.cascadeAttributedString(self) + } + + // MARK: Syntax Highlighting + + public override func processEditing() { + if let range = editedLineRange { + let layoutManager = layoutManagers[0] as NSLayoutManager + //println("Non Contigigous Layout: \(layoutManager.hasNonContiguousLayout)") + let editedLineIndexSet = NSIndexSet(indexesInRange: range) + documentScope.perform(editedLineIndexSet) + editedLineRange = nil + } + super.processEditing() + } + + // MARK: Text Storage Backing + + private var backingStore = NSMutableAttributedString() + private var editedLineRange: NSRange? + + public override var string: String { return backingStore.string } + + public override func attributesAtIndex(location: Int, effectiveRange range: NSRangePointer) -> [NSObject : AnyObject]! { + return backingStore.attributesAtIndex(location, effectiveRange: range) + } + + public override func replaceCharactersInRange(range: NSRange, withString str: String!) { + let actions = NSTextStorageEditActions.EditedCharacters | NSTextStorageEditActions.EditedAttributes + let delta = str.bridgeToObjectiveC().length - range.length + edited(actions, range: range, changeInLength: delta) + backingStore.replaceCharactersInRange(range, withString: str) + editedLineRange = string.bridgeToObjectiveC().lineRangeForRange(editedRange) + documentScope.invalidateAttributesInIndexes(NSIndexSet(indexesInRange: range)) + documentScope.shiftIndexesAtLoaction(range.end, by: delta) + } + + public override func setAttributes(attrs: [NSObject : AnyObject]!, range: NSRange) { + backingStore.setAttributes(attrs, range: range) + edited(.EditedAttributes, range: range, changeInLength: 0) + } +} diff --git a/Chromatism/Chromatism/JLTextView.h b/Chromatism/Chromatism/JLTextView.h deleted file mode 100644 index e11b3cb..0000000 --- a/Chromatism/Chromatism/JLTextView.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// JLTextView.h -// Chromatism -// -// Created by Johannes Lund on 2013-07-16. -// Copyright (c) 2013 Johannes Lund -// -// 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 -#import "Chromatism+Internal.h" -#import "JLTokenizer.h" - -@class JLTokenizer; - -@interface JLTextView : UITextView - -@property (nonatomic, strong) JLTokenizer *syntaxTokenizer; -@property (nonatomic, assign) JLTokenizerTheme theme; -@end diff --git a/Chromatism/Chromatism/JLTextView.m b/Chromatism/Chromatism/JLTextView.m deleted file mode 100644 index 121437b..0000000 --- a/Chromatism/Chromatism/JLTextView.m +++ /dev/null @@ -1,185 +0,0 @@ -// -// JLTextView.m -// Chromatism -// -// Created by Johannes Lund on 2013-07-16. -// -// Copyright (c) 2013 Johannes Lund -// -// 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 "JLTextView.h" -#import "Chromatism.h" - -@implementation JLTextView -@synthesize theme = _theme; - -#pragma mark - Initialization & Setup - -- (id)init -{ - self = [super init]; - if (self) { - [self setup]; - } - return self; -} - -- (id)initWithFrame:(CGRect)frame -{ - self = [super initWithFrame:frame]; - if (self) { - [self setup]; - } - return self; -} - -- (id)initWithFrame:(CGRect)frame textContainer:(NSTextContainer *)textContainer -{ - self = [super initWithFrame:frame textContainer:textContainer]; - if (self) { - [self setup]; - } - return self; -} - -- (id)initWithCoder:(NSCoder *)aDecoder -{ - self = [super initWithCoder:aDecoder]; - if (self) { - [self setup]; - } - return self; -} - -- (void)setup -{ - // Setup tokenizer - self.syntaxTokenizer = [[JLTokenizer alloc] init]; - self.theme = JLTokenizerThemeDusk; - - // Set default properties - self.scrollEnabled = YES; - self.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive; - self.font = [UIFont fontWithName:@"Menlo" size:12]; - self.autocorrectionType = UITextAutocorrectionTypeNo; - self.autocapitalizationType = UITextAutocapitalizationTypeNone; - self.layoutManager.allowsNonContiguousLayout = YES; - -} - -- (void)setSyntaxTokenizer:(JLTokenizer *)tokenizer -{ - _syntaxTokenizer = tokenizer; - - self.textStorage.delegate = self.syntaxTokenizer; - self.layoutManager.delegate = self.syntaxTokenizer; - self.delegate = self.syntaxTokenizer; -} - -#pragma mark - Color Themes - --(void)setTheme:(JLTokenizerTheme)theme -{ - _theme = theme; - - // Set font- and background color from the theme - self.syntaxTokenizer.colors = [Chromatism colorsForTheme:theme]; - NSMutableDictionary *typingAttributes = self.typingAttributes.mutableCopy; - typingAttributes[NSForegroundColorAttributeName] = self.syntaxTokenizer.colors[JLTokenTypeText]; - self.typingAttributes = typingAttributes; - - UIColor *backgroundColor = self.syntaxTokenizer.colors[JLTokenTypeBackground]; - [self setBackgroundColor:backgroundColor ? backgroundColor : [UIColor whiteColor] ]; - - // Refresh Tokenization - [self.syntaxTokenizer refreshTokenizationOfTextStorage:self.textStorage]; -} - -- (JLTokenizerTheme)theme -{ - if (!_theme) _theme = JLTokenizerThemeDefault; - return _theme; -} - -// http://stackoverflow.com/questions/19235762/how-can-i-support-the-up-and-down-arrow-keys-with-a-bluetooth-keyboard-under-ios - -#pragma mark - Bluethooth Keyboard Extension - -- (NSArray *)keyCommands { - UIKeyCommand *upArrow = [UIKeyCommand keyCommandWithInput: UIKeyInputUpArrow modifierFlags: 0 action: @selector(upArrow:)]; - UIKeyCommand *downArrow = [UIKeyCommand keyCommandWithInput: UIKeyInputDownArrow modifierFlags: 0 action: @selector(downArrow:)]; - return [[NSArray alloc] initWithObjects: upArrow, downArrow, nil]; -} - -- (void)upArrow:(UIKeyCommand *)keyCommand { - UITextRange *range = self.selectedTextRange; - if (range != nil) { - float lineHeight = self.font.lineHeight; - - CGRect caret = [self firstRectForRange: range]; - if (isinf(caret.origin.y)) { - // Work-around for a bug in iOS 7 that returns bogus values when the caret is at the start of a line. - range = [self textRangeFromPosition: range.start toPosition: [self positionFromPosition: range.start offset: 1]]; - caret = [self firstRectForRange: range]; - caret.origin.y = caret.origin.y + lineHeight; - } - caret.origin.y = caret.origin.y - lineHeight < 0 ? 0 : caret.origin.y - lineHeight; - caret.size.width = 1; - UITextPosition *position = [self closestPositionToPoint: caret.origin]; - self.selectedTextRange = [self textRangeFromPosition: position toPosition: position]; - - caret = [self firstRectForRange: self.selectedTextRange]; - if (isinf(caret.origin.y)) { - // Work-around for a bug in iOS 7 that occurs when the range is set to a position past the end of the last character - // on a line. - NSRange range = {0, 0}; - range.location = [self offsetFromPosition: self.beginningOfDocument toPosition: position]; - self.selectedRange = range; - } - } -} - -- (void)downArrow:(UIKeyCommand *)keyCommand { - UITextRange *range = self.selectedTextRange; - if (range != nil) { - float lineHeight = self.font.lineHeight; - - CGRect caret = [self firstRectForRange: range]; - if (isinf(caret.origin.y)) { - // Work-around for a bug in iOS 7 that returns bogus values when the caret is at the start of a line. - range = [self textRangeFromPosition: range.start toPosition: [self positionFromPosition: range.start offset: 1]]; - caret = [self firstRectForRange: range]; - caret.origin.y = caret.origin.y + lineHeight; - } - caret.origin.y = caret.origin.y + lineHeight < 0 ? 0 : caret.origin.y + lineHeight; - caret.size.width = 1; - UITextPosition *position = [self closestPositionToPoint: caret.origin]; - self.selectedTextRange = [self textRangeFromPosition: position toPosition: position]; - - caret = [self firstRectForRange: self.selectedTextRange]; - if (isinf(caret.origin.y)) { - // Work-around for a bug in iOS 7 that occurs when the range is set to a position past the end of the last character - // on a line. - NSRange range = {0, 0}; - range.location = [self offsetFromPosition: self.beginningOfDocument toPosition: position]; - self.selectedRange = range; - } - } -} -@end diff --git a/Chromatism/Chromatism/JLTextView.swift b/Chromatism/Chromatism/JLTextView.swift new file mode 100644 index 0000000..1d27531 --- /dev/null +++ b/Chromatism/Chromatism/JLTextView.swift @@ -0,0 +1,131 @@ +// +// JLTextView.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-18. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +public class JLTextView: UITextView, JLNestedScopeDelegate { + + public var language: JLLanguage + public var theme: JLColorTheme { + didSet { + backgroundColor = theme[.Background] + language.documentScope.theme = theme + }} + + private var _textStorage: JLTextStorage + + public init(language: JLLanguageType, theme: JLColorTheme) { + self.language = language.language() + self.theme = theme + + let frame = CGRect.zeroRect + _textStorage = JLTextStorage(documentScope: self.language.documentScope) + self.language.documentScope.theme = theme + let layoutManager = NSLayoutManager() + let textContainer = NSTextContainer() + textContainer.widthTracksTextView = true + layoutManager.addTextContainer(textContainer) + _textStorage.addLayoutManager(layoutManager) + super.init(frame: frame, textContainer: textContainer) + + self.language.documentScope.cascade { $0.delegate = self } + backgroundColor = theme[JLTokenType.Background] + font = UIFont(name: "Menlo-Regular", size: 15) +// layoutManager.allowsNonContiguousLayout = true + } + + // MARK: Override UITextView + + override public var attributedText: NSAttributedString! { + didSet { + + } + } + + func updateTypingAttributes() { + let color = theme[JLTokenType.Text]! + typingAttributes = [NSForegroundColorAttributeName: color, NSFontAttributeName: font] + } + + override public var text: String! { + didSet { + updateTypingAttributes() + attributedText = NSAttributedString(string: text, attributes: typingAttributes) + } + } + + override public var textColor: UIColor! { + didSet { + updateTypingAttributes() + } + } + + override public var font: UIFont! { + didSet { + updateTypingAttributes() + } + } +} + +// MARK: JLScopeDelegate + +extension JLTextView: JLNestedScopeDelegate { + func nestedScopeDidPerform(scope: JLNestedScope, additions: NSIndexSet) { + dispatch_async(dispatch_get_main_queue(), { + additions.enumerateRangesUsingBlock { (range, stop) in + + let range = self.textRange(range.start ..< range.end) + let array = self.selectionRectsForRange(range) as [UITextSelectionRect] + for value in array { + self.flash(value.rect, color: UIColor(white: 0.0, alpha: 0.1)) + } + } + }) + } + + func flash(rect: CGRect, color: UIColor) { + let view = UIView(frame: rect) + view.backgroundColor = UIColor.clearColor() + self.addSubview(view) + + let duration = 0.2 + + + let gone = CGAffineTransformMakeScale(0, 0) + let visible = CGAffineTransformMakeScale(1, 1) + + view.transform = gone + + // Its ok for this to be hacky for now + view.animateToColor(color, transform: visible, duration: duration, completion: { + view.animateToColor(UIColor.clearColor(), transform: gone, duration: duration, completion: { + view.removeFromSuperview() + }) + }) + } +} + +private extension UIView { + func animateToColor(color: UIColor, transform: CGAffineTransform, duration: Double, completion: () -> Void) { + UIView.animateWithDuration(duration, delay: 0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.3, options: nil, animations: { + self.backgroundColor = color + self.transform = transform + }, completion: { _ in + completion() + }) + } +} + +private extension UITextView { + func textRange(range: Range) -> UITextRange { + let beginning = beginningOfDocument + let start = positionFromPosition(beginning, offset: range.startIndex) + let end = positionFromPosition(beginning, offset: range.endIndex) + return textRangeFromPosition(start, toPosition: end) + } +} diff --git a/Chromatism/Chromatism/JLTextViewController.h b/Chromatism/Chromatism/JLTextViewController.h deleted file mode 100644 index 3fc1b82..0000000 --- a/Chromatism/Chromatism/JLTextViewController.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// JLTextViewController.h -// iGitpad -// -// Created by Johannes Lund on 2013-06-13. -// Copyright (c) 2013 Johannes Lund -// -// 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 - -@class JLTokenizer, JLTextView; - -@interface JLTextViewController : UIViewController - -- (instancetype)initWithText:(NSString *)text; - -@property (nonatomic, strong) IBOutlet JLTextView *textView; - -// Convenience property for self.textView.syntaxTokenizer -@property (nonatomic, weak, readonly) JLTokenizer *tokenizer; -@end diff --git a/Chromatism/Chromatism/JLTextViewController.m b/Chromatism/Chromatism/JLTextViewController.m deleted file mode 100644 index f2f6041..0000000 --- a/Chromatism/Chromatism/JLTextViewController.m +++ /dev/null @@ -1,141 +0,0 @@ -// -// JLTextViewController.m -// iGitpad -// -// Created by Johannes Lund on 2013-06-13. -// Copyright (c) 2013 Johannes Lund -// -// 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 "JLTextViewController.h" -#import "JLTokenizer.h" -#import "JLTokenizer.h" -#import "JLTextView.h" - -@interface JLTextViewController () -/// Only set from -initWithText: and directly set to nil in -loadView -@property (nonatomic, strong) NSString *defaultText; -@end - -@implementation JLTextViewController - -- (instancetype)initWithText:(NSString *)text -{ - self = [super init]; - if (self) { - _defaultText = text; - } - return self; -} - -- (void)loadView -{ - self.view = self.textView; -} - -- (JLTextView *)textView -{ - if (!_textView) { - JLTextView *textView = [[JLTextView alloc] initWithFrame:CGRectZero]; - textView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - - if (self.defaultText) { - textView.text = self.defaultText; - self.defaultText = nil; - } - - [self setTextView:textView]; - } - return _textView; -} - -- (JLTokenizer *)tokenizer -{ - return self.textView.tokenizer; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - self.view.backgroundColor = self.textView.backgroundColor; - self.navigationController.navigationBar.translucent = TRUE; - - [self registerForKeyboardNotifications]; -} - -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. -} - -#pragma mark - Content Insets and Keyboard - -// Call this method somewhere in your view controller setup code. -- (void)registerForKeyboardNotifications -{ - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(keyboardWasShown:) - name:UIKeyboardDidShowNotification object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(keyboardWillBeHidden:) - name:UIKeyboardWillHideNotification object:nil]; - -} - -// Called when the UIKeyboardDidShowNotification is sent. -- (void)keyboardWasShown:(NSNotification *)notification -{ - NSDictionary* info = [notification userInfo]; - UIScrollView *scrollView = self.textView; - CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; - - UIEdgeInsets contentInsets = scrollView.contentInset; - contentInsets.bottom = kbSize.height; - scrollView.contentInset = contentInsets; - scrollView.scrollIndicatorInsets = contentInsets; - - CGPoint point = [self.textView caretRectForPosition:self.textView.selectedTextRange.start].origin; - point.y = MIN(point.y, self.textView.frame.size.height - kbSize.height); - - CGRect aRect = self.view.frame; - aRect.size.height -= kbSize.height; - if (!CGRectContainsPoint(aRect, point) ) { - - CGRect rect = CGRectMake(point.x, point.y, 1, 1); - rect.size.height = kbSize.height; - rect.origin.y += kbSize.height; - [self.textView scrollRectToVisible:rect animated:YES]; - } -} - -// Called when the UIKeyboardWillHideNotification is sent -- (void)keyboardWillBeHidden:(NSNotification *)notification -{ - UIScrollView *scrollView = self.textView; - UIEdgeInsets contentInsets = scrollView.contentInset; - contentInsets.bottom = 0; - scrollView.contentInset = contentInsets; - scrollView.scrollIndicatorInsets = contentInsets; - scrollView.contentInset = contentInsets; - scrollView.scrollIndicatorInsets = contentInsets; -} - -@end diff --git a/Chromatism/Chromatism/JLTextViewController.swift b/Chromatism/Chromatism/JLTextViewController.swift new file mode 100644 index 0000000..ef477ca --- /dev/null +++ b/Chromatism/Chromatism/JLTextViewController.swift @@ -0,0 +1,76 @@ +// +// JLTextViewController.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-18. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +public class JLTextViewController: UIViewController { + + public var textView: JLTextView + + public required init(text: String, language: JLLanguageType, theme: JLColorTheme) { + textView = JLTextView(language: language, theme: theme) + textView.text = text + super.init(nibName: nil, bundle: nil) + registerForKeyboardNotifications() + } + + deinit { + unregisterForKeyboardNotifications() + } + + override public func loadView() { + view = textView + } + + // MARK: Content Insets and Keyboard + + func registerForKeyboardNotifications() + { + NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil) + NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil) + } + + func unregisterForKeyboardNotifications() { + NSNotificationCenter.defaultCenter().removeObserver(self) + } + + // Called when the UIKeyboardDidShowNotification is sent. + func keyboardWasShown(notification: NSNotification) { + let info = notification.userInfo + let scrollView = self.textView + let kbSize = (info[UIKeyboardFrameBeginUserInfoKey] as NSValue).CGRectValue().size; + + var contentInsets = scrollView.contentInset; + contentInsets.bottom = kbSize.height; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; + + var point = textView.caretRectForPosition(textView.selectedTextRange.start).origin; + point.y = min(point.y, self.textView.frame.size.height - kbSize.height); + + var aRect = self.view.frame; + aRect.size.height -= kbSize.height; + if (!CGRectContainsPoint(aRect, point) ) { + + var rect = CGRectMake(point.x, point.y, 1, 1) + rect.size.height = kbSize.height + rect.origin.y += kbSize.height + textView.scrollRectToVisible(rect, animated: true) + } + } + + // Called when the UIKeyboardWillHideNotification is sent + func keyboardWillBeHidden(notification: NSNotification) { + var contentInsets = textView.contentInset; + contentInsets.bottom = 0; + textView.contentInset = contentInsets; + textView.scrollIndicatorInsets = contentInsets; + textView.contentInset = contentInsets; + textView.scrollIndicatorInsets = contentInsets; + } +} diff --git a/Chromatism/Chromatism/JLTokenPattern.h b/Chromatism/Chromatism/JLTokenPattern.h deleted file mode 100644 index 9e88804..0000000 --- a/Chromatism/Chromatism/JLTokenPattern.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// JLTokenPattern.h -// iGitpad -// -// Created by Johannes Lund on 2013-06-30. -// Copyright (c) 2013 Johannes Lund -// -// 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 "JLScope.h" - -@interface JLTokenPattern : JLScope - -+ (instancetype)tokenPatternWithRegularExpression:(NSRegularExpression *)expressino;; - -@property (nonatomic, strong) NSRegularExpression *expression; - -@property (nonatomic, assign) NSMatchingOptions matchingOptions; - -/// The index of the capture group which will be used as result from the regex search. Default is 0. -@property (nonatomic, assign) NSUInteger captureGroup; - -@property (nonatomic, strong) UIColor *color; - -@end diff --git a/Chromatism/Chromatism/JLTokenPattern.m b/Chromatism/Chromatism/JLTokenPattern.m deleted file mode 100644 index 2b61f5c..0000000 --- a/Chromatism/Chromatism/JLTokenPattern.m +++ /dev/null @@ -1,82 +0,0 @@ - // -// JLTokenPattern.m -// iGitpad -// -// Created by Johannes Lund on 2013-06-30. -// Copyright (c) 2013 Johannes Lund -// -// 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 "JLTokenPattern.h" -#import "Helpers.h" - -@interface JLScope () -- (BOOL)shouldPerform; -@property (nonatomic, strong) NSMutableIndexSet *backupSet; -@property (nonatomic, readwrite, strong) NSString *string; -@end - -@implementation JLTokenPattern - -#pragma mark - Initialization - -static NSCache *cache; - -+ (instancetype)tokenPatternWithRegularExpression:(NSRegularExpression *)expression; -{ - JLTokenPattern *tokenPattern = [JLTokenPattern new]; - tokenPattern.expression = expression; - - return tokenPattern; -} - -- (id)init -{ - self = [super init]; - if (self) { - self.opaque = YES; - self.captureGroup = 0; - } - return self; -} - -#pragma mark - Perform - -- (void)performInIndexSet:(NSMutableIndexSet *)set -{ - NSDictionary *attributes = @{ NSForegroundColorAttributeName : self.color }; - NSAssert(attributes, @""); - [set enumerateRangesUsingBlock:^(NSRange range, BOOL *stop) { - [self.expression enumerateMatchesInString:self.string options:self.matchingOptions range:range usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self.textStorage addAttributes:attributes range:[result rangeAtIndex:self.captureGroup]]; - }); - [self.set addIndexesInRange:[result rangeAtIndex:self.captureGroup]]; - }]; - }]; -} - -#pragma mark - Debugging - -- (NSString *)description -{ - NSString *subscopes = [[[[self.dependencies valueForKey:@"description"] componentsJoinedByString:@"\n"] componentsSeparatedByString:@"\n"] componentsJoinedByString:@"\n\t\t"]; - return [NSString stringWithFormat:@"%@, %@, Regex Pattern: %@, opaque: %i, indexesSet:%@ \nsubscopes, %@", NSStringFromClass(self.class), self.identifier, self.expression, self.opaque, self.set, subscopes]; -} - -@end diff --git a/Chromatism/Chromatism/JLTokenType.swift b/Chromatism/Chromatism/JLTokenType.swift new file mode 100644 index 0000000..319a5ce --- /dev/null +++ b/Chromatism/Chromatism/JLTokenType.swift @@ -0,0 +1,34 @@ +// +// JLTokenType.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-18. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +public enum JLTokenType { + case None + case Text + case Background + case Comment + case DocumentationComment + case DocumentationCommentKeyword + case String + case Character + case Number + case Keyword + case Preprocessor + case URL + case Attribute + case Project + case OtherMethodNames + case OtherProperties + case OtherConstants + case OtherClassNames + case ProjectMethodNames + case ProjectProperties + case ProjectConstants + case ProjectClassNames +} diff --git a/Chromatism/Chromatism/JLTokenizer+Additions.h b/Chromatism/Chromatism/JLTokenizer+Additions.h deleted file mode 100644 index 25a87b0..0000000 --- a/Chromatism/Chromatism/JLTokenizer+Additions.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// JLTokenizer+Additions.h -// Chromatism -// -// Created by Johannes Lund on 2013-11-19. -// Copyright (c) 2013 Anviking. All rights reserved. -// - -#import - -@class JLObjectiveCTokenizer; - -@interface JLTokenizer (Additions) - -+ (JLObjectiveCTokenizer *)objectiveCTokenizer; - -@end diff --git a/Chromatism/Chromatism/JLTokenizer+Additions.m b/Chromatism/Chromatism/JLTokenizer+Additions.m deleted file mode 100644 index cd8ff38..0000000 --- a/Chromatism/Chromatism/JLTokenizer+Additions.m +++ /dev/null @@ -1,29 +0,0 @@ -// -// JLTokenizer+Additions.m -// Chromatism -// -// Created by Johannes Lund on 2013-11-19. -// Copyright (c) 2013 Anviking. All rights reserved. -// - -#import "JLTokenizer+Additions.h" -#import "JLObjectiveCTokenizer.h" - -@implementation JLTokenizer (Additions) - -+ (JLObjectiveCTokenizer *)objectiveCTokenizer -{ - return [[JLObjectiveCTokenizer alloc] init]; -} - -// For now, let every JLTokenizer be created as a JLObjectiveCTokenizer - -+ (id)alloc -{ - if ([self class] == [JLTokenizer class]) { - return [JLObjectiveCTokenizer alloc]; - } - return [super alloc]; -} - -@end diff --git a/Chromatism/Chromatism/JLTokenizer.h b/Chromatism/Chromatism/JLTokenizer.h deleted file mode 100644 index dbc6477..0000000 --- a/Chromatism/Chromatism/JLTokenizer.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// Tokenizer.h -// iGitpad -// -// Created by Johannes Lund on 2012-11-24. -// -// - -#import -#import "Helpers.h" -#import "Chromatism+Internal.h" -#import "JLScope.h" - -typedef NS_ENUM(NSInteger, JLTokenizerIntendtationAction) { - JLTokenizerIntendtationActionIncrease = 1, - JLTokenizerIntendtationActionDecrease = -1, - JLTokenizerIntendtationActionNone = 0 -} NS_ENUM_AVAILABLE_IOS(7_0); - -@class TextViewChange, JLTextView, JLTokenPattern; - -@protocol JLTokenizerDelegate; - -@interface JLTokenizer : NSObject - -- (void)waitUntilFinished; /// Wait untill all syntax-highlighting operations are finished. - -- (void)refreshTokenizationOfTextStorage:(NSTextStorage *)textStorage; - -- (void)tokenizeTextStorage:(NSTextStorage *)textStorage withScope:(JLScope *)scope; -- (JLScope *)documentScopeForTokenizingTextStorage:(NSTextStorage *)textStorage inRange:(NSRange)range; - -// Override these two methods and add your own scopes and tokenPatterns -- (void)prepareDocumentScope:(JLScope *)documentScope; -- (void)prepareLineScope:(JLScope *)lineScope; - -- (NSMutableArray *)symbolsWithPattern:(NSString *)pattern captureGroup:(int)group textStorage:(NSTextStorage *)textStorage; - -// Creates JLTokenPatterns and adds them to the operationQueue -- (JLTokenPattern *)addToken:(NSString *)type withPattern:(NSString *)pattern andScope:(JLScope *)scope; -- (JLTokenPattern *)addToken:(NSString *)type withKeywords:(NSString *)keywords andScope:(JLScope *)scope; - - -- (void)clearColorAttributesInRange:(NSRange)range textStorage:(NSTextStorage *)storage; - -- (JLTokenizerIntendtationAction)intendationActionAfterReplacingTextInRange:(NSRange)range replacementText:(NSString *)text previousCharacter:(unichar)character textView:(UITextView *)textView; - -@property (nonatomic, strong) NSDictionary *colors; -@property (nonatomic, weak) id delegate; -@end - -@protocol JLTokenizerDelegate - -- (void)scope:(JLScope *)scope didFinishProcessing:(JLTokenizer *)tokenizer; - -@end diff --git a/Chromatism/Chromatism/JLTokenizer.m b/Chromatism/Chromatism/JLTokenizer.m deleted file mode 100644 index f156fe1..0000000 --- a/Chromatism/Chromatism/JLTokenizer.m +++ /dev/null @@ -1,263 +0,0 @@ -// -// Tokenizer.m -// iGitpad -// -// Created by Johannes Lund on 2012-11-24. -// -// - -// This file builds upon the work of Kristian Kraljic -// -// RegexHighlightView.m -// Simple Objective-C Syntax Highlighter -// -// Created by Kristian Kraljic on 30/08/12. -// Copyright (c) 2012 Kristian Kraljic (dikrypt.com, ksquared.de). All rights reserved. -// -// 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 "JLTokenizer.h" -#import "JLTextViewController.h" -#import "JLScope.h" -#import "JLTokenPattern.h" -#import "Chromatism+Internal.h" - -@interface JLTokenizer () -@property (nonatomic, strong) NSOperationQueue *operationQueue; -@property (nonatomic, strong) NSMutableDictionary *expressions; -@end - -@implementation JLTokenizer - -#pragma mark - Setup - -- (id)init -{ - self = [super init]; - if (self) { - self.operationQueue = [[NSOperationQueue alloc] init]; - self.operationQueue.maxConcurrentOperationCount = 1; - } - return self; -} - - -- (void)waitUntilFinished -{ - [self.operationQueue waitUntilAllOperationsAreFinished]; -} - -#pragma mark - NSTextStorageDelegate - -- (void)textStorage:(NSTextStorage *)textStorage willProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta -{ - -} - -- (void)textStorage:(NSTextStorage *)textStorage didProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta -{ - if (textStorage.editedMask == NSTextStorageEditedAttributes) return; - [self tokenizeTextStorage:textStorage withScope:[self documentScopeForTokenizingTextStorage:textStorage inRange:editedRange]]; -} - -#pragma mark - NSLayoutManager delegeate - -- (CGFloat)layoutManager:(NSLayoutManager *)layoutManager paragraphSpacingBeforeGlyphAtIndex:(NSUInteger)glyphIndex withProposedLineFragmentRect:(CGRect)rect -{ - return 0; -} - -- (BOOL)layoutManager:(NSLayoutManager *)layoutManager shouldBreakLineByWordBeforeCharacterAtIndex:(NSUInteger)charIndex -{ - unichar character = [layoutManager.textStorage.string characterAtIndex:charIndex]; - if (character == '*') return NO; - return YES; -} - -#pragma mark - UITextViewDelegate - -- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text -{ - if (![text isEqualToString:@"\n"]) return YES; // Something else than return - - // Return has been pressed, start the new line with as many tabs or white spaces as the previous one. - NSString *prefixString = [@"\n" stringByAppendingString:[self prefixStringFromRange:range inTextView:textView]]; - - unichar previousCharacter = [textView.text characterAtIndex:range.location - 1]; - switch ([self intendationActionAfterReplacingTextInRange:range replacementText:text previousCharacter:previousCharacter textView:textView]) { - case JLTokenizerIntendtationActionIncrease: - prefixString = [prefixString stringByAppendingString:@" "]; - break; - case JLTokenizerIntendtationActionDecrease: - if ([[prefixString substringFromIndex:prefixString.length - 4] isEqualToString:@" "]) { - prefixString = [prefixString substringToIndex:prefixString.length - 4]; - } - else if ([[prefixString substringFromIndex:prefixString.length - 1] isEqualToString:@"\t"]) { - prefixString = [prefixString substringToIndex:prefixString.length - 1]; - } - break; - case JLTokenizerIntendtationActionNone: - break; - } - - [textView replaceRange:[self rangeWithRange:range inTextView:textView] withText:prefixString]; - return NO; -} - - -#pragma mark - Tokenizing - -- (void)refreshTokenizationOfTextStorage:(NSTextStorage *)textStorage; -{ - [self tokenizeTextStorage:textStorage withScope:[self documentScopeForTokenizingTextStorage:textStorage inRange:NSMakeRange(0, textStorage.length)]]; -} - -- (JLScope *)documentScopeForTokenizingTextStorage:(NSTextStorage *)textStorage inRange:(NSRange)range -{ - JLScope *documentScope = [JLScope new]; - JLScope *lineScope = [JLScope new]; - - [self prepareDocumentScope:documentScope]; - [self prepareLineScope:lineScope]; - - [documentScope addSubscope:lineScope]; - - [self clearColorAttributesInRange:range textStorage:textStorage]; - - [documentScope setTextStorage:textStorage]; - [documentScope setSet:[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, textStorage.length)]]; - [lineScope setSet:[NSMutableIndexSet indexSetWithIndexesInRange:[textStorage.string lineRangeForRange:range]]]; - - return documentScope; -} - -- (void)tokenizeTextStorage:(NSTextStorage *)textStorage withScope:(JLScope *)scope -{ - //[textStorage beginEditing]; - [self.operationQueue addOperations:[[scope recursiveSubscopes] allObjects] waitUntilFinished:YES]; - //[textStorage endEditing]; -} - -#pragma mark - Setup Token Patterns - -- (void)prepareDocumentScope:(JLScope *)documentScope -{ - -} - -- (void)prepareLineScope:(JLScope *)lineScope -{ - -} - - -#pragma mark - Symbolication - -/* -- (void)symbolicate -{ - [self.scopes[PROJECT_CLASS_NAMES] setPattern:[NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@implementation (\\w+)" captureGroup:1] componentsJoinedByString:@"|"]]]; - [self.scopes[PROJECT_METHOD_NAMES] setPattern:[NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@property \\(.*?\\)\\s*\\w+[\\s*]+(\\w+);" captureGroup:1] componentsJoinedByString:@"|"]]]; -} -*/ - -#pragma mark - Helpers - -- (JLTokenPattern *)addToken:(NSString *)type withPattern:(NSString *)pattern andScope:(JLScope *)scope -{ - - NSParameterAssert(type); - NSParameterAssert(pattern); - NSParameterAssert(scope); - - NSRegularExpression *expression = self.expressions[pattern]; - if (expression) { - self.expressions[pattern] = expression; - } else { - expression = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionAnchorsMatchLines error:NULL]; - self.expressions[pattern] = expression; - } - - JLTokenPattern *token = [JLTokenPattern tokenPatternWithRegularExpression:expression]; - token.type = type; - token.color = self.colors[type]; - - [token addScope:scope]; - - return token; -} - -- (JLTokenPattern *)addToken:(NSString *)type withKeywords:(NSString *)keywords andScope:(JLScope *)scope -{ - NSString *pattern = [NSString stringWithFormat:@"\\b(%@)\\b", [[keywords componentsSeparatedByString:@" "] componentsJoinedByString:@"|"]]; - return [self addToken:type withPattern:pattern andScope:scope]; -} - -- (NSMutableArray *)symbolsWithPattern:(NSString *)pattern captureGroup:(int)group textStorage:(NSTextStorage *)textStorage -{ - NSMutableArray *array = [NSMutableArray array]; - NSError *error = nil; - NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionAnchorsMatchLines error:&error]; - [expression enumerateMatchesInString:textStorage.string options:0 range:NSMakeRange(0, textStorage.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { - [array addObject:[textStorage.string substringWithRange:[result rangeAtIndex:group]]]; - }]; - NSAssert(!error, @"%@",error); - return array; -} - -- (JLTokenizerIntendtationAction)intendationActionAfterReplacingTextInRange:(NSRange)range replacementText:(NSString *)text previousCharacter:(unichar)character textView:(UITextView *)textView; -{ - if (character == '{') { - return JLTokenizerIntendtationActionIncrease; - } else if (character == '}') { - return JLTokenizerIntendtationActionDecrease; - } else { - return JLTokenizerIntendtationActionNone; - } -} - -#pragma mark - Helpers - -- (UITextRange *)rangeWithRange:(NSRange)range inTextView:(UITextView *)textView -{ - UITextPosition *beginning = textView.beginningOfDocument; - UITextPosition *start = [textView positionFromPosition:beginning offset:range.location]; - UITextPosition *stop = [textView positionFromPosition:start offset:range.length]; - - return [textView textRangeFromPosition:start toPosition:stop]; -} - -- (void)clearColorAttributesInRange:(NSRange)range textStorage:(NSTextStorage *)storage; -{ - [storage removeAttribute:NSForegroundColorAttributeName range:range]; - [storage addAttribute:NSForegroundColorAttributeName value:self.colors[JLTokenTypeText] range:range]; -} - -- (NSString *)prefixStringFromRange:(NSRange)range inTextView:(UITextView *)textView -{ - NSRange lineRange = [textView.text lineRangeForRange:range]; - NSRange prefixRange = [textView.text rangeOfString:@"[\\t| ]*" options:NSRegularExpressionSearch range:lineRange]; - return [textView.text substringWithRange:prefixRange]; -} - -@end diff --git a/Chromatism/Chromatism/JLTokenizingScope.swift b/Chromatism/Chromatism/JLTokenizingScope.swift new file mode 100644 index 0000000..65491d7 --- /dev/null +++ b/Chromatism/Chromatism/JLTokenizingScope.swift @@ -0,0 +1,158 @@ +// +// JLTokenizingScope.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-28. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +/** +This class keeps track of "tokens" in the attributed string. This enables subscopes of type JLNestedScope to efficiently match tokens in to pairs. +*/ +public class JLTokenizingScope: JLScope { + + /** + Simple class to be used with JLTokenizingScope. It represents a type of symbol in the attributed string that can be nested to form scopes. + + Two tokens that represent open- and close-paranthesis could be created with + + :code: Token("\\(", delta: 1), Token("\\)", delta: -1) :endcode: + */ + public class Token: Equatable { + var delta: Int /// Set to +1 to increment by one level, or -1 to decrement + var expression: NSRegularExpression + + init(pattern: String, delta: Int) { + self.delta = delta + self.expression = NSRegularExpression(pattern: pattern, options: nil, error: nil) + } + } + + let tokens: [Token] + + public init(tokens: [Token]) { + self.tokens = tokens + super.init() + + multiline = true + } + + public convenience init(incrementing: [String], decrementing:[String]) { + var tokens = [Token]() + for string in incrementing { + tokens += Token(pattern: string, delta: 1) + } + + for string in decrementing { + tokens += Token(pattern: string, delta: -1) + } + + self.init(tokens: tokens) + + multiline = true + } + + /** + Returns an instance with one fully set-up JLNestedScope as subscope. + */ + public convenience init(incrementingPattern: String, decrementingPattern: String, tokenType: JLTokenType, hollow: Bool) { + let a = Token(pattern: incrementingPattern, delta: 1) + let b = Token(pattern: decrementingPattern, delta: -1) + let descriptor = JLNestedScope(incrementingToken: a, decrementingToken: b, tokenType: tokenType, hollow: hollow) + self.init(tokens: [a, b]) + self.subscopes = [descriptor] + } + + + var matches = [TokenResult]() + private var deletions = [TokenResult]() + + override func perform(indexSet: NSIndexSet) { + self.indexSet = NSMutableIndexSet() + + // Find Matches + var array = [TokenResult]() + var foundTokenIndexes = NSMutableIndexSet() + indexSet.enumerateRangesUsingBlock { (range, _) in + for token in self.tokens { + token.expression.enumerateMatchesInString(self.attributedString.string, options: nil, range: range, usingBlock: { (result, _, _) in + if !foundTokenIndexes.containsAnyIndexesInRange(result.range) { + array += TokenResult(result: result, token: token) + foundTokenIndexes.addIndexesInRange(result.range) + } + }) + } + } + + + matches += array + matches.sort { $0.range.location < $1.range.location } + +// oldLineIndexes = + + for scope in subscopes { + if let scope = scope as? JLNestedScope { + scope.theme = theme + scope.perform(indexSet, tokens: matches) + self.indexSet += scope.indexSet + } + } + } + + + override func shiftIndexesAtLoaction(location: Int, by delta: Int) { + + for (index, token) in enumerate(matches.reverse()) { + if token.range.location < location { break } + token.shiftRanges(delta) + } + + super.shiftIndexesAtLoaction(location, by: delta) + } + + override func invalidateAttributesInIndexes(indexSet: NSIndexSet) { + self.indexSet -= indexSet + matches = matches.filter { !(indexSet.containsIndexesInRange($0.range)) } + } + + public class TokenResult: Printable { + var range: NSRange { return ranges[0] } + var ranges: [NSRange] + var token: Token + + init(result: NSTextCheckingResult, token: Token) { + self.ranges = [] + self.token = token + var i = 0 + while i < result.numberOfRanges { + ranges += result.rangeAtIndex(i) + i++ + } + } + + func shiftRanges(delta: Int) { + ranges = ranges.map { return NSMakeRange($0.location + delta, $0.length)} + } + + public var description: String { return "∆\(token.delta) \(range)"} + } +} + +public func ==(lhs: JLTokenizingScope.Token, rhs: JLTokenizingScope.Token) -> Bool { + return (lhs.expression.pattern == rhs.expression.pattern && lhs.delta == rhs.delta) +} + +private extension NSIndexSet { + func containsAnyIndexesInRange(range: NSRange) -> Bool { + for index in range.start ..< range.end { + if self.containsIndex(index) { + return true + } + } + return false + } +} + + diff --git a/Chromatism/Chromatism/NSIndexSet+Additions.swift b/Chromatism/Chromatism/NSIndexSet+Additions.swift new file mode 100644 index 0000000..a32ba91 --- /dev/null +++ b/Chromatism/Chromatism/NSIndexSet+Additions.swift @@ -0,0 +1,74 @@ +// +// NSIndexSet+Intersection.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-14. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +extension NSIndexSet { + func intersectionWithSet(set: NSIndexSet) -> NSMutableIndexSet { + let finalSet = NSMutableIndexSet() + self.enumerateIndexesUsingBlock({ (index, stop) in + if set.containsIndex(index) { + finalSet.addIndex(index) + } + }) + return finalSet + } +} + +func NSIndexSetDelta(oldSet: NSIndexSet, newSet: NSIndexSet) -> (additions: NSMutableIndexSet, deletions: NSMutableIndexSet) { + // Old: ABC + // ∆(-) B + // ∆(+) D + // New: A CD + + // deletions = old - new + // additions = new - old + + let additions = newSet - oldSet + let deletions = oldSet - newSet + + return (additions, deletions) +} + +@infix func -(left: NSIndexSet, right: NSIndexSet) -> NSMutableIndexSet { + let indexSet = left.mutableCopy() as NSMutableIndexSet + indexSet.removeIndexes(right) + return indexSet +} + +@infix func +(left: NSIndexSet, right: NSIndexSet) -> NSMutableIndexSet { + let indexSet = left.mutableCopy() as NSMutableIndexSet + indexSet.addIndexes(right) + return indexSet +} + +@infix func -=(left: NSMutableIndexSet, right: NSIndexSet) { + left.removeIndexes(right) +} + +@infix func +=(left: NSMutableIndexSet, right: NSIndexSet) { + left.addIndexes(right) +} + +@infix func -=(left: NSMutableIndexSet, right: NSRange) { + left.removeIndexesInRange(right) +} + +@infix func +=(left: NSMutableIndexSet, right: NSRange) { + left.addIndexesInRange(right) +} + +extension NSRange { + var end: Int { + return location + length + } + + var start: Int { + return location + } +} \ No newline at end of file diff --git a/Chromatism/Chromatism/UIColor+Chromatism.h b/Chromatism/Chromatism/UIColor+Chromatism.h deleted file mode 100644 index e67e335..0000000 --- a/Chromatism/Chromatism/UIColor+Chromatism.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// UIColor+Chromatism.h -// Chromatism -// -// Created by Johannes Lund on 2013-08-20. -// Copyright (c) 2013 Johannes Lund -// -// 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 - -@interface UIColor (Chromatism) - -+ (UIColor *)backgroundMarkupColor; - -@end diff --git a/Chromatism/Chromatism/UIColor+Chromatism.m b/Chromatism/Chromatism/UIColor+Chromatism.m deleted file mode 100644 index 52022cb..0000000 --- a/Chromatism/Chromatism/UIColor+Chromatism.m +++ /dev/null @@ -1,38 +0,0 @@ -// -// UIColor+Chromatism.m -// Chromatism -// -// Created by Johannes Lund on 2013-08-20. -// Copyright (c) 2013 Johannes Lund -// -// 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 "UIColor+Chromatism.h" - -@implementation UIColor (Chromatism) - -+ (UIColor *)backgroundMarkupColor -{ - static UIColor *color; - if (!color) { - color = [UIColor colorWithWhite:0.1122334455 alpha:1]; - } - return color; -} - -@end diff --git a/Chromatism/Chromatism/test.json b/Chromatism/Chromatism/test.json deleted file mode 100644 index 5e8fcb5..0000000 --- a/Chromatism/Chromatism/test.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "import" : "c", // imports c.json - "language" : "objective-c", // - "filetypes" : ["m" "h"], - "patterns" : [ - { - "name" : "blockComments", - "color" : "JLTokenTypeComment", - "regex" : "/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/", - }, - { - "name" : "lineComments", - "color" : "JLTokenTypeComment", - "regex" : "//.*+\n", - }, - { - "name" : "block comments", - "color" : "JLTokenTypeComment", - "regex" : "/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/", - }, - { - "name" : "block comments", - "color" : "JLTokenTypeComment", - "regex" : "/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/", - }, - ], - -} diff --git a/Chromatism/ChromatismTests/ChromatismTests.m b/Chromatism/ChromatismTests/ChromatismTests.m deleted file mode 100644 index 0045758..0000000 --- a/Chromatism/ChromatismTests/ChromatismTests.m +++ /dev/null @@ -1,98 +0,0 @@ -// -// ChromatismTests.m -// ChromatismTests -// -// Created by Johannes Lund on 2013-07-01. -// Copyright (c) 2013 Johannes Lund -// -// 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 -#import "Chromatism.h" -#import "Helpers.h" - -@interface ChromatismTests : XCTestCase - -@end - -@implementation ChromatismTests - -- (void)setUp -{ - [super setUp]; - - // Set-up code here. -} - -- (void)tearDown -{ - // Tear-down code here. - - [super tearDown]; -} - -- (void)testIntersection -{ - NSIndexSet *setA = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(5, 20)]; - NSIndexSet *setB = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(3, 7)]; - - NSIndexSet *result = [setA intersectionWithSet:setB]; - - XCTAssertEqualObjects(result, [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(5, 5)], @""); - -} - -- (void)testSubscopes -{ - NSTextStorage *storage = [[NSTextStorage alloc] initWithString:@"Test test test test"]; - JLScope *scope = [JLScope scopeWithTextStorage:storage]; - - XCTAssert(scope.opaque, @"scopes should be opaque per default"); - - JLScope *subscope1 = [JLScope scopeWithRange:NSMakeRange(0, 1) inTextStorage:nil]; - JLScope *subscope2 = [JLScope scopeWithRange:NSMakeRange(1, 1) inTextStorage:nil]; - JLScope *subscope3 = [JLScope scopeWithRange:NSMakeRange(2, 1) inTextStorage:nil]; - JLScope *subscope4 = [JLScope scopeWithRange:NSMakeRange(3, 1) inTextStorage:nil]; - - [scope setSubscopes:@[subscope1, subscope2]]; - [scope addSubscope:subscope3]; - - subscope4.scope = scope; - - - XCTAssertEqualObjects(subscope1.scope, scope, @""); - XCTAssertEqualObjects(subscope2.scope, scope, @""); - XCTAssertEqualObjects(subscope3.scope, scope, @""); - XCTAssertEqualObjects(subscope4.scope, scope, @""); - - XCTAssertNotEqualObjects(subscope1.textStorage, scope.textStorage, @""); - XCTAssertNotEqualObjects(subscope2.textStorage, scope.textStorage, @""); - XCTAssertNotEqualObjects(subscope3.textStorage, scope.textStorage, @""); - XCTAssertNotEqualObjects(subscope4.textStorage, scope.textStorage, @""); - - [scope perform]; - - XCTAssertEqualObjects(subscope1.textStorage, scope.textStorage, @""); - XCTAssertEqualObjects(subscope2.textStorage, scope.textStorage, @""); - XCTAssertEqualObjects(subscope3.textStorage, scope.textStorage, @""); - XCTAssertEqualObjects(subscope4.textStorage, scope.textStorage, @""); - - XCTAssertTrue([scope.subscopes isKindOfClass:[NSMutableArray class]], @"subscopes should be of type NSMutableArray"); -} - -@end diff --git a/Chromatism/ChromatismTests/ChromatismTests.swift b/Chromatism/ChromatismTests/ChromatismTests.swift new file mode 100644 index 0000000..938d8dd --- /dev/null +++ b/Chromatism/ChromatismTests/ChromatismTests.swift @@ -0,0 +1,50 @@ +// +// ChromatismTests.swift +// ChromatismTests +// +// Created by Johannes Lund on 2014-07-14. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit +import XCTest + +class ChromatismTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testExample() { + // This is an example of a functional test case. + XCTAssert(true, "Pass") + } + + func testIndexSetIntersection() { + // This is an example of a performance test case. + + let set1 = NSMutableIndexSet(indexesInRange: NSMakeRange(0, 200)) + set1.addIndexesInRange(NSMakeRange(400, 200)) + + let set2 = NSMutableIndexSet(indexesInRange: NSMakeRange(100, 200)) + set2.addIndexesInRange(NSMakeRange(300, 200)) + + let set3 = NSMutableIndexSet(indexesInRange: NSMakeRange(100, 100)) + set3.addIndexesInRange(NSMakeRange(400, 100)) + + self.measureBlock() { + // Put the code you want to measure the time of here. + for _ in 1...1000 { + let finalSet = set1.intersectionWithSet(set2) + XCTAssertEqual(set3, finalSet, "") + } + } + } + +} diff --git a/Chromatism/ChromatismTests/ChromatismTests-Info.plist b/Chromatism/ChromatismTests/Info.plist similarity index 92% rename from Chromatism/ChromatismTests/ChromatismTests-Info.plist rename to Chromatism/ChromatismTests/Info.plist index 4b3d885..592dae7 100644 --- a/Chromatism/ChromatismTests/ChromatismTests-Info.plist +++ b/Chromatism/ChromatismTests/Info.plist @@ -10,6 +10,8 @@ anviking.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 + CFBundleName + ${PRODUCT_NAME} CFBundlePackageType BNDL CFBundleShortVersionString diff --git a/Chromatism/ChromatismTests/JLKeywordScopeTests.swift b/Chromatism/ChromatismTests/JLKeywordScopeTests.swift new file mode 100644 index 0000000..d3ff184 --- /dev/null +++ b/Chromatism/ChromatismTests/JLKeywordScopeTests.swift @@ -0,0 +1,56 @@ +// +// JLKeywordScopeTests.swift +// Chromatism +// +// Created by Johannes Lund on 2014-08-02. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit +import XCTest + +class JLKeywordScopeTests: XCTestCase { + + let string = NSString(contentsOfURL: NSBundle(forClass: ObjectiveC.self).URLForResource("demo", withExtension: "txt"), encoding: NSUTF8StringEncoding, error: nil) + var attributedString: NSMutableAttributedString! + + var keywords = "Array|AutoreleasingUnsafePointer|BidirectionalReverseView|Bit|Bool|CFunctionPointer|COpaquePointer|CVaListPointer|Character|CollectionOfOne|ConstUnsafePointer|ContiguousArray|Dictionary|DictionaryGenerator|DictionaryIndex|Double|EmptyCollection|EmptyGenerator|EnumerateGenerator|FilterCollectionView|FilterCollectionViewIndex|FilterGenerator|FilterSequenceView|Float|Float80|FloatingPointClassification|GeneratorOf|GeneratorOfOne|GeneratorSequence|HeapBuffer|HeapBuffer|HeapBufferStorage|HeapBufferStorageBase|ImplicitlyUnwrappedOptional|IndexingGenerator|Int|Int16|Int32|Int64|Int8|IntEncoder|LazyBidirectionalCollection|LazyForwardCollection|LazyRandomAccessCollection|LazySequence|Less|MapCollectionView|MapSequenceGenerator|MapSequenceView|MirrorDisposition|ObjectIdentifier|OnHeap|Optional|PermutationGenerator|QuickLookObject|RandomAccessReverseView|Range|RangeGenerator|RawByte|Repeat|ReverseBidirectionalIndex|ReverseRandomAccessIndex|SequenceOf|SinkOf|Slice|StaticString|StrideThrough|StrideThroughGenerator|StrideTo|StrideToGenerator|String|Index|UTF8View|Index|UnicodeScalarView|IndexType|GeneratorType|UTF16View|UInt|UInt16|UInt32|UInt64|UInt8|UTF16|UTF32|UTF8|UnicodeDecodingResult|UnicodeScalar|Unmanaged|UnsafeArray|UnsafeArrayGenerator|UnsafeMutableArray|UnsafePointer|VaListBuilder|Header|Zip2|ZipGenerator2".componentsSeparatedByString("|") + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + attributedString = NSMutableAttributedString(string: string) + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testExample() { + // This is an example of a functional test case. + XCTAssert(true, "Pass") + } + + func testOrdinaryPattern() { + // This is an example of a performance test case. + let pattern = "\\b(" + join("|", keywords) + ")\\b" + let scope = JLRegexScope(pattern: pattern, tokenTypes: .Keyword) + scope.attributedString = attributedString + scope.theme = .Default + self.measureBlock() { + scope.perform() + } + } + + func testKeywordPattern() { + // This is an example of a performance test case. + let scope = JLKeywordScope(keywords: keywords, tokenTypes: .Keyword) + scope.attributedString = attributedString + scope.theme = .Default + self.measureBlock() { + scope.perform() + } + } + +} diff --git a/Chromatism/ChromatismTests/JLScopeTests.swift b/Chromatism/ChromatismTests/JLScopeTests.swift new file mode 100644 index 0000000..386ba17 --- /dev/null +++ b/Chromatism/ChromatismTests/JLScopeTests.swift @@ -0,0 +1,79 @@ +// +// JLScopeTests.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-14. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit +import XCTest + +let ChromatismTestsDefaultTheme = JLColorTheme.Default + +class JLScopeTests: XCTestCase { + + let blue = UIColor.blueColor() + let green = UIColor.greenColor() + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + func testSubscripting() { + + let a = JLScope() + let b = JLScope() + let c = JLScope() + let d = JLScope() + let e = JLScope() + let f = JLScope() + let g = JLScope() + let h = JLScope() + + a[ + b[c,d], + e[f], + g, + h + ] + + XCTAssert(a.subscopes == [b,e,g,h], "") + XCTAssert(b.subscopes == [c,d], "") + XCTAssert(e.subscopes == [f], "") + XCTAssert(g.subscopes.count == 0, "") + XCTAssert(h.subscopes.count == 0, "") + + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measureBlock() { + // Put the code you want to measure the time of here. + } + } + +} + +extension String { + // I'm lazy + var comment: NSMutableAttributedString { return attributedStringWithTokenType(.Comment) } + var text: NSMutableAttributedString { return attributedStringWithTokenType(.Text) } + var keyword: NSMutableAttributedString { return attributedStringWithTokenType(.Keyword) } + + func attributedStringWithTokenType(token: JLTokenType) -> NSMutableAttributedString { + let colors = JLColorTheme.Default.dictionary + return NSMutableAttributedString(string: self, attributes: [NSForegroundColorAttributeName:colors[token]! ]) + } +} + +@infix func + (left: NSAttributedString, right: NSAttributedString) -> NSMutableAttributedString { + let string = left.mutableCopy() as NSMutableAttributedString + string.appendAttributedString(right) + return string +} diff --git a/Chromatism/ChromatismTests/JLTokenTests.swift b/Chromatism/ChromatismTests/JLTokenTests.swift new file mode 100644 index 0000000..c786a3a --- /dev/null +++ b/Chromatism/ChromatismTests/JLTokenTests.swift @@ -0,0 +1,17 @@ +// +// JLTokenTests.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-14. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit +import XCTest + +class JLTokenTests: XCTestCase { + + var attributedString = "//Hello World!\nHello".text + let commentColor = JLColorTheme.Default.dictionary[.Comment]! + let worldColor = JLColorTheme.Default.dictionary[.Keyword]! +} \ No newline at end of file diff --git a/Chromatism/ChromatismTests/JLTokenizerTests.m b/Chromatism/ChromatismTests/JLTokenizerTests.m deleted file mode 100644 index 59fdf9c..0000000 --- a/Chromatism/ChromatismTests/JLTokenizerTests.m +++ /dev/null @@ -1,202 +0,0 @@ -// -// JLTokenizerTests.m -// Chromatism -// -// Created by Anviking on 2013-07-31. -// Copyright (c) 2013 Johannes Lund -// -// 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 -#import "Chromatism.h" -#import "JLTokenizer.h" - -@interface JLTokenizer () -- (JLTokenPattern *)addToken:(NSString *)type withPattern:(NSString *)pattern andScope:(JLScope *)scope; -@end - -@interface JLTokenizerTests : XCTestCase - -@end - -@implementation JLTokenizerTests -{ - JLTokenizer *tokenizer; -} - -- (void)setUp -{ - [super setUp]; - // Put setup code here. This method is called before the invocation of each test method in the class. - - tokenizer = [[JLTokenizer alloc] init]; - tokenizer.colors = [Chromatism colorsForTheme:JLTokenizerThemeDefault]; -} - -- (void)tearDown -{ - // Put teardown code here. This method is called after the invocation of each test method in the class. - [super tearDown]; -} - -- (void)testBasicTokenizing -{ - NSString *string = @"self //test"; - // 01234567891 - NSTextStorage* textStorage = [[NSTextStorage alloc] initWithString:string attributes:@{ @"attribute" : @42 }]; - [tokenizer tokenizeTextStorage:textStorage withRange:NSMakeRange(0, textStorage.length)]; - - XCTAssertEqualObjects([textStorage attribute:@"attribute" atIndex:0 effectiveRange:NULL], @42, @"Should keep attribute value"); - - NSRange selfRange; - NSRange commentRange; - - UIColor *keywordColor = tokenizer.colors[JLTokenTypeKeyword]; - UIColor *commentColor = tokenizer.colors[JLTokenTypeComment]; - - XCTAssertEqualObjects([textStorage attribute:NSForegroundColorAttributeName atIndex:0 effectiveRange:&selfRange], keywordColor, @"Self should be keyword-colored"); - XCTAssertEqualObjects([textStorage attribute:NSForegroundColorAttributeName atIndex:5 effectiveRange:&commentRange], commentColor, @"Should be comment-colored"); - - XCTAssertEqual(selfRange, NSMakeRange(0, 4), @"self should be colored"); - XCTAssertEqual(commentRange, NSMakeRange(5, 6), @"//test should be colored"); -} - -- (void)testDemoTextDescription -{ - // Load demo text - - NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - - NSURL *URL = [bundle URLForResource:@"demo" withExtension:@"txt"]; - NSString *string = [[NSString alloc] initWithData:[NSData dataWithContentsOfURL:URL] encoding:NSUTF8StringEncoding]; - NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:string]; - - NSRange range = NSMakeRange(0, textStorage.length); - - JLScope *documentScope = [JLScope scopeWithTextStorage:textStorage]; - JLScope *rangeScope = [JLScope scopeWithRange:range inTextStorage:textStorage]; - - // Block and line comments - [tokenizer addToken:JLTokenTypeComment withPattern:@"/\\*([^*]|[\\r\\n]|(\\*+([^*/]|[\\r\\n])))*\\*+/" andScope:documentScope]; - [tokenizer addToken:JLTokenTypeComment withPattern:@"//.*+$" andScope:rangeScope]; - - // Preprocessor macros - JLTokenPattern *preprocessor = [tokenizer addToken:JLTokenTypePreprocessor withPattern:@"#.*+$" andScope:rangeScope]; - - // #import - // In xcode it only works for #import and #include, not all preprocessor statements. - [tokenizer addToken:JLTokenTypeString withPattern:@"<.*?>" andScope:preprocessor]; - - // Strings - [[tokenizer addToken:JLTokenTypeString withPattern:@"(\"|@\")[^\"\\n]*(@\"|\")" andScope:rangeScope] addScope:preprocessor]; - - // Numbers - [tokenizer addToken:JLTokenTypeNumber withPattern:@"(?<=\\s)\\d+" andScope:rangeScope]; - - // New literals, for example @[] - // TODO: Literals don't search through multiple lines. Nor does it keep track of nested things. - [[tokenizer addToken:JLTokenTypeNumber withPattern:@"@[\\(|\\{|\\[][^\\(\\{\\[]+[\\)|\\}|\\]]" andScope:rangeScope] setOpaque:NO]; - - // C function names - [[tokenizer addToken:JLTokenTypeOtherMethodNames withPattern:@"\\w+\\s*(?>\\(.*\\)" andScope:rangeScope] setCaptureGroup:1]; - - // Dot notation - [[tokenizer addToken:JLTokenTypeOtherMethodNames withPattern:@"\\.(\\w+)" andScope:rangeScope] setCaptureGroup:1]; - - // Method Calls - [[tokenizer addToken:JLTokenTypeOtherMethodNames withPattern:@"\\[\\w+\\s+(\\w+)\\]" andScope:rangeScope] setCaptureGroup:1]; - - // Method call parts - [[tokenizer addToken:JLTokenTypeOtherMethodNames withPattern:@"(?<=\\w+):\\s*[^\\s;\\]]+" andScope:rangeScope] setCaptureGroup:1]; - - // NS and UI prefixes words - [tokenizer addToken:JLTokenTypeOtherClassNames withPattern:@"(\\b(?>NS|UI))\\w+\\b" andScope:rangeScope]; - - [tokenizer addToken:JLTokenTypeKeyword withPattern:@"(?<=\\b)(?>true|false|yes|no|TRUE|FALSE|bool|BOOL|nil|id|void|self|NULL|if|else|strong|weak|nonatomic|atomic|assign|copy|typedef|enum|auto|break|case|const|char|continue|do|default|double|extern|float|for|goto|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|volatile|while|nonatomic|atomic|nonatomic|readonly|super )(\\b)" andScope:rangeScope]; - [tokenizer addToken:JLTokenTypeKeyword withPattern:@"@[a-zA-Z0-9_]+" andScope:rangeScope]; - - [documentScope addSubscope:rangeScope]; - [documentScope perform]; - - NSURL *descriptionURL = [bundle URLForResource:@"description" withExtension:@"txt"]; - NSMutableString *description = [[NSString alloc] initWithData:[NSData dataWithContentsOfURL:descriptionURL] encoding:NSUTF8StringEncoding].mutableCopy; - NSMutableString *newDescription = [documentScope description].mutableCopy; - - // Remove hexadecimal garbage - NSError *error = nil; - NSRegularExpression *expression = [[NSRegularExpression alloc] initWithPattern:@"0(x|X)[0-9a-fA-F]{7}>" options:0 error:&error]; - [expression replaceMatchesInString:description options:0 range:NSMakeRange(0, description.length) withTemplate:@""]; - [expression replaceMatchesInString:newDescription options:0 range:NSMakeRange(0, newDescription.length) withTemplate:@""]; - - XCTAssertNil(nil, @""); - XCTAssertEqualObjects(description, newDescription, @""); - -} - -- (NSTimeInterval)timeOfTokenizingString:(NSString *)string multiplied:(NSInteger)multiplier -{ - string = [string stringByPaddingToLength:(string.length * multiplier) withString:string startingAtIndex:0]; - NSTextStorage *storage = [[NSTextStorage alloc] initWithString:string]; - NSDate *date = [NSDate date]; - [tokenizer tokenizeTextStorage:storage withRange:NSMakeRange(0, string.length)]; - return ABS([date timeIntervalSinceNow]); -} - -- (NSTimeInterval)timeOfTokenizingString:(NSString *)string range:(NSRange)range multiplied:(NSInteger)multiplier -{ - string = [string stringByPaddingToLength:(string.length * multiplier) withString:string startingAtIndex:0]; - NSTextStorage *storage = [[NSTextStorage alloc] initWithString:string]; - NSDate *date = [NSDate date]; - [tokenizer tokenizeTextStorage:storage withRange:range]; - return ABS([date timeIntervalSinceNow]); -} - -/* -- (void)testAndPlotLater -{ - NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - NSURL *URL = [bundle URLForResource:@"demo" withExtension:@"txt"]; - NSString *string = [[NSString alloc] initWithData:[NSData dataWithContentsOfURL:URL] encoding:NSUTF8StringEncoding]; - NSMutableString *result = [[NSMutableString alloc] init]; - for (int i = 1; i<50; i++) { - NSTimeInterval interval = [self timeOfTokenizingString:string multiplied:i]; - [result appendFormat:@"%f,",interval]; - } - NSLog(@"Result:%@",result); -} - */ - -- (void)testLargeFilePerformance -{ - NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - NSURL *URL = [bundle URLForResource:@"demo" withExtension:@"txt"]; - NSString *string = [[NSString alloc] initWithData:[NSData dataWithContentsOfURL:URL] encoding:NSUTF8StringEncoding]; - NSTimeInterval interval = [self timeOfTokenizingString:string multiplied:10]; - NSLog(@"\n\nLarge file tokenizing: %fms\n\n", interval*1000); -} - -- (void)testSmallEditPerformance -{ - NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - NSURL *URL = [bundle URLForResource:@"demo" withExtension:@"txt"]; - NSString *string = [[NSString alloc] initWithData:[NSData dataWithContentsOfURL:URL] encoding:NSUTF8StringEncoding]; - NSTimeInterval interval = [self timeOfTokenizingString:string range:[string lineRangeForRange:NSMakeRange(500, 5)] multiplied:1]; - NSLog(@"\n\nLine edit Performance: %fms\n\n", interval*1000); -} - -@end diff --git a/Chromatism/ChromatismTests/ObjectiveC.swift b/Chromatism/ChromatismTests/ObjectiveC.swift new file mode 100644 index 0000000..d669d4b --- /dev/null +++ b/Chromatism/ChromatismTests/ObjectiveC.swift @@ -0,0 +1,92 @@ +// +// JLLanguageTests.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-21. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit +import XCTest + +class ObjectiveC: XCTestCase { + + let string = NSString(contentsOfURL: NSBundle(forClass: ObjectiveC.self).URLForResource("demo", withExtension: "txt"), encoding: NSUTF8StringEncoding, error: nil) + + var attributedString: NSMutableAttributedString! + var language: JLLanguage.ObjectiveC! + + override func setUp() { + super.setUp() + attributedString = NSMutableAttributedString(string: string) + language = JLLanguage.ObjectiveC() + language.documentScope.cascadeAttributedString(attributedString) + language.documentScope.theme = .Default + } + + func testEverything() { + measureBlock { + self.language.documentScope.perform() + } + } + + func testSquareBrackets() { + measureBlock { + self.language.squareBrackets.perform() + } + } + + func testBlockComments() { + measureBlock { + self.language.blockComments.perform() + } + } + + func testLineComments() { + measureBlock { + self.language.lineComments.perform() + } + } + + func testPreprocessor() { + measureBlock { + self.language.preprocessor.perform() + } + } + + func testStrings() { + measureBlock { + self.language.strings.perform() + } + } + + func testNumbers() { + measureBlock { + self.language.numbers.perform() + } + } + + func testFunctions() { + measureBlock { + self.language.functions.perform() + } + } + + func testKeywords() { + measureBlock { + self.language.keywords.perform() + } + } + + func testDotNotation() { + measureBlock { + self.language.dotNotation.perform() + } + } + + func testObjectiveCKeywords() { + measureBlock { + self.language.objcKeywords.perform() + } + } +} diff --git a/Chromatism/ChromatismTests/Swift.swift b/Chromatism/ChromatismTests/Swift.swift new file mode 100644 index 0000000..d6b2f67 --- /dev/null +++ b/Chromatism/ChromatismTests/Swift.swift @@ -0,0 +1,38 @@ +// +// Swift.swift +// Chromatism +// +// Created by Johannes Lund on 2014-08-02. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit +import XCTest + +class Swift: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testExample() { + // This is an example of a functional test case. + XCTAssert(true, "Pass") + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measureBlock() { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/Chromatism/ChromatismTests/bundle.bundle/Root.plist b/Chromatism/ChromatismTests/bundle.bundle/Root.plist deleted file mode 100644 index fa98306..0000000 --- a/Chromatism/ChromatismTests/bundle.bundle/Root.plist +++ /dev/null @@ -1,61 +0,0 @@ - - - - - PreferenceSpecifiers - - - Title - Group - Type - PSGroupSpecifier - - - AutocapitalizationType - None - AutocorrectionType - No - DefaultValue - - IsSecure - - Key - name_preference - KeyboardType - Alphabet - Title - Name - Type - PSTextFieldSpecifier - - - DefaultValue - - Key - enabled_preference - Title - Enabled - Type - PSToggleSwitchSpecifier - - - DefaultValue - 0.5 - Key - slider_preference - MaximumValue - 1 - MaximumValueImage - - MinimumValue - 0 - MinimumValueImage - - Type - PSSliderSpecifier - - - StringsTable - Root - - diff --git a/Chromatism/ChromatismTests/bundle.bundle/demo.txt b/Chromatism/ChromatismTests/bundle.bundle/demo.txt deleted file mode 100644 index 482a0e1..0000000 --- a/Chromatism/ChromatismTests/bundle.bundle/demo.txt +++ /dev/null @@ -1,956 +0,0 @@ -// -// RKObjectManager.m -// RestKit -// -// Created by Jeremy Ellison on 8/14/09. -// Copyright (c) 2009-2012 RestKit. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#import -#import "RKObjectManager.h" -#import "RKObjectParameterization.h" -#import "RKManagedObjectStore.h" -#import "RKRequestDescriptor.h" -#import "RKResponseDescriptor.h" -#import "RKDictionaryUtilities.h" -#import "RKMIMETypes.h" -#import "RKLog.h" -#import "RKMIMETypeSerialization.h" -#import "RKPathMatcher.h" -#import "RKMappingErrors.h" -#import "RKPaginator.h" -#import "RKDynamicMapping.h" -#import "RKRelationshipMapping.h" - -#if !__has_feature(objc_arc) -#error RestKit must be built with ARC. -// You can turn on ARC for only RestKit files by adding "-fobjc-arc" to the build phase for each of its files. -#endif - -////////////////////////////////// -// Shared Instance - -static RKObjectManager *sharedManager = nil; - -////////////////////////////////// -// Utility Functions - -/** - Returns the subset of the given array of `RKResponseDescriptor` objects that match the given path. - - @param responseDescriptors An array of `RKResponseDescriptor` objects. - @param path The path for which to select matching response descriptors. - @param method The method for which to select matching response descriptors. - @return An `NSArray` object whose elements are `RKResponseDescriptor` objects matching the given path and method. - */ -static NSArray *RKFilteredArrayOfResponseDescriptorsMatchingPathAndMethod(NSArray *responseDescriptors, NSString *path, RKRequestMethod method) -{ - NSIndexSet *indexSet = [responseDescriptors indexesOfObjectsPassingTest:^BOOL(RKResponseDescriptor *responseDescriptor, NSUInteger idx, BOOL *stop) { - return [responseDescriptor matchesPath:path] && (method & responseDescriptor.method); - }]; - return [responseDescriptors objectsAtIndexes:indexSet]; -} - -/** - Returns the first `RKRequestDescriptor` object from the given array that matches the given object. - - @param requestDescriptors An array of `RKRequestDescriptor` objects. - @param object The object to find a matching request descriptor for. - @return An `RKRequestDescriptor` object matching the given object, or `nil` if none could be found. - */ -RKRequestDescriptor *RKRequestDescriptorFromArrayMatchingObjectAndRequestMethod(NSArray *requestDescriptors, id object, RKRequestMethod requestMethod); -RKRequestDescriptor *RKRequestDescriptorFromArrayMatchingObjectAndRequestMethod(NSArray *requestDescriptors, id object, RKRequestMethod requestMethod) -{ - Class searchClass = [object class]; - do { - for (RKRequestDescriptor *requestDescriptor in requestDescriptors) { - if ([requestDescriptor.objectClass isEqual:searchClass] && (requestMethod == requestDescriptor.method)) return requestDescriptor; - } - - for (RKRequestDescriptor *requestDescriptor in requestDescriptors) { - if ([requestDescriptor.objectClass isEqual:searchClass] && (requestMethod & requestDescriptor.method)) return requestDescriptor; - } - searchClass = [searchClass superclass]; - } while (searchClass); - - return nil; -} - -extern NSString *RKStringDescribingRequestMethod(RKRequestMethod method); - -@interface RKObjectParameters : NSObject - -@property (nonatomic, strong) NSMutableDictionary *parameters; -- (void)addParameters:(NSDictionary *)serialization atRootKeyPath:(NSString *)rootKeyPath inArray:(BOOL)inArray; - -@end - -@implementation RKObjectParameters - -- (id)init -{ - self = [super init]; - if (self) { - self.parameters = [NSMutableDictionary new]; - } - return self; -} - -- (void)addParameters:(NSDictionary *)parameters atRootKeyPath:(NSString *)rootKeyPath inArray:(BOOL)inArray -{ - id rootKey = rootKeyPath ?: [NSNull null]; - id nonNestedParameters = rootKeyPath ? [parameters objectForKey:rootKeyPath] : parameters; - id value = [self.parameters objectForKey:rootKey]; - if (value) { - if ([value isKindOfClass:[NSMutableArray class]]) { - [value addObject:nonNestedParameters]; - } else if ([value isKindOfClass:[NSDictionary class]]) { - NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:value, nonNestedParameters, nil]; - [self.parameters setObject:mutableArray forKey:rootKey]; - } else { - [NSException raise:NSInvalidArgumentException format:@"Unexpected argument of type '%@': expected an NSDictionary or NSArray.", [value class]]; - } - } else { - [self.parameters setObject:(inArray ? @[ nonNestedParameters ] : nonNestedParameters) forKey:rootKey]; - } -} - -- (id)requestParameters -{ - if ([self.parameters count] == 0) return nil; - id valueAtNullKey = [self.parameters objectForKey:[NSNull null]]; - if (valueAtNullKey) { - if ([self.parameters count] == 1) return valueAtNullKey; - - // If we have values at `[NSNull null]` and other key paths, we have an invalid configuration - [NSException raise:NSInvalidArgumentException format:@"Invalid request descriptor configuration: The request descriptors specify that multiple objects be serialized at incompatible key paths. Cannot serialize objects at the `nil` root key path in the same request as objects with a non-nil root key path. Please check your request descriptors and try again."]; - } - return self.parameters; -} - -@end - -/** - Visits all mappings accessible via relationships or dynamic mapping in an object graph starting from a given mapping. - */ -@interface RKMappingGraphVisitor : NSObject - -@property (nonatomic, readonly) NSSet *mappings; - -- (id)initWithMapping:(RKMapping *)mapping; - -@end - -@interface RKMappingGraphVisitor () -@property (nonatomic, readwrite) NSMutableSet *mutableMappings; -@end - -@implementation RKMappingGraphVisitor - -- (id)initWithMapping:(RKMapping *)mapping -{ - self = [super init]; - if (self) { - self.mutableMappings = [NSMutableSet set]; - [self visitMapping:mapping]; - } - return self; -} - -- (NSSet *)mappings -{ - return self.mutableMappings; -} - -- (void)visitMapping:(RKMapping *)mapping -{ - if ([self.mappings containsObject:mapping]) return; - [self.mutableMappings addObject:mapping]; - - if ([mapping isKindOfClass:[RKDynamicMapping class]]) { - RKDynamicMapping *dynamicMapping = (RKDynamicMapping *)mapping; - for (RKMapping *nestedMapping in dynamicMapping.objectMappings) { - [self visitMapping:nestedMapping]; - } - } else if ([mapping isKindOfClass:[RKObjectMapping class]]) { - RKObjectMapping *objectMapping = (RKObjectMapping *)mapping; - for (RKRelationshipMapping *relationshipMapping in objectMapping.relationshipMappings) { - [self visitMapping:relationshipMapping.mapping]; - } - } -} - -@end - -/** - Returns `YES` if the given array of `RKResponseDescriptor` objects contains an `RKEntityMapping` anywhere in its object graph. - - @param responseDescriptors An array of `RKResponseDescriptor` objects. - @return `YES` if the `mapping` property of any of the response descriptor objects in the given array is an instance of `RKEntityMapping`, else `NO`. - */ -static BOOL RKDoesArrayOfResponseDescriptorsContainEntityMapping(NSArray *responseDescriptors) -{ - // Visit all mappings accessible from the object graphs of all response descriptors - NSMutableSet *accessibleMappings = [NSMutableSet set]; - for (RKResponseDescriptor *responseDescriptor in responseDescriptors) { - if (! [accessibleMappings containsObject:responseDescriptor.mapping]) { - RKMappingGraphVisitor *graphVisitor = [[RKMappingGraphVisitor alloc] initWithMapping:responseDescriptor.mapping]; - [accessibleMappings unionSet:graphVisitor.mappings]; - } - } - - // Enumerate all mappings and search for an `RKEntityMapping` - for (RKMapping *mapping in accessibleMappings) { - if ([mapping isKindOfClass:[RKEntityMapping class]]) { - return YES; - } - - if ([mapping isKindOfClass:[RKDynamicMapping class]]) { - RKDynamicMapping *dynamicMapping = (RKDynamicMapping *)mapping; - if ([dynamicMapping.objectMappings count] == 0) { - // Likely means that there is a representation block, assume `YES` - return YES; - } - } - } - - return NO; -} - -BOOL RKDoesArrayOfResponseDescriptorsContainOnlyEntityMappings(NSArray *responseDescriptors); -BOOL RKDoesArrayOfResponseDescriptorsContainOnlyEntityMappings(NSArray *responseDescriptors) -{ - // Visit all mappings accessible from the object graphs of all response descriptors - NSMutableSet *accessibleMappings = [NSMutableSet set]; - for (RKResponseDescriptor *responseDescriptor in responseDescriptors) { - if (! [accessibleMappings containsObject:responseDescriptor.mapping]) { - RKMappingGraphVisitor *graphVisitor = [[RKMappingGraphVisitor alloc] initWithMapping:responseDescriptor.mapping]; - [accessibleMappings unionSet:graphVisitor.mappings]; - } - } - - NSMutableSet *mappingClasses = [NSMutableSet set]; - // Enumerate all mappings and search for an `RKEntityMapping` - for (RKMapping *mapping in accessibleMappings) { - if ([mapping isKindOfClass:[RKDynamicMapping class]]) { - [mappingClasses addObjectsFromArray:[[(RKDynamicMapping *)mapping objectMappings] valueForKey:@"class"]]; - } else { - [mappingClasses addObject:mapping.class]; - } - } - - if ([mappingClasses count]) { - for (Class mappingClass in mappingClasses) { - if (! [mappingClass isSubclassOfClass:[RKEntityMapping class]]) { - return NO; - } - } - return YES; - } - - return NO; -} - -static BOOL RKDoesArrayOfResponseDescriptorsContainMappingForClass(NSArray *responseDescriptors, Class classToBeMapped) -{ - // Visit all mappings accessible from the object graphs of all response descriptors - NSMutableSet *accessibleMappings = [NSMutableSet set]; - for (RKResponseDescriptor *responseDescriptor in responseDescriptors) { - if (! [accessibleMappings containsObject:responseDescriptor.mapping]) { - RKMappingGraphVisitor *graphVisitor = [[RKMappingGraphVisitor alloc] initWithMapping:responseDescriptor.mapping]; - [accessibleMappings unionSet:graphVisitor.mappings]; - } - } - - // Enumerate all mappings and search for a mapping matching the class - for (RKMapping *mapping in accessibleMappings) { - if ([mapping isKindOfClass:[RKObjectMapping class]]) { - if ([[(RKObjectMapping *)mapping objectClass] isSubclassOfClass:classToBeMapped]) return YES; - } - - if ([mapping isKindOfClass:[RKDynamicMapping class]]) { - RKDynamicMapping *dynamicMapping = (RKDynamicMapping *)mapping; - for (RKObjectMapping *mapping in dynamicMapping.objectMappings) { - if ([[(RKObjectMapping *)mapping objectClass] isSubclassOfClass:classToBeMapped]) return YES; - } - } - } - - return NO; -} - -static NSString *RKMIMETypeFromAFHTTPClientParameterEncoding(AFHTTPClientParameterEncoding encoding) -{ - switch (encoding) { - case AFFormURLParameterEncoding: - return RKMIMETypeFormURLEncoded; - break; - - case AFJSONParameterEncoding: - return RKMIMETypeJSON; - break; - - case AFPropertyListParameterEncoding: - break; - - default: - RKLogWarning(@"RestKit is unable to infer the appropriate request serialization MIME Type from an `AFHTTPClientParameterEncoding` value of %d: defaulting to `RKMIMETypeFormURLEncoded`", encoding); - break; - } - - return RKMIMETypeFormURLEncoded; -} - -@interface AFHTTPClient () -@property (readonly, nonatomic, strong) NSURLCredential *defaultCredential; -@end - -/////////////////////////////////// - -@interface RKObjectManager () -@property (nonatomic, strong) NSMutableArray *mutableRequestDescriptors; -@property (nonatomic, strong) NSMutableArray *mutableResponseDescriptors; -@property (nonatomic, strong) NSMutableArray *mutableFetchRequestBlocks; -@property (nonatomic, strong) NSMutableArray *registeredHTTPRequestOperationClasses; -@property (nonatomic, strong) NSMutableArray *registeredObjectRequestOperationClasses; -@property (nonatomic, strong) NSMutableArray *registeredManagedObjectRequestOperationClasses; - -@end - -@implementation RKObjectManager - -- (id)initWithHTTPClient:(AFHTTPClient *)client -{ - self = [super init]; - if (self) { - self.HTTPClient = client; - self.router = [[RKRouter alloc] initWithBaseURL:client.baseURL]; - self.operationQueue = [NSOperationQueue new]; - self.mutableRequestDescriptors = [NSMutableArray new]; - self.mutableResponseDescriptors = [NSMutableArray new]; - self.mutableFetchRequestBlocks = [NSMutableArray new]; - self.registeredHTTPRequestOperationClasses = [NSMutableArray new]; - self.registeredManagedObjectRequestOperationClasses = [NSMutableArray new]; - self.registeredObjectRequestOperationClasses = [NSMutableArray new]; - self.requestSerializationMIMEType = RKMIMETypeFromAFHTTPClientParameterEncoding(client.parameterEncoding); - - // Set shared manager if nil - if (nil == sharedManager) { - [RKObjectManager setSharedManager:self]; - } - } - - return self; -} - -+ (instancetype)sharedManager -{ - return sharedManager; -} - -+ (void)setSharedManager:(RKObjectManager *)manager -{ - sharedManager = manager; -} - -+ (RKObjectManager *)managerWithBaseURL:(NSURL *)baseURL -{ - RKObjectManager *manager = [[self alloc] initWithHTTPClient:[AFHTTPClient clientWithBaseURL:baseURL]]; - [manager.HTTPClient registerHTTPOperationClass:[AFJSONRequestOperation class]]; - [manager setAcceptHeaderWithMIMEType:RKMIMETypeJSON]; - manager.requestSerializationMIMEType = RKMIMETypeFormURLEncoded; - return manager; -} - -- (void)setAcceptHeaderWithMIMEType:(NSString *)MIMEType; -{ - [self.HTTPClient setDefaultHeader:@"Accept" value:MIMEType]; -} - -- (NSURL *)baseURL -{ - return self.HTTPClient.baseURL; -} - -- (NSDictionary *)defaultHeaders -{ - return self.HTTPClient.defaultHeaders; -} - -#pragma mark - Building Requests - -/** - This method is the `RKObjectManager` analog for the method of the same name on `AFHTTPClient`. - */ -- (NSMutableURLRequest *)requestWithMethod:(NSString *)method - path:(NSString *)path - parameters:(NSDictionary *)parameters -{ - NSMutableURLRequest* request; - if (parameters && !([method isEqualToString:@"GET"] || [method isEqualToString:@"HEAD"] || [method isEqualToString:@"DELETE"])) { - // NOTE: If the HTTP client has been subclasses, then the developer may be trying to perform signing on the request - NSDictionary *parametersForClient = [self.HTTPClient isMemberOfClass:[AFHTTPClient class]] ? nil : parameters; - request = [self.HTTPClient requestWithMethod:method path:path parameters:parametersForClient]; - - NSError *error = nil; - NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(self.HTTPClient.stringEncoding)); - [request setValue:[NSString stringWithFormat:@"%@; charset=%@", self.requestSerializationMIMEType, charset] forHTTPHeaderField:@"Content-Type"]; - NSData *requestBody = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:self.requestSerializationMIMEType error:&error]; - [request setHTTPBody:requestBody]; - } else { - request = [self.HTTPClient requestWithMethod:method path:path parameters:parameters]; - } - - return request; -} - -- (NSMutableURLRequest *)requestWithPathForRouteNamed:(NSString *)routeName - object:(id)object - parameters:(NSDictionary *)parameters -{ - RKRequestMethod method; - NSURL *URL = [self.router URLForRouteNamed:routeName method:&method object:object]; - NSAssert(URL, @"No route found named '%@'", routeName); - return [self requestWithMethod:RKStringFromRequestMethod(method) path:[URL relativeString] parameters:parameters]; -} - -- (NSMutableURLRequest *)requestWithPathForRelationship:(NSString *)relationship - ofObject:(id)object - method:(RKRequestMethod)method - parameters:(NSDictionary *)parameters -{ - NSURL *URL = [self.router URLForRelationship:relationship ofObject:object method:method]; - NSAssert(URL, @"No relationship route found for the '%@' class with the name '%@'", NSStringFromClass([object class]), relationship); - return [self requestWithMethod:RKStringFromRequestMethod(method) path:[URL relativeString] parameters:parameters]; -} - -- (id)mergedParametersWithObject:(id)object method:(RKRequestMethod)method parameters:(NSDictionary *)parameters -{ - NSArray *objectsToParameterize = ([object isKindOfClass:[NSArray class]] || object == nil) ? object : @[ object ]; - RKObjectParameters *objectParameters = [RKObjectParameters new]; - for (id objectToParameterize in objectsToParameterize) { - RKRequestDescriptor *requestDescriptor = RKRequestDescriptorFromArrayMatchingObjectAndRequestMethod(self.requestDescriptors, objectToParameterize, method); - if ((method != RKRequestMethodGET && method != RKRequestMethodDELETE) && requestDescriptor) { - NSError *error = nil; - NSDictionary *parametersForObject = [RKObjectParameterization parametersWithObject:objectToParameterize requestDescriptor:requestDescriptor error:&error]; - if (error) { - RKLogError(@"Object parameterization failed while building %@ request for object '%@': %@", RKStringFromRequestMethod(method), objectToParameterize, error); - return nil; - } - // Ensure that a single object inputted as an array is emitted as an array when serialized - BOOL inArray = ([object isKindOfClass:[NSArray class]] && [object count] == 1); - [objectParameters addParameters:parametersForObject atRootKeyPath:requestDescriptor.rootKeyPath inArray:inArray]; - } - } - id requestParameters = [objectParameters requestParameters]; - - // Merge the extra parameters if possible - if ([requestParameters isKindOfClass:[NSArray class]] && parameters) { - [NSException raise:NSInvalidArgumentException format:@"Cannot merge parameters with array of object representations serialized with a nil root key path."]; - } else if (requestParameters && parameters) { - requestParameters = RKDictionaryByMergingDictionaryWithDictionary(requestParameters, parameters); - } else if (parameters && !requestParameters) { - requestParameters = parameters; - } - - return requestParameters; -} - -- (NSMutableURLRequest *)requestWithObject:(id)object - method:(RKRequestMethod)method - path:(NSString *)path - parameters:(NSDictionary *)parameters; -{ - NSString *requestPath = (path) ? path : [[self.router URLForObject:object method:method] relativeString]; - id requestParameters = [self mergedParametersWithObject:object method:method parameters:parameters]; - return [self requestWithMethod:RKStringFromRequestMethod(method) path:requestPath parameters:requestParameters]; -} - -- (NSMutableURLRequest *)multipartFormRequestWithObject:(id)object - method:(RKRequestMethod)method - path:(NSString *)path - parameters:(NSDictionary *)parameters - constructingBodyWithBlock:(void (^)(id formData))block -{ - NSString *requestPath = (path) ? path : [[self.router URLForObject:object method:method] relativeString]; - id requestParameters = [self mergedParametersWithObject:object method:method parameters:parameters]; - NSMutableURLRequest *multipartRequest = [self.HTTPClient multipartFormRequestWithMethod:RKStringFromRequestMethod(method) - path:requestPath - parameters:requestParameters - constructingBodyWithBlock:block]; - return multipartRequest; -} - -#pragma mark - Registering Subclasses - -- (BOOL)registerRequestOperationClass:(Class)operationClass -{ - if ([operationClass isSubclassOfClass:[RKManagedObjectRequestOperation class]]) { - [self.registeredManagedObjectRequestOperationClasses removeObject:operationClass]; - [self.registeredManagedObjectRequestOperationClasses insertObject:operationClass atIndex:0]; - return YES; - } else if ([operationClass isSubclassOfClass:[RKObjectRequestOperation class]]) { - [self.registeredObjectRequestOperationClasses removeObject:operationClass]; - [self.registeredObjectRequestOperationClasses insertObject:operationClass atIndex:0]; - return YES; - } else if ([operationClass isSubclassOfClass:[RKHTTPRequestOperation class]]) { - [self.registeredHTTPRequestOperationClasses removeObject:operationClass]; - [self.registeredHTTPRequestOperationClasses insertObject:operationClass atIndex:0]; - return YES; - } - - return NO; -} - -- (void)unregisterRequestOperationClass:(Class)operationClass -{ - [self.registeredHTTPRequestOperationClasses removeObject:operationClass]; - [self.registeredObjectRequestOperationClasses removeObject:operationClass]; - [self.registeredManagedObjectRequestOperationClasses removeObject:operationClass]; -} - -- (Class)requestOperationClassForRequest:(NSURLRequest *)request fromRegisteredClasses:(NSArray *)registeredClasses -{ - Class requestOperationClass = nil; - NSEnumerator *enumerator = [registeredClasses reverseObjectEnumerator]; - while (requestOperationClass = [enumerator nextObject]) { - if ([requestOperationClass canProcessRequest:request]) break; - requestOperationClass = nil; - } - return requestOperationClass; -} - -#pragma mark - Object Request Operations - -- (void)copyStateFromHTTPClientToHTTPRequestOperation:(AFHTTPRequestOperation *)operation -{ - operation.credential = self.HTTPClient.defaultCredential; - operation.allowsInvalidSSLCertificate = self.HTTPClient.allowsInvalidSSLCertificate; -#ifdef _AFNETWORKING_PIN_SSL_CERTIFICATES_ - operation.SSLPinningMode = self.HTTPClient.defaultSSLPinningMode; -#endif -} - -- (RKObjectRequestOperation *)objectRequestOperationWithRequest:(NSURLRequest *)request - success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success - failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure -{ - Class HTTPRequestOperationClass = [self requestOperationClassForRequest:request fromRegisteredClasses:self.registeredHTTPRequestOperationClasses] ?: [RKHTTPRequestOperation class]; - RKHTTPRequestOperation *HTTPRequestOperation = [[HTTPRequestOperationClass alloc] initWithRequest:request]; - [self copyStateFromHTTPClientToHTTPRequestOperation:HTTPRequestOperation]; - Class objectRequestOperationClass = [self requestOperationClassForRequest:request fromRegisteredClasses:self.registeredObjectRequestOperationClasses] ?: [RKObjectRequestOperation class]; - RKObjectRequestOperation *operation = [[objectRequestOperationClass alloc] initWithHTTPRequestOperation:HTTPRequestOperation responseDescriptors:self.responseDescriptors]; - [operation setCompletionBlockWithSuccess:success failure:failure]; - return operation; -} - -- (RKManagedObjectRequestOperation *)managedObjectRequestOperationWithRequest:(NSURLRequest *)request - managedObjectContext:(NSManagedObjectContext *)managedObjectContext - success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success - failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure -{ - Class HTTPRequestOperationClass = [self requestOperationClassForRequest:request fromRegisteredClasses:self.registeredHTTPRequestOperationClasses] ?: [RKHTTPRequestOperation class]; - RKHTTPRequestOperation *HTTPRequestOperation = [[HTTPRequestOperationClass alloc] initWithRequest:request]; - [self copyStateFromHTTPClientToHTTPRequestOperation:HTTPRequestOperation]; - Class objectRequestOperationClass = [self requestOperationClassForRequest:request fromRegisteredClasses:self.registeredManagedObjectRequestOperationClasses] ?: [RKManagedObjectRequestOperation class]; - RKManagedObjectRequestOperation *operation = (RKManagedObjectRequestOperation *)[[objectRequestOperationClass alloc] initWithHTTPRequestOperation:HTTPRequestOperation responseDescriptors:self.responseDescriptors]; - [operation setCompletionBlockWithSuccess:success failure:failure]; - operation.managedObjectContext = managedObjectContext ?: self.managedObjectStore.mainQueueManagedObjectContext; - operation.managedObjectCache = self.managedObjectStore.managedObjectCache; - operation.fetchRequestBlocks = self.fetchRequestBlocks; - return operation; -} - -- (id)appropriateObjectRequestOperationWithObject:(id)object - method:(RKRequestMethod)method - path:(NSString *)path - parameters:(NSDictionary *)parameters -{ - RKObjectRequestOperation *operation = nil; - NSURLRequest *request = [self requestWithObject:object method:method path:path parameters:parameters]; - NSDictionary *routingMetadata = nil; - if (! path) { - RKRoute *route = [self.router.routeSet routeForObject:object method:method]; - NSDictionary *interpolatedParameters = nil; - NSURL *URL = [self URLWithRoute:route object:object interpolatedParameters:&interpolatedParameters]; - if (! URL) { - RKLogError(@"Failed to construct a URL from the provided object. Returning nil."); - return operation; - } - path = [URL relativeString]; - routingMetadata = @{ @"routing": @{ @"parameters": interpolatedParameters, @"route": route } }; - } - - NSArray *matchingDescriptors = RKFilteredArrayOfResponseDescriptorsMatchingPathAndMethod(self.responseDescriptors, path, method); - BOOL containsEntityMapping = RKDoesArrayOfResponseDescriptorsContainEntityMapping(matchingDescriptors); - BOOL isManagedObjectRequestOperation = (containsEntityMapping || [object isKindOfClass:[NSManagedObject class]]); - - if (isManagedObjectRequestOperation && !self.managedObjectStore) RKLogWarning(@"Asked to create an `RKManagedObjectRequestOperation` object, but managedObjectStore is nil."); - if (isManagedObjectRequestOperation && self.managedObjectStore) { - // Construct a Core Data operation - NSManagedObjectContext *managedObjectContext = [object respondsToSelector:@selector(managedObjectContext)] ? [object managedObjectContext] : self.managedObjectStore.mainQueueManagedObjectContext; - operation = [self managedObjectRequestOperationWithRequest:request managedObjectContext:managedObjectContext success:nil failure:nil]; - - if ([object isKindOfClass:[NSManagedObject class]]) { - static NSPredicate *temporaryObjectsPredicate = nil; - if (! temporaryObjectsPredicate) temporaryObjectsPredicate = [NSPredicate predicateWithFormat:@"objectID.isTemporaryID == YES"]; - NSSet *temporaryObjects = [[managedObjectContext insertedObjects] filteredSetUsingPredicate:temporaryObjectsPredicate]; - if ([temporaryObjects count]) { - RKLogInfo(@"Asked to perform object request for NSManagedObject with temporary object IDs: Obtaining permanent ID before proceeding."); - __block BOOL _blockSuccess; - __block NSError *_blockError; - - [[object managedObjectContext] performBlockAndWait:^{ - _blockSuccess = [[object managedObjectContext] obtainPermanentIDsForObjects:[temporaryObjects allObjects] error:&_blockError]; - }]; - if (! _blockSuccess) RKLogWarning(@"Failed to obtain permanent ID for object %@: %@", object, _blockError); - } - } - } else { - // Non-Core Data operation - operation = [self objectRequestOperationWithRequest:request success:nil failure:nil]; - } - - if (RKDoesArrayOfResponseDescriptorsContainMappingForClass(self.responseDescriptors, [object class])) operation.targetObject = object; - operation.mappingMetadata = routingMetadata; - return operation; -} - -- (NSURL *)URLWithRoute:(RKRoute *)route object:(id)object interpolatedParameters:(NSDictionary **)interpolatedParameters -{ - NSString *path = nil; - if (object) { - RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:route.pathPattern]; - path = [pathMatcher pathFromObject:object addingEscapes:route.shouldEscapePath interpolatedParameters:interpolatedParameters]; - } else { - // When there is no object, the path pattern is our complete path - path = route.pathPattern; - if (interpolatedParameters) *interpolatedParameters = @{}; - } - return [NSURL URLWithString:path relativeToURL:self.baseURL]; -} - -- (void)getObjectsAtPathForRelationship:(NSString *)relationshipName - ofObject:(id)object - parameters:(NSDictionary *)parameters - success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success - failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure -{ - RKRoute *route = [self.router.routeSet routeForRelationship:relationshipName ofClass:[object class] method:RKRequestMethodGET]; - NSDictionary *interpolatedParameters = nil; - NSURL *URL = [self URLWithRoute:route object:object interpolatedParameters:&interpolatedParameters]; - NSAssert(URL, @"Failed to generate URL for relationship named '%@' for object: %@", relationshipName, object); - RKObjectRequestOperation *operation = [self appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:[URL relativeString] parameters:parameters]; - operation.mappingMetadata = @{ @"routing": @{ @"parameters": interpolatedParameters, @"route": route } }; - [operation setCompletionBlockWithSuccess:success failure:failure]; - [self enqueueObjectRequestOperation:operation]; -} - -- (void)getObjectsAtPathForRouteNamed:(NSString *)routeName - object:(id)object - parameters:(NSDictionary *)parameters - success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success - failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure -{ - NSParameterAssert(routeName); - RKRoute *route = [self.router.routeSet routeForName:routeName]; - NSDictionary *interpolatedParameters = nil; - NSURL *URL = [self URLWithRoute:route object:object interpolatedParameters:&interpolatedParameters]; - NSAssert(URL, @"No route found named '%@'", routeName); - NSAssert(route.method & RKRequestMethodGET, @"Expected route named '%@' to specify a GET, but it does not", routeName); - - RKObjectRequestOperation *operation = [self appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:[URL relativeString] parameters:parameters]; - operation.mappingMetadata = @{ @"routing": @{ @"parameters": interpolatedParameters, @"route": route } }; - [operation setCompletionBlockWithSuccess:success failure:failure]; - [self enqueueObjectRequestOperation:operation]; - -} - -- (void)getObjectsAtPath:(NSString *)path - parameters:(NSDictionary *)parameters - success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success - failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure -{ - NSParameterAssert(path); - RKObjectRequestOperation *operation = [self appropriateObjectRequestOperationWithObject:nil method:RKRequestMethodGET path:path parameters:parameters]; - [operation setCompletionBlockWithSuccess:success failure:failure]; - [self enqueueObjectRequestOperation:operation]; -} - -- (void)getObject:(id)object - path:(NSString *)path - parameters:(NSDictionary *)parameters - success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success - failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure -{ - NSAssert(object || path, @"Cannot make a request without an object or a path."); - RKObjectRequestOperation *operation = [self appropriateObjectRequestOperationWithObject:object method:RKRequestMethodGET path:path parameters:parameters]; - [operation setCompletionBlockWithSuccess:success failure:failure]; - [self enqueueObjectRequestOperation:operation]; -} - -- (void)postObject:(id)object - path:(NSString *)path - parameters:(NSDictionary *)parameters - success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success - failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure -{ - NSAssert(object || path, @"Cannot make a request without an object or a path."); - RKObjectRequestOperation *operation = [self appropriateObjectRequestOperationWithObject:object method:RKRequestMethodPOST path:path parameters:parameters]; - [operation setCompletionBlockWithSuccess:success failure:failure]; - [self enqueueObjectRequestOperation:operation]; -} - -- (void)putObject:(id)object - path:(NSString *)path - parameters:(NSDictionary *)parameters - success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success - failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure -{ - NSAssert(object || path, @"Cannot make a request without an object or a path."); - RKObjectRequestOperation *operation = [self appropriateObjectRequestOperationWithObject:object method:RKRequestMethodPUT path:path parameters:parameters]; - [operation setCompletionBlockWithSuccess:success failure:failure]; - [self enqueueObjectRequestOperation:operation]; -} - -- (void)patchObject:(id)object - path:(NSString *)path - parameters:(NSDictionary *)parameters - success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success - failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure -{ - NSAssert(object || path, @"Cannot make a request without an object or a path."); - RKObjectRequestOperation *operation = [self appropriateObjectRequestOperationWithObject:object method:RKRequestMethodPATCH path:path parameters:parameters]; - [operation setCompletionBlockWithSuccess:success failure:failure]; - [self enqueueObjectRequestOperation:operation]; -} - -- (void)deleteObject:(id)object - path:(NSString *)path - parameters:(NSDictionary *)parameters - success:(void (^)(RKObjectRequestOperation *operation, RKMappingResult *mappingResult))success - failure:(void (^)(RKObjectRequestOperation *operation, NSError *error))failure -{ - NSAssert(object || path, @"Cannot make a request without an object or a path."); - RKObjectRequestOperation *operation = [self appropriateObjectRequestOperationWithObject:object method:RKRequestMethodDELETE path:path parameters:parameters]; - [operation setCompletionBlockWithSuccess:success failure:failure]; - [self enqueueObjectRequestOperation:operation]; -} - -- (RKPaginator *)paginatorWithPathPattern:(NSString *)pathPattern -{ - NSAssert(self.paginationMapping, @"Cannot instantiate a paginator when `paginationMapping` is nil."); - NSMutableURLRequest *request = [self requestWithMethod:@"GET" path:pathPattern parameters:nil]; - RKPaginator *paginator = [[RKPaginator alloc] initWithRequest:request paginationMapping:self.paginationMapping responseDescriptors:self.responseDescriptors]; - paginator.managedObjectContext = self.managedObjectStore.mainQueueManagedObjectContext; - paginator.managedObjectCache = self.managedObjectStore.managedObjectCache; - paginator.fetchRequestBlocks = self.fetchRequestBlocks; - paginator.operationQueue = self.operationQueue; - Class HTTPOperationClass = [self requestOperationClassForRequest:request fromRegisteredClasses:self.registeredHTTPRequestOperationClasses]; - if (HTTPOperationClass) [paginator setHTTPOperationClass:HTTPOperationClass]; - return paginator; -} - -#pragma mark - Request & Response Descriptors - -- (NSArray *)requestDescriptors -{ - return [NSArray arrayWithArray:self.mutableRequestDescriptors]; -} - -- (void)addRequestDescriptor:(RKRequestDescriptor *)requestDescriptor -{ - NSParameterAssert(requestDescriptor); - if ([self.requestDescriptors containsObject:requestDescriptor]) return; - NSAssert([requestDescriptor isKindOfClass:[RKRequestDescriptor class]], @"Expected an object of type RKRequestDescriptor, got '%@'", [requestDescriptor class]); - [self.requestDescriptors enumerateObjectsUsingBlock:^(RKRequestDescriptor *registeredDescriptor, NSUInteger idx, BOOL *stop) { - NSAssert(!([registeredDescriptor.objectClass isEqual:requestDescriptor.objectClass] && (requestDescriptor.method == registeredDescriptor.method)), @"Cannot add request descriptor: An existing descriptor is already registered for the class '%@' and HTTP method'%@'.", requestDescriptor.objectClass, RKStringDescribingRequestMethod(requestDescriptor.method)); - }]; - [self.mutableRequestDescriptors addObject:requestDescriptor]; -} - -- (void)addRequestDescriptorsFromArray:(NSArray *)requestDescriptors -{ - for (RKRequestDescriptor *requestDescriptor in requestDescriptors) { - [self addRequestDescriptor:requestDescriptor]; - } -} - -- (void)removeRequestDescriptor:(RKRequestDescriptor *)requestDescriptor -{ - NSParameterAssert(requestDescriptor); - NSAssert([requestDescriptor isKindOfClass:[RKRequestDescriptor class]], @"Expected an object of type RKRequestDescriptor, got '%@'", [requestDescriptor class]); - [self.mutableRequestDescriptors removeObject:requestDescriptor]; -} - -- (NSArray *)responseDescriptors -{ - return [NSArray arrayWithArray:self.mutableResponseDescriptors]; -} - -- (void)addResponseDescriptor:(RKResponseDescriptor *)responseDescriptor -{ - NSParameterAssert(responseDescriptor); - NSAssert([responseDescriptor isKindOfClass:[RKResponseDescriptor class]], @"Expected an object of type RKResponseDescriptor, got '%@'", [responseDescriptor class]); - responseDescriptor.baseURL = self.baseURL; - [self.mutableResponseDescriptors addObject:responseDescriptor]; -} - -- (void)addResponseDescriptorsFromArray:(NSArray *)responseDescriptors -{ - for (RKResponseDescriptor *responseDescriptor in responseDescriptors) { - [self addResponseDescriptor:responseDescriptor]; - } -} - -- (void)removeResponseDescriptor:(RKResponseDescriptor *)responseDescriptor -{ - NSParameterAssert(responseDescriptor); - NSAssert([responseDescriptor isKindOfClass:[RKResponseDescriptor class]], @"Expected an object of type RKResponseDescriptor, got '%@'", [responseDescriptor class]); - [self.mutableResponseDescriptors removeObject:responseDescriptor]; -} - -#pragma mark - Fetch Request Blocks - -- (NSArray *)fetchRequestBlocks -{ - return [NSArray arrayWithArray:self.mutableFetchRequestBlocks]; -} - -- (void)addFetchRequestBlock:(RKFetchRequestBlock)block -{ - NSParameterAssert(block); - [self.mutableFetchRequestBlocks addObject:block]; -} - -#pragma mark - Queue Management - -- (void)enqueueObjectRequestOperation:(RKObjectRequestOperation *)objectRequestOperation -{ - [self.operationQueue addOperation:objectRequestOperation]; -} - -- (NSArray *)enqueuedObjectRequestOperationsWithMethod:(RKRequestMethod)method matchingPathPattern:(NSString *)pathPattern -{ - NSMutableArray *matches = [NSMutableArray array]; - RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:pathPattern]; - for (NSOperation *operation in [self.operationQueue operations]) { - if (![operation isKindOfClass:[RKObjectRequestOperation class]]) { - continue; - } - NSURLRequest *request = [(RKObjectRequestOperation *)operation HTTPRequestOperation].request; - NSString *pathAndQueryString = RKPathAndQueryStringFromURLRelativeToURL([request URL], self.baseURL); - - RKRequestMethod operationMethod = RKRequestMethodFromString([request HTTPMethod]); - if ((method & operationMethod) && [pathMatcher matchesPath:pathAndQueryString tokenizeQueryStrings:NO parsedArguments:nil]) { - [matches addObject:operation]; - } - } - return [matches copy]; -} - -- (void)cancelAllObjectRequestOperationsWithMethod:(RKRequestMethod)method matchingPathPattern:(NSString *)pathPattern -{ - for (RKObjectRequestOperation *operation in [self enqueuedObjectRequestOperationsWithMethod:method matchingPathPattern:pathPattern]) { - [operation cancel]; - } -} - -- (void)enqueueBatchOfObjectRequestOperationsWithRoute:(RKRoute *)route - objects:(NSArray *)objects - progress:(void (^)(NSUInteger numberOfFinishedOperations, - NSUInteger totalNumberOfOperations))progress - completion:(void (^)(NSArray *operations))completion { - NSMutableArray *operations = [[NSMutableArray alloc] initWithCapacity:objects.count]; - for (id object in objects) { - RKObjectRequestOperation *operation = nil; - NSDictionary *interpolatedParameters = nil; - NSURL *URL = [self URLWithRoute:route object:object interpolatedParameters:&interpolatedParameters]; - NSAssert(URL, @"Failed to generate URL for route %@ with object %@", route, object); - if ([route isClassRoute]) { - operation = [self appropriateObjectRequestOperationWithObject:object method:route.method path:[URL relativeString] parameters:nil]; - } else { - operation = [self appropriateObjectRequestOperationWithObject:nil method:route.method path:[URL relativeString] parameters:nil]; - } - operation.mappingMetadata = @{ @"routing": interpolatedParameters, @"route": route }; - [operations addObject:operation]; - } - return [self enqueueBatchOfObjectRequestOperations:operations progress:progress completion:completion]; -} - -- (void)enqueueBatchOfObjectRequestOperations:(NSArray *)operations - progress:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progress - completion:(void (^)(NSArray *operations))completion { - - __block dispatch_group_t dispatchGroup = dispatch_group_create(); - NSBlockOperation *batchedOperation = [NSBlockOperation blockOperationWithBlock:^{ - dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ - if (completion) { - completion(operations); - } - }); -#if !OS_OBJECT_USE_OBJC - dispatch_release(dispatchGroup); -#endif - }]; - - for (RKObjectRequestOperation *operation in operations) { - void (^originalCompletionBlock)(void) = [operation.completionBlock copy]; - __weak RKObjectRequestOperation *weakOperation = operation; - [operation setCompletionBlock:^{ - dispatch_queue_t queue = weakOperation.successCallbackQueue ?: dispatch_get_main_queue(); - dispatch_group_async(dispatchGroup, queue, ^{ - if (originalCompletionBlock) { - originalCompletionBlock(); - } - - __block NSUInteger numberOfFinishedOperations = 0; - [operations enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - if ([(NSOperation *)obj isFinished]) { - numberOfFinishedOperations++; - } - }]; - - if (progress) { - progress(numberOfFinishedOperations, [operations count]); - } - - dispatch_group_leave(dispatchGroup); - }); - }]; - - dispatch_group_enter(dispatchGroup); - [batchedOperation addDependency:operation]; - - [self enqueueObjectRequestOperation:operation]; - } - [self.operationQueue addOperation:batchedOperation]; -} - -@end - -#ifdef _SYSTEMCONFIGURATION_H -NSString *RKStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus networkReachabilityStatus) -{ - switch (networkReachabilityStatus) { - case AFNetworkReachabilityStatusNotReachable: return @"Not Reachable"; - case AFNetworkReachabilityStatusReachableViaWiFi: return @"Reachable via WiFi"; - case AFNetworkReachabilityStatusReachableViaWWAN: return @"Reachable via WWAN"; - case AFNetworkReachabilityStatusUnknown: return @"Reachability Unknown"; - default: break; - } - return nil; -} -#endif \ No newline at end of file diff --git a/Chromatism/ChromatismTests/bundle.bundle/description.txt b/Chromatism/ChromatismTests/bundle.bundle/description.txt deleted file mode 100644 index 725bbb1..0000000 --- a/Chromatism/ChromatismTests/bundle.bundle/description.txt +++ /dev/null @@ -1,31 +0,0 @@ -JLScope, (null), nopaque: 1, nindexesSet:[number of indexes: 46555 (in 1 ranges), indexes: (0-46554)], - subscopes, JLTokenPattern, comment, Regex Pattern: /\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/, opaque: 1, indexesSet:[number of indexes: 1383 (in 5 ranges), indexes: (1495-1940 2407-2755 5893-6018 7301-7659 14851-14953)] - subscopes, - JLScope, (null), nopaque: 1, nindexesSet:[number of indexes: 45172 (in 6 ranges), indexes: (0-1494 1941-2406 2756-5892 6019-7300 7660-14850 14954-46554)], - subscopes, JLTokenPattern, comment, Regex Pattern: //.*+$, opaque: 1, indexesSet:[number of indexes: 1936 (in 40 ranges), indexes: (0-1 3-23 25-35 37-38 40-80 82-138 140-141 143-209 211-278 280-322 324-325 327-372 374-375 377-447 449-517 519-594 596-666 668-701 703-704 1217-1326 1336-1369 1371-1388 1438-1471 1473-1492 5387-5479 7762-7844 8277-8337 8716-8781 9057-9139 9623-9683 10395-10477 10910-10978 12435-12469 13846-13873 15325-15439 18598-18687 18993-19033 27994-28027 29470-29495 30234-30298)] - subscopes, - JLTokenPattern, preprocessor, Regex Pattern: #.*+$, opaque: 1, indexesSet:[number of indexes: 830 (in 30 ranges), indexes: (707-730 732-758 760-795 797-828 830-860 862-893 895-927 929-951 953-969 971-1005 1007-1031 1033-1059 1061-1083 1085-1112 1114-1146 1149-1176 1178-1215 1328-1333 14817-14848 21249-21285 23000-23039 23285-23326 23398-23403 37974-38018 40708-40742 40995-41025 44573-44595 44638-44643 45935-45963 46549-46554)] - subscopes, JLTokenPattern, string, Regex Pattern: <.*?>, opaque: 1, indexesSet:[number of indexes: 16 (in 1 ranges), indexes: (715-730)] - subscopes, - JLTokenPattern, (null), Regex Pattern: ("|@")[^"\n]*(@"|"), opaque: 1, indexesSet:[number of indexes: 290 (in 14 ranges), indexes: (740-758 768-795 805-828 838-860 870-893 903-927 937-951 961-969 979-1005 1015-1031 1041-1059 1069-1083 1093-1112 1122-1146)] - subscopes, - JLTokenPattern, string, Regex Pattern: ("|@")[^"\n]*(@"|"), opaque: 1, indexesSet:[number of indexes: 2359 (in 50 ranges), indexes: (4907-4979 5542-5846 9908-9915 12072-12242 14646-14654 15231-15236 15266-15272 15302-15310 15913-15929 15995-16009 16684-16711 17273-17340 18398-18476 19171-19270 27108-27176 27286-27295 27301-27313 27340-27347 27819-27912 28610-28641 28847-28969 29351-29400 31206-31273 31510-31519 31525-31537 31564-31571 32398-32425 32488-32549 32776-32785 32791-32803 32830-32837 33927-33979 34607-34659 35283-35335 35968-36020 36660-36712 37109-37174 37237-37242 38392-38450 38767-38884 39456-39514 39920-39979 40543-40602 43275-43327 43733-43742 43769-43776 46176-46191 46259-46279 46347-46367 46435-46457)] - subscopes, - JLTokenPattern, number, Regex Pattern: (?<=\s)\d+, opaque: 1, indexesSet:[number of indexes: 5 (in 5 ranges), indexes: (5202 5352 8695 18777 45244)] - subscopes, - JLTokenPattern, number, Regex Pattern: @[\(|\{|\[][^\(\{\[]+[\)|\}|\]], opaque: 0, indexesSet:[number of indexes: 93 (in 3 ranges), indexes: (5067-5138 17736-17746 30396-30405)] - subscopes, - JLTokenPattern, other_method_names, Regex Pattern: \w+\s*(?>\(.*\), opaque: 1, indexesSet:(no indexes) - subscopes, - JLTokenPattern, other_method_names, Regex Pattern: \.(\w+), opaque: 1, indexesSet:[number of indexes: 2694 (in 161 ranges), indexes: (2327-2332 3223-3233 3295-3300 3461-3471 3532-3537 4079-4088 4419-4428 4774-4783 5035-5044 5181-5190 5247-5256 5331-5340 5872-5881 6410-6424 6549-6563 6627-6634 6679-6693 6908-6921 7191-7210 7266-7272 8049-8055 8177-8183 8241-8248 8670-8683 9344-9350 9472-9478 9536-9543 9983-9987 10682-10688 10810-10816 10874-10881 11421-11434 13132-13141 13166-13171 13216-13222 13247-13260 13301-13325 13364-13389 13428-13452 13491-13527 13566-13611 13650-13688 13727-13754 13809-13825 14327-14336 14468-14495 14618-14627 14713-14722 14724-14730 14787-14796 14798-14811 15491-15500 15584-15593 15831-15840 15842-15855 15937-15964 16108-16135 16229-16238 16601-16606 17184-17189 17992-18009 18877-18887 19866-19871 20613-20618 20827-20836 21450-21495 21541-21586 21748-21786 21832-21870 22030-22066 22112-22148 22313-22349 22391-22429 22471-22516 23148-23157 23166-23175 23177-23193 23210-23236 23245-23254 23256-23282 23342-23355 23364-23373 23375-23395 23895-23931 24273-24311 24505-24523 25277-25313 25655-25700 25943-25961 26058-26077 26110-26127 26129-26157 26174-26191 26200-26217 26219-26236 26253-26270 26279-26296 26849-26854 26856-26863 27470-27488 27786-27803 27964-27981 28183-28200 28202-28230 29670-29688 29718-29729 29755-29769 30064-30074 30148-30163 30321-30331 30463-30469 30930-30935 30937-30944 31489-31503 32186-32191 32193-32200 32459-32464 32755-32769 37090-37106 37375-37391 37418-37436 37454-37473 37482-37499 37501-37529 37546-37563 37572-37589 37591-37608 37625-37642 37651-37668 37685-37698 37707-37720 37827-37863 38095-38119 38254-38271 38491-38508 38653-38663 38691-38701 38726-38731 38757-38762 38905-38915 38968-38973 38996-39020 39555-39579 39692-39717 40034-40040 40049-40055 40068-40093 40644-40669 40819-40843 40948-40972 41129-41142 41490-41503 41720-41726 41829-41835 43000-43004 43476-43481 43634-43639 43712-43726 44775-44789 44958-44977 45879-45892)] - subscopes, - JLTokenPattern, other_method_names, Regex Pattern: \[\w+\s+(\w+)\], opaque: 1, indexesSet:[number of indexes: 610 (in 94 ranges), indexes: (3094-3098 3612-3621 4043-4046 4113-4115 4296-4299 4519-4523 4635-4639 4989-4993 5279-5282 6374-6377 6442-6444 6769-6773 7038-7042 7899-7901 8135-8139 8444-8448 8551-8555 9194-9196 9430-9434 9613-9615 9791-9795 10032-10036 10162-10166 10532-10534 10768-10772 11085-11089 11274-11278 13096-13099 13186-13190 13282-13284 13345-13347 13409-13411 13472-13474 13547-13549 13631-13633 13708-13710 14245-14249 14389-14393 15532-15536 16805-16818 17369-17373 17472-17485 17699-17703 17812-17814 18748-18752 18767-18771 18968-18984 19085-19089 21425-21429 21723-21727 22005-22009 22758-22780 22831-22840 23961-23965 24048-24052 24343-24347 24423-24427 25343-25347 25430-25434 25739-25743 25861-25865 27240-27253 27722-27726 28154-28173 28428-28432 28706-28720 28811-28815 29089-29108 29179-29198 29248-29257 29699-29703 31000-31004 31435-31448 32701-32714 37321-37325 38383-38387 38472-38476 39447-39451 39536-39540 39911-39915 40002-40006 40534-40538 40625-40629 41356-41360 41584-41588 41818-41820 41925-41934 42152-42155 42441-42446 42968-42972 43365-43376 43493-43506 43651-43664 45599-45603)] - subscopes, - JLTokenPattern, other_method_names, Regex Pattern: (?<=\w+):\s*[^\s;\]]+, opaque: 1, indexesSet:(no indexes) - subscopes, - JLTokenPattern, other_class_names, Regex Pattern: (\b(?>NS|UI))\w+\b, opaque: 1, indexesSet:[number of indexes: 2261 (in 214 ranges), indexes: (1949-1955 2016-2022 2046-2053 2092-2101 2212-2221 2837-2843 2989-2995 3683-3690 3783-3790 3823-3841 3879-3890 3923-3930 4093-4111 4168-4179 4209-4216 4289-4294 4504-4517 4622-4633 4658-4671 4690-4703 4855-4865 4873-4898 5272-5277 5490-5500 5508-5533 6055-6062 6097-6101 6235-6246 6429-6440 6514-6518 7726-7732 7850-7861 7886-7897 8927-8933 9021-9027 9145-9156 9181-9192 9568-9579 9600-9611 10336-10342 10483-10494 10519-10530 11609-11616 12393-12407 12532-12545 12605-12618 12679-12692 12752-12765 12837-12850 12924-12937 13265-13280 13330-13343 13394-13407 13457-13470 13532-13545 13616-13629 13693-13706 14189-14193 14585-14592 14679-14683 14739-14750 14958-14976 14999-15006 15061-15068 15121-15132 15153-15171 15449-15460 15672-15678 15702-15709 15732-15739 15887-15894 16021-16026 16329-16347 16381-16388 16522-16533 16582-16586 16670-16677 16851-16869 16905-16912 17133-17144 17165-17169 17259-17266 17343-17359 17602-17613 17634-17640 17691-17697 18157-18163 18191-18202 18740-18746 19077-19083 19119-19129 19137-19162 19564-19582 19726-19733 19786-19797 19819-19826 20153-20171 20354-20361 20427-20438 20566-20573 20781-20799 22593-22604 22639-22645 22712-22723 23473-23484 23758-23764 24702-24713 24804-24825 25140-25146 26510-26517 26577-26588 26656-26667 26763-26774 26911-26922 26963-26967 27376-27382 27706-27720 28037-28058 28412-28426 28458-28468 28578-28588 28657-28661 29041-29047 29818-29822 29898-29909 29943-29950 30419-30423 30517-30524 30637-30648 30877-30883 31039-31050 31087-31091 31192-31199 31750-31757 31859-31870 32095-32101 32125-32141 32231-32242 32279-32283 32384-32391 32444-32451 33004-33011 33046-33057 33256-33262 33286-33302 33641-33648 33676-33687 33872-33878 33902-33909 34318-34325 34354-34365 34552-34558 34582-34589 34997-35004 35032-35043 35228-35234 35258-35265 35676-35683 35713-35724 35913-35919 35943-35950 36365-36372 36403-36414 36605-36611 36635-36642 37047-37054 37076-37083 37182-37200 38024-38030 38067-38073 38202-38218 38320-38327 38582-38591 38620-38627 39095-39101 39342-39358 39384-39391 39620-39626 39664-39670 39803-39819 39846-39853 40170-40176 40426-40442 40469-40476 40748-40754 40791-40797 40912-40928 41188-41194 41285-41292 41314-41327 41341-41354 41458-41468 41635-41646 41737-41744 42258-42265 42587-42593 42670-42679 42774-42783 42884-42890 42922-42935 42953-42966 43100-43111 43152-43156 43261-43268 43994-44000 44071-44080 44110-44119 44211-44217 44320-44335 44358-44373 45204-45213 45312-45321 45368-45378 45965-45972)] - subscopes, - JLTokenPattern, keyword, Regex Pattern: (?<=\b)(?>true|false|yes|no|TRUE|FALSE|bool|BOOL|nil|id|void|self|NULL|if|else|strong|weak|nonatomic|atomic|assign|copy|typedef|enum|auto|break|case|const|char|continue|do|default|double|extern|float|for|goto|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|volatile|while|nonatomic|atomic|nonatomic|readonly|super )(\b), opaque: 1, indexesSet:[number of indexes: 1817 (in 470 ranges), indexes: (1391-1396 1432-1434 1942-1947 2165-2168 2228-2231 2250-2255 2348-2353 2866-2867 3018-3019 3106-3107 3119-3121 3200-3201 3304-3309 3357-3359 3438-3439 3541-3546 3631-3635 3661-3666 3668-3670 3676-3681 3815-3820 3859-3862 3955-3958 4015-4016 4029-4032 4054-4055 4058-4061 4074-4077 4129-4134 4136-4139 4148-4151 4241-4244 4260-4261 4307-4308 4402-4403 4414-4417 4457-4458 4478-4479 4591-4594 4596-4597 4750-4752 4769-4772 4835-4838 5014-5017 5030-5033 5144-5145 5171-5172 5176-5179 5205-5210 5212-5214 5221-5222 5242-5245 5291-5292 5321-5322 5326-5329 5355-5360 5860-5865 5867-5870 6087-6094 6118-6119 6314-6315 6360-6363 6385-6386 6389-6392 6405-6408 6457-6460 6495-6500 6502-6505 6537-6542 6544-6547 6572-6575 6617-6618 6622-6625 6661-6666 6674-6677 6724-6725 6860-6862 6939-6942 6989-6992 6994-6995 7126-7128 7228-7231 7661-7666 7668-7671 7909-7911 7989-7990 8343-8345 8400-8401 8467-8472 8506-8507 8650-8651 8799-8804 8850-8855 8864-8867 8958-8961 9204-9206 9284-9285 9689-9691 9746-9747 9930-9933 10012-10013 10050-10052 10107-10108 10189-10194 10232-10237 10255-10260 10269-10274 10276-10279 10542-10544 10622-10623 10984-10986 11041-11042 11108-11109 11190-11195 11229-11230 11373-11375 11455-11456 11537-11542 11588-11593 11602-11607 11709-11714 11737-11740 11782-11787 11827-11831 11855-11858 11897-11902 11932-11936 11960-11963 12010-12014 12038-12044 12268-12272 12290-12295 12364-12371 12385-12390 12524-12529 12597-12602 12671-12676 12744-12749 12829-12834 12916-12921 13031-13032 13082-13085 13107-13108 13111-13114 13127-13130 13161-13164 13242-13245 13296-13299 13359-13362 13423-13426 13486-13489 13561-13564 13645-13648 13722-13725 13883-13884 13887-13889 13957-13960 13985-13990 13992-13995 14037-14042 14065-14068 14240-14243 14529-14534 14551-14554 14613-14616 14701-14706 14708-14711 14775-14780 14782-14785 15187-15188 15486-15489 15542-15544 15579-15582 15689-15691 15826-15829 15932-15935 16103-16106 16198-16201 16224-16227 16307-16312 16457-16458 16596-16599 16730-16735 16738-16741 16986-16987 17179-17182 17397-17402 17405-17408 17518-17519 17549-17550 17720-17722 17822-17824 17827-17828 17987-17990 18051-18052 18174-18176 18358-18359 18560-18565 18567-18569 18701-18704 18927-18928 19039-19040 19280-19283 19285-19286 19436-19439 19441-19442 19532-19537 19605-19606 19861-19864 19929-19930 19953-19956 20034-20039 20042-20045 20207-20208 20510-20513 20519-20520 20608-20611 20676-20677 20700-20703 20822-20825 21221-21226 21291-21294 21354-21355 21445-21448 21536-21539 21636-21641 21654-21657 21659-21660 21743-21746 21827-21830 21920-21925 21938-21941 21943-21944 22025-22028 22107-22110 22198-22203 22225-22230 22242-22245 22308-22311 22386-22389 22466-22469 22703-22705 22788-22792 22854-22855 22909-22913 22948-22950 22967-22972 23045-23048 23161-23164 23240-23243 23359-23362 23561-23564 23712-23715 23823-23826 23890-23893 24086-24089 24201-24204 24268-24271 24500-24503 24602-24607 24929-24932 25094-25097 25205-25208 25272-25275 25468-25471 25583-25586 25650-25653 25938-25941 26105-26108 26195-26198 26274-26277 26303-26308 26327-26328 26375-26376 26647-26649 26681-26684 26795-26797 26804-26805 26844-26847 26950-26952 26977-26980 27072-27073 27192-27197 27465-27468 27510-27513 27618-27621 27741-27742 27781-27784 27920-27921 27959-27962 28178-28181 28254-28257 28358-28360 28370-28372 28385-28386 28451-28456 28499-28501 28516-28517 28789-28790 28997-29000 29317-29318 29455-29458 29518-29521 29573-29575 29585-29587 29606-29607 29665-29668 29794-29799 29864-29865 29960-29962 29969-29970 30219-30222 30342-30343 30411-30416 30458-30461 30479-30482 30586-30587 30704-30707 30831-30834 30925-30928 31078-31080 31101-31104 31346-31349 31395-31397 31661-31664 31714-31717 31810-31811 31924-31927 32049-32052 32181-32184 32270-32272 32293-32296 32612-32615 32661-32663 32927-32930 32981-32984 33098-33101 33210-33213 33354-33357 33403-33405 33543-33546 33596-33599 33612-33613 33721-33724 33826-33829 34026-34029 34218-34221 34271-34274 34288-34289 34400-34403 34506-34509 34706-34709 34899-34902 34952-34955 34968-34969 35077-35080 35182-35185 35382-35385 35574-35577 35627-35630 35645-35646 35760-35763 35867-35870 36067-36070 36261-36264 36314-36317 36333-36334 36451-36454 36559-36562 36759-36762 36954-36957 37085-37088 37214-37217 37272-37274 37370-37373 37413-37416 37477-37480 37567-37570 37646-37649 37702-37705 37755-37758 37822-37825 37871-37872 37953-37958 38059-38064 38090-38093 38129-38132 38244-38245 38249-38252 38308-38313 38486-38489 38598-38601 38991-38994 39058-39061 39130-39132 39208-39211 39266-39269 39550-39553 39656-39661 39687-39690 39727-39730 40044-40047 40063-40066 40132-40135 40206-40208 40287-40290 40347-40350 40639-40642 40783-40788 40814-40817 40853-40856 40943-40946 41031-41034 41124-41127 41453-41455 41485-41488 41528-41529 41607-41614 41824-41827 41947-41948 42065-42067 42136-42141 42165-42168 42287-42289 42332-42335 42462-42465 42661-42664 42875-42878 43012-43014 43017-43018 43087-43089 43139-43141 43166-43169 43354-43355 43407-43410 43520-43522 43536-43539 43568-43571 43617-43619 43678-43680 43840-43845 43848-43851 43950-43953 44062-44065 44202-44205 44489-44490 44658-44660 44724-44727 44756-44759 44791-44794 45083-45084 45304-45305 45328-45331 45362-45363 45514-45515 45816-45819 45874-45877 46074-46079 46119-46122 46169-46174 46202-46205 46252-46257 46290-46293 46340-46345 46378-46381 46428-46433 46468-46474 46518-46522 46535-46540 46542-46544)] - subscopes, - JLTokenPattern, keyword, Regex Pattern: @[a-zA-Z0-9_]+, opaque: 1, indexesSet:[number of indexes: 226 (in 27 ranges), indexes: (3751-3760 3793-3801 3970-3973 3976-3990 5887-5890 6020-6029 6065-6073 6160-6163 6166-6175 6202-6210 6266-6269 6272-6286 7295-7298 12326-12335 12353-12361 12429-12432 12472-12481 12502-12510 12575-12583 12649-12657 12722-12730 12807-12815 12894-12902 12989-12992 12995-13009 28111-28119 45929-45932)] - subscopes, \ No newline at end of file diff --git a/Chromatism/ChromatismTests/bundle.bundle/en.lproj/Root.strings b/Chromatism/ChromatismTests/bundle.bundle/en.lproj/Root.strings deleted file mode 100644 index 8cd87b9..0000000 Binary files a/Chromatism/ChromatismTests/bundle.bundle/en.lproj/Root.strings and /dev/null differ diff --git a/Chromatism/ChromatismTests/demo.txt b/Chromatism/ChromatismTests/demo.txt new file mode 100644 index 0000000..0bb17e8 --- /dev/null +++ b/Chromatism/ChromatismTests/demo.txt @@ -0,0 +1,2906 @@ +// +// AppDelegate.m +// ChromatismDemo +// +// Created by Anviking on 2013-07-31. +// Copyright (c) 2013 Anviking. All rights reserved. +// + +#import "AppDelegate.h" +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + + JLTextViewController *viewController = [[JLTextViewController alloc] init]; + UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; + viewController.title = @"Chromatism"; + + self.window.rootViewController = navigationController; + self.window.backgroundColor = [UIColor whiteColor]; + [self.window makeKeyAndVisible]; + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +/* +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} +*/ + +@end + +// +// Tokenizer.m +// iGitpad +// +// Created by Johannes Lund on 2012-11-24. +// +// + +// This file builds upon the work of Kristian Kraljic +// +// RegexHighlightView.m +// Simple Objective-C Syntax Highlighter +// +// Created by Kristian Kraljic on 30/08/12. +// Copyright (c) 2012 Kristian Kraljic (dikrypt.com, ksquared.de). All rights reserved. +// +// 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 "JLTokenizer.h" +#import "JLTextViewController.h" +#import "JLScope.h" +#import "JLTokenPattern.h" +#import "Chromatism+Internal.h" + +@interface JLTokenizer () +@property (nonatomic, strong) NSOperationQueue *operationQueue; +@end + +@implementation JLTokenizer + +#pragma mark - Setup + +- (id)init +{ + self = [super init]; + if (self) { + self.operationQueue = [[NSOperationQueue alloc] init]; + self.operationQueue.maxConcurrentOperationCount = 1; + } + return self; +} + +#pragma mark - NSTextStorageDelegate + +- (void)textStorage:(NSTextStorage *)textStorage willProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta +{ + +} + +- (void)textStorage:(NSTextStorage *)textStorage didProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta +{ + if (textStorage.editedMask == NSTextStorageEditedAttributes) return; + [self tokenizeTextStorage:textStorage withScope:[self documentScopeForTokenizingTextStorage:textStorage inRange:editedRange]]; +} + +#pragma mark - NSLayoutManager delegeate + +- (CGFloat)layoutManager:(NSLayoutManager *)layoutManager paragraphSpacingBeforeGlyphAtIndex:(NSUInteger)glyphIndex withProposedLineFragmentRect:(CGRect)rect +{ + return 0; +} + +- (BOOL)layoutManager:(NSLayoutManager *)layoutManager shouldBreakLineByWordBeforeCharacterAtIndex:(NSUInteger)charIndex +{ + unichar character = [layoutManager.textStorage.string characterAtIndex:charIndex]; + if (character == '*') return NO; + return YES; +} + +#pragma mark - UITextViewDelegate + +- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text +{ + if (![text isEqualToString:@"\n"]) return YES; // Something else than return + + // Return has been pressed, start the new line with as many tabs or white spaces as the previous one. + NSString *prefixString = [@"\n" stringByAppendingString:[self prefixStringFromRange:range inTextView:textView]]; + + unichar previousCharacter = [textView.text characterAtIndex:range.location - 1]; + if (self.intendator && [self.intendator respondsToSelector:@selector(indentationActionAfterReplacingTextInRange:replacementText:previousCharacter:textView:)]) { + switch ([self indentationActionAfterReplacingTextInRange:range replacementText:text previousCharacter:previousCharacter textView:textView]) { + case JLIndentationActionIncrease: + prefixString = [prefixString stringByAppendingString:@" "]; + break; + case JLIndentationActionDecrease: + if ([[prefixString substringFromIndex:prefixString.length - 4] isEqualToString:@" "]) { + prefixString = [prefixString substringToIndex:prefixString.length - 4]; + } + else if ([[prefixString substringFromIndex:prefixString.length - 1] isEqualToString:@"\t"]) { + prefixString = [prefixString substringToIndex:prefixString.length - 1]; + } + break; + case JLIndentationActionNone: + break; + } + } + + + [textView replaceRange:[self rangeWithRange:range inTextView:textView] withText:prefixString]; + return NO; +} + + +#pragma mark - Tokenizing + +- (void)refreshTokenizationOfTextStorage:(NSTextStorage *)textStorage; +{ + [self tokenizeTextStorage:textStorage withScope:[self documentScopeForTokenizingTextStorage:textStorage inRange:NSMakeRange(0, textStorage.length)]]; +} + +- (JLScope *)documentScopeForTokenizingTextStorage:(NSTextStorage *)textStorage inRange:(NSRange)range +{ + JLScope *documentScope = [JLScope new]; + JLScope *lineScope = [JLScope new]; + + [self prepareDocumentScope:documentScope]; + [self prepareLineScope:lineScope]; + + [documentScope addSubscope:lineScope]; + + [self clearColorAttributesInRange:range textStorage:textStorage]; + + [documentScope setTextStorage:textStorage]; + [documentScope setSet:[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, textStorage.length)]]; + [lineScope setSet:[NSMutableIndexSet indexSetWithIndexesInRange:[textStorage.string lineRangeForRange:range]]]; + + return documentScope; +} + +- (void)tokenizeTextStorage:(NSTextStorage *)textStorage withScope:(JLScope *)scope +{ + //[textStorage beginEditing]; + [self.operationQueue addOperations:[[scope recursiveSubscopes] allObjects] waitUntilFinished:YES]; + //[textStorage endEditing]; +} + +#pragma mark - Synchronous Tokenization + +- (void)tokenizeAttributedString:(NSMutableAttributedString *)string +{ + JLScope *scope = [self documentScopeForTokenizingTextStorage:(NSTextStorage *)string inRange:NSMakeRange(0, string.length)]; + [self.operationQueue addOperations:[[scope recursiveSubscopes] allObjects] waitUntilFinished:YES]; +} + +#pragma mark - Setup Token Patterns + +- (void)prepareDocumentScope:(JLScope *)documentScope +{ + +} + +- (void)prepareLineScope:(JLScope *)lineScope +{ + +} + + +#pragma mark - Symbolication + +/* +- (void)symbolicate +{ + [self.scopes[PROJECT_CLASS_NAMES] setPattern:[NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@implementation (\\w+)" captureGroup:1] componentsJoinedByString:@"|"]]]; + [self.scopes[PROJECT_METHOD_NAMES] setPattern:[NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@property \\(.*?\\)\\s*\\w+[\\s*]+(\\w+);" captureGroup:1] componentsJoinedByString:@"|"]]]; +} +*/ + +#pragma mark - Helpers + +- (JLTokenPattern *)addToken:(NSString *)type withPattern:(NSString *)pattern andScope:(JLScope *)scope +{ + + NSParameterAssert(type); + NSParameterAssert(pattern); + NSParameterAssert(scope); + + JLTokenPattern *token = [JLTokenPattern token:type withPattern:pattern andScope:scope]; + token.color = self.colors[type]; + + return token; +} + +- (JLTokenPattern *)addToken:(NSString *)type withKeywords:(NSString *)keywords andScope:(JLScope *)scope +{ + NSString *pattern = [NSString stringWithFormat:@"\\b(%@)\\b", [[keywords componentsSeparatedByString:@" "] componentsJoinedByString:@"|"]]; + return [self addToken:type withPattern:pattern andScope:scope]; +} + +- (NSMutableArray *)symbolsWithPattern:(NSString *)pattern captureGroup:(int)group textStorage:(NSTextStorage *)textStorage +{ + NSMutableArray *array = [NSMutableArray array]; + NSError *error = nil; + NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionAnchorsMatchLines error:&error]; + [expression enumerateMatchesInString:textStorage.string options:0 range:NSMakeRange(0, textStorage.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { + [array addObject:[textStorage.string substringWithRange:[result rangeAtIndex:group]]]; + }]; + NSAssert(!error, @"%@",error); + return array; +} + +#pragma mark - Indentation + +- (id )intendator +{ + if (!_intendator) { + _intendator = self; + } + return _intendator; +} + +- (JLIndentationAction)indentationActionAfterReplacingTextInRange:(NSRange)range replacementText:(NSString *)text previousCharacter:(unichar)character textView:(UITextView *)textView; +{ + if (character == '{') { + return JLIndentationActionIncrease; + } else if (character == '}') { + return JLIndentationActionDecrease; + } else { + return JLIndentationActionNone; + } +} + +#pragma mark - Helpers + +- (UITextRange *)rangeWithRange:(NSRange)range inTextView:(UITextView *)textView +{ + UITextPosition *beginning = textView.beginningOfDocument; + UITextPosition *start = [textView positionFromPosition:beginning offset:range.location]; + UITextPosition *stop = [textView positionFromPosition:start offset:range.length]; + + return [textView textRangeFromPosition:start toPosition:stop]; +} + +- (void)clearColorAttributesInRange:(NSRange)range textStorage:(NSTextStorage *)storage; +{ + [storage removeAttribute:NSForegroundColorAttributeName range:range]; + [storage addAttribute:NSForegroundColorAttributeName value:self.colors[JLTokenTypeText] range:range]; +} + +- (NSString *)prefixStringFromRange:(NSRange)range inTextView:(UITextView *)textView +{ + NSRange lineRange = [textView.text lineRangeForRange:range]; + NSRange prefixRange = [textView.text rangeOfString:@"[\\t| ]*" options:NSRegularExpressionSearch range:lineRange]; + return [textView.text substringWithRange:prefixRange]; +} + +@end + + +// +// JLTextViewController.m +// iGitpad +// +// Created by Johannes Lund on 2013-06-13. +// Copyright (c) 2013 Johannes Lund +// +// 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 "JLTextViewController.h" +#import "JLTokenizer.h" +#import "JLTokenizer.h" +#import "JLTextView.h" + +@interface JLTextViewController () +/// Only set from -initWithText: and directly set to nil in -loadView +@property (nonatomic, strong) NSString *defaultText; +@end + +@implementation JLTextViewController + +- (instancetype)initWithText:(NSString *)text +{ + self = [super init]; + if (self) { + _defaultText = text; + } + return self; +} + +- (void)loadView +{ + self.view = self.textView; +} + +- (JLTextView *)textView +{ + if (!_textView) { + JLTextView *textView = [[JLTextView alloc] initWithFrame:CGRectZero]; + textView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + if (self.defaultText) { + textView.text = self.defaultText; + self.defaultText = nil; + } + + [self setTextView:textView]; + } + return _textView; +} +/* +- (JLTokenizer *)tokenizer +{ + return self.textView.syntaxTokenizer; +} +*/ +/* +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.view.backgroundColor = self.textView.backgroundColor; + self.navigationController.navigationBar.translucent = TRUE; + + [self registerForKeyboardNotifications]; +} +*/ + +/* +- (void)didReceiveMemoryWarning +{/* + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. + */ +} +*/ + +#pragma mark - Content Insets and Keyboard + +// Call this method somewhere in your view controller setup code. +- (void)registerForKeyboardNotifications +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWasShown:) + name:UIKeyboardDidShowNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillBeHidden:) + name:UIKeyboardWillHideNotification object:nil]; + +} + +// Called when the UIKeyboardDidShowNotification is sent. +- (void)keyboardWasShown:(NSNotification *)notification +{ + NSDictionary* info = [notification userInfo]; + UIScrollView *scrollView = self.textView; + CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + + UIEdgeInsets contentInsets = scrollView.contentInset; + contentInsets.bottom = kbSize.height; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; + + CGPoint point = [self.textView caretRectForPosition:self.textView.selectedTextRange.start].origin; + point.y = MIN(point.y, self.textView.frame.size.height - kbSize.height); + + CGRect aRect = self.view.frame; + aRect.size.height -= kbSize.height; + if (!CGRectContainsPoint(aRect, point) ) { + + CGRect rect = CGRectMake(point.x, point.y, 1, 1); + rect.size.height = kbSize.height; + rect.origin.y += kbSize.height; + [self.textView scrollRectToVisible:rect animated:YES]; + } +} + +// Called when the UIKeyboardWillHideNotification is sent +- (void)keyboardWillBeHidden:(NSNotification *)notification +{ + UIScrollView *scrollView = self.textView; + UIEdgeInsets contentInsets = scrollView.contentInset; + contentInsets.bottom = 0; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; +} + +@end + +// +// JLTextViewController.h +// iGitpad +// +// Created by Johannes Lund on 2013-06-13. +// Copyright (c) 2013 Johannes Lund +// +// 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 + +@class JLTokenizer, JLTextView; + +@interface JLTextViewController : UIViewController + +- (instancetype)initWithText:(NSString *)text; + +@property (nonatomic, strong) IBOutlet JLTextView *textView; + +// Convenience property for self.textView.syntaxTokenizer +@property (nonatomic, weak, readonly) JLTokenizer *tokenizer; +@end +*/ + +// +// AppDelegate.m +// ChromatismDemo +// +// Created by Anviking on 2013-07-31. +// Copyright (c) 2013 Anviking. All rights reserved. +// + +#import "AppDelegate.h" +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + + JLTextViewController *viewController = [[JLTextViewController alloc] init]; + UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; + viewController.title = @"Chromatism"; + + self.window.rootViewController = navigationController; + self.window.backgroundColor = [UIColor whiteColor]; + [self.window makeKeyAndVisible]; + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +/* +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} +*/ + +@end + +// +// Tokenizer.m +// iGitpad +// +// Created by Johannes Lund on 2012-11-24. +// +// + +// This file builds upon the work of Kristian Kraljic +// +// RegexHighlightView.m +// Simple Objective-C Syntax Highlighter +// +// Created by Kristian Kraljic on 30/08/12. +// Copyright (c) 2012 Kristian Kraljic (dikrypt.com, ksquared.de). All rights reserved. +// +// 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 "JLTokenizer.h" +#import "JLTextViewController.h" +#import "JLScope.h" +#import "JLTokenPattern.h" +#import "Chromatism+Internal.h" + +@interface JLTokenizer () +@property (nonatomic, strong) NSOperationQueue *operationQueue; +@end + +@implementation JLTokenizer + +#pragma mark - Setup + +- (id)init +{ + self = [super init]; + if (self) { + self.operationQueue = [[NSOperationQueue alloc] init]; + self.operationQueue.maxConcurrentOperationCount = 1; + } + return self; +} + +#pragma mark - NSTextStorageDelegate + +- (void)textStorage:(NSTextStorage *)textStorage willProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta +{ + +} + +- (void)textStorage:(NSTextStorage *)textStorage didProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta +{ + if (textStorage.editedMask == NSTextStorageEditedAttributes) return; + [self tokenizeTextStorage:textStorage withScope:[self documentScopeForTokenizingTextStorage:textStorage inRange:editedRange]]; +} + +#pragma mark - NSLayoutManager delegeate + +- (CGFloat)layoutManager:(NSLayoutManager *)layoutManager paragraphSpacingBeforeGlyphAtIndex:(NSUInteger)glyphIndex withProposedLineFragmentRect:(CGRect)rect +{ + return 0; +} + +- (BOOL)layoutManager:(NSLayoutManager *)layoutManager shouldBreakLineByWordBeforeCharacterAtIndex:(NSUInteger)charIndex +{ + unichar character = [layoutManager.textStorage.string characterAtIndex:charIndex]; + if (character == '*') return NO; + return YES; +} + +#pragma mark - UITextViewDelegate + +- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text +{ + if (![text isEqualToString:@"\n"]) return YES; // Something else than return + + // Return has been pressed, start the new line with as many tabs or white spaces as the previous one. + NSString *prefixString = [@"\n" stringByAppendingString:[self prefixStringFromRange:range inTextView:textView]]; + + unichar previousCharacter = [textView.text characterAtIndex:range.location - 1]; + if (self.intendator && [self.intendator respondsToSelector:@selector(indentationActionAfterReplacingTextInRange:replacementText:previousCharacter:textView:)]) { + switch ([self indentationActionAfterReplacingTextInRange:range replacementText:text previousCharacter:previousCharacter textView:textView]) { + case JLIndentationActionIncrease: + prefixString = [prefixString stringByAppendingString:@" "]; + break; + case JLIndentationActionDecrease: + if ([[prefixString substringFromIndex:prefixString.length - 4] isEqualToString:@" "]) { + prefixString = [prefixString substringToIndex:prefixString.length - 4]; + } + else if ([[prefixString substringFromIndex:prefixString.length - 1] isEqualToString:@"\t"]) { + prefixString = [prefixString substringToIndex:prefixString.length - 1]; + } + break; + case JLIndentationActionNone: + break; + } + } + + + [textView replaceRange:[self rangeWithRange:range inTextView:textView] withText:prefixString]; + return NO; +} + + +#pragma mark - Tokenizing + +- (void)refreshTokenizationOfTextStorage:(NSTextStorage *)textStorage; +{ + [self tokenizeTextStorage:textStorage withScope:[self documentScopeForTokenizingTextStorage:textStorage inRange:NSMakeRange(0, textStorage.length)]]; +} + +- (JLScope *)documentScopeForTokenizingTextStorage:(NSTextStorage *)textStorage inRange:(NSRange)range +{ + JLScope *documentScope = [JLScope new]; + JLScope *lineScope = [JLScope new]; + + [self prepareDocumentScope:documentScope]; + [self prepareLineScope:lineScope]; + + [documentScope addSubscope:lineScope]; + + [self clearColorAttributesInRange:range textStorage:textStorage]; + + [documentScope setTextStorage:textStorage]; + [documentScope setSet:[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, textStorage.length)]]; + [lineScope setSet:[NSMutableIndexSet indexSetWithIndexesInRange:[textStorage.string lineRangeForRange:range]]]; + + return documentScope; +} + +- (void)tokenizeTextStorage:(NSTextStorage *)textStorage withScope:(JLScope *)scope +{ + //[textStorage beginEditing]; + [self.operationQueue addOperations:[[scope recursiveSubscopes] allObjects] waitUntilFinished:YES]; + //[textStorage endEditing]; +} + +#pragma mark - Synchronous Tokenization + +- (void)tokenizeAttributedString:(NSMutableAttributedString *)string +{ + JLScope *scope = [self documentScopeForTokenizingTextStorage:(NSTextStorage *)string inRange:NSMakeRange(0, string.length)]; + [self.operationQueue addOperations:[[scope recursiveSubscopes] allObjects] waitUntilFinished:YES]; +} + +#pragma mark - Setup Token Patterns + +- (void)prepareDocumentScope:(JLScope *)documentScope +{ + +} + +- (void)prepareLineScope:(JLScope *)lineScope +{ + +} + + +#pragma mark - Symbolication + +/* +- (void)symbolicate +{ + [self.scopes[PROJECT_CLASS_NAMES] setPattern:[NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@implementation (\\w+)" captureGroup:1] componentsJoinedByString:@"|"]]]; + [self.scopes[PROJECT_METHOD_NAMES] setPattern:[NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@property \\(.*?\\)\\s*\\w+[\\s*]+(\\w+);" captureGroup:1] componentsJoinedByString:@"|"]]]; +} +*/ + +#pragma mark - Helpers + +- (JLTokenPattern *)addToken:(NSString *)type withPattern:(NSString *)pattern andScope:(JLScope *)scope +{ + + NSParameterAssert(type); + NSParameterAssert(pattern); + NSParameterAssert(scope); + + JLTokenPattern *token = [JLTokenPattern token:type withPattern:pattern andScope:scope]; + token.color = self.colors[type]; + + return token; +} + +- (JLTokenPattern *)addToken:(NSString *)type withKeywords:(NSString *)keywords andScope:(JLScope *)scope +{ + NSString *pattern = [NSString stringWithFormat:@"\\b(%@)\\b", [[keywords componentsSeparatedByString:@" "] componentsJoinedByString:@"|"]]; + return [self addToken:type withPattern:pattern andScope:scope]; +} + +- (NSMutableArray *)symbolsWithPattern:(NSString *)pattern captureGroup:(int)group textStorage:(NSTextStorage *)textStorage +{ + NSMutableArray *array = [NSMutableArray array]; + NSError *error = nil; + NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionAnchorsMatchLines error:&error]; + [expression enumerateMatchesInString:textStorage.string options:0 range:NSMakeRange(0, textStorage.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { + [array addObject:[textStorage.string substringWithRange:[result rangeAtIndex:group]]]; + }]; + NSAssert(!error, @"%@",error); + return array; +} + +#pragma mark - Indentation + +- (id )intendator +{ + if (!_intendator) { + _intendator = self; + } + return _intendator; +} + +- (JLIndentationAction)indentationActionAfterReplacingTextInRange:(NSRange)range replacementText:(NSString *)text previousCharacter:(unichar)character textView:(UITextView *)textView; +{ + if (character == '{') { + return JLIndentationActionIncrease; + } else if (character == '}') { + return JLIndentationActionDecrease; + } else { + return JLIndentationActionNone; + } +} + +#pragma mark - Helpers + +- (UITextRange *)rangeWithRange:(NSRange)range inTextView:(UITextView *)textView +{ + UITextPosition *beginning = textView.beginningOfDocument; + UITextPosition *start = [textView positionFromPosition:beginning offset:range.location]; + UITextPosition *stop = [textView positionFromPosition:start offset:range.length]; + + return [textView textRangeFromPosition:start toPosition:stop]; +} + +- (void)clearColorAttributesInRange:(NSRange)range textStorage:(NSTextStorage *)storage; +{ + [storage removeAttribute:NSForegroundColorAttributeName range:range]; + [storage addAttribute:NSForegroundColorAttributeName value:self.colors[JLTokenTypeText] range:range]; +} + +- (NSString *)prefixStringFromRange:(NSRange)range inTextView:(UITextView *)textView +{ + NSRange lineRange = [textView.text lineRangeForRange:range]; + NSRange prefixRange = [textView.text rangeOfString:@"[\\t| ]*" options:NSRegularExpressionSearch range:lineRange]; + return [textView.text substringWithRange:prefixRange]; +} + +@end + + +// +// JLTextViewController.m +// iGitpad +// +// Created by Johannes Lund on 2013-06-13. +// Copyright (c) 2013 Johannes Lund +// +// 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 "JLTextViewController.h" +#import "JLTokenizer.h" +#import "JLTokenizer.h" +#import "JLTextView.h" + +@interface JLTextViewController () +/// Only set from -initWithText: and directly set to nil in -loadView +@property (nonatomic, strong) NSString *defaultText; +@end + +@implementation JLTextViewController + +- (instancetype)initWithText:(NSString *)text +{ + self = [super init]; + if (self) { + _defaultText = text; + } + return self; +} + +- (void)loadView +{ + self.view = self.textView; +} + +- (JLTextView *)textView +{ + if (!_textView) { + JLTextView *textView = [[JLTextView alloc] initWithFrame:CGRectZero]; + textView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + if (self.defaultText) { + textView.text = self.defaultText; + self.defaultText = nil; + } + + [self setTextView:textView]; + } + return _textView; +} +/* +- (JLTokenizer *)tokenizer +{ + return self.textView.syntaxTokenizer; +} +*/ +/* +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.view.backgroundColor = self.textView.backgroundColor; + self.navigationController.navigationBar.translucent = TRUE; + + [self registerForKeyboardNotifications]; +} +*/ + +/* +- (void)didReceiveMemoryWarning +{/* + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. + */ +} +*/ + +#pragma mark - Content Insets and Keyboard + +// Call this method somewhere in your view controller setup code. +- (void)registerForKeyboardNotifications +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWasShown:) + name:UIKeyboardDidShowNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillBeHidden:) + name:UIKeyboardWillHideNotification object:nil]; + +} + +// Called when the UIKeyboardDidShowNotification is sent. +- (void)keyboardWasShown:(NSNotification *)notification +{ + NSDictionary* info = [notification userInfo]; + UIScrollView *scrollView = self.textView; + CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + + UIEdgeInsets contentInsets = scrollView.contentInset; + contentInsets.bottom = kbSize.height; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; + + CGPoint point = [self.textView caretRectForPosition:self.textView.selectedTextRange.start].origin; + point.y = MIN(point.y, self.textView.frame.size.height - kbSize.height); + + CGRect aRect = self.view.frame; + aRect.size.height -= kbSize.height; + if (!CGRectContainsPoint(aRect, point) ) { + + CGRect rect = CGRectMake(point.x, point.y, 1, 1); + rect.size.height = kbSize.height; + rect.origin.y += kbSize.height; + [self.textView scrollRectToVisible:rect animated:YES]; + } +} + +// Called when the UIKeyboardWillHideNotification is sent +- (void)keyboardWillBeHidden:(NSNotification *)notification +{ + UIScrollView *scrollView = self.textView; + UIEdgeInsets contentInsets = scrollView.contentInset; + contentInsets.bottom = 0; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; +} + +@end + +// +// JLTextViewController.h +// iGitpad +// +// Created by Johannes Lund on 2013-06-13. +// Copyright (c) 2013 Johannes Lund +// +// 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 + +@class JLTokenizer, JLTextView; + +@interface JLTextViewController : UIViewController + +- (instancetype)initWithText:(NSString *)text; + +@property (nonatomic, strong) IBOutlet JLTextView *textView; + +// Convenience property for self.textView.syntaxTokenizer +@property (nonatomic, weak, readonly) JLTokenizer *tokenizer; +@end +*/ + +#import "helpers.h" +void new_application(lua_State* L, pid_t pid); + +#define hydra_window(L, idx) *((AXUIElementRef*)luaL_checkudata(L, idx, "window")) + +static int window_gc(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + CFRelease(win); + return 0; +} + +static int window_eq(lua_State* L) { + AXUIElementRef winA = hydra_window(L, 1); + AXUIElementRef winB = hydra_window(L, 2); + lua_pushboolean(L, CFEqual(winA, winB)); + return 1; +} + +extern AXError _AXUIElementGetWindow(AXUIElementRef, CGWindowID* out); +NSWindow* hydra_nswindow_for_accessibility_window(AXUIElementRef win) { + CGWindowID winid; + AXError err = _AXUIElementGetWindow(win, &winid); + if (err) return nil; + + for (NSWindow* window in [NSApp windows]) { + if ([window windowNumber] == winid) + return window; + } + + return nil; +} + +void new_window(lua_State* L, AXUIElementRef win) { + AXUIElementRef* winptr = lua_newuserdata(L, sizeof(AXUIElementRef)); + *winptr = win; + + luaL_getmetatable(L, "window"); + lua_setmetatable(L, -2); + + lua_newtable(L); + lua_setuservalue(L, -2); +} + +static AXUIElementRef system_wide_element() { + static AXUIElementRef element; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + element = AXUIElementCreateSystemWide(); + }); + return element; +} + +/// window.focusedwindow() -> window +/// Returns the focused window, or nil. +static int window_focusedwindow(lua_State* L) { + CFTypeRef app; + AXUIElementCopyAttributeValue(system_wide_element(), kAXFocusedApplicationAttribute, &app); + + if (app) { + CFTypeRef win; + AXError result = AXUIElementCopyAttributeValue(app, (CFStringRef)NSAccessibilityFocusedWindowAttribute, &win); + + CFRelease(app); + + if (result == kAXErrorSuccess) { + new_window(L, win); + return 1; + } + } + + lua_pushnil(L); + return 1; +} + +static id get_window_prop(AXUIElementRef win, NSString* propType, id defaultValue) { + CFTypeRef _someProperty; + if (AXUIElementCopyAttributeValue(win, (__bridge CFStringRef)propType, &_someProperty) == kAXErrorSuccess) + return CFBridgingRelease(_someProperty); + + return defaultValue; +} + +static BOOL set_window_prop(AXUIElementRef win, NSString* propType, id value) { + if ([value isKindOfClass:[NSNumber class]]) { + AXError result = AXUIElementSetAttributeValue(win, (__bridge CFStringRef)(propType), (__bridge CFTypeRef)(value)); + if (result == kAXErrorSuccess) + return YES; + } + return NO; +} + +/// window:title() -> string +/// Returns the title of the window (as UTF8). +static int window_title(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + NSString* title = get_window_prop(win, NSAccessibilityTitleAttribute, @""); + lua_pushstring(L, [title UTF8String]); + return 1; +} + +/// window:subrole() -> string +/// Returns the subrole of the window, whatever that means. +static int window_subrole(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + NSString* str = get_window_prop(win, NSAccessibilitySubroleAttribute, @""); + + lua_pushstring(L, [str UTF8String]); + return 1; +} + +/// window:role() -> string +/// Returns the role of the window, whatever that means. +static int window_role(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + NSString* str = get_window_prop(win, NSAccessibilityRoleAttribute, @""); + + lua_pushstring(L, [str UTF8String]); + return 1; +} + +/// window:isstandard() -> bool +/// True if the window's subrole indicates it's 'a standard window'. +static int window_isstandard(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + NSString* subrole = get_window_prop(win, NSAccessibilitySubroleAttribute, @""); + + BOOL is_standard = [subrole isEqualToString: (__bridge NSString*)kAXStandardWindowSubrole]; + lua_pushboolean(L, is_standard); + return 1; +} + +/// window:topleft() -> point +/// The top-left corner of the window in absolute coordinates. +static int window_topleft(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + CFTypeRef positionStorage; + AXError result = AXUIElementCopyAttributeValue(win, (CFStringRef)NSAccessibilityPositionAttribute, &positionStorage); + + CGPoint topLeft; + if (result == kAXErrorSuccess) { + if (!AXValueGetValue(positionStorage, kAXValueCGPointType, (void *)&topLeft)) { +// NSLog(@"could not decode topLeft"); + topLeft = CGPointZero; + } + } + else { +// NSLog(@"could not get window topLeft"); + topLeft = CGPointZero; + } + + if (positionStorage) + CFRelease(positionStorage); + + hydra_pushpoint(L, topLeft); + return 1; +} + +/// window:size() -> size +/// The size of the window. +static int window_size(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + CFTypeRef sizeStorage; + AXError result = AXUIElementCopyAttributeValue(win, (CFStringRef)NSAccessibilitySizeAttribute, &sizeStorage); + + CGSize size; + if (result == kAXErrorSuccess) { + if (!AXValueGetValue(sizeStorage, kAXValueCGSizeType, (void *)&size)) { +// NSLog(@"could not decode topLeft"); + size = CGSizeZero; + } + } + else { +// NSLog(@"could not get window size"); + size = CGSizeZero; + } + + if (sizeStorage) + CFRelease(sizeStorage); + + hydra_pushsize(L, size); + return 1; +} + +/// window:settopleft(point) +/// Moves the window to the given point in absolute coordinate. +static int window_settopleft(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + NSPoint thePoint = hydra_topoint(L, 2); + + CFTypeRef positionStorage = (CFTypeRef)(AXValueCreate(kAXValueCGPointType, (const void *)&thePoint)); + AXUIElementSetAttributeValue(win, (CFStringRef)NSAccessibilityPositionAttribute, positionStorage); + if (positionStorage) + CFRelease(positionStorage); + + return 0; +} + +/// window:setsize(size) +/// Resizes the window. +static int window_setsize(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + NSSize theSize = hydra_tosize(L, 2); + + CFTypeRef sizeStorage = (CFTypeRef)(AXValueCreate(kAXValueCGSizeType, (const void *)&theSize)); + AXUIElementSetAttributeValue(win, (CFStringRef)NSAccessibilitySizeAttribute, sizeStorage); + if (sizeStorage) + CFRelease(sizeStorage); + + return 0; +} + +/// window:close() -> bool +/// Closes the window; returns whether it succeeded. +static int window_close(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + BOOL worked = NO; + AXUIElementRef button = NULL; + + if (AXUIElementCopyAttributeValue(win, kAXCloseButtonAttribute, (CFTypeRef*)&button) != noErr) goto cleanup; + if (AXUIElementPerformAction(button, kAXPressAction) != noErr) goto cleanup; + + worked = YES; + +cleanup: + if (button) CFRelease(button); + + lua_pushboolean(L, worked); + return 1; +} + +/// window:setfullscreen(bool) -> bool +/// Sets whether the window is full screen; returns whether it succeeded. +static int window_setfullscreen(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + CFBooleanRef befullscreen = lua_toboolean(L, 2) ? kCFBooleanTrue : kCFBooleanFalse; + BOOL succeeded = (AXUIElementSetAttributeValue(win, CFSTR("AXFullScreen"), befullscreen) == noErr); + lua_pushboolean(L, succeeded); + return 1; +} + +/// window:isfullscreen() -> bool or nil +/// Returns whether the window is full screen, or nil if asking that question fails. +static int window_isfullscreen(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + id isfullscreen = nil; + CFBooleanRef fullscreen = kCFBooleanFalse; + + if (AXUIElementCopyAttributeValue(win, CFSTR("AXFullScreen"), (CFTypeRef*)&fullscreen) != noErr) goto cleanup; + + isfullscreen = @(CFBooleanGetValue(fullscreen)); + +cleanup: + if (fullscreen) CFRelease(fullscreen); + + if (isfullscreen) + lua_pushboolean(L, [isfullscreen boolValue]); + else + lua_pushnil(L); + + return 1; +} + +/// window:minimize() +/// Minimizes the window. +static int window_minimize(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + set_window_prop(win, NSAccessibilityMinimizedAttribute, @YES); + return 0; +} + +/// window:unminimize() +/// Un-minimizes the window. +static int window_unminimize(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + set_window_prop(win, NSAccessibilityMinimizedAttribute, @NO); + return 0; +} + +/// window:isminimized() -> bool +/// True if the window is currently minimized in the dock. +static int window_isminimized(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + BOOL minimized = [get_window_prop(win, NSAccessibilityMinimizedAttribute, @(NO)) boolValue]; + lua_pushboolean(L, minimized); + return 1; +} + +// private function +// args: [win] +// ret: [pid] +static int window_pid(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + pid_t pid = 0; + if (AXUIElementGetPid(win, &pid) == kAXErrorSuccess) { + lua_pushnumber(L, pid); + return 1; + } + else { + return 0; + } +} + +/// window:application() -> app +/// Returns the app that the window belongs to. +static int window_application(lua_State* L) { + if (window_pid(L)) { + pid_t pid = lua_tonumber(L, -1); + new_application(L, pid); + return 1; + } + else { + return 0; + } +} + +/// window:becomemain() -> bool +/// Make this window the main window of the given application; deos not implicitly focus the app. +static int window_becomemain(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + BOOL success = (AXUIElementSetAttributeValue(win, (CFStringRef)NSAccessibilityMainAttribute, kCFBooleanTrue) == kAXErrorSuccess); + lua_pushboolean(L, success); + return 1; +} + +static int window__orderedwinids(lua_State* L) { + lua_newtable(L); + + CFArrayRef wins = CGWindowListCreate(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); + + for (int i = 0; i < CFArrayGetCount(wins); i++) { + int winid = (int)CFArrayGetValueAtIndex(wins, i); + + lua_pushnumber(L, winid); + lua_rawseti(L, -2, i+1); + } + + CFRelease(wins); + + return 1; +} + +/// window:id() -> number, sometimes nil +/// Returns a unique number identifying this window. +static int window_id(lua_State* L) { + lua_settop(L, 1); + AXUIElementRef win = hydra_window(L, 1); + + lua_getuservalue(L, 1); + + lua_getfield(L, -1, "id"); + if (lua_isnumber(L, -1)) + return 1; + else + lua_pop(L, 1); + + CGWindowID winid; + AXError err = _AXUIElementGetWindow(win, &winid); + if (err) { + lua_pushnil(L); + return 1; + } + + // cache it + lua_pushnumber(L, winid); + lua_setfield(L, -2, "id"); + + lua_pushnumber(L, winid); + return 1; +} + +static const luaL_Reg windowlib[] = { + {"focusedwindow", window_focusedwindow}, + {"_orderedwinids", window__orderedwinids}, + + {"title", window_title}, + {"subrole", window_subrole}, + {"role", window_role}, + {"isstandard", window_isstandard}, + {"topleft", window_topleft}, + {"size", window_size}, + {"settopleft", window_settopleft}, + {"setsize", window_setsize}, + {"minimize", window_minimize}, + {"unminimize", window_unminimize}, + {"isminimized", window_isminimized}, + {"pid", window_pid}, + {"application", window_application}, + {"becomemain", window_becomemain}, + {"id", window_id}, + {"close", window_close}, + {"setfullscreen", window_setfullscreen}, + {"isfullscreen", window_isfullscreen}, + + {NULL, NULL} +}; + +int luaopen_window(lua_State* L) { + luaL_newlib(L, windowlib); + + if (luaL_newmetatable(L, "window")) { + lua_pushvalue(L, -2); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, window_gc); + lua_setfield(L, -2, "__gc"); + + lua_pushcfunction(L, window_eq); + lua_setfield(L, -2, "__eq"); + } + lua_pop(L, 1); + + return 1; +} + +// +// AppDelegate.m +// ChromatismDemo +// +// Created by Anviking on 2013-07-31. +// Copyright (c) 2013 Anviking. All rights reserved. +// + +#import "AppDelegate.h" +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + + JLTextViewController *viewController = [[JLTextViewController alloc] init]; + UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; + viewController.title = @"Chromatism"; + + self.window.rootViewController = navigationController; + self.window.backgroundColor = [UIColor whiteColor]; + [self.window makeKeyAndVisible]; + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +/* +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} +*/ + +@end + +// +// Tokenizer.m +// iGitpad +// +// Created by Johannes Lund on 2012-11-24. +// +// + +// This file builds upon the work of Kristian Kraljic +// +// RegexHighlightView.m +// Simple Objective-C Syntax Highlighter +// +// Created by Kristian Kraljic on 30/08/12. +// Copyright (c) 2012 Kristian Kraljic (dikrypt.com, ksquared.de). All rights reserved. +// +// 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 "JLTokenizer.h" +#import "JLTextViewController.h" +#import "JLScope.h" +#import "JLTokenPattern.h" +#import "Chromatism+Internal.h" + +@interface JLTokenizer () +@property (nonatomic, strong) NSOperationQueue *operationQueue; +@end + +@implementation JLTokenizer + +#pragma mark - Setup + +- (id)init +{ + self = [super init]; + if (self) { + self.operationQueue = [[NSOperationQueue alloc] init]; + self.operationQueue.maxConcurrentOperationCount = 1; + } + return self; +} + +#pragma mark - NSTextStorageDelegate + +- (void)textStorage:(NSTextStorage *)textStorage willProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta +{ + +} + +- (void)textStorage:(NSTextStorage *)textStorage didProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta +{ + if (textStorage.editedMask == NSTextStorageEditedAttributes) return; + [self tokenizeTextStorage:textStorage withScope:[self documentScopeForTokenizingTextStorage:textStorage inRange:editedRange]]; +} + +#pragma mark - NSLayoutManager delegeate + +- (CGFloat)layoutManager:(NSLayoutManager *)layoutManager paragraphSpacingBeforeGlyphAtIndex:(NSUInteger)glyphIndex withProposedLineFragmentRect:(CGRect)rect +{ + return 0; +} + +- (BOOL)layoutManager:(NSLayoutManager *)layoutManager shouldBreakLineByWordBeforeCharacterAtIndex:(NSUInteger)charIndex +{ + unichar character = [layoutManager.textStorage.string characterAtIndex:charIndex]; + if (character == '*') return NO; + return YES; +} + +#pragma mark - UITextViewDelegate + +- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text +{ + if (![text isEqualToString:@"\n"]) return YES; // Something else than return + + // Return has been pressed, start the new line with as many tabs or white spaces as the previous one. + NSString *prefixString = [@"\n" stringByAppendingString:[self prefixStringFromRange:range inTextView:textView]]; + + unichar previousCharacter = [textView.text characterAtIndex:range.location - 1]; + if (self.intendator && [self.intendator respondsToSelector:@selector(indentationActionAfterReplacingTextInRange:replacementText:previousCharacter:textView:)]) { + switch ([self indentationActionAfterReplacingTextInRange:range replacementText:text previousCharacter:previousCharacter textView:textView]) { + case JLIndentationActionIncrease: + prefixString = [prefixString stringByAppendingString:@" "]; + break; + case JLIndentationActionDecrease: + if ([[prefixString substringFromIndex:prefixString.length - 4] isEqualToString:@" "]) { + prefixString = [prefixString substringToIndex:prefixString.length - 4]; + } + else if ([[prefixString substringFromIndex:prefixString.length - 1] isEqualToString:@"\t"]) { + prefixString = [prefixString substringToIndex:prefixString.length - 1]; + } + break; + case JLIndentationActionNone: + break; + } + } + + + [textView replaceRange:[self rangeWithRange:range inTextView:textView] withText:prefixString]; + return NO; +} + + +#pragma mark - Tokenizing + +- (void)refreshTokenizationOfTextStorage:(NSTextStorage *)textStorage; +{ + [self tokenizeTextStorage:textStorage withScope:[self documentScopeForTokenizingTextStorage:textStorage inRange:NSMakeRange(0, textStorage.length)]]; +} + +- (JLScope *)documentScopeForTokenizingTextStorage:(NSTextStorage *)textStorage inRange:(NSRange)range +{ + JLScope *documentScope = [JLScope new]; + JLScope *lineScope = [JLScope new]; + + [self prepareDocumentScope:documentScope]; + [self prepareLineScope:lineScope]; + + [documentScope addSubscope:lineScope]; + + [self clearColorAttributesInRange:range textStorage:textStorage]; + + [documentScope setTextStorage:textStorage]; + [documentScope setSet:[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, textStorage.length)]]; + [lineScope setSet:[NSMutableIndexSet indexSetWithIndexesInRange:[textStorage.string lineRangeForRange:range]]]; + + return documentScope; +} + +- (void)tokenizeTextStorage:(NSTextStorage *)textStorage withScope:(JLScope *)scope +{ + //[textStorage beginEditing]; + [self.operationQueue addOperations:[[scope recursiveSubscopes] allObjects] waitUntilFinished:YES]; + //[textStorage endEditing]; +} + +#pragma mark - Synchronous Tokenization + +- (void)tokenizeAttributedString:(NSMutableAttributedString *)string +{ + JLScope *scope = [self documentScopeForTokenizingTextStorage:(NSTextStorage *)string inRange:NSMakeRange(0, string.length)]; + [self.operationQueue addOperations:[[scope recursiveSubscopes] allObjects] waitUntilFinished:YES]; +} + +#pragma mark - Setup Token Patterns + +- (void)prepareDocumentScope:(JLScope *)documentScope +{ + +} + +- (void)prepareLineScope:(JLScope *)lineScope +{ + +} + + +#pragma mark - Symbolication + +/* +- (void)symbolicate +{ + [self.scopes[PROJECT_CLASS_NAMES] setPattern:[NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@implementation (\\w+)" captureGroup:1] componentsJoinedByString:@"|"]]]; + [self.scopes[PROJECT_METHOD_NAMES] setPattern:[NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@property \\(.*?\\)\\s*\\w+[\\s*]+(\\w+);" captureGroup:1] componentsJoinedByString:@"|"]]]; +} +*/ + +#pragma mark - Helpers + +- (JLTokenPattern *)addToken:(NSString *)type withPattern:(NSString *)pattern andScope:(JLScope *)scope +{ + + NSParameterAssert(type); + NSParameterAssert(pattern); + NSParameterAssert(scope); + + JLTokenPattern *token = [JLTokenPattern token:type withPattern:pattern andScope:scope]; + token.color = self.colors[type]; + + return token; +} + +- (JLTokenPattern *)addToken:(NSString *)type withKeywords:(NSString *)keywords andScope:(JLScope *)scope +{ + NSString *pattern = [NSString stringWithFormat:@"\\b(%@)\\b", [[keywords componentsSeparatedByString:@" "] componentsJoinedByString:@"|"]]; + return [self addToken:type withPattern:pattern andScope:scope]; +} + +- (NSMutableArray *)symbolsWithPattern:(NSString *)pattern captureGroup:(int)group textStorage:(NSTextStorage *)textStorage +{ + NSMutableArray *array = [NSMutableArray array]; + NSError *error = nil; + NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionAnchorsMatchLines error:&error]; + [expression enumerateMatchesInString:textStorage.string options:0 range:NSMakeRange(0, textStorage.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { + [array addObject:[textStorage.string substringWithRange:[result rangeAtIndex:group]]]; + }]; + NSAssert(!error, @"%@",error); + return array; +} + +#pragma mark - Indentation + +- (id )intendator +{ + if (!_intendator) { + _intendator = self; + } + return _intendator; +} + +- (JLIndentationAction)indentationActionAfterReplacingTextInRange:(NSRange)range replacementText:(NSString *)text previousCharacter:(unichar)character textView:(UITextView *)textView; +{ + if (character == '{') { + return JLIndentationActionIncrease; + } else if (character == '}') { + return JLIndentationActionDecrease; + } else { + return JLIndentationActionNone; + } +} + +#pragma mark - Helpers + +- (UITextRange *)rangeWithRange:(NSRange)range inTextView:(UITextView *)textView +{ + UITextPosition *beginning = textView.beginningOfDocument; + UITextPosition *start = [textView positionFromPosition:beginning offset:range.location]; + UITextPosition *stop = [textView positionFromPosition:start offset:range.length]; + + return [textView textRangeFromPosition:start toPosition:stop]; +} + +- (void)clearColorAttributesInRange:(NSRange)range textStorage:(NSTextStorage *)storage; +{ + [storage removeAttribute:NSForegroundColorAttributeName range:range]; + [storage addAttribute:NSForegroundColorAttributeName value:self.colors[JLTokenTypeText] range:range]; +} + +- (NSString *)prefixStringFromRange:(NSRange)range inTextView:(UITextView *)textView +{ + NSRange lineRange = [textView.text lineRangeForRange:range]; + NSRange prefixRange = [textView.text rangeOfString:@"[\\t| ]*" options:NSRegularExpressionSearch range:lineRange]; + return [textView.text substringWithRange:prefixRange]; +} + +@end + + +// +// JLTextViewController.m +// iGitpad +// +// Created by Johannes Lund on 2013-06-13. +// Copyright (c) 2013 Johannes Lund +// +// 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 "JLTextViewController.h" +#import "JLTokenizer.h" +#import "JLTokenizer.h" +#import "JLTextView.h" + +@interface JLTextViewController () +/// Only set from -initWithText: and directly set to nil in -loadView +@property (nonatomic, strong) NSString *defaultText; +@end + +@implementation JLTextViewController + +- (instancetype)initWithText:(NSString *)text +{ + self = [super init]; + if (self) { + _defaultText = text; + } + return self; +} + +- (void)loadView +{ + self.view = self.textView; +} + +- (JLTextView *)textView +{ + if (!_textView) { + JLTextView *textView = [[JLTextView alloc] initWithFrame:CGRectZero]; + textView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + if (self.defaultText) { + textView.text = self.defaultText; + self.defaultText = nil; + } + + [self setTextView:textView]; + } + return _textView; +} +/* +- (JLTokenizer *)tokenizer +{ + return self.textView.syntaxTokenizer; +} +*/ +/* +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.view.backgroundColor = self.textView.backgroundColor; + self.navigationController.navigationBar.translucent = TRUE; + + [self registerForKeyboardNotifications]; +} +*/ + +/* +- (void)didReceiveMemoryWarning +{/* + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. + */ +} +*/ + +#pragma mark - Content Insets and Keyboard + +// Call this method somewhere in your view controller setup code. +- (void)registerForKeyboardNotifications +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWasShown:) + name:UIKeyboardDidShowNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillBeHidden:) + name:UIKeyboardWillHideNotification object:nil]; + +} + +// Called when the UIKeyboardDidShowNotification is sent. +- (void)keyboardWasShown:(NSNotification *)notification +{ + NSDictionary* info = [notification userInfo]; + UIScrollView *scrollView = self.textView; + CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + + UIEdgeInsets contentInsets = scrollView.contentInset; + contentInsets.bottom = kbSize.height; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; + + CGPoint point = [self.textView caretRectForPosition:self.textView.selectedTextRange.start].origin; + point.y = MIN(point.y, self.textView.frame.size.height - kbSize.height); + + CGRect aRect = self.view.frame; + aRect.size.height -= kbSize.height; + if (!CGRectContainsPoint(aRect, point) ) { + + CGRect rect = CGRectMake(point.x, point.y, 1, 1); + rect.size.height = kbSize.height; + rect.origin.y += kbSize.height; + [self.textView scrollRectToVisible:rect animated:YES]; + } +} + +// Called when the UIKeyboardWillHideNotification is sent +- (void)keyboardWillBeHidden:(NSNotification *)notification +{ + UIScrollView *scrollView = self.textView; + UIEdgeInsets contentInsets = scrollView.contentInset; + contentInsets.bottom = 0; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; +} + +@end + +// +// JLTextViewController.h +// iGitpad +// +// Created by Johannes Lund on 2013-06-13. +// Copyright (c) 2013 Johannes Lund +// +// 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 + +@class JLTokenizer, JLTextView; + +@interface JLTextViewController : UIViewController + +- (instancetype)initWithText:(NSString *)text; + +@property (nonatomic, strong) IBOutlet JLTextView *textView; + +// Convenience property for self.textView.syntaxTokenizer +@property (nonatomic, weak, readonly) JLTokenizer *tokenizer; +@end +*/ + +// +// AppDelegate.m +// ChromatismDemo +// +// Created by Anviking on 2013-07-31. +// Copyright (c) 2013 Anviking. All rights reserved. +// + +#import "AppDelegate.h" +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + + JLTextViewController *viewController = [[JLTextViewController alloc] init]; + UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; + viewController.title = @"Chromatism"; + + self.window.rootViewController = navigationController; + self.window.backgroundColor = [UIColor whiteColor]; + [self.window makeKeyAndVisible]; + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +/* +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} +*/ + +@end + +// +// Tokenizer.m +// iGitpad +// +// Created by Johannes Lund on 2012-11-24. +// +// + +// This file builds upon the work of Kristian Kraljic +// +// RegexHighlightView.m +// Simple Objective-C Syntax Highlighter +// +// Created by Kristian Kraljic on 30/08/12. +// Copyright (c) 2012 Kristian Kraljic (dikrypt.com, ksquared.de). All rights reserved. +// +// 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 "JLTokenizer.h" +#import "JLTextViewController.h" +#import "JLScope.h" +#import "JLTokenPattern.h" +#import "Chromatism+Internal.h" + +@interface JLTokenizer () +@property (nonatomic, strong) NSOperationQueue *operationQueue; +@end + +@implementation JLTokenizer + +#pragma mark - Setup + +- (id)init +{ + self = [super init]; + if (self) { + self.operationQueue = [[NSOperationQueue alloc] init]; + self.operationQueue.maxConcurrentOperationCount = 1; + } + return self; +} + +#pragma mark - NSTextStorageDelegate + +- (void)textStorage:(NSTextStorage *)textStorage willProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta +{ + +} + +- (void)textStorage:(NSTextStorage *)textStorage didProcessEditing:(NSTextStorageEditActions)editedMask range:(NSRange)editedRange changeInLength:(NSInteger)delta +{ + if (textStorage.editedMask == NSTextStorageEditedAttributes) return; + [self tokenizeTextStorage:textStorage withScope:[self documentScopeForTokenizingTextStorage:textStorage inRange:editedRange]]; +} + +#pragma mark - NSLayoutManager delegeate + +- (CGFloat)layoutManager:(NSLayoutManager *)layoutManager paragraphSpacingBeforeGlyphAtIndex:(NSUInteger)glyphIndex withProposedLineFragmentRect:(CGRect)rect +{ + return 0; +} + +- (BOOL)layoutManager:(NSLayoutManager *)layoutManager shouldBreakLineByWordBeforeCharacterAtIndex:(NSUInteger)charIndex +{ + unichar character = [layoutManager.textStorage.string characterAtIndex:charIndex]; + if (character == '*') return NO; + return YES; +} + +#pragma mark - UITextViewDelegate + +- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text +{ + if (![text isEqualToString:@"\n"]) return YES; // Something else than return + + // Return has been pressed, start the new line with as many tabs or white spaces as the previous one. + NSString *prefixString = [@"\n" stringByAppendingString:[self prefixStringFromRange:range inTextView:textView]]; + + unichar previousCharacter = [textView.text characterAtIndex:range.location - 1]; + if (self.intendator && [self.intendator respondsToSelector:@selector(indentationActionAfterReplacingTextInRange:replacementText:previousCharacter:textView:)]) { + switch ([self indentationActionAfterReplacingTextInRange:range replacementText:text previousCharacter:previousCharacter textView:textView]) { + case JLIndentationActionIncrease: + prefixString = [prefixString stringByAppendingString:@" "]; + break; + case JLIndentationActionDecrease: + if ([[prefixString substringFromIndex:prefixString.length - 4] isEqualToString:@" "]) { + prefixString = [prefixString substringToIndex:prefixString.length - 4]; + } + else if ([[prefixString substringFromIndex:prefixString.length - 1] isEqualToString:@"\t"]) { + prefixString = [prefixString substringToIndex:prefixString.length - 1]; + } + break; + case JLIndentationActionNone: + break; + } + } + + + [textView replaceRange:[self rangeWithRange:range inTextView:textView] withText:prefixString]; + return NO; +} + + +#pragma mark - Tokenizing + +- (void)refreshTokenizationOfTextStorage:(NSTextStorage *)textStorage; +{ + [self tokenizeTextStorage:textStorage withScope:[self documentScopeForTokenizingTextStorage:textStorage inRange:NSMakeRange(0, textStorage.length)]]; +} + +- (JLScope *)documentScopeForTokenizingTextStorage:(NSTextStorage *)textStorage inRange:(NSRange)range +{ + JLScope *documentScope = [JLScope new]; + JLScope *lineScope = [JLScope new]; + + [self prepareDocumentScope:documentScope]; + [self prepareLineScope:lineScope]; + + [documentScope addSubscope:lineScope]; + + [self clearColorAttributesInRange:range textStorage:textStorage]; + + [documentScope setTextStorage:textStorage]; + [documentScope setSet:[NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, textStorage.length)]]; + [lineScope setSet:[NSMutableIndexSet indexSetWithIndexesInRange:[textStorage.string lineRangeForRange:range]]]; + + return documentScope; +} + +- (void)tokenizeTextStorage:(NSTextStorage *)textStorage withScope:(JLScope *)scope +{ + //[textStorage beginEditing]; + [self.operationQueue addOperations:[[scope recursiveSubscopes] allObjects] waitUntilFinished:YES]; + //[textStorage endEditing]; +} + +#pragma mark - Synchronous Tokenization + +- (void)tokenizeAttributedString:(NSMutableAttributedString *)string +{ + JLScope *scope = [self documentScopeForTokenizingTextStorage:(NSTextStorage *)string inRange:NSMakeRange(0, string.length)]; + [self.operationQueue addOperations:[[scope recursiveSubscopes] allObjects] waitUntilFinished:YES]; +} + +#pragma mark - Setup Token Patterns + +- (void)prepareDocumentScope:(JLScope *)documentScope +{ + +} + +- (void)prepareLineScope:(JLScope *)lineScope +{ + +} + + +#pragma mark - Symbolication + +/* +- (void)symbolicate +{ + [self.scopes[PROJECT_CLASS_NAMES] setPattern:[NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@implementation (\\w+)" captureGroup:1] componentsJoinedByString:@"|"]]]; + [self.scopes[PROJECT_METHOD_NAMES] setPattern:[NSString stringWithFormat:@"\\b(%@)\\b", [[self symbolsWithPattern:@"^@property \\(.*?\\)\\s*\\w+[\\s*]+(\\w+);" captureGroup:1] componentsJoinedByString:@"|"]]]; +} +*/ + +#pragma mark - Helpers + +- (JLTokenPattern *)addToken:(NSString *)type withPattern:(NSString *)pattern andScope:(JLScope *)scope +{ + + NSParameterAssert(type); + NSParameterAssert(pattern); + NSParameterAssert(scope); + + JLTokenPattern *token = [JLTokenPattern token:type withPattern:pattern andScope:scope]; + token.color = self.colors[type]; + + return token; +} + +- (JLTokenPattern *)addToken:(NSString *)type withKeywords:(NSString *)keywords andScope:(JLScope *)scope +{ + NSString *pattern = [NSString stringWithFormat:@"\\b(%@)\\b", [[keywords componentsSeparatedByString:@" "] componentsJoinedByString:@"|"]]; + return [self addToken:type withPattern:pattern andScope:scope]; +} + +- (NSMutableArray *)symbolsWithPattern:(NSString *)pattern captureGroup:(int)group textStorage:(NSTextStorage *)textStorage +{ + NSMutableArray *array = [NSMutableArray array]; + NSError *error = nil; + NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionAnchorsMatchLines error:&error]; + [expression enumerateMatchesInString:textStorage.string options:0 range:NSMakeRange(0, textStorage.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { + [array addObject:[textStorage.string substringWithRange:[result rangeAtIndex:group]]]; + }]; + NSAssert(!error, @"%@",error); + return array; +} + +#pragma mark - Indentation + +- (id )intendator +{ + if (!_intendator) { + _intendator = self; + } + return _intendator; +} + +- (JLIndentationAction)indentationActionAfterReplacingTextInRange:(NSRange)range replacementText:(NSString *)text previousCharacter:(unichar)character textView:(UITextView *)textView; +{ + if (character == '{') { + return JLIndentationActionIncrease; + } else if (character == '}') { + return JLIndentationActionDecrease; + } else { + return JLIndentationActionNone; + } +} + +#pragma mark - Helpers + +- (UITextRange *)rangeWithRange:(NSRange)range inTextView:(UITextView *)textView +{ + UITextPosition *beginning = textView.beginningOfDocument; + UITextPosition *start = [textView positionFromPosition:beginning offset:range.location]; + UITextPosition *stop = [textView positionFromPosition:start offset:range.length]; + + return [textView textRangeFromPosition:start toPosition:stop]; +} + +- (void)clearColorAttributesInRange:(NSRange)range textStorage:(NSTextStorage *)storage; +{ + [storage removeAttribute:NSForegroundColorAttributeName range:range]; + [storage addAttribute:NSForegroundColorAttributeName value:self.colors[JLTokenTypeText] range:range]; +} + +- (NSString *)prefixStringFromRange:(NSRange)range inTextView:(UITextView *)textView +{ + NSRange lineRange = [textView.text lineRangeForRange:range]; + NSRange prefixRange = [textView.text rangeOfString:@"[\\t| ]*" options:NSRegularExpressionSearch range:lineRange]; + return [textView.text substringWithRange:prefixRange]; +} + +@end + + +// +// JLTextViewController.m +// iGitpad +// +// Created by Johannes Lund on 2013-06-13. +// Copyright (c) 2013 Johannes Lund +// +// 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 "JLTextViewController.h" +#import "JLTokenizer.h" +#import "JLTokenizer.h" +#import "JLTextView.h" + +@interface JLTextViewController () +/// Only set from -initWithText: and directly set to nil in -loadView +@property (nonatomic, strong) NSString *defaultText; +@end + +@implementation JLTextViewController + +- (instancetype)initWithText:(NSString *)text +{ + self = [super init]; + if (self) { + _defaultText = text; + } + return self; +} + +- (void)loadView +{ + self.view = self.textView; +} + +- (JLTextView *)textView +{ + if (!_textView) { + JLTextView *textView = [[JLTextView alloc] initWithFrame:CGRectZero]; + textView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + if (self.defaultText) { + textView.text = self.defaultText; + self.defaultText = nil; + } + + [self setTextView:textView]; + } + return _textView; +} +/* +- (JLTokenizer *)tokenizer +{ + return self.textView.syntaxTokenizer; +} +*/ +/* +- (void)viewDidLoad +{ + [super viewDidLoad]; + + self.view.backgroundColor = self.textView.backgroundColor; + self.navigationController.navigationBar.translucent = TRUE; + + [self registerForKeyboardNotifications]; +} +*/ + +/* +- (void)didReceiveMemoryWarning +{/* + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. + */ +} +*/ + +#pragma mark - Content Insets and Keyboard + +// Call this method somewhere in your view controller setup code. +- (void)registerForKeyboardNotifications +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWasShown:) + name:UIKeyboardDidShowNotification object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(keyboardWillBeHidden:) + name:UIKeyboardWillHideNotification object:nil]; + +} + +// Called when the UIKeyboardDidShowNotification is sent. +- (void)keyboardWasShown:(NSNotification *)notification +{ + NSDictionary* info = [notification userInfo]; + UIScrollView *scrollView = self.textView; + CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; + + UIEdgeInsets contentInsets = scrollView.contentInset; + contentInsets.bottom = kbSize.height; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; + + CGPoint point = [self.textView caretRectForPosition:self.textView.selectedTextRange.start].origin; + point.y = MIN(point.y, self.textView.frame.size.height - kbSize.height); + + CGRect aRect = self.view.frame; + aRect.size.height -= kbSize.height; + if (!CGRectContainsPoint(aRect, point) ) { + + CGRect rect = CGRectMake(point.x, point.y, 1, 1); + rect.size.height = kbSize.height; + rect.origin.y += kbSize.height; + [self.textView scrollRectToVisible:rect animated:YES]; + } +} + +// Called when the UIKeyboardWillHideNotification is sent +- (void)keyboardWillBeHidden:(NSNotification *)notification +{ + UIScrollView *scrollView = self.textView; + UIEdgeInsets contentInsets = scrollView.contentInset; + contentInsets.bottom = 0; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; +} + +@end + +// +// JLTextViewController.h +// iGitpad +// +// Created by Johannes Lund on 2013-06-13. +// Copyright (c) 2013 Johannes Lund +// +// 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 + +@class JLTokenizer, JLTextView; + +@interface JLTextViewController : UIViewController + +- (instancetype)initWithText:(NSString *)text; + +@property (nonatomic, strong) IBOutlet JLTextView *textView; + +// Convenience property for self.textView.syntaxTokenizer +@property (nonatomic, weak, readonly) JLTokenizer *tokenizer; +@end +*/ + +#import "helpers.h" +void new_application(lua_State* L, pid_t pid); + +#define hydra_window(L, idx) *((AXUIElementRef*)luaL_checkudata(L, idx, "window")) + +static int window_gc(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + CFRelease(win); + return 0; +} + +static int window_eq(lua_State* L) { + AXUIElementRef winA = hydra_window(L, 1); + AXUIElementRef winB = hydra_window(L, 2); + lua_pushboolean(L, CFEqual(winA, winB)); + return 1; +} + +extern AXError _AXUIElementGetWindow(AXUIElementRef, CGWindowID* out); +NSWindow* hydra_nswindow_for_accessibility_window(AXUIElementRef win) { + CGWindowID winid; + AXError err = _AXUIElementGetWindow(win, &winid); + if (err) return nil; + + for (NSWindow* window in [NSApp windows]) { + if ([window windowNumber] == winid) + return window; + } + + return nil; +} + +void new_window(lua_State* L, AXUIElementRef win) { + AXUIElementRef* winptr = lua_newuserdata(L, sizeof(AXUIElementRef)); + *winptr = win; + + luaL_getmetatable(L, "window"); + lua_setmetatable(L, -2); + + lua_newtable(L); + lua_setuservalue(L, -2); +} + +static AXUIElementRef system_wide_element() { + static AXUIElementRef element; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + element = AXUIElementCreateSystemWide(); + }); + return element; +} + +/// window.focusedwindow() -> window +/// Returns the focused window, or nil. +static int window_focusedwindow(lua_State* L) { + CFTypeRef app; + AXUIElementCopyAttributeValue(system_wide_element(), kAXFocusedApplicationAttribute, &app); + + if (app) { + CFTypeRef win; + AXError result = AXUIElementCopyAttributeValue(app, (CFStringRef)NSAccessibilityFocusedWindowAttribute, &win); + + CFRelease(app); + + if (result == kAXErrorSuccess) { + new_window(L, win); + return 1; + } + } + + lua_pushnil(L); + return 1; +} + +static id get_window_prop(AXUIElementRef win, NSString* propType, id defaultValue) { + CFTypeRef _someProperty; + if (AXUIElementCopyAttributeValue(win, (__bridge CFStringRef)propType, &_someProperty) == kAXErrorSuccess) + return CFBridgingRelease(_someProperty); + + return defaultValue; +} + +static BOOL set_window_prop(AXUIElementRef win, NSString* propType, id value) { + if ([value isKindOfClass:[NSNumber class]]) { + AXError result = AXUIElementSetAttributeValue(win, (__bridge CFStringRef)(propType), (__bridge CFTypeRef)(value)); + if (result == kAXErrorSuccess) + return YES; + } + return NO; +} + +/// window:title() -> string +/// Returns the title of the window (as UTF8). +static int window_title(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + NSString* title = get_window_prop(win, NSAccessibilityTitleAttribute, @""); + lua_pushstring(L, [title UTF8String]); + return 1; +} + +/// window:subrole() -> string +/// Returns the subrole of the window, whatever that means. +static int window_subrole(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + NSString* str = get_window_prop(win, NSAccessibilitySubroleAttribute, @""); + + lua_pushstring(L, [str UTF8String]); + return 1; +} + +/// window:role() -> string +/// Returns the role of the window, whatever that means. +static int window_role(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + NSString* str = get_window_prop(win, NSAccessibilityRoleAttribute, @""); + + lua_pushstring(L, [str UTF8String]); + return 1; +} + +/// window:isstandard() -> bool +/// True if the window's subrole indicates it's 'a standard window'. +static int window_isstandard(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + NSString* subrole = get_window_prop(win, NSAccessibilitySubroleAttribute, @""); + + BOOL is_standard = [subrole isEqualToString: (__bridge NSString*)kAXStandardWindowSubrole]; + lua_pushboolean(L, is_standard); + return 1; +} + +/// window:topleft() -> point +/// The top-left corner of the window in absolute coordinates. +static int window_topleft(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + CFTypeRef positionStorage; + AXError result = AXUIElementCopyAttributeValue(win, (CFStringRef)NSAccessibilityPositionAttribute, &positionStorage); + + CGPoint topLeft; + if (result == kAXErrorSuccess) { + if (!AXValueGetValue(positionStorage, kAXValueCGPointType, (void *)&topLeft)) { +// NSLog(@"could not decode topLeft"); + topLeft = CGPointZero; + } + } + else { +// NSLog(@"could not get window topLeft"); + topLeft = CGPointZero; + } + + if (positionStorage) + CFRelease(positionStorage); + + hydra_pushpoint(L, topLeft); + return 1; +} + +/// window:size() -> size +/// The size of the window. +static int window_size(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + CFTypeRef sizeStorage; + AXError result = AXUIElementCopyAttributeValue(win, (CFStringRef)NSAccessibilitySizeAttribute, &sizeStorage); + + CGSize size; + if (result == kAXErrorSuccess) { + if (!AXValueGetValue(sizeStorage, kAXValueCGSizeType, (void *)&size)) { +// NSLog(@"could not decode topLeft"); + size = CGSizeZero; + } + } + else { +// NSLog(@"could not get window size"); + size = CGSizeZero; + } + + if (sizeStorage) + CFRelease(sizeStorage); + + hydra_pushsize(L, size); + return 1; +} + +/// window:settopleft(point) +/// Moves the window to the given point in absolute coordinate. +static int window_settopleft(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + NSPoint thePoint = hydra_topoint(L, 2); + + CFTypeRef positionStorage = (CFTypeRef)(AXValueCreate(kAXValueCGPointType, (const void *)&thePoint)); + AXUIElementSetAttributeValue(win, (CFStringRef)NSAccessibilityPositionAttribute, positionStorage); + if (positionStorage) + CFRelease(positionStorage); + + return 0; +} + +/// window:setsize(size) +/// Resizes the window. +static int window_setsize(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + NSSize theSize = hydra_tosize(L, 2); + + CFTypeRef sizeStorage = (CFTypeRef)(AXValueCreate(kAXValueCGSizeType, (const void *)&theSize)); + AXUIElementSetAttributeValue(win, (CFStringRef)NSAccessibilitySizeAttribute, sizeStorage); + if (sizeStorage) + CFRelease(sizeStorage); + + return 0; +} + +/// window:close() -> bool +/// Closes the window; returns whether it succeeded. +static int window_close(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + BOOL worked = NO; + AXUIElementRef button = NULL; + + if (AXUIElementCopyAttributeValue(win, kAXCloseButtonAttribute, (CFTypeRef*)&button) != noErr) goto cleanup; + if (AXUIElementPerformAction(button, kAXPressAction) != noErr) goto cleanup; + + worked = YES; + +cleanup: + if (button) CFRelease(button); + + lua_pushboolean(L, worked); + return 1; +} + +/// window:setfullscreen(bool) -> bool +/// Sets whether the window is full screen; returns whether it succeeded. +static int window_setfullscreen(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + CFBooleanRef befullscreen = lua_toboolean(L, 2) ? kCFBooleanTrue : kCFBooleanFalse; + BOOL succeeded = (AXUIElementSetAttributeValue(win, CFSTR("AXFullScreen"), befullscreen) == noErr); + lua_pushboolean(L, succeeded); + return 1; +} + +/// window:isfullscreen() -> bool or nil +/// Returns whether the window is full screen, or nil if asking that question fails. +static int window_isfullscreen(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + id isfullscreen = nil; + CFBooleanRef fullscreen = kCFBooleanFalse; + + if (AXUIElementCopyAttributeValue(win, CFSTR("AXFullScreen"), (CFTypeRef*)&fullscreen) != noErr) goto cleanup; + + isfullscreen = @(CFBooleanGetValue(fullscreen)); + +cleanup: + if (fullscreen) CFRelease(fullscreen); + + if (isfullscreen) + lua_pushboolean(L, [isfullscreen boolValue]); + else + lua_pushnil(L); + + return 1; +} + +/// window:minimize() +/// Minimizes the window. +static int window_minimize(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + set_window_prop(win, NSAccessibilityMinimizedAttribute, @YES); + return 0; +} + +/// window:unminimize() +/// Un-minimizes the window. +static int window_unminimize(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + set_window_prop(win, NSAccessibilityMinimizedAttribute, @NO); + return 0; +} + +/// window:isminimized() -> bool +/// True if the window is currently minimized in the dock. +static int window_isminimized(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + BOOL minimized = [get_window_prop(win, NSAccessibilityMinimizedAttribute, @(NO)) boolValue]; + lua_pushboolean(L, minimized); + return 1; +} + +// private function +// args: [win] +// ret: [pid] +static int window_pid(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + pid_t pid = 0; + if (AXUIElementGetPid(win, &pid) == kAXErrorSuccess) { + lua_pushnumber(L, pid); + return 1; + } + else { + return 0; + } +} + +/// window:application() -> app +/// Returns the app that the window belongs to. +static int window_application(lua_State* L) { + if (window_pid(L)) { + pid_t pid = lua_tonumber(L, -1); + new_application(L, pid); + return 1; + } + else { + return 0; + } +} + +/// window:becomemain() -> bool +/// Make this window the main window of the given application; deos not implicitly focus the app. +static int window_becomemain(lua_State* L) { + AXUIElementRef win = hydra_window(L, 1); + + BOOL success = (AXUIElementSetAttributeValue(win, (CFStringRef)NSAccessibilityMainAttribute, kCFBooleanTrue) == kAXErrorSuccess); + lua_pushboolean(L, success); + return 1; +} + +static int window__orderedwinids(lua_State* L) { + lua_newtable(L); + + CFArrayRef wins = CGWindowListCreate(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); + + for (int i = 0; i < CFArrayGetCount(wins); i++) { + int winid = (int)CFArrayGetValueAtIndex(wins, i); + + lua_pushnumber(L, winid); + lua_rawseti(L, -2, i+1); + } + + CFRelease(wins); + + return 1; +} + +/// window:id() -> number, sometimes nil +/// Returns a unique number identifying this window. +static int window_id(lua_State* L) { + lua_settop(L, 1); + AXUIElementRef win = hydra_window(L, 1); + + lua_getuservalue(L, 1); + + lua_getfield(L, -1, "id"); + if (lua_isnumber(L, -1)) + return 1; + else + lua_pop(L, 1); + + CGWindowID winid; + AXError err = _AXUIElementGetWindow(win, &winid); + if (err) { + lua_pushnil(L); + return 1; + } + + // cache it + lua_pushnumber(L, winid); + lua_setfield(L, -2, "id"); + + lua_pushnumber(L, winid); + return 1; +} + +static const luaL_Reg windowlib[] = { + {"focusedwindow", window_focusedwindow}, + {"_orderedwinids", window__orderedwinids}, + + {"title", window_title}, + {"subrole", window_subrole}, + {"role", window_role}, + {"isstandard", window_isstandard}, + {"topleft", window_topleft}, + {"size", window_size}, + {"settopleft", window_settopleft}, + {"setsize", window_setsize}, + {"minimize", window_minimize}, + {"unminimize", window_unminimize}, + {"isminimized", window_isminimized}, + {"pid", window_pid}, + {"application", window_application}, + {"becomemain", window_becomemain}, + {"id", window_id}, + {"close", window_close}, + {"setfullscreen", window_setfullscreen}, + {"isfullscreen", window_isfullscreen}, + + {NULL, NULL} +}; + +int luaopen_window(lua_State* L) { + luaL_newlib(L, windowlib); + + if (luaL_newmetatable(L, "window")) { + lua_pushvalue(L, -2); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, window_gc); + lua_setfield(L, -2, "__gc"); + + lua_pushcfunction(L, window_eq); + lua_setfield(L, -2, "__eq"); + } + lua_pop(L, 1); + + return 1; +} + + + diff --git a/Chromatism/ChromatismTests/en.lproj/InfoPlist.strings b/Chromatism/ChromatismTests/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28f..0000000 --- a/Chromatism/ChromatismTests/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/ChromatismDemo/ChromatismDemo.xcodeproj/project.pbxproj b/ChromatismDemo/ChromatismDemo.xcodeproj/project.pbxproj deleted file mode 100644 index 36000b9..0000000 --- a/ChromatismDemo/ChromatismDemo.xcodeproj/project.pbxproj +++ /dev/null @@ -1,534 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 3260A16417A88BA9008792E6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3260A16317A88BA9008792E6 /* Foundation.framework */; }; - 3260A16617A88BA9008792E6 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3260A16517A88BA9008792E6 /* CoreGraphics.framework */; }; - 3260A16817A88BA9008792E6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3260A16717A88BA9008792E6 /* UIKit.framework */; }; - 3260A16E17A88BA9008792E6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3260A16C17A88BA9008792E6 /* InfoPlist.strings */; }; - 3260A17017A88BA9008792E6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3260A16F17A88BA9008792E6 /* main.m */; }; - 3260A17417A88BA9008792E6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3260A17317A88BA9008792E6 /* AppDelegate.m */; }; - 3260A17617A88BA9008792E6 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3260A17517A88BA9008792E6 /* Images.xcassets */; }; - 3260A17D17A88BA9008792E6 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3260A17C17A88BA9008792E6 /* XCTest.framework */; }; - 3260A17E17A88BA9008792E6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3260A16317A88BA9008792E6 /* Foundation.framework */; }; - 3260A17F17A88BA9008792E6 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3260A16717A88BA9008792E6 /* UIKit.framework */; }; - 3260A18717A88BA9008792E6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3260A18517A88BA9008792E6 /* InfoPlist.strings */; }; - 3260A18917A88BA9008792E6 /* ChromatismDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3260A18817A88BA9008792E6 /* ChromatismDemoTests.m */; }; - 3260A19D17A88BC8008792E6 /* libChromatism.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3260A19817A88BB8008792E6 /* libChromatism.a */; }; - 3260A1A517A88EF4008792E6 /* demo.txt in Resources */ = {isa = PBXBuildFile; fileRef = 3260A1A417A88EF4008792E6 /* demo.txt */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 3260A18017A88BA9008792E6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3260A15817A88BA9008792E6 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 3260A15F17A88BA9008792E6; - remoteInfo = ChromatismDemo; - }; - 3260A19717A88BB8008792E6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3260A19217A88BB7008792E6 /* Chromatism.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 8F3AB9181781C0BA0023348A; - remoteInfo = Chromatism; - }; - 3260A19917A88BB8008792E6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3260A19217A88BB7008792E6 /* Chromatism.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 8F3AB9281781C0BA0023348A; - remoteInfo = ChromatismTests; - }; - 3260A19B17A88BC4008792E6 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 3260A19217A88BB7008792E6 /* Chromatism.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 8F3AB9171781C0BA0023348A; - remoteInfo = Chromatism; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 3260A16017A88BA9008792E6 /* ChromatismDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ChromatismDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 3260A16317A88BA9008792E6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - 3260A16517A88BA9008792E6 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; - 3260A16717A88BA9008792E6 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - 3260A16B17A88BA9008792E6 /* ChromatismDemo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ChromatismDemo-Info.plist"; sourceTree = ""; }; - 3260A16D17A88BA9008792E6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 3260A16F17A88BA9008792E6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - 3260A17117A88BA9008792E6 /* ChromatismDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ChromatismDemo-Prefix.pch"; sourceTree = ""; }; - 3260A17217A88BA9008792E6 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 3260A17317A88BA9008792E6 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 3260A17517A88BA9008792E6 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 3260A17B17A88BA9008792E6 /* ChromatismDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ChromatismDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3260A17C17A88BA9008792E6 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; - 3260A18417A88BA9008792E6 /* ChromatismDemoTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ChromatismDemoTests-Info.plist"; sourceTree = ""; }; - 3260A18617A88BA9008792E6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 3260A18817A88BA9008792E6 /* ChromatismDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChromatismDemoTests.m; sourceTree = ""; }; - 3260A19217A88BB7008792E6 /* Chromatism.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Chromatism.xcodeproj; path = ../Chromatism/Chromatism.xcodeproj; sourceTree = ""; }; - 3260A1A417A88EF4008792E6 /* demo.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = demo.txt; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 3260A15D17A88BA9008792E6 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3260A19D17A88BC8008792E6 /* libChromatism.a in Frameworks */, - 3260A16617A88BA9008792E6 /* CoreGraphics.framework in Frameworks */, - 3260A16817A88BA9008792E6 /* UIKit.framework in Frameworks */, - 3260A16417A88BA9008792E6 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3260A17817A88BA9008792E6 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 3260A17D17A88BA9008792E6 /* XCTest.framework in Frameworks */, - 3260A17F17A88BA9008792E6 /* UIKit.framework in Frameworks */, - 3260A17E17A88BA9008792E6 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 3260A15717A88BA9008792E6 = { - isa = PBXGroup; - children = ( - 3260A16917A88BA9008792E6 /* ChromatismDemo */, - 3260A18217A88BA9008792E6 /* ChromatismDemoTests */, - 3260A16217A88BA9008792E6 /* Frameworks */, - 3260A16117A88BA9008792E6 /* Products */, - ); - sourceTree = ""; - }; - 3260A16117A88BA9008792E6 /* Products */ = { - isa = PBXGroup; - children = ( - 3260A16017A88BA9008792E6 /* ChromatismDemo.app */, - 3260A17B17A88BA9008792E6 /* ChromatismDemoTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 3260A16217A88BA9008792E6 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 3260A19217A88BB7008792E6 /* Chromatism.xcodeproj */, - 3260A16317A88BA9008792E6 /* Foundation.framework */, - 3260A16517A88BA9008792E6 /* CoreGraphics.framework */, - 3260A16717A88BA9008792E6 /* UIKit.framework */, - 3260A17C17A88BA9008792E6 /* XCTest.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 3260A16917A88BA9008792E6 /* ChromatismDemo */ = { - isa = PBXGroup; - children = ( - 3260A17217A88BA9008792E6 /* AppDelegate.h */, - 3260A17317A88BA9008792E6 /* AppDelegate.m */, - 3260A17517A88BA9008792E6 /* Images.xcassets */, - 3260A16A17A88BA9008792E6 /* Supporting Files */, - ); - path = ChromatismDemo; - sourceTree = ""; - }; - 3260A16A17A88BA9008792E6 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 3260A1A417A88EF4008792E6 /* demo.txt */, - 3260A16B17A88BA9008792E6 /* ChromatismDemo-Info.plist */, - 3260A16C17A88BA9008792E6 /* InfoPlist.strings */, - 3260A16F17A88BA9008792E6 /* main.m */, - 3260A17117A88BA9008792E6 /* ChromatismDemo-Prefix.pch */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 3260A18217A88BA9008792E6 /* ChromatismDemoTests */ = { - isa = PBXGroup; - children = ( - 3260A18817A88BA9008792E6 /* ChromatismDemoTests.m */, - 3260A18317A88BA9008792E6 /* Supporting Files */, - ); - path = ChromatismDemoTests; - sourceTree = ""; - }; - 3260A18317A88BA9008792E6 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 3260A18417A88BA9008792E6 /* ChromatismDemoTests-Info.plist */, - 3260A18517A88BA9008792E6 /* InfoPlist.strings */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 3260A19317A88BB7008792E6 /* Products */ = { - isa = PBXGroup; - children = ( - 3260A19817A88BB8008792E6 /* libChromatism.a */, - 3260A19A17A88BB8008792E6 /* ChromatismTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 3260A15F17A88BA9008792E6 /* ChromatismDemo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3260A18C17A88BA9008792E6 /* Build configuration list for PBXNativeTarget "ChromatismDemo" */; - buildPhases = ( - 3260A15C17A88BA9008792E6 /* Sources */, - 3260A15D17A88BA9008792E6 /* Frameworks */, - 3260A15E17A88BA9008792E6 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 3260A19C17A88BC4008792E6 /* PBXTargetDependency */, - ); - name = ChromatismDemo; - productName = ChromatismDemo; - productReference = 3260A16017A88BA9008792E6 /* ChromatismDemo.app */; - productType = "com.apple.product-type.application"; - }; - 3260A17A17A88BA9008792E6 /* ChromatismDemoTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 3260A18F17A88BA9008792E6 /* Build configuration list for PBXNativeTarget "ChromatismDemoTests" */; - buildPhases = ( - 3260A17717A88BA9008792E6 /* Sources */, - 3260A17817A88BA9008792E6 /* Frameworks */, - 3260A17917A88BA9008792E6 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 3260A18117A88BA9008792E6 /* PBXTargetDependency */, - ); - name = ChromatismDemoTests; - productName = ChromatismDemoTests; - productReference = 3260A17B17A88BA9008792E6 /* ChromatismDemoTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 3260A15817A88BA9008792E6 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0500; - ORGANIZATIONNAME = Anviking; - TargetAttributes = { - 3260A15F17A88BA9008792E6 = { - DevelopmentTeam = XU2559U3TH; - }; - 3260A17A17A88BA9008792E6 = { - TestTargetID = 3260A15F17A88BA9008792E6; - }; - }; - }; - buildConfigurationList = 3260A15B17A88BA9008792E6 /* Build configuration list for PBXProject "ChromatismDemo" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 3260A15717A88BA9008792E6; - productRefGroup = 3260A16117A88BA9008792E6 /* Products */; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 3260A19317A88BB7008792E6 /* Products */; - ProjectRef = 3260A19217A88BB7008792E6 /* Chromatism.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 3260A15F17A88BA9008792E6 /* ChromatismDemo */, - 3260A17A17A88BA9008792E6 /* ChromatismDemoTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - 3260A19817A88BB8008792E6 /* libChromatism.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libChromatism.a; - remoteRef = 3260A19717A88BB8008792E6 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3260A19A17A88BB8008792E6 /* ChromatismTests.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = ChromatismTests.xctest; - remoteRef = 3260A19917A88BB8008792E6 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXResourcesBuildPhase section */ - 3260A15E17A88BA9008792E6 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3260A16E17A88BA9008792E6 /* InfoPlist.strings in Resources */, - 3260A1A517A88EF4008792E6 /* demo.txt in Resources */, - 3260A17617A88BA9008792E6 /* Images.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3260A17917A88BA9008792E6 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3260A18717A88BA9008792E6 /* InfoPlist.strings in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 3260A15C17A88BA9008792E6 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3260A17417A88BA9008792E6 /* AppDelegate.m in Sources */, - 3260A17017A88BA9008792E6 /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 3260A17717A88BA9008792E6 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3260A18917A88BA9008792E6 /* ChromatismDemoTests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 3260A18117A88BA9008792E6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 3260A15F17A88BA9008792E6 /* ChromatismDemo */; - targetProxy = 3260A18017A88BA9008792E6 /* PBXContainerItemProxy */; - }; - 3260A19C17A88BC4008792E6 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = Chromatism; - targetProxy = 3260A19B17A88BC4008792E6 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 3260A16C17A88BA9008792E6 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 3260A16D17A88BA9008792E6 /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; - 3260A18517A88BA9008792E6 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 3260A18617A88BA9008792E6 /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 3260A18A17A88BA9008792E6 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 3260A18B17A88BA9008792E6 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 3260A18D17A88BA9008792E6 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "ChromatismDemo/ChromatismDemo-Prefix.pch"; - HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/../../Headers\""; - INFOPLIST_FILE = "ChromatismDemo/ChromatismDemo-Info.plist"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - WRAPPER_EXTENSION = app; - }; - name = Debug; - }; - 3260A18E17A88BA9008792E6 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "ChromatismDemo/ChromatismDemo-Prefix.pch"; - HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/../../Headers\""; - INFOPLIST_FILE = "ChromatismDemo/ChromatismDemo-Info.plist"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = ""; - WRAPPER_EXTENSION = app; - }; - name = Release; - }; - 3260A19017A88BA9008792E6 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ChromatismDemo.app/ChromatismDemo"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - "$(DEVELOPER_FRAMEWORKS_DIR)", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "ChromatismDemo/ChromatismDemo-Prefix.pch"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = "ChromatismDemoTests/ChromatismDemoTests-Info.plist"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUNDLE_LOADER)"; - WRAPPER_EXTENSION = xctest; - }; - name = Debug; - }; - 3260A19117A88BA9008792E6 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ChromatismDemo.app/ChromatismDemo"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - "$(DEVELOPER_FRAMEWORKS_DIR)", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "ChromatismDemo/ChromatismDemo-Prefix.pch"; - INFOPLIST_FILE = "ChromatismDemoTests/ChromatismDemoTests-Info.plist"; - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUNDLE_LOADER)"; - WRAPPER_EXTENSION = xctest; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 3260A15B17A88BA9008792E6 /* Build configuration list for PBXProject "ChromatismDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3260A18A17A88BA9008792E6 /* Debug */, - 3260A18B17A88BA9008792E6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3260A18C17A88BA9008792E6 /* Build configuration list for PBXNativeTarget "ChromatismDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3260A18D17A88BA9008792E6 /* Debug */, - 3260A18E17A88BA9008792E6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 3260A18F17A88BA9008792E6 /* Build configuration list for PBXNativeTarget "ChromatismDemoTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 3260A19017A88BA9008792E6 /* Debug */, - 3260A19117A88BA9008792E6 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 3260A15817A88BA9008792E6 /* Project object */; -} diff --git a/ChromatismDemo/ChromatismDemo/AppDelegate.h b/ChromatismDemo/ChromatismDemo/AppDelegate.h deleted file mode 100644 index dcc918d..0000000 --- a/ChromatismDemo/ChromatismDemo/AppDelegate.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// AppDelegate.h -// ChromatismDemo -// -// Created by Anviking on 2013-07-31. -// Copyright (c) 2013 Johannes Lund -// -// 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 - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - -@end diff --git a/ChromatismDemo/ChromatismDemo/AppDelegate.m b/ChromatismDemo/ChromatismDemo/AppDelegate.m deleted file mode 100644 index 3c276d4..0000000 --- a/ChromatismDemo/ChromatismDemo/AppDelegate.m +++ /dev/null @@ -1,79 +0,0 @@ -// -// AppDelegate.m -// ChromatismDemo -// -// Created by Anviking on 2013-07-31. -// Copyright (c) 2013 Johannes Lund -// -// 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 "AppDelegate.h" -#import - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - - // Load demo text - NSURL *URL = [[NSBundle mainBundle] URLForResource:@"demo" withExtension:@"txt"]; - NSString *string = [[NSString alloc] initWithData:[NSData dataWithContentsOfURL:URL] encoding:NSUTF8StringEncoding]; - - JLTextViewController *viewController = [[JLTextViewController alloc] initWithText:string]; - viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Resign" style:UIBarButtonItemStylePlain target:viewController.textView action:@selector(resignFirstResponder)]; - UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; - viewController.title = @"Chromatism"; - - [navigationController.navigationBar setBarStyle:UIBarStyleBlack]; - viewController.textView.keyboardAppearance = UIKeyboardAppearanceDark; - - self.window.rootViewController = navigationController; - self.window.backgroundColor = [UIColor whiteColor]; - [self.window makeKeyAndVisible]; - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application -{ - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application -{ - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application -{ - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application -{ - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application -{ - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/ChromatismDemo/ChromatismDemo/ChromatismDemo-Prefix.pch b/ChromatismDemo/ChromatismDemo/ChromatismDemo-Prefix.pch deleted file mode 100644 index 743435c..0000000 --- a/ChromatismDemo/ChromatismDemo/ChromatismDemo-Prefix.pch +++ /dev/null @@ -1,16 +0,0 @@ -// -// Prefix header -// -// The contents of this file are implicitly included at the beginning of every source file. -// - -#import - -#ifndef __IPHONE_3_0 -#warning "This project uses features only available in iOS SDK 3.0 and later." -#endif - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/ChromatismDemo/ChromatismDemo/Images.xcassets/AppIcon.appiconset/Contents.json b/ChromatismDemo/ChromatismDemo/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 91bf9c1..0000000 --- a/ChromatismDemo/ChromatismDemo/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ChromatismDemo/ChromatismDemo/Images.xcassets/LaunchImage.launchimage/Contents.json b/ChromatismDemo/ChromatismDemo/Images.xcassets/LaunchImage.launchimage/Contents.json deleted file mode 100644 index 6f870a4..0000000 --- a/ChromatismDemo/ChromatismDemo/Images.xcassets/LaunchImage.launchimage/Contents.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "images" : [ - { - "orientation" : "portrait", - "idiom" : "iphone", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "iphone", - "subtype" : "retina4", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "1x" - }, - { - "orientation" : "portrait", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - }, - { - "orientation" : "landscape", - "idiom" : "ipad", - "extent" : "full-screen", - "minimum-system-version" : "7.0", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ChromatismDemo/ChromatismDemo/en.lproj/InfoPlist.strings b/ChromatismDemo/ChromatismDemo/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28f..0000000 --- a/ChromatismDemo/ChromatismDemo/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/ChromatismDemo/ChromatismDemo/main.m b/ChromatismDemo/ChromatismDemo/main.m deleted file mode 100644 index 526290a..0000000 --- a/ChromatismDemo/ChromatismDemo/main.m +++ /dev/null @@ -1,34 +0,0 @@ -// -// main.m -// ChromatismDemo -// -// Created by Anviking on 2013-07-31. -// Copyright (c) 2013 Johannes Lund -// -// 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 - -#import "AppDelegate.h" - -int main(int argc, char * argv[]) -{ - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/ChromatismDemo/ChromatismDemoTests/ChromatismDemoTests.m b/ChromatismDemo/ChromatismDemoTests/ChromatismDemoTests.m deleted file mode 100644 index 0ab6965..0000000 --- a/ChromatismDemo/ChromatismDemoTests/ChromatismDemoTests.m +++ /dev/null @@ -1,45 +0,0 @@ -// -// ChromatismDemoTests.m -// ChromatismDemoTests -// -// Created by Anviking on 2013-07-31. -// Copyright (c) 2013 Johannes Lund -// -// 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 - -@interface ChromatismDemoTests : XCTestCase - -@end - -@implementation ChromatismDemoTests - -- (void)setUp -{ - [super setUp]; - // Put setup code here. This method is called before the invocation of each test method in the class. -} - -- (void)tearDown -{ - // Put teardown code here. This method is called after the invocation of each test method in the class. - [super tearDown]; -} - -@end diff --git a/ChromatismDemo/ChromatismDemoTests/en.lproj/InfoPlist.strings b/ChromatismDemo/ChromatismDemoTests/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28f..0000000 --- a/ChromatismDemo/ChromatismDemoTests/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index bd28954..0000000 --- a/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Johannes Lund - -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. diff --git a/README.md b/README.md index 3f57e02..0cea3ff 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,19 @@ Chromatism ========== -This is the beginning of a syntax highlighting `UITextView` for iOS. Currently it only knows about Obj-C. Previously Chromatism used a combination of `CoreText` and `UITableView` for performance, but luckily that is not needed anymore. +iOS Syntax highlightning using Swift built for performance, but still at a very experimental non-reliable state. -**Chromatism is currently unstable, changing quickly and without test-coverage.** +![image](http://i.imgur.com/P1ENCfv.png) -![](http://anviking.com/img/chromatism_black.png) +## New since Swift rewrite: +- JLNestedToken `/* Comment /* Another Comment */ */`. Could possible do great stuff with {}-scope-aware-auto-completion. Needs some more work though. +- Tests – sort of. +- `JLKeywordScope` Optimizes regex patterns for keywords. `(?:He(?:j(?:san|)|llo))` -## License -MIT, see [LICENSE.txt](https://github.com/Anviking/Chromatism/blob/master/LICENSE.txt). If you develop Chromatism further, sharing your improvements are encouraged. - -## How to add Chromatism to your application: - -1. Drag and drop `Chromatism.xcodeproj` to your project. -2. Add `Chromatism` as a target dependency and link to `libChromatism.a` -3. Make sure you have the `-ObjC` flag on the `Other Linker Flags` build setting. -4. Add `"$(BUILT_PRODUCTS_DIR)/../../Headers"` to the `Header Search Paths` build setting. - -## Classes -- `JLTextView` is a textView with a syntaxTokenixer property to a `JLTokenizer` -- `JLTokenizer` is the work horse of Chromatism. It uses scopes and tokenPatterns to appropriately tokenize a textStorage or a string. It is a delegate of `NSTextStorage` and `UITextView`. -- `JLScope` has a `NSMutableIndexSet`-property that corresponds to ranges in the textStorage. Scopes can be arranged in a complex hierarchy, especially since it is a subclass of `NSOperation`. -- `JLTokenPattern` is a subclass of `JLScope`. It has a regex-pattern that in `-perform` searches through the ranges of its parent scope. - - -## Implementing your own syntax highlighting for another language -1. Subclass `JLTokenizer`. -2. Checkout `JLObjectiveCTokenizer` to see what to do next. -3. (Optional) Be awesome and submit a PR. +## Todo +- `JLTokenizingScope` should keep track of additions/deletions of tokens, and JLNestedScope should be able to use that information. Better performance, JLNestedScope don't have to keep track of both hollow and non-hollow indexes anymore, and enables proper "parantesis-flash-blink-thing-handling" in JLTextView. +- Make the code and classes more logical + - How much should `JLLanguage` and `JLDocumentScope` be responsable for? +- Add a symbol-recognicion-scope +- Add more languages diff --git a/SwiftChromatismDemo/SwiftChromatismDemo.xcodeproj/project.pbxproj b/SwiftChromatismDemo/SwiftChromatismDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..a7fc36b --- /dev/null +++ b/SwiftChromatismDemo/SwiftChromatismDemo.xcodeproj/project.pbxproj @@ -0,0 +1,483 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 8F105F1D194D1C8100BF037F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8F105F1C194D1C8100BF037F /* Images.xcassets */; }; + 8F105F29194D1C8100BF037F /* SwiftChromatismDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F105F28194D1C8100BF037F /* SwiftChromatismDemoTests.swift */; }; + 8F26E488195714590055D235 /* objc.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8F26E487195714590055D235 /* objc.txt */; }; + 8F2959EC198C0EE1004B33CB /* swift.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8F2959EB198C0EE1004B33CB /* swift.txt */; }; + 8F729300197DFA920006D903 /* Chromatism.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8F7292FD197DFA880006D903 /* Chromatism.framework */; }; + 8FB10D34197F0B46001A83B1 /* objc.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8F26E487195714590055D235 /* objc.txt */; }; + 8FCDC0031979EE7F00F4B3EC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F105F1A194D1C8100BF037F /* AppDelegate.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 8F105F23194D1C8100BF037F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F105F0D194D1C8100BF037F /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8F105F14194D1C8100BF037F; + remoteInfo = SwiftChromatismDemo; + }; + 8F7292FC197DFA880006D903 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F7292F7197DFA880006D903 /* Chromatism.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 8FBFC16F19738B0400F75A76; + remoteInfo = Chromatism; + }; + 8F7292FE197DFA880006D903 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F7292F7197DFA880006D903 /* Chromatism.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 8FBFC17A19738B0400F75A76; + remoteInfo = ChromatismTests; + }; + 8F72932E197DFB200006D903 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8F105F0D194D1C8100BF037F /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8F105F14194D1C8100BF037F; + remoteInfo = SwiftChromatismDemo; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8F729324197DFB160006D903 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 8F105F15194D1C8100BF037F /* SwiftChromatismDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftChromatismDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8F105F19194D1C8100BF037F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8F105F1A194D1C8100BF037F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 8F105F1C194D1C8100BF037F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 8F105F22194D1C8100BF037F /* SwiftChromatismDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftChromatismDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 8F105F27194D1C8100BF037F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 8F105F28194D1C8100BF037F /* SwiftChromatismDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftChromatismDemoTests.swift; sourceTree = ""; }; + 8F26E487195714590055D235 /* objc.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = objc.txt; sourceTree = ""; }; + 8F2959EB198C0EE1004B33CB /* swift.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = swift.txt; sourceTree = ""; }; + 8F7292F7197DFA880006D903 /* Chromatism.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Chromatism.xcodeproj; path = ../../Chromatism/Chromatism.xcodeproj; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8F105F12194D1C8100BF037F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8F729300197DFA920006D903 /* Chromatism.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8F105F1F194D1C8100BF037F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 8F105F0C194D1C8100BF037F = { + isa = PBXGroup; + children = ( + 8F105F17194D1C8100BF037F /* SwiftChromatismDemo */, + 8F105F25194D1C8100BF037F /* SwiftChromatismDemoTests */, + 8F105F16194D1C8100BF037F /* Products */, + ); + sourceTree = ""; + }; + 8F105F16194D1C8100BF037F /* Products */ = { + isa = PBXGroup; + children = ( + 8F105F15194D1C8100BF037F /* SwiftChromatismDemo.app */, + 8F105F22194D1C8100BF037F /* SwiftChromatismDemoTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 8F105F17194D1C8100BF037F /* SwiftChromatismDemo */ = { + isa = PBXGroup; + children = ( + 8F105F1A194D1C8100BF037F /* AppDelegate.swift */, + 8F105F1C194D1C8100BF037F /* Images.xcassets */, + 8F105F18194D1C8100BF037F /* Supporting Files */, + ); + path = SwiftChromatismDemo; + sourceTree = ""; + }; + 8F105F18194D1C8100BF037F /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 8F26E487195714590055D235 /* objc.txt */, + 8F2959EB198C0EE1004B33CB /* swift.txt */, + 8F105F19194D1C8100BF037F /* Info.plist */, + 8F7292F7197DFA880006D903 /* Chromatism.xcodeproj */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 8F105F25194D1C8100BF037F /* SwiftChromatismDemoTests */ = { + isa = PBXGroup; + children = ( + 8F105F28194D1C8100BF037F /* SwiftChromatismDemoTests.swift */, + 8F105F26194D1C8100BF037F /* Supporting Files */, + ); + path = SwiftChromatismDemoTests; + sourceTree = ""; + }; + 8F105F26194D1C8100BF037F /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 8F105F27194D1C8100BF037F /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 8F7292F8197DFA880006D903 /* Products */ = { + isa = PBXGroup; + children = ( + 8F7292FD197DFA880006D903 /* Chromatism.framework */, + 8F7292FF197DFA880006D903 /* ChromatismTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8F105F14194D1C8100BF037F /* SwiftChromatismDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8F105F2C194D1C8100BF037F /* Build configuration list for PBXNativeTarget "SwiftChromatismDemo" */; + buildPhases = ( + 8F105F11194D1C8100BF037F /* Sources */, + 8F105F12194D1C8100BF037F /* Frameworks */, + 8F105F13194D1C8100BF037F /* Resources */, + 8F729324197DFB160006D903 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SwiftChromatismDemo; + productName = SwiftChromatismDemo; + productReference = 8F105F15194D1C8100BF037F /* SwiftChromatismDemo.app */; + productType = "com.apple.product-type.application"; + }; + 8F105F21194D1C8100BF037F /* SwiftChromatismDemoTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8F105F2F194D1C8100BF037F /* Build configuration list for PBXNativeTarget "SwiftChromatismDemoTests" */; + buildPhases = ( + 8F105F1E194D1C8100BF037F /* Sources */, + 8F105F1F194D1C8100BF037F /* Frameworks */, + 8F105F20194D1C8100BF037F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 8F105F24194D1C8100BF037F /* PBXTargetDependency */, + 8F72932F197DFB200006D903 /* PBXTargetDependency */, + ); + name = SwiftChromatismDemoTests; + productName = SwiftChromatismDemoTests; + productReference = 8F105F22194D1C8100BF037F /* SwiftChromatismDemoTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8F105F0D194D1C8100BF037F /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0600; + ORGANIZATIONNAME = anviking; + TargetAttributes = { + 8F105F14194D1C8100BF037F = { + CreatedOnToolsVersion = 6.0; + }; + 8F105F21194D1C8100BF037F = { + CreatedOnToolsVersion = 6.0; + TestTargetID = 8F105F14194D1C8100BF037F; + }; + }; + }; + buildConfigurationList = 8F105F10194D1C8100BF037F /* Build configuration list for PBXProject "SwiftChromatismDemo" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 8F105F0C194D1C8100BF037F; + productRefGroup = 8F105F16194D1C8100BF037F /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 8F7292F8197DFA880006D903 /* Products */; + ProjectRef = 8F7292F7197DFA880006D903 /* Chromatism.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 8F105F14194D1C8100BF037F /* SwiftChromatismDemo */, + 8F105F21194D1C8100BF037F /* SwiftChromatismDemoTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 8F7292FD197DFA880006D903 /* Chromatism.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Chromatism.framework; + remoteRef = 8F7292FC197DFA880006D903 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 8F7292FF197DFA880006D903 /* ChromatismTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = ChromatismTests.xctest; + remoteRef = 8F7292FE197DFA880006D903 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 8F105F13194D1C8100BF037F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8F105F1D194D1C8100BF037F /* Images.xcassets in Resources */, + 8F26E488195714590055D235 /* objc.txt in Resources */, + 8F2959EC198C0EE1004B33CB /* swift.txt in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8F105F20194D1C8100BF037F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8FB10D34197F0B46001A83B1 /* objc.txt in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 8F105F11194D1C8100BF037F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8FCDC0031979EE7F00F4B3EC /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8F105F1E194D1C8100BF037F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 8F105F29194D1C8100BF037F /* SwiftChromatismDemoTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 8F105F24194D1C8100BF037F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8F105F14194D1C8100BF037F /* SwiftChromatismDemo */; + targetProxy = 8F105F23194D1C8100BF037F /* PBXContainerItemProxy */; + }; + 8F72932F197DFB200006D903 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8F105F14194D1C8100BF037F /* SwiftChromatismDemo */; + targetProxy = 8F72932E197DFB200006D903 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 8F105F2A194D1C8100BF037F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 8F105F2B194D1C8100BF037F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + METAL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 8F105F2D194D1C8100BF037F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + DEFINES_MODULE = YES; + INFOPLIST_FILE = SwiftChromatismDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 8F105F2E194D1C8100BF037F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + DEFINES_MODULE = YES; + INFOPLIST_FILE = SwiftChromatismDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 8F105F30194D1C8100BF037F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SwiftChromatismDemo.app/SwiftChromatismDemo"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = SwiftChromatismDemoTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + }; + name = Debug; + }; + 8F105F31194D1C8100BF037F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/SwiftChromatismDemo.app/SwiftChromatismDemo"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = SwiftChromatismDemoTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 8F105F10194D1C8100BF037F /* Build configuration list for PBXProject "SwiftChromatismDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8F105F2A194D1C8100BF037F /* Debug */, + 8F105F2B194D1C8100BF037F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8F105F2C194D1C8100BF037F /* Build configuration list for PBXNativeTarget "SwiftChromatismDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8F105F2D194D1C8100BF037F /* Debug */, + 8F105F2E194D1C8100BF037F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8F105F2F194D1C8100BF037F /* Build configuration list for PBXNativeTarget "SwiftChromatismDemoTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8F105F30194D1C8100BF037F /* Debug */, + 8F105F31194D1C8100BF037F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8F105F0D194D1C8100BF037F /* Project object */; +} diff --git a/SwiftChromatismDemo/SwiftChromatismDemo/AppDelegate.swift b/SwiftChromatismDemo/SwiftChromatismDemo/AppDelegate.swift new file mode 100644 index 0000000..9c6f18f --- /dev/null +++ b/SwiftChromatismDemo/SwiftChromatismDemo/AppDelegate.swift @@ -0,0 +1,61 @@ +// +// AppDelegate.swift +// SwiftChromatismDemo +// +// Created by Johannes Lund on 2014-06-15. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit +import Chromatism + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool { + self.window = UIWindow(frame: UIScreen.mainScreen().bounds) + // Override point for customization after application launch. + + // Load demo text + let url = NSBundle.mainBundle().URLForResource("swift", withExtension: "txt"); + let string = NSString(contentsOfURL: url, encoding: NSUTF8StringEncoding, error: nil) + + let viewController = JLTextViewController(text: string, language: .Swift, theme: .Default) + + viewController.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Resign", style: .Plain, target: viewController.textView, action:"resignFirstResponder") + + let navigationController = UINavigationController(rootViewController: viewController) + viewController.title = "Chromatism"; + + self.window!.rootViewController = navigationController + self.window!.makeKeyAndVisible() + return true + } + + func applicationWillResignActive(application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(application: UIApplication) { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} \ No newline at end of file diff --git a/SwiftChromatismDemo/SwiftChromatismDemo/Images.xcassets/AppIcon.appiconset/Contents.json b/SwiftChromatismDemo/SwiftChromatismDemo/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a396706 --- /dev/null +++ b/SwiftChromatismDemo/SwiftChromatismDemo/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/SwiftChromatismDemo/SwiftChromatismDemo/Images.xcassets/LaunchImage.launchimage/Contents.json b/SwiftChromatismDemo/SwiftChromatismDemo/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000..c79ebd3 --- /dev/null +++ b/SwiftChromatismDemo/SwiftChromatismDemo/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "subtype" : "retina4", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ChromatismDemo/ChromatismDemo/ChromatismDemo-Info.plist b/SwiftChromatismDemo/SwiftChromatismDemo/Info.plist similarity index 54% rename from ChromatismDemo/ChromatismDemo/ChromatismDemo-Info.plist rename to SwiftChromatismDemo/SwiftChromatismDemo/Info.plist index 79ce451..f7dcd98 100644 --- a/ChromatismDemo/ChromatismDemo/ChromatismDemo-Info.plist +++ b/SwiftChromatismDemo/SwiftChromatismDemo/Info.plist @@ -4,12 +4,10 @@ CFBundleDevelopmentRegion en - CFBundleDisplayName - ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.anviking.${PRODUCT_NAME:rfc1034identifier} + anviking.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -21,25 +19,12 @@ CFBundleSignature ???? CFBundleVersion - 1.0 + 1 LSRequiresIPhoneOS UIRequiredDeviceCapabilities armv7 - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - diff --git a/ChromatismDemo/ChromatismDemo/demo.txt b/SwiftChromatismDemo/SwiftChromatismDemo/objc.txt similarity index 100% rename from ChromatismDemo/ChromatismDemo/demo.txt rename to SwiftChromatismDemo/SwiftChromatismDemo/objc.txt diff --git a/SwiftChromatismDemo/SwiftChromatismDemo/swift.txt b/SwiftChromatismDemo/SwiftChromatismDemo/swift.txt new file mode 100644 index 0000000..ef477ca --- /dev/null +++ b/SwiftChromatismDemo/SwiftChromatismDemo/swift.txt @@ -0,0 +1,76 @@ +// +// JLTextViewController.swift +// Chromatism +// +// Created by Johannes Lund on 2014-07-18. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import UIKit + +public class JLTextViewController: UIViewController { + + public var textView: JLTextView + + public required init(text: String, language: JLLanguageType, theme: JLColorTheme) { + textView = JLTextView(language: language, theme: theme) + textView.text = text + super.init(nibName: nil, bundle: nil) + registerForKeyboardNotifications() + } + + deinit { + unregisterForKeyboardNotifications() + } + + override public func loadView() { + view = textView + } + + // MARK: Content Insets and Keyboard + + func registerForKeyboardNotifications() + { + NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil) + NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil) + } + + func unregisterForKeyboardNotifications() { + NSNotificationCenter.defaultCenter().removeObserver(self) + } + + // Called when the UIKeyboardDidShowNotification is sent. + func keyboardWasShown(notification: NSNotification) { + let info = notification.userInfo + let scrollView = self.textView + let kbSize = (info[UIKeyboardFrameBeginUserInfoKey] as NSValue).CGRectValue().size; + + var contentInsets = scrollView.contentInset; + contentInsets.bottom = kbSize.height; + scrollView.contentInset = contentInsets; + scrollView.scrollIndicatorInsets = contentInsets; + + var point = textView.caretRectForPosition(textView.selectedTextRange.start).origin; + point.y = min(point.y, self.textView.frame.size.height - kbSize.height); + + var aRect = self.view.frame; + aRect.size.height -= kbSize.height; + if (!CGRectContainsPoint(aRect, point) ) { + + var rect = CGRectMake(point.x, point.y, 1, 1) + rect.size.height = kbSize.height + rect.origin.y += kbSize.height + textView.scrollRectToVisible(rect, animated: true) + } + } + + // Called when the UIKeyboardWillHideNotification is sent + func keyboardWillBeHidden(notification: NSNotification) { + var contentInsets = textView.contentInset; + contentInsets.bottom = 0; + textView.contentInset = contentInsets; + textView.scrollIndicatorInsets = contentInsets; + textView.contentInset = contentInsets; + textView.scrollIndicatorInsets = contentInsets; + } +} diff --git a/ChromatismDemo/ChromatismDemoTests/ChromatismDemoTests-Info.plist b/SwiftChromatismDemo/SwiftChromatismDemoTests/Info.plist similarity index 83% rename from ChromatismDemo/ChromatismDemoTests/ChromatismDemoTests-Info.plist rename to SwiftChromatismDemo/SwiftChromatismDemoTests/Info.plist index 614d82a..592dae7 100644 --- a/ChromatismDemo/ChromatismDemoTests/ChromatismDemoTests-Info.plist +++ b/SwiftChromatismDemo/SwiftChromatismDemoTests/Info.plist @@ -7,9 +7,11 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.anviking.${PRODUCT_NAME:rfc1034identifier} + anviking.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 + CFBundleName + ${PRODUCT_NAME} CFBundlePackageType BNDL CFBundleShortVersionString diff --git a/SwiftChromatismDemo/SwiftChromatismDemoTests/SwiftChromatismDemoTests.swift b/SwiftChromatismDemo/SwiftChromatismDemoTests/SwiftChromatismDemoTests.swift new file mode 100644 index 0000000..9f0204e --- /dev/null +++ b/SwiftChromatismDemo/SwiftChromatismDemoTests/SwiftChromatismDemoTests.swift @@ -0,0 +1,35 @@ +// +// SwiftChromatismDemoTests.swift +// SwiftChromatismDemoTests +// +// Created by Johannes Lund on 2014-06-15. +// Copyright (c) 2014 anviking. All rights reserved. +// + +import XCTest + +class SwiftChromatismDemoTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testExample() { + // This is an example of a functional test case. + XCTAssert(true, "Pass") + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measureBlock() { + // Put the code you want to measure the time of here. + } + } + +}