mirror of
https://github.com/qvacua/vimr.git
synced 2024-12-25 06:43:24 +03:00
GH-264 Add file items related files and restructure the project a bit
This commit is contained in:
parent
308727a65a
commit
d15ee6a2fe
@ -7,11 +7,32 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
1929B0E0C3BC59F52713D5A2 /* FoundationCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */; };
|
||||||
|
1929B10DD8CD7EE0B8BE529F /* Scorer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9D510177918080BE39B /* Scorer.swift */; };
|
||||||
1929B165820D7177743B537A /* Component.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B39DA7AC4A9B62D7CD39 /* Component.swift */; };
|
1929B165820D7177743B537A /* Component.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B39DA7AC4A9B62D7CD39 /* Component.swift */; };
|
||||||
1929B1E05C116514C1D3A384 /* CocoaCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B5C3F2F1CA4113DABFFD /* CocoaCategories.m */; };
|
1929B1E05C116514C1D3A384 /* CocoaCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B5C3F2F1CA4113DABFFD /* CocoaCategories.m */; };
|
||||||
|
1929B2ADD407219BADBD5A70 /* CwlUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B0DD7AE34C049D26DA8C /* CwlUtils.swift */; };
|
||||||
|
1929B2B6F571129EB8D231C5 /* CwlUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B0DD7AE34C049D26DA8C /* CwlUtils.swift */; };
|
||||||
|
1929B2E1A64297B8E05BB64A /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA8AC40B901B20F20B71 /* FileUtils.swift */; };
|
||||||
|
1929B3BF1DB87B57559DC27D /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BEEB33113B0E33C3830F /* Matcher.swift */; };
|
||||||
|
1929B3F5743967125F357C9F /* Matcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BEEB33113B0E33C3830F /* Matcher.swift */; };
|
||||||
|
1929B43FBA7A31F39D294CD0 /* FileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7CB4863F80230C32D3C /* FileItem.swift */; };
|
||||||
|
1929B462CD4935AFF6D69457 /* FileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7CB4863F80230C32D3C /* FileItem.swift */; };
|
||||||
|
1929B4D3A4429651C2AF55E5 /* FoundationCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */; };
|
||||||
|
1929B53876E6952D378C2B30 /* ScoredFileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BDF9EBAF1D9D44399045 /* ScoredFileItem.swift */; };
|
||||||
|
1929B6388EAF16C190B82955 /* FileItemIgnorePattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B69499B2569793350CEC /* FileItemIgnorePattern.swift */; };
|
||||||
|
1929B63CD9CBB9C122BD99A5 /* ScoredFileItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BDF9EBAF1D9D44399045 /* ScoredFileItem.swift */; };
|
||||||
|
1929B67DA3EB21A631EF1DBB /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA8AC40B901B20F20B71 /* FileUtils.swift */; };
|
||||||
1929B728262BAA14FC93F6AC /* NeoVimView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BF00B466B40629C2AABE /* NeoVimView.swift */; };
|
1929B728262BAA14FC93F6AC /* NeoVimView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BF00B466B40629C2AABE /* NeoVimView.swift */; };
|
||||||
|
1929B73E5EC0B108B83F82EB /* FileItemService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B3A98687DF171307AAC8 /* FileItemService.swift */; };
|
||||||
|
1929B741C4E58EEDAF901353 /* FileItemIgnorePattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B69499B2569793350CEC /* FileItemIgnorePattern.swift */; };
|
||||||
|
1929B7A2F2B423AA9740FD45 /* FileUtilsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B5D977261F1EBFA9E8F1 /* FileUtilsTest.swift */; };
|
||||||
|
1929B7C981A0EFCC8D631E3F /* FileItemService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B3A98687DF171307AAC8 /* FileItemService.swift */; };
|
||||||
1929B93DBAD09835E428F610 /* PrefPane.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB251F74BEFC82CEEF84 /* PrefPane.swift */; };
|
1929B93DBAD09835E428F610 /* PrefPane.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB251F74BEFC82CEEF84 /* PrefPane.swift */; };
|
||||||
|
1929BD3F9E609BFADB27584B /* Scorer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9D510177918080BE39B /* Scorer.swift */; };
|
||||||
|
1929BD4CA2204E061A86A140 /* MatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BC19C1BC19246AFF1621 /* MatcherTests.swift */; };
|
||||||
1929BEB90DCDAF7A2B68C886 /* ColorUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA6128BFDD54CA92F46E /* ColorUtils.swift */; };
|
1929BEB90DCDAF7A2B68C886 /* ColorUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA6128BFDD54CA92F46E /* ColorUtils.swift */; };
|
||||||
|
1929BEFEABA0448306CDB6D4 /* FileItemIgnorePatternTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BBC84557C8351EC6183E /* FileItemIgnorePatternTest.swift */; };
|
||||||
1929BF81A40B4154D3EA33CE /* server_ui.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B93013228985F509C8F6 /* server_ui.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
1929BF81A40B4154D3EA33CE /* server_ui.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B93013228985F509C8F6 /* server_ui.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||||
4B029F1A1D45E349004EE0D3 /* PrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B029F1C1D45E349004EE0D3 /* PrefWindow.xib */; };
|
4B029F1A1D45E349004EE0D3 /* PrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B029F1C1D45E349004EE0D3 /* PrefWindow.xib */; };
|
||||||
4B0BCC941D70320C00D3CE65 /* Logger.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B0BCC931D70320C00D3CE65 /* Logger.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
4B0BCC941D70320C00D3CE65 /* Logger.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B0BCC931D70320C00D3CE65 /* Logger.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||||
@ -41,7 +62,7 @@
|
|||||||
4B56F29D1D29926600C1F92E /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B56F29B1D29926600C1F92E /* Nimble.framework */; };
|
4B56F29D1D29926600C1F92E /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B56F29B1D29926600C1F92E /* Nimble.framework */; };
|
||||||
4B570DC21D303CAF006EDC21 /* NeoVimAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B570DC01D303CAF006EDC21 /* NeoVimAgent.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
4B570DC21D303CAF006EDC21 /* NeoVimAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B570DC01D303CAF006EDC21 /* NeoVimAgent.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
4B570DC31D303CAF006EDC21 /* NeoVimAgent.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B570DC11D303CAF006EDC21 /* NeoVimAgent.m */; };
|
4B570DC31D303CAF006EDC21 /* NeoVimAgent.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B570DC11D303CAF006EDC21 /* NeoVimAgent.m */; };
|
||||||
4B6A70941D60E04200E12030 /* CocoaExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70931D60E04200E12030 /* CocoaExtensions.swift */; };
|
4B6A70941D60E04200E12030 /* AppKitCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70931D60E04200E12030 /* AppKitCommons.swift */; };
|
||||||
4B6A70961D6100E300E12030 /* SwiftCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70951D6100E300E12030 /* SwiftCommons.swift */; };
|
4B6A70961D6100E300E12030 /* SwiftCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B6A70951D6100E300E12030 /* SwiftCommons.swift */; };
|
||||||
4B6A70991D65058A00E12030 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B56F29B1D29926600C1F92E /* Nimble.framework */; };
|
4B6A70991D65058A00E12030 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B56F29B1D29926600C1F92E /* Nimble.framework */; };
|
||||||
4B6A709C1D6507A000E12030 /* Nimble.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B56F29B1D29926600C1F92E /* Nimble.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
4B6A709C1D6507A000E12030 /* Nimble.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B56F29B1D29926600C1F92E /* Nimble.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
@ -68,6 +89,10 @@
|
|||||||
4BDF50081D7607BF00D8FBC3 /* EonilFileSystemEvents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDF50071D7607BF00D8FBC3 /* EonilFileSystemEvents.framework */; };
|
4BDF50081D7607BF00D8FBC3 /* EonilFileSystemEvents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDF50071D7607BF00D8FBC3 /* EonilFileSystemEvents.framework */; };
|
||||||
4BDF50091D7607BF00D8FBC3 /* EonilFileSystemEvents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDF50071D7607BF00D8FBC3 /* EonilFileSystemEvents.framework */; };
|
4BDF50091D7607BF00D8FBC3 /* EonilFileSystemEvents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDF50071D7607BF00D8FBC3 /* EonilFileSystemEvents.framework */; };
|
||||||
4BDF500A1D7607C600D8FBC3 /* EonilFileSystemEvents.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BDF50071D7607BF00D8FBC3 /* EonilFileSystemEvents.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
4BDF500A1D7607C600D8FBC3 /* EonilFileSystemEvents.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BDF50071D7607BF00D8FBC3 /* EonilFileSystemEvents.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
4BDF500C1D760A3500D8FBC3 /* FileUtilsTest in Resources */ = {isa = PBXBuildFile; fileRef = 4BDF500B1D760A3500D8FBC3 /* FileUtilsTest */; };
|
||||||
|
4BDF500D1D760A6D00D8FBC3 /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B2A2BE31D0225800074CE9A /* RxSwift.framework */; };
|
||||||
|
4BDF500E1D760A7500D8FBC3 /* RxSwift.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B2A2BE31D0225800074CE9A /* RxSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
4BDF50121D760B7200D8FBC3 /* EonilFileSystemEvents.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4BDF50071D7607BF00D8FBC3 /* EonilFileSystemEvents.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
4BDF641C1D0887C100D47E1D /* TextDrawer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BDF641A1D0887C100D47E1D /* TextDrawer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
4BDF641C1D0887C100D47E1D /* TextDrawer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BDF641A1D0887C100D47E1D /* TextDrawer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
4BDF641D1D0887C100D47E1D /* TextDrawer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BDF641B1D0887C100D47E1D /* TextDrawer.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
4BDF641D1D0887C100D47E1D /* TextDrawer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BDF641B1D0887C100D47E1D /* TextDrawer.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||||
4BDF64241D08CAB000D47E1D /* MMCoreTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BDF64221D08CAB000D47E1D /* MMCoreTextView.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
4BDF64241D08CAB000D47E1D /* MMCoreTextView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BDF64221D08CAB000D47E1D /* MMCoreTextView.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||||
@ -119,6 +144,7 @@
|
|||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 10;
|
dstSubfolderSpec = 10;
|
||||||
files = (
|
files = (
|
||||||
|
4BDF50121D760B7200D8FBC3 /* EonilFileSystemEvents.framework in Embed Frameworks */,
|
||||||
4B2A2BFF1D0351810074CE9A /* SwiftNeoVim.framework in Embed Frameworks */,
|
4B2A2BFF1D0351810074CE9A /* SwiftNeoVim.framework in Embed Frameworks */,
|
||||||
4B2A2BEF1D02261F0074CE9A /* RxSwift.framework in Embed Frameworks */,
|
4B2A2BEF1D02261F0074CE9A /* RxSwift.framework in Embed Frameworks */,
|
||||||
4B401B161D0454E900D99EDC /* PureLayout.framework in Embed Frameworks */,
|
4B401B161D0454E900D99EDC /* PureLayout.framework in Embed Frameworks */,
|
||||||
@ -133,6 +159,7 @@
|
|||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 10;
|
dstSubfolderSpec = 10;
|
||||||
files = (
|
files = (
|
||||||
|
4BDF500E1D760A7500D8FBC3 /* RxSwift.framework in CopyFiles */,
|
||||||
4BDF500A1D7607C600D8FBC3 /* EonilFileSystemEvents.framework in CopyFiles */,
|
4BDF500A1D7607C600D8FBC3 /* EonilFileSystemEvents.framework in CopyFiles */,
|
||||||
4B6A709C1D6507A000E12030 /* Nimble.framework in CopyFiles */,
|
4B6A709C1D6507A000E12030 /* Nimble.framework in CopyFiles */,
|
||||||
);
|
);
|
||||||
@ -171,14 +198,26 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
1929B0DD7AE34C049D26DA8C /* CwlUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CwlUtils.swift; sourceTree = "<group>"; };
|
||||||
1929B15B7EDC9B0F40E5E95C /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logging.h; sourceTree = "<group>"; };
|
1929B15B7EDC9B0F40E5E95C /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logging.h; sourceTree = "<group>"; };
|
||||||
1929B1A51F076E088EF4CCA4 /* server_globals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = server_globals.h; sourceTree = "<group>"; };
|
1929B1A51F076E088EF4CCA4 /* server_globals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = server_globals.h; sourceTree = "<group>"; };
|
||||||
1929B39DA7AC4A9B62D7CD39 /* Component.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Component.swift; sourceTree = "<group>"; };
|
1929B39DA7AC4A9B62D7CD39 /* Component.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Component.swift; sourceTree = "<group>"; };
|
||||||
|
1929B3A98687DF171307AAC8 /* FileItemService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileItemService.swift; sourceTree = "<group>"; };
|
||||||
1929B5C3F2F1CA4113DABFFD /* CocoaCategories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CocoaCategories.m; sourceTree = "<group>"; };
|
1929B5C3F2F1CA4113DABFFD /* CocoaCategories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CocoaCategories.m; sourceTree = "<group>"; };
|
||||||
|
1929B5D977261F1EBFA9E8F1 /* FileUtilsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileUtilsTest.swift; sourceTree = "<group>"; };
|
||||||
|
1929B69499B2569793350CEC /* FileItemIgnorePattern.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileItemIgnorePattern.swift; sourceTree = "<group>"; };
|
||||||
|
1929B7CB4863F80230C32D3C /* FileItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileItem.swift; sourceTree = "<group>"; };
|
||||||
1929B93013228985F509C8F6 /* server_ui.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = server_ui.m; sourceTree = "<group>"; };
|
1929B93013228985F509C8F6 /* server_ui.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = server_ui.m; sourceTree = "<group>"; };
|
||||||
|
1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationCommons.swift; sourceTree = "<group>"; };
|
||||||
|
1929B9D510177918080BE39B /* Scorer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scorer.swift; sourceTree = "<group>"; };
|
||||||
1929BA6128BFDD54CA92F46E /* ColorUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorUtils.swift; sourceTree = "<group>"; };
|
1929BA6128BFDD54CA92F46E /* ColorUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorUtils.swift; sourceTree = "<group>"; };
|
||||||
|
1929BA8AC40B901B20F20B71 /* FileUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = "<group>"; };
|
||||||
1929BB251F74BEFC82CEEF84 /* PrefPane.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefPane.swift; sourceTree = "<group>"; };
|
1929BB251F74BEFC82CEEF84 /* PrefPane.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrefPane.swift; sourceTree = "<group>"; };
|
||||||
|
1929BBC84557C8351EC6183E /* FileItemIgnorePatternTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileItemIgnorePatternTest.swift; sourceTree = "<group>"; };
|
||||||
|
1929BC19C1BC19246AFF1621 /* MatcherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MatcherTests.swift; sourceTree = "<group>"; };
|
||||||
|
1929BDF9EBAF1D9D44399045 /* ScoredFileItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScoredFileItem.swift; sourceTree = "<group>"; };
|
||||||
1929BE69CF9AB1A10D0DD4F2 /* CocoaCategories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CocoaCategories.h; sourceTree = "<group>"; };
|
1929BE69CF9AB1A10D0DD4F2 /* CocoaCategories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CocoaCategories.h; sourceTree = "<group>"; };
|
||||||
|
1929BEEB33113B0E33C3830F /* Matcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Matcher.swift; sourceTree = "<group>"; };
|
||||||
1929BF00B466B40629C2AABE /* NeoVimView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeoVimView.swift; sourceTree = "<group>"; };
|
1929BF00B466B40629C2AABE /* NeoVimView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeoVimView.swift; sourceTree = "<group>"; };
|
||||||
4B029F1B1D45E349004EE0D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PrefWindow.xib; sourceTree = "<group>"; };
|
4B029F1B1D45E349004EE0D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PrefWindow.xib; sourceTree = "<group>"; };
|
||||||
4B0BCC931D70320C00D3CE65 /* Logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logger.h; path = VimR/Logger.h; sourceTree = SOURCE_ROOT; };
|
4B0BCC931D70320C00D3CE65 /* Logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logger.h; path = VimR/Logger.h; sourceTree = SOURCE_ROOT; };
|
||||||
@ -208,7 +247,7 @@
|
|||||||
4B56F29B1D29926600C1F92E /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = Carthage/Build/Mac/Nimble.framework; sourceTree = SOURCE_ROOT; };
|
4B56F29B1D29926600C1F92E /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = Carthage/Build/Mac/Nimble.framework; sourceTree = SOURCE_ROOT; };
|
||||||
4B570DC01D303CAF006EDC21 /* NeoVimAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NeoVimAgent.h; sourceTree = "<group>"; };
|
4B570DC01D303CAF006EDC21 /* NeoVimAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NeoVimAgent.h; sourceTree = "<group>"; };
|
||||||
4B570DC11D303CAF006EDC21 /* NeoVimAgent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NeoVimAgent.m; sourceTree = "<group>"; };
|
4B570DC11D303CAF006EDC21 /* NeoVimAgent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NeoVimAgent.m; sourceTree = "<group>"; };
|
||||||
4B6A70931D60E04200E12030 /* CocoaExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CocoaExtensions.swift; sourceTree = "<group>"; };
|
4B6A70931D60E04200E12030 /* AppKitCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppKitCommons.swift; sourceTree = "<group>"; };
|
||||||
4B6A70951D6100E300E12030 /* SwiftCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftCommons.swift; sourceTree = "<group>"; };
|
4B6A70951D6100E300E12030 /* SwiftCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftCommons.swift; sourceTree = "<group>"; };
|
||||||
4B854A1A1D31447C00E08DE1 /* NeoVimServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NeoVimServer; sourceTree = BUILT_PRODUCTS_DIR; };
|
4B854A1A1D31447C00E08DE1 /* NeoVimServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NeoVimServer; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
4B854A1C1D31447C00E08DE1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
4B854A1C1D31447C00E08DE1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||||
@ -230,6 +269,7 @@
|
|||||||
4BDCFAD41D3145E500F62670 /* libvterm.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvterm.a; path = neovim/.deps/usr/lib/libvterm.a; sourceTree = SOURCE_ROOT; };
|
4BDCFAD41D3145E500F62670 /* libvterm.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libvterm.a; path = neovim/.deps/usr/lib/libvterm.a; sourceTree = SOURCE_ROOT; };
|
||||||
4BDCFAE91D3147A300F62670 /* NeoVimMsgIds.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NeoVimMsgIds.h; sourceTree = "<group>"; };
|
4BDCFAE91D3147A300F62670 /* NeoVimMsgIds.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NeoVimMsgIds.h; sourceTree = "<group>"; };
|
||||||
4BDF50071D7607BF00D8FBC3 /* EonilFileSystemEvents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = EonilFileSystemEvents.framework; path = Carthage/Build/Mac/EonilFileSystemEvents.framework; sourceTree = SOURCE_ROOT; };
|
4BDF50071D7607BF00D8FBC3 /* EonilFileSystemEvents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = EonilFileSystemEvents.framework; path = Carthage/Build/Mac/EonilFileSystemEvents.framework; sourceTree = SOURCE_ROOT; };
|
||||||
|
4BDF500B1D760A3500D8FBC3 /* FileUtilsTest */ = {isa = PBXFileReference; lastKnownFileType = folder; path = FileUtilsTest; sourceTree = "<group>"; };
|
||||||
4BDF641A1D0887C100D47E1D /* TextDrawer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextDrawer.h; sourceTree = "<group>"; };
|
4BDF641A1D0887C100D47E1D /* TextDrawer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextDrawer.h; sourceTree = "<group>"; };
|
||||||
4BDF641B1D0887C100D47E1D /* TextDrawer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextDrawer.m; sourceTree = "<group>"; };
|
4BDF641B1D0887C100D47E1D /* TextDrawer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextDrawer.m; sourceTree = "<group>"; };
|
||||||
4BDF64221D08CAB000D47E1D /* MMCoreTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMCoreTextView.h; sourceTree = "<group>"; };
|
4BDF64221D08CAB000D47E1D /* MMCoreTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMCoreTextView.h; sourceTree = "<group>"; };
|
||||||
@ -298,12 +338,21 @@
|
|||||||
files = (
|
files = (
|
||||||
4BDF50091D7607BF00D8FBC3 /* EonilFileSystemEvents.framework in Frameworks */,
|
4BDF50091D7607BF00D8FBC3 /* EonilFileSystemEvents.framework in Frameworks */,
|
||||||
4B6A70991D65058A00E12030 /* Nimble.framework in Frameworks */,
|
4B6A70991D65058A00E12030 /* Nimble.framework in Frameworks */,
|
||||||
|
4BDF500D1D760A6D00D8FBC3 /* RxSwift.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
1929B41F745CDCDFE09ACDCF /* resources */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
4BDF500B1D760A3500D8FBC3 /* FileUtilsTest */,
|
||||||
|
);
|
||||||
|
path = resources;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
4B238BED1D3ED55300CBDD98 /* Preferences */ = {
|
4B238BED1D3ED55300CBDD98 /* Preferences */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -418,6 +467,43 @@
|
|||||||
name = lib;
|
name = lib;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
4BDF500F1D760A9500D8FBC3 /* UI */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1929B39DA7AC4A9B62D7CD39 /* Component.swift */,
|
||||||
|
4BD3BF961D32B0DB00082605 /* MainWindowManager.swift */,
|
||||||
|
4BD3BF921D32A95800082605 /* MainWindowComponent.swift */,
|
||||||
|
4B238BED1D3ED55300CBDD98 /* Preferences */,
|
||||||
|
);
|
||||||
|
name = UI;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
4BDF50101D760AB700D8FBC3 /* Commons */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
4B6A70931D60E04200E12030 /* AppKitCommons.swift */,
|
||||||
|
1929B0DD7AE34C049D26DA8C /* CwlUtils.swift */,
|
||||||
|
1929BA8AC40B901B20F20B71 /* FileUtils.swift */,
|
||||||
|
1929B9AF20D7BD6E5C975128 /* FoundationCommons.swift */,
|
||||||
|
1929BEEB33113B0E33C3830F /* Matcher.swift */,
|
||||||
|
4BB1BEA81D48773200463C29 /* RxSwiftUtils.swift */,
|
||||||
|
1929B9D510177918080BE39B /* Scorer.swift */,
|
||||||
|
4B6A70951D6100E300E12030 /* SwiftCommons.swift */,
|
||||||
|
);
|
||||||
|
name = Commons;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
4BDF50111D760B1100D8FBC3 /* File Items */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
1929B7CB4863F80230C32D3C /* FileItem.swift */,
|
||||||
|
1929B69499B2569793350CEC /* FileItemIgnorePattern.swift */,
|
||||||
|
1929BDF9EBAF1D9D44399045 /* ScoredFileItem.swift */,
|
||||||
|
1929B3A98687DF171307AAC8 /* FileItemService.swift */,
|
||||||
|
);
|
||||||
|
name = "File Items";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
4BEBA4FC1CFF374B00673FDF = {
|
4BEBA4FC1CFF374B00673FDF = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -446,17 +532,13 @@
|
|||||||
4BEBA5071CFF374B00673FDF /* VimR */ = {
|
4BEBA5071CFF374B00673FDF /* VimR */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4B6A70951D6100E300E12030 /* SwiftCommons.swift */,
|
4B2A2C0D1D0353750074CE9A /* Bridge.h */,
|
||||||
4B238BE01D3BF24200CBDD98 /* Application.swift */,
|
4B238BE01D3BF24200CBDD98 /* Application.swift */,
|
||||||
4BEBA5081CFF374B00673FDF /* AppDelegate.swift */,
|
4BEBA5081CFF374B00673FDF /* AppDelegate.swift */,
|
||||||
1929B39DA7AC4A9B62D7CD39 /* Component.swift */,
|
4BDF500F1D760A9500D8FBC3 /* UI */,
|
||||||
4BD3BF961D32B0DB00082605 /* MainWindowManager.swift */,
|
4BDF50111D760B1100D8FBC3 /* File Items */,
|
||||||
4BD3BF921D32A95800082605 /* MainWindowComponent.swift */,
|
4BDF50101D760AB700D8FBC3 /* Commons */,
|
||||||
4BB1BEA81D48773200463C29 /* RxSwiftUtils.swift */,
|
|
||||||
4B6A70931D60E04200E12030 /* CocoaExtensions.swift */,
|
|
||||||
4B238BED1D3ED55300CBDD98 /* Preferences */,
|
|
||||||
4B97E2CF1D33F92200FC0660 /* resources */,
|
4B97E2CF1D33F92200FC0660 /* resources */,
|
||||||
4B2A2C0D1D0353750074CE9A /* Bridge.h */,
|
|
||||||
);
|
);
|
||||||
path = VimR;
|
path = VimR;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -465,6 +547,10 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
4BEBA51A1CFF374B00673FDF /* Info.plist */,
|
4BEBA51A1CFF374B00673FDF /* Info.plist */,
|
||||||
|
1929BBC84557C8351EC6183E /* FileItemIgnorePatternTest.swift */,
|
||||||
|
1929B5D977261F1EBFA9E8F1 /* FileUtilsTest.swift */,
|
||||||
|
1929BC19C1BC19246AFF1621 /* MatcherTests.swift */,
|
||||||
|
1929B41F745CDCDFE09ACDCF /* resources */,
|
||||||
);
|
);
|
||||||
path = VimRTests;
|
path = VimRTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -682,6 +768,7 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
4BDF500C1D760A3500D8FBC3 /* FileUtilsTest in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -748,7 +835,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
4B238BE11D3BF24200CBDD98 /* Application.swift in Sources */,
|
4B238BE11D3BF24200CBDD98 /* Application.swift in Sources */,
|
||||||
4B6A70941D60E04200E12030 /* CocoaExtensions.swift in Sources */,
|
4B6A70941D60E04200E12030 /* AppKitCommons.swift in Sources */,
|
||||||
4BD3BF971D32B0DB00082605 /* MainWindowManager.swift in Sources */,
|
4BD3BF971D32B0DB00082605 /* MainWindowManager.swift in Sources */,
|
||||||
4B238BEC1D3ED54D00CBDD98 /* AppearancePrefPane.swift in Sources */,
|
4B238BEC1D3ED54D00CBDD98 /* AppearancePrefPane.swift in Sources */,
|
||||||
4BD3BF931D32A95800082605 /* MainWindowComponent.swift in Sources */,
|
4BD3BF931D32A95800082605 /* MainWindowComponent.swift in Sources */,
|
||||||
@ -760,6 +847,15 @@
|
|||||||
4BEBA5091CFF374B00673FDF /* AppDelegate.swift in Sources */,
|
4BEBA5091CFF374B00673FDF /* AppDelegate.swift in Sources */,
|
||||||
1929B165820D7177743B537A /* Component.swift in Sources */,
|
1929B165820D7177743B537A /* Component.swift in Sources */,
|
||||||
1929B93DBAD09835E428F610 /* PrefPane.swift in Sources */,
|
1929B93DBAD09835E428F610 /* PrefPane.swift in Sources */,
|
||||||
|
1929B2ADD407219BADBD5A70 /* CwlUtils.swift in Sources */,
|
||||||
|
1929B462CD4935AFF6D69457 /* FileItem.swift in Sources */,
|
||||||
|
1929B6388EAF16C190B82955 /* FileItemIgnorePattern.swift in Sources */,
|
||||||
|
1929B73E5EC0B108B83F82EB /* FileItemService.swift in Sources */,
|
||||||
|
1929B67DA3EB21A631EF1DBB /* FileUtils.swift in Sources */,
|
||||||
|
1929B3F5743967125F357C9F /* Matcher.swift in Sources */,
|
||||||
|
1929B53876E6952D378C2B30 /* ScoredFileItem.swift in Sources */,
|
||||||
|
1929BD3F9E609BFADB27584B /* Scorer.swift in Sources */,
|
||||||
|
1929B0E0C3BC59F52713D5A2 /* FoundationCommons.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -767,6 +863,18 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
1929B2B6F571129EB8D231C5 /* CwlUtils.swift in Sources */,
|
||||||
|
1929B43FBA7A31F39D294CD0 /* FileItem.swift in Sources */,
|
||||||
|
1929B741C4E58EEDAF901353 /* FileItemIgnorePattern.swift in Sources */,
|
||||||
|
1929B7C981A0EFCC8D631E3F /* FileItemService.swift in Sources */,
|
||||||
|
1929B2E1A64297B8E05BB64A /* FileUtils.swift in Sources */,
|
||||||
|
1929B3BF1DB87B57559DC27D /* Matcher.swift in Sources */,
|
||||||
|
1929B63CD9CBB9C122BD99A5 /* ScoredFileItem.swift in Sources */,
|
||||||
|
1929B10DD8CD7EE0B8BE529F /* Scorer.swift in Sources */,
|
||||||
|
1929B4D3A4429651C2AF55E5 /* FoundationCommons.swift in Sources */,
|
||||||
|
1929BEFEABA0448306CDB6D4 /* FileItemIgnorePatternTest.swift in Sources */,
|
||||||
|
1929B7A2F2B423AA9740FD45 /* FileUtilsTest.swift in Sources */,
|
||||||
|
1929BD4CA2204E061A86A140 /* MatcherTests.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
124
VimR/CwlUtils.swift
Normal file
124
VimR/CwlUtils.swift
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
//
|
||||||
|
// CwlMutex.swift
|
||||||
|
// CwlUtils
|
||||||
|
//
|
||||||
|
// Created by Matt Gallagher on 2015/02/03.
|
||||||
|
// Copyright © 2015 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||||
|
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
// Slightly modified by Tae Won Ha
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/// A basic wrapper around the "NORMAL" and "RECURSIVE" pthread mutex types. This type is a "class" type to take advantage of the "deinit" method.
|
||||||
|
final class PThreadMutex {
|
||||||
|
// Non-recursive "PTHREAD_MUTEX_NORMAL" and recursive "PTHREAD_MUTEX_RECURSIVE" mutex types.
|
||||||
|
enum PThreadMutexType {
|
||||||
|
case Normal
|
||||||
|
case Recursive
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Exposed as an "unsafe" public property so non-scoped patterns can be implemented, if required.
|
||||||
|
private(set) var unsafeMutex = pthread_mutex_t()
|
||||||
|
|
||||||
|
/// Default constructs as ".Normal" or ".Recursive" on request.
|
||||||
|
init(type: PThreadMutexType = .Normal) {
|
||||||
|
var attr = pthread_mutexattr_t()
|
||||||
|
guard pthread_mutexattr_init(&attr) == 0 else {
|
||||||
|
preconditionFailure()
|
||||||
|
}
|
||||||
|
switch type {
|
||||||
|
case .Normal:
|
||||||
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL)
|
||||||
|
case .Recursive:
|
||||||
|
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)
|
||||||
|
}
|
||||||
|
guard pthread_mutex_init(&unsafeMutex, &attr) == 0 else {
|
||||||
|
preconditionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
pthread_mutex_destroy(&unsafeMutex)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RECOMMENDATION: Don't use the `slowsync` function if you care about performance. Instead, copy this extension into your file and call it:
|
||||||
|
|
||||||
|
extension PThreadMutex {
|
||||||
|
private func sync<R>(@noescape f: () throws -> R) rethrows -> R {
|
||||||
|
pthread_mutex_lock(&unsafeMutex)
|
||||||
|
defer { pthread_mutex_unlock(&unsafeMutex) }
|
||||||
|
return try f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
func sync<R>(@noescape f: () throws -> R) rethrows -> R {
|
||||||
|
pthread_mutex_lock(&unsafeMutex)
|
||||||
|
defer { pthread_mutex_unlock(&unsafeMutex) }
|
||||||
|
return try f()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RECOMMENDATION: Don't use the `trySlowsync` function if you care about performance. Instead, copy this extension into your file and call it:
|
||||||
|
|
||||||
|
extension PThreadMutex {
|
||||||
|
private func trySync<R>(@noescape f: () throws -> R) rethrows -> R? {
|
||||||
|
guard pthread_mutex_trylock(&unsafeMutex) == 0 else { return nil }
|
||||||
|
defer { pthread_mutex_unlock(&unsafeMutex) }
|
||||||
|
return try f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
func trySlowsync<R>(@noescape f: () throws -> R) rethrows -> R? {
|
||||||
|
guard pthread_mutex_trylock(&unsafeMutex) == 0 else { return nil }
|
||||||
|
defer { pthread_mutex_unlock(&unsafeMutex) }
|
||||||
|
return try f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if PERFORMANCE_TESTS
|
||||||
|
|
||||||
|
/// A basic scoped mutex wrapper around a `dispatch_semaphore_t`.
|
||||||
|
/// For maximum performance, it is recommended that you copy this entire type into the same compilation unit as your code that uses it to ensure inlining.
|
||||||
|
public struct DispatchSemaphore {
|
||||||
|
let s = dispatch_semaphore_create(1)
|
||||||
|
public init() {}
|
||||||
|
public func sync<R>(@noescape f: () throws -> R) rethrows -> R {
|
||||||
|
_ = dispatch_semaphore_wait(s, DISPATCH_TIME_FOREVER)
|
||||||
|
defer { _ = dispatch_semaphore_signal(s) }
|
||||||
|
return try f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension PThreadMutex {
|
||||||
|
public func sync_2<T>(inout param: T, @noescape f: (inout T) throws -> Void) rethrows -> Void {
|
||||||
|
pthread_mutex_lock(&unsafeMutex)
|
||||||
|
defer { pthread_mutex_unlock(&unsafeMutex) }
|
||||||
|
try f(¶m)
|
||||||
|
}
|
||||||
|
public func sync_3<T, R>(inout param: T, @noescape f: (inout T) throws -> R) rethrows -> R {
|
||||||
|
pthread_mutex_lock(&unsafeMutex)
|
||||||
|
defer { pthread_mutex_unlock(&unsafeMutex) }
|
||||||
|
return try f(¶m)
|
||||||
|
}
|
||||||
|
public func sync_4<T, U>(inout param1: T, inout _ param2: U, @noescape f: (inout T, inout U) throws -> Void) rethrows -> Void {
|
||||||
|
pthread_mutex_lock(&unsafeMutex)
|
||||||
|
defer { pthread_mutex_unlock(&unsafeMutex) }
|
||||||
|
return try f(¶m1, ¶m2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
37
VimR/FileItem.swift
Normal file
37
VimR/FileItem.swift
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Tae Won Ha - http://taewon.de - @hataewon
|
||||||
|
* See LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class FileItem : CustomStringConvertible {
|
||||||
|
|
||||||
|
let mutex = PThreadMutex()
|
||||||
|
|
||||||
|
let url: NSURL
|
||||||
|
let dir: Bool
|
||||||
|
let hidden: Bool
|
||||||
|
|
||||||
|
/// When nil, then it has never been fnmatch'ed.
|
||||||
|
weak var ignoreToken: Token?
|
||||||
|
var ignore = false
|
||||||
|
|
||||||
|
var needsScanChildren = false
|
||||||
|
var childrenScanned = false
|
||||||
|
|
||||||
|
var children: [FileItem] = []
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
return "<FileItem: \(self.url), dir=\(self.dir), hidden=\(self.hidden), "
|
||||||
|
+ "needsScan=\(self.needsScanChildren), childrenScanned=\(self.childrenScanned), "
|
||||||
|
+ "ignore=\(self.ignore), ignoreToken=\(self.ignoreToken), "
|
||||||
|
+ "children=\(self.children.count)>"
|
||||||
|
}
|
||||||
|
|
||||||
|
init(_ url: NSURL) {
|
||||||
|
self.url = url
|
||||||
|
self.dir = url.dir
|
||||||
|
self.hidden = url.hidden
|
||||||
|
}
|
||||||
|
}
|
56
VimR/FileItemIgnorePattern.swift
Normal file
56
VimR/FileItemIgnorePattern.swift
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* Tae Won Ha - http://taewon.de - @hataewon
|
||||||
|
* See LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
func ==(lhs: FileItemIgnorePattern, rhs: FileItemIgnorePattern) -> Bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileItemIgnorePattern: Hashable {
|
||||||
|
|
||||||
|
var hashValue: Int {
|
||||||
|
return self.pattern.hashValue
|
||||||
|
}
|
||||||
|
|
||||||
|
let folderPattern: Bool
|
||||||
|
let pattern: String
|
||||||
|
|
||||||
|
private let patternAsFileSysRep: UnsafeMutablePointer<Int8>
|
||||||
|
|
||||||
|
init(pattern: String) {
|
||||||
|
self.pattern = pattern
|
||||||
|
self.folderPattern = pattern.hasPrefix("*/")
|
||||||
|
|
||||||
|
let fileSysRep = (pattern as NSString).fileSystemRepresentation
|
||||||
|
let len = Int(strlen(fileSysRep))
|
||||||
|
|
||||||
|
self.patternAsFileSysRep = UnsafeMutablePointer<Int8>.alloc(len + 1)
|
||||||
|
memcpy(self.patternAsFileSysRep, fileSysRep, len)
|
||||||
|
self.patternAsFileSysRep[len] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
let len = Int(strlen(self.patternAsFileSysRep))
|
||||||
|
self.patternAsFileSysRep.dealloc(len + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func match(absolutePath path: String) -> Bool {
|
||||||
|
let matches: Int32
|
||||||
|
let absolutePath = path as NSString
|
||||||
|
|
||||||
|
if self.folderPattern {
|
||||||
|
matches = fnmatch(self.patternAsFileSysRep,
|
||||||
|
absolutePath.fileSystemRepresentation,
|
||||||
|
FNM_LEADING_DIR | FNM_NOESCAPE)
|
||||||
|
} else {
|
||||||
|
matches = fnmatch(self.patternAsFileSysRep,
|
||||||
|
(absolutePath.lastPathComponent as NSString).fileSystemRepresentation,
|
||||||
|
FNM_NOESCAPE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches != FNM_NOMATCH
|
||||||
|
}
|
||||||
|
}
|
203
VimR/FileItemService.swift
Normal file
203
VimR/FileItemService.swift
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/**
|
||||||
|
* Tae Won Ha - http://taewon.de - @hataewon
|
||||||
|
* See LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import RxSwift
|
||||||
|
import EonilFileSystemEvents
|
||||||
|
|
||||||
|
func == (left: Token, right: Token) -> Bool {
|
||||||
|
return left === right
|
||||||
|
}
|
||||||
|
|
||||||
|
class Token: Equatable {}
|
||||||
|
|
||||||
|
class FileItemService {
|
||||||
|
|
||||||
|
private(set) var ignorePatterns: Set<FileItemIgnorePattern> = [] {
|
||||||
|
didSet {
|
||||||
|
self.ignoreToken = Token()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used to cache fnmatch calls in `FileItem`.
|
||||||
|
private var ignoreToken = Token()
|
||||||
|
|
||||||
|
/// When at least this much of non-directory and visible files are scanned, they are emitted.
|
||||||
|
private let emitChunkSize = 200
|
||||||
|
|
||||||
|
private let scanDispatchQueue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
|
||||||
|
private let monitorDispatchQueue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
|
||||||
|
|
||||||
|
private let root = FileItem(NSURL(fileURLWithPath: "/", isDirectory: true))
|
||||||
|
|
||||||
|
private let fileSystemEventsLatency = Double(2)
|
||||||
|
private var monitors = [NSURL: FileSystemEventMonitor]()
|
||||||
|
|
||||||
|
func set(ignorePatterns patterns: Set<FileItemIgnorePattern>) {
|
||||||
|
self.ignorePatterns = patterns
|
||||||
|
}
|
||||||
|
|
||||||
|
func monitor(url url: NSURL) {
|
||||||
|
guard let path = url.path else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Handle EonilFileSystemEventFlag.RootChanged, ie watchRoot: true
|
||||||
|
let monitor = FileSystemEventMonitor(pathsToWatch: [path],
|
||||||
|
latency: self.fileSystemEventsLatency,
|
||||||
|
watchRoot: false,
|
||||||
|
queue: self.monitorDispatchQueue)
|
||||||
|
{ [unowned self] events in
|
||||||
|
let urls = events.map { NSURL(fileURLWithPath: $0.path) }
|
||||||
|
let parent = FileUtils.commonParent(ofUrls: urls)
|
||||||
|
self.fileItem(forUrl: parent)?.needsScanChildren = true
|
||||||
|
}
|
||||||
|
|
||||||
|
self.monitors[url] = monitor
|
||||||
|
}
|
||||||
|
|
||||||
|
func unmonitor(url url: NSURL) {
|
||||||
|
self.monitors.removeValueForKey(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
func flatFileItems(ofUrl url: NSURL) -> Observable<[FileItem]> {
|
||||||
|
guard url.fileURL else {
|
||||||
|
return Observable.empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
guard FileUtils.fileExistsAtUrl(url) else {
|
||||||
|
return Observable.empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let pathComponents = url.pathComponents else {
|
||||||
|
return Observable.empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
return Observable.create { [unowned self] observer in
|
||||||
|
let cancel = AnonymousDisposable {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch_async(self.scanDispatchQueue) { [unowned self] in
|
||||||
|
guard let targetItem = self.fileItem(forPathComponents: pathComponents) else {
|
||||||
|
observer.onCompleted()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var flatNewFileItems: [FileItem] = []
|
||||||
|
|
||||||
|
var dirStack: [FileItem] = [targetItem]
|
||||||
|
while let curItem = dirStack.popLast() {
|
||||||
|
if cancel.disposed {
|
||||||
|
observer.onCompleted()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !curItem.childrenScanned || curItem.needsScanChildren {
|
||||||
|
self.scanChildren(curItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
curItem.children
|
||||||
|
.filter { item in
|
||||||
|
if item.hidden {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// This item already has been fnmatch'ed, thus return the cached value.
|
||||||
|
if item.ignoreToken == self.ignoreToken {
|
||||||
|
return !item.ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
item.ignoreToken = self.ignoreToken
|
||||||
|
item.ignore = false
|
||||||
|
|
||||||
|
let path = item.url.path!
|
||||||
|
for pattern in self.ignorePatterns {
|
||||||
|
// We don't use `String.FnMatchOption.leadingDir` (`FNM_LEADING_DIR`) for directories since we do not
|
||||||
|
// scan ignored directories at all when filtering. For example "*/.git" would create a `FileItem`
|
||||||
|
// for `/some/path/.git`, but not scan its children when we filter.
|
||||||
|
if pattern.match(absolutePath: path) {
|
||||||
|
item.ignore = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
.forEach { $0.dir ? dirStack.append($0) : flatNewFileItems.append($0) }
|
||||||
|
|
||||||
|
if flatNewFileItems.count >= self.emitChunkSize {
|
||||||
|
observer.onNext(flatNewFileItems)
|
||||||
|
flatNewFileItems = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cancel.disposed {
|
||||||
|
observer.onNext(flatNewFileItems)
|
||||||
|
observer.onCompleted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cancel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func fileItem(forUrl url: NSURL) -> FileItem? {
|
||||||
|
guard let pathComponents = url.pathComponents else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.fileItem(forPathComponents: pathComponents)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `FileItem` corresponding to the `pathComponents` parameter. This is like mkdir -p, i.e. it
|
||||||
|
/// instantiates the intermediate `FileItem`s.
|
||||||
|
///
|
||||||
|
/// - returns: `FileItem` corresponding to `pathComponents`. `nil` if the file does not exist.
|
||||||
|
private func fileItem(forPathComponents pathComponents: [String]) -> FileItem? {
|
||||||
|
let result = pathComponents.dropFirst().reduce(self.root) { (resultItem, childName) -> FileItem? in
|
||||||
|
guard let parent = resultItem else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.child(withName: childName, ofParent: parent, create: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Even when the result is nil it does not mean that there's no child with the given name. It could well be that
|
||||||
|
/// it's not been scanned yet. However, if `create` parameter was true and `nil` is returned, the requested
|
||||||
|
/// child does not exist.
|
||||||
|
///
|
||||||
|
/// - parameters:
|
||||||
|
/// - name: name of the child to get.
|
||||||
|
/// - parent: parent of the child.
|
||||||
|
/// - create: whether to create the child `FileItem` if it's not scanned yet.
|
||||||
|
/// - returns: child `FileItem` or nil.
|
||||||
|
private func child(withName name: String, ofParent parent: FileItem, create: Bool = false) -> FileItem? {
|
||||||
|
let filteredChildren = parent.children.filter { $0.url.lastPathComponent == name }
|
||||||
|
|
||||||
|
if filteredChildren.isEmpty && create {
|
||||||
|
let childUrl = parent.url.URLByAppendingPathComponent(name)
|
||||||
|
|
||||||
|
guard FileUtils.fileExistsAtUrl(childUrl) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let child = FileItem(childUrl)
|
||||||
|
parent.mutex.sync { parent.children.append(child) }
|
||||||
|
return child
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredChildren.first
|
||||||
|
}
|
||||||
|
|
||||||
|
private func scanChildren(item: FileItem) {
|
||||||
|
item.mutex.sync { item.children = FileUtils.directDescendants(item.url).map(FileItem.init) }
|
||||||
|
item.childrenScanned = true
|
||||||
|
item.needsScanChildren = false
|
||||||
|
}
|
||||||
|
}
|
64
VimR/FileUtils.swift
Normal file
64
VimR/FileUtils.swift
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Tae Won Ha - http://taewon.de - @hataewon
|
||||||
|
* See LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class FileUtils {
|
||||||
|
|
||||||
|
private static let keysToGet = [
|
||||||
|
NSURLIsDirectoryKey,
|
||||||
|
NSURLIsHiddenKey,
|
||||||
|
NSURLIsAliasFileKey,
|
||||||
|
NSURLIsSymbolicLinkKey
|
||||||
|
]
|
||||||
|
|
||||||
|
private static let scanOptions: NSDirectoryEnumerationOptions = [
|
||||||
|
NSDirectoryEnumerationOptions.SkipsSubdirectoryDescendants,
|
||||||
|
NSDirectoryEnumerationOptions.SkipsPackageDescendants
|
||||||
|
]
|
||||||
|
|
||||||
|
private static let fileManager = NSFileManager.defaultManager()
|
||||||
|
|
||||||
|
static func directDescendants(url: NSURL) -> [NSURL] {
|
||||||
|
guard let childUrls = try? self.fileManager.contentsOfDirectoryAtURL(
|
||||||
|
url, includingPropertiesForKeys: self.keysToGet, options: self.scanOptions
|
||||||
|
) else {
|
||||||
|
// FIXME error handling
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
return childUrls
|
||||||
|
}
|
||||||
|
|
||||||
|
static func fileExistsAtUrl(url: NSURL) -> Bool {
|
||||||
|
guard url.fileURL else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let path = url.path else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.fileManager.fileExistsAtPath(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
static func commonParent(ofUrls urls: [NSURL]) -> NSURL {
|
||||||
|
guard urls.count > 0 else {
|
||||||
|
return NSURL(fileURLWithPath: "/", isDirectory: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
let pathComps = urls.map { $0.pathComponents! }
|
||||||
|
let min = pathComps.reduce(pathComps[0].count) { (result, comps) in result < comps.count ? result : comps.count }
|
||||||
|
let pathCompsWithMinCount = pathComps.filter { $0.count == min }
|
||||||
|
let possibleParent = NSURL.fileURLWithPathComponents(pathCompsWithMinCount[0])!
|
||||||
|
|
||||||
|
let minPathComponents = Set(pathComps.map { $0[min - 1] })
|
||||||
|
if minPathComponents.count == 1 {
|
||||||
|
return possibleParent.dir ? possibleParent : possibleParent.URLByDeletingLastPathComponent!
|
||||||
|
}
|
||||||
|
|
||||||
|
return possibleParent.URLByDeletingLastPathComponent!
|
||||||
|
}
|
||||||
|
}
|
75
VimR/FoundationCommons.swift
Normal file
75
VimR/FoundationCommons.swift
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* Tae Won Ha - http://taewon.de - @hataewon
|
||||||
|
* See LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension NSURL {
|
||||||
|
|
||||||
|
/// Wrapper function for NSURL.getResourceValue for Bool values.
|
||||||
|
/// Returns also `false` when
|
||||||
|
/// - there is no value for the given `key` or
|
||||||
|
/// - the value cannot be converted to `NSNumber`.
|
||||||
|
///
|
||||||
|
/// - parameters:
|
||||||
|
/// - key: The `key`-parameter of `NSURL.getResourceValue`.
|
||||||
|
func resourceValue(key: String) -> Bool {
|
||||||
|
var rsrc: AnyObject?
|
||||||
|
|
||||||
|
do {
|
||||||
|
try self.getResourceValue(&rsrc, forKey: key)
|
||||||
|
} catch {
|
||||||
|
// FIXME error handling
|
||||||
|
print("\(#function): \(self) -> ERROR while getting \(key)")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if let result = rsrc as? NSNumber {
|
||||||
|
return result.boolValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var dir: Bool {
|
||||||
|
return self.resourceValue(NSURLIsDirectoryKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
var hidden: Bool {
|
||||||
|
return self.resourceValue(NSURLIsHiddenKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Array {
|
||||||
|
|
||||||
|
/// Concurrent and chunked version of `Array.map`.
|
||||||
|
///
|
||||||
|
/// - parameters:
|
||||||
|
/// - chunk: Batch size; defaults to `100`.
|
||||||
|
/// - queue: Defaults to `dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)`.
|
||||||
|
/// - transform: The transform function.
|
||||||
|
/// - returns: Transformed array of `self`.
|
||||||
|
func concurrentChunkMap<R>(
|
||||||
|
chunk: Int = 100,
|
||||||
|
queue: dispatch_queue_t = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0),
|
||||||
|
transform: (Element) -> R) -> [R]
|
||||||
|
{
|
||||||
|
let count = self.count
|
||||||
|
|
||||||
|
let chunkedCount = Int(ceil(Float(count) / Float(chunk)))
|
||||||
|
var result: [[R]] = []
|
||||||
|
|
||||||
|
let mutex = PThreadMutex()
|
||||||
|
|
||||||
|
dispatch_apply(chunkedCount, queue) { idx in
|
||||||
|
let startIndex = min(idx * chunk, count)
|
||||||
|
let endIndex = min(startIndex + chunk, count)
|
||||||
|
|
||||||
|
let mappedChunk = self[startIndex..<endIndex].map(transform)
|
||||||
|
mutex.sync { result.append(mappedChunk) }
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.flatMap { $0 }
|
||||||
|
}
|
||||||
|
}
|
142
VimR/Matcher.swift
Normal file
142
VimR/Matcher.swift
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/**
|
||||||
|
* Tae Won Ha - http://taewon.de - @hataewon
|
||||||
|
* See LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class Matcher {
|
||||||
|
|
||||||
|
static let uppercaseCharSet = NSCharacterSet.uppercaseLetterCharacterSet()
|
||||||
|
|
||||||
|
enum ExactMatchResult {
|
||||||
|
case none
|
||||||
|
case exact
|
||||||
|
case prefix
|
||||||
|
case suffix
|
||||||
|
case contains
|
||||||
|
}
|
||||||
|
|
||||||
|
static func exactMatchIgnoringCase(target: String, pattern: String) -> ExactMatchResult {
|
||||||
|
let ltarget = target.lowercaseString
|
||||||
|
let lpattern = pattern.lowercaseString
|
||||||
|
if ltarget == lpattern {
|
||||||
|
return .exact
|
||||||
|
}
|
||||||
|
|
||||||
|
if ltarget.hasPrefix(lpattern) {
|
||||||
|
return .prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
if ltarget.hasSuffix(lpattern) {
|
||||||
|
return .suffix
|
||||||
|
}
|
||||||
|
|
||||||
|
if ltarget.containsString(lpattern) {
|
||||||
|
return .contains
|
||||||
|
}
|
||||||
|
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
|
||||||
|
static func numberOfUppercaseMatches(target: String, pattern: String) -> Int {
|
||||||
|
let tscalars = target.unicodeScalars.filter { uppercaseCharSet.longCharacterIsMember($0.value) }
|
||||||
|
|
||||||
|
guard tscalars.count > 0 else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
let pscalars = pattern.uppercaseString.unicodeScalars
|
||||||
|
let pidxStart = pscalars.startIndex
|
||||||
|
let pidx = tscalars.reduce(pidxStart) { pscalars[$0] == $1 ? $0.successor() : $0 }
|
||||||
|
|
||||||
|
return pidxStart.distanceTo(pidx)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Matches `pattern` to `target` in a fuzzy way.
|
||||||
|
/// - returns: `Array` of `Range<String.UnicodeScalarIndex>`
|
||||||
|
static func fuzzyIgnoringCase(target: String, pattern: String) -> (matches: Int, ranges: [Range<Int>]) {
|
||||||
|
let tlower = target.lowercaseString
|
||||||
|
let plower = pattern.lowercaseString
|
||||||
|
|
||||||
|
let tchars = tlower.unicodeScalars
|
||||||
|
let pchars = plower.unicodeScalars
|
||||||
|
|
||||||
|
var flags = Array(count: tchars.count, repeatedValue: false)
|
||||||
|
|
||||||
|
var pidx = pchars.startIndex
|
||||||
|
for (i, tchar) in tchars.enumerate() {
|
||||||
|
if pchars[pidx] == tchar {
|
||||||
|
flags[i] = true
|
||||||
|
pidx = pidx.successor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ranges: [Range<Int>] = []
|
||||||
|
var matches = 0
|
||||||
|
|
||||||
|
var lastTrue = -1
|
||||||
|
var curTrue = -1
|
||||||
|
|
||||||
|
for (i, isTrue) in flags.enumerate() {
|
||||||
|
if isTrue {
|
||||||
|
matches = matches &+ 1
|
||||||
|
if lastTrue == -1 {
|
||||||
|
lastTrue = i
|
||||||
|
}
|
||||||
|
curTrue = i
|
||||||
|
|
||||||
|
if i == flags.count &- 1 {
|
||||||
|
if lastTrue > -1 && curTrue > -1 {
|
||||||
|
ranges.append(lastTrue...curTrue)
|
||||||
|
lastTrue = -1
|
||||||
|
curTrue = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if lastTrue > -1 && curTrue > -1 {
|
||||||
|
ranges.append(lastTrue...curTrue)
|
||||||
|
lastTrue = -1
|
||||||
|
curTrue = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (matches, ranges)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wagner-Fischer algorithm.
|
||||||
|
/// We use the 32 bit representation (`String.unicodeScalars`) of both parameters to compare them.
|
||||||
|
///
|
||||||
|
/// - returns: the distance of pattern from target
|
||||||
|
/// - seealso: https://en.wikipedia.org/wiki/Wagner–Fischer_algorithm
|
||||||
|
static func wagnerFisherDistance(target: String, pattern: String) -> Int {
|
||||||
|
let s = target.unicodeScalars
|
||||||
|
let t = pattern.unicodeScalars
|
||||||
|
|
||||||
|
let m = s.count
|
||||||
|
|
||||||
|
var prevRow = Array(count: m &+ 1, repeatedValue: 0)
|
||||||
|
var curRow = Array(count: m &+ 1, repeatedValue: 0)
|
||||||
|
|
||||||
|
for i in 0...m {
|
||||||
|
prevRow[i] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j, tchar) in t.enumerate() {
|
||||||
|
curRow[0] = j &+ 1
|
||||||
|
|
||||||
|
for (i, schar) in s.enumerate() {
|
||||||
|
if schar == tchar {
|
||||||
|
curRow[i &+ 1] = prevRow[i]
|
||||||
|
} else {
|
||||||
|
curRow[i &+ 1] = min(curRow[i] &+ 1, prevRow[i &+ 1] &+ 1, prevRow[i] &+ 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prevRow = curRow
|
||||||
|
}
|
||||||
|
|
||||||
|
return curRow[m]
|
||||||
|
}
|
||||||
|
}
|
25
VimR/ScoredFileItem.swift
Normal file
25
VimR/ScoredFileItem.swift
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* Tae Won Ha - http://taewon.de - @hataewon
|
||||||
|
* See LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import RxSwift
|
||||||
|
|
||||||
|
class ScoredFileItem: Comparable {
|
||||||
|
let score: Float
|
||||||
|
let url: NSURL
|
||||||
|
|
||||||
|
init(score: Float, url: NSURL) {
|
||||||
|
self.score = score
|
||||||
|
self.url = url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func == (left: ScoredFileItem, right: ScoredFileItem) -> Bool {
|
||||||
|
return left.score == right.score
|
||||||
|
}
|
||||||
|
|
||||||
|
func <(left: ScoredFileItem, right: ScoredFileItem) -> Bool {
|
||||||
|
return left.score < right.score
|
||||||
|
}
|
31
VimR/Scorer.swift
Normal file
31
VimR/Scorer.swift
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Tae Won Ha - http://taewon.de - @hataewon
|
||||||
|
* See LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class Scorer {
|
||||||
|
|
||||||
|
static func score(target: String, pattern: String) -> Float {
|
||||||
|
let wf = Matcher.wagnerFisherDistance(target, pattern: pattern)
|
||||||
|
let fuzzy = Matcher.fuzzyIgnoringCase(target, pattern: pattern)
|
||||||
|
let upper = Matcher.numberOfUppercaseMatches(target, pattern: pattern)
|
||||||
|
let exactMatch = Matcher.exactMatchIgnoringCase(target, pattern: pattern)
|
||||||
|
|
||||||
|
let exactScore: Float
|
||||||
|
switch exactMatch {
|
||||||
|
case .none:
|
||||||
|
exactScore = 0
|
||||||
|
case .exact:
|
||||||
|
return 100
|
||||||
|
case .prefix, .contains, .suffix:
|
||||||
|
exactScore = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
return (wf == 0 ? 0 : 5.0 / Float(wf))
|
||||||
|
+ Float(fuzzy.matches)
|
||||||
|
+ Float(upper)
|
||||||
|
+ exactScore
|
||||||
|
}
|
||||||
|
}
|
64
VimRTests/FileItemIgnorePatternTest.swift
Normal file
64
VimRTests/FileItemIgnorePatternTest.swift
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/**
|
||||||
|
* Tae Won Ha - http://taewon.de - @hataewon
|
||||||
|
* See LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
import Nimble
|
||||||
|
|
||||||
|
class FileItemIgnorePatternTest: XCTestCase {
|
||||||
|
|
||||||
|
var pattern: FileItemIgnorePattern = FileItemIgnorePattern(pattern: "dummy")
|
||||||
|
|
||||||
|
func testMatchFolder() {
|
||||||
|
pattern = FileItemIgnorePattern(pattern: "*/.git")
|
||||||
|
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/.git")).to(equal(true))
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/.git/d")).to(equal(true))
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/.git/d/e")).to(equal(true))
|
||||||
|
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/.gitfolder/d")).to(equal(false))
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/1.git/d")).to(equal(false))
|
||||||
|
expect(self.pattern.match(absolutePath: ".git")).to(equal(false))
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/.hg/d")).to(equal(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMatchFolderMultipleWildCards() {
|
||||||
|
pattern = FileItemIgnorePattern(pattern: "*/*.xcodeproj")
|
||||||
|
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/VimR.xcodeproj")).to(equal(true))
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/VimR.xcodeproj/somefile")).to(equal(true))
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/VimR.xcodeproj/somefile/deep")).to(equal(true))
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/VimR.xcworkspace/somefile")).to(equal(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMatchSuffix() {
|
||||||
|
pattern = FileItemIgnorePattern(pattern: "*.png")
|
||||||
|
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/d.png")).to(equal(true))
|
||||||
|
expect(self.pattern.match(absolutePath: "a.png")).to(equal(true))
|
||||||
|
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/d.pnge")).to(equal(false))
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/d.png/e")).to(equal(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMatchPrefix() {
|
||||||
|
pattern = FileItemIgnorePattern(pattern: "vr*")
|
||||||
|
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/vr.png")).to(equal(true))
|
||||||
|
expect(self.pattern.match(absolutePath: "vr.png")).to(equal(true))
|
||||||
|
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/wvr.png")).to(equal(false))
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/wvr.png/e")).to(equal(false))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMatchExact() {
|
||||||
|
pattern = FileItemIgnorePattern(pattern: "some")
|
||||||
|
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/some")).to(equal(true))
|
||||||
|
expect(self.pattern.match(absolutePath: "some")).to(equal(true))
|
||||||
|
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/some1")).to(equal(false))
|
||||||
|
expect(self.pattern.match(absolutePath: "/a/b/c/1some")).to(equal(false))
|
||||||
|
}
|
||||||
|
}
|
89
VimRTests/FileUtilsTest.swift
Normal file
89
VimRTests/FileUtilsTest.swift
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* Tae Won Ha - http://taewon.de - @hataewon
|
||||||
|
* See LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
import Nimble
|
||||||
|
|
||||||
|
class FileUtilsTest: XCTestCase {
|
||||||
|
|
||||||
|
var fileUtilsRsrcUrl = NSURL()
|
||||||
|
var a1Dir = NSURL()
|
||||||
|
|
||||||
|
override func setUp() {
|
||||||
|
fileUtilsRsrcUrl = NSBundle.init(forClass: self.dynamicType).URLForResource("FileUtilsTest", withExtension: "")!
|
||||||
|
a1Dir = fileUtilsRsrcUrl.URLByAppendingPathComponent("a1")
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCommonParentOneDirUrl() {
|
||||||
|
let urls = [
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1"),
|
||||||
|
]
|
||||||
|
|
||||||
|
expect(FileUtils.commonParent(ofUrls: urls)).to(equal(a1Dir))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCommonParentOneFileUrl() {
|
||||||
|
let urls = [
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1/a1-file1"),
|
||||||
|
]
|
||||||
|
|
||||||
|
expect(FileUtils.commonParent(ofUrls: urls)).to(equal(a1Dir))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCommonParentEmptyParams() {
|
||||||
|
expect(FileUtils.commonParent(ofUrls: [])).to(equal(NSURL(fileURLWithPath: "/", isDirectory: true)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCommonParent1() {
|
||||||
|
let urls = [
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1"),
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1/a1-file1"),
|
||||||
|
]
|
||||||
|
|
||||||
|
expect(FileUtils.commonParent(ofUrls: urls)).to(equal(a1Dir))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCommonParent2() {
|
||||||
|
let urls = [
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1"),
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1/a1-file1"),
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1/a2/a1-a2-file1"),
|
||||||
|
]
|
||||||
|
|
||||||
|
expect(FileUtils.commonParent(ofUrls: urls)).to(equal(a1Dir))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCommonParent3() {
|
||||||
|
let urls = [
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1"),
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1/a1-file1"),
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1/a2/a1-a2-file1"),
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("b1/b1-file1"),
|
||||||
|
]
|
||||||
|
|
||||||
|
expect(FileUtils.commonParent(ofUrls: urls)).to(equal(fileUtilsRsrcUrl))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCommonParent4() {
|
||||||
|
let urls = [
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1"),
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1/a1-file1"),
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1/a2/a1-a2-file1"),
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("b1"),
|
||||||
|
]
|
||||||
|
|
||||||
|
expect(FileUtils.commonParent(ofUrls: urls)).to(equal(fileUtilsRsrcUrl))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCommonParent5() {
|
||||||
|
let urls = [
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1/a1-file1"),
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1/a2/a1-a2-file1"),
|
||||||
|
fileUtilsRsrcUrl.URLByAppendingPathComponent("a1/a2"),
|
||||||
|
]
|
||||||
|
|
||||||
|
expect(FileUtils.commonParent(ofUrls: urls)).to(equal(a1Dir))
|
||||||
|
}
|
||||||
|
}
|
50
VimRTests/MatcherTests.swift
Normal file
50
VimRTests/MatcherTests.swift
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* Tae Won Ha - http://taewon.de - @hataewon
|
||||||
|
* See LICENSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
import Nimble
|
||||||
|
|
||||||
|
class MatcherTest: XCTestCase {
|
||||||
|
|
||||||
|
let target = "UserDefaultContextTest.swift"
|
||||||
|
|
||||||
|
func testFnmatch() {
|
||||||
|
expect(fnmatch(
|
||||||
|
".git".cStringUsingEncoding(NSUTF8StringEncoding),
|
||||||
|
"/test/.git".cStringUsingEncoding(NSUTF8StringEncoding),
|
||||||
|
0)
|
||||||
|
)
|
||||||
|
.to(equal(FNM_NOMATCH))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testExactMatch() {
|
||||||
|
expect(Matcher.exactMatchIgnoringCase(self.target, pattern: "uSERdEFAULTcONTEXTtEST.SWIFT"))
|
||||||
|
.to(equal(Matcher.ExactMatchResult.exact))
|
||||||
|
expect(Matcher.exactMatchIgnoringCase(self.target, pattern: "uSERdEFAULt"))
|
||||||
|
.to(equal(Matcher.ExactMatchResult.prefix))
|
||||||
|
expect(Matcher.exactMatchIgnoringCase(self.target, pattern: "swIFt")).to(equal(Matcher.ExactMatchResult.suffix))
|
||||||
|
expect(Matcher.exactMatchIgnoringCase(self.target, pattern: "userdecon")).to(equal(Matcher.ExactMatchResult.none))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUppercaseMatcher() {
|
||||||
|
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "xct")).to(equal(0))
|
||||||
|
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "uct")).to(equal(3))
|
||||||
|
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "uDcT")).to(equal(4))
|
||||||
|
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "dct")).to(equal(3))
|
||||||
|
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "ut")).to(equal(2))
|
||||||
|
expect(Matcher.numberOfUppercaseMatches(self.target, pattern: "de")).to(equal(1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFuzzyMatcher() {
|
||||||
|
expect(Matcher.fuzzyIgnoringCase(self.target, pattern: "ucotft").matches).to(equal(6))
|
||||||
|
expect(Matcher.fuzzyIgnoringCase(self.target, pattern: "uco-tft").matches).to(equal(3))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testWagerFischerAlgo() {
|
||||||
|
expect(Matcher.wagnerFisherDistance("sitting", pattern: "kitten")).to(equal(3))
|
||||||
|
expect(Matcher.wagnerFisherDistance("saturday", pattern: "sunday")).to(equal(3))
|
||||||
|
expect(Matcher.wagnerFisherDistance("하태원", pattern: "하태이")).to(equal(1))
|
||||||
|
}
|
||||||
|
}
|
0
VimRTests/resources/FileUtilsTest/a1/a1-file1
Normal file
0
VimRTests/resources/FileUtilsTest/a1/a1-file1
Normal file
0
VimRTests/resources/FileUtilsTest/a1/a2/a1-a2-file1
Normal file
0
VimRTests/resources/FileUtilsTest/a1/a2/a1-a2-file1
Normal file
0
VimRTests/resources/FileUtilsTest/b1/b1-file1
Normal file
0
VimRTests/resources/FileUtilsTest/b1/b1-file1
Normal file
Loading…
Reference in New Issue
Block a user