diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..02cb4fb --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +[*.swift] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..cff2ddd --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,54 @@ +disabled_rules: + - line_length + +opt_in_rules: + - attributes + - closure_end_indentation + - closure_spacing + - conditional_returns_on_newline + - empty_count + - explicit_enum_raw_value + - explicit_init + - explicit_top_level_acl + - explicit_type_interface + - extension_access_modifier + - fatal_error_message + - file_header + - first_where + - force_unwrapping + - implicit_return + - implicitly_unwrapped_optional + - joined_default_parameter + - let_var_whitespace + - multiline_parameters + - nimble_operator + - no_extension_access_modifier + - no_grouping_extension + - number_separator + - object_literal + - operator_usage_whitespace + - overridden_super_call + - pattern_matching_keywords + - private_outlet + - prohibited_super_call + - quick_discouraged_call + - redundant_nil_coalescing + - single_test_class + - sorted_imports + - strict_fileprivate + - switch_case_on_newline + - trailing_closure + - unneeded_parentheses_in_closure_argument + - vertical_parameter_alignment_on_call + +file_header: + required_pattern: | + \/\/ + \/\/ .*?\.swift + \/\/ SyntaxKit + \/\/( + \/\/ .* + \/\/)? + \/\/ Created by .*? on \d{1,2}\/\d{1,2}\/\d{2}\. + \/\/ Copyright © \d{4}(-\d{4})? .*?\. All rights reserved\. + \/\/ diff --git a/Cartfile b/Cartfile deleted file mode 100644 index f2fffd9..0000000 --- a/Cartfile +++ /dev/null @@ -1 +0,0 @@ -github "soffes/X" diff --git a/Cartfile.resolved b/Cartfile.resolved deleted file mode 100644 index f9795d5..0000000 --- a/Cartfile.resolved +++ /dev/null @@ -1 +0,0 @@ -github "soffes/X" "v0.3.1" diff --git a/Readme.markdown b/Readme.markdown index 530eaf8..b0b9580 100644 --- a/Readme.markdown +++ b/Readme.markdown @@ -4,12 +4,12 @@ SyntaxKit makes TextMate-style syntax highlighting easy. It works on iOS, watchOS, and OS X. -SyntaxKit was abstracted from [Whiskey](http://usewhiskey.com). +SyntaxKit was originally abstracted from [Whiskey](http://usewhiskey.com). ## Building -SyntaxKit is written in Swift 2 so Xcode 7 is required. There aren't any dependencies besides system frameworks. +SyntaxKit is written in Swift 5 so Xcode 10 is required. There aren't any dependencies besides system frameworks. ## Installation @@ -35,19 +35,20 @@ SyntaxKit uses `tmLanguage` and `tmTheme` files to highlight source code. None a ### Basic Parsing -Once you have a language, you can get started: +Once you have a BundleManager, you can get started: ```swift import SyntaxKit -let path = "path to your .tmLanguage file" -let plist = NSDictionary(contentsOfFile: path)! as [NSObject: AnyObject] -let yaml = Language(dictionary: plist) +let manager = BundleManager() { identifier, kind in + URL(string: "Location of Bundles/" + identifier + ".plist") +} +let yaml = manager.language(withIdentifier: "source.yaml")! let parser = Parser(language: yaml) ``` -`Parser` is a very simple class that just calls a block when it finds something the language file knows about. Let's print all of the elements in this string: +`Parser` is a class that calls a block when it finds something the language file knows about. Let's print all of the elements in this string: ```swift let input = "title: \"Hello World\"\n" @@ -64,7 +65,7 @@ parser.parse(input) { scope, range in SyntaxKit also comes with `AttributedParser`. This is a simple subclass of `Parser` that knows how to work with themes. ```swift -let tomorrow = Theme(dictionary: themePlist) +let tomorrow = manager.theme(withIdentifier: "tomorrow")! let attributedParser = AttributedParser(language: yaml, theme: tomorrow) attributedParser.parse(input) { scope, range, attributes in @@ -72,16 +73,19 @@ attributedParser.parse(input) { scope, range, attributes in } ``` -Notice that `attributes` is the third paramenter to the block now. This is a dictionary of attributes you can give to `NSAttributedString`. Other values may be included here that don't work with `NSAttributedString`. You can do your own inspection and do something custom if you want. +Notice that `attributes` is the third parameter to the block now. This is a dictionary of attributes you can give to `NSAttributedString`. `AttributedParser` includes a convenience method for turning a `String` of source code into an `NSAttributedString`: ```swift -let attributedString = attributedParser.attributedStringForString(input) +let attributedString = attributedParser.attributedString(for: input) ``` Easy as that. This method takes an optional `baseAttributes` parameter to customize how the string is created. This is great if you want to specify a font, etc. +### Parsing Operations + +There is also a `AttributedParsingOperation` subclass of NSOperation that facilitates multithreaded parsing. ### Custom Parsers diff --git a/SyntaxKit.podspec b/SyntaxKit.podspec index 57d6ff7..9dcc333 100644 --- a/SyntaxKit.podspec +++ b/SyntaxKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'SyntaxKit' - spec.version = '0.1.0' + spec.version = '1.0' spec.authors = {'Sam Soffes' => 'sam@soff.es'} spec.homepage = 'https://github.com/soffes/SyntaxKit' spec.summary = 'TextMate-style syntax highlighting.' @@ -14,4 +14,6 @@ Pod::Spec.new do |spec| spec.osx.frameworks = 'Foundation', 'AppKit' spec.source_files = 'SyntaxKit/*.{h,m,swift}' + + spec.module_name = 'SyntaxKit' end diff --git a/SyntaxKit.xcodeproj/project.pbxproj b/SyntaxKit.xcodeproj/project.pbxproj index eb2ab12..281827a 100644 --- a/SyntaxKit.xcodeproj/project.pbxproj +++ b/SyntaxKit.xcodeproj/project.pbxproj @@ -17,7 +17,6 @@ 211826F11D257A7E003F2BF2 /* AttributedParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898C1B2EC38B00F0D786 /* AttributedParser.swift */; }; 211826F21D257A7E003F2BF2 /* Capture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898D1B2EC38B00F0D786 /* Capture.swift */; }; 211826F31D257A7E003F2BF2 /* CaptureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898E1B2EC38B00F0D786 /* CaptureCollection.swift */; }; - 211826F41D257A7E003F2BF2 /* Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989901B2EC38B00F0D786 /* Language.swift */; }; 211826F51D257A7E003F2BF2 /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989911B2EC38B00F0D786 /* Parser.swift */; }; 211826F61D257A7E003F2BF2 /* Pattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989921B2EC38B00F0D786 /* Pattern.swift */; }; 211826F71D257A7E003F2BF2 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989931B2EC38B00F0D786 /* Result.swift */; }; @@ -31,20 +30,16 @@ 211826FF1D257A8A003F2BF2 /* Ruby.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 210BF26F1B37C0A2008AA4F0 /* Ruby.tmLanguage */; }; 211827001D257A8A003F2BF2 /* test.rb.txt in Resources */ = {isa = PBXBuildFile; fileRef = 210BF26C1B37C04E008AA4F0 /* test.rb.txt */; }; 211827011D257A8A003F2BF2 /* Tomorrow.tmTheme in Resources */ = {isa = PBXBuildFile; fileRef = 2119897E1B2EAF0900F0D786 /* Tomorrow.tmTheme */; }; - 211827021D257A8A003F2BF2 /* YAML.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 2119897F1B2EAF0900F0D786 /* YAML.tmLanguage */; }; + 211827021D257A8A003F2BF2 /* Yaml.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 2119897F1B2EAF0900F0D786 /* Yaml.tmLanguage */; }; 211827031D257AA3003F2BF2 /* SyntaxKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 211989951B2EC38B00F0D786 /* SyntaxKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 211827071D257B3F003F2BF2 /* X.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 211827051D257B3C003F2BF2 /* X.framework */; }; - 211827BE1D258068003F2BF2 /* X.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 211827051D257B3C003F2BF2 /* X.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 211827BF1D2580A8003F2BF2 /* X.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 211827051D257B3C003F2BF2 /* X.framework */; }; 211989801B2EAF0900F0D786 /* Tomorrow.tmTheme in Resources */ = {isa = PBXBuildFile; fileRef = 2119897E1B2EAF0900F0D786 /* Tomorrow.tmTheme */; }; - 211989811B2EAF0900F0D786 /* YAML.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 2119897F1B2EAF0900F0D786 /* YAML.tmLanguage */; }; + 211989811B2EAF0900F0D786 /* Yaml.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 2119897F1B2EAF0900F0D786 /* Yaml.tmLanguage */; }; 211989841B2EB18600F0D786 /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989821B2EB18000F0D786 /* TestHelper.swift */; }; 211989891B2EB8D400F0D786 /* ParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989881B2EB8D400F0D786 /* ParserTests.swift */; }; 2119898B1B2EBA2C00F0D786 /* ThemeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898A1B2EBA2C00F0D786 /* ThemeTests.swift */; }; 211989971B2EC38B00F0D786 /* AttributedParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898C1B2EC38B00F0D786 /* AttributedParser.swift */; }; 211989981B2EC38B00F0D786 /* Capture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898D1B2EC38B00F0D786 /* Capture.swift */; }; 211989991B2EC38B00F0D786 /* CaptureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898E1B2EC38B00F0D786 /* CaptureCollection.swift */; }; - 2119899B1B2EC38B00F0D786 /* Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989901B2EC38B00F0D786 /* Language.swift */; }; 2119899C1B2EC38B00F0D786 /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989911B2EC38B00F0D786 /* Parser.swift */; }; 2119899D1B2EC38B00F0D786 /* Pattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989921B2EC38B00F0D786 /* Pattern.swift */; }; 2119899E1B2EC38B00F0D786 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989931B2EC38B00F0D786 /* Result.swift */; }; @@ -56,41 +51,86 @@ 211989BF1B2EC40500F0D786 /* AttributedParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898C1B2EC38B00F0D786 /* AttributedParser.swift */; }; 211989C01B2EC40500F0D786 /* Capture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898D1B2EC38B00F0D786 /* Capture.swift */; }; 211989C11B2EC40500F0D786 /* CaptureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898E1B2EC38B00F0D786 /* CaptureCollection.swift */; }; - 211989C31B2EC40500F0D786 /* Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989901B2EC38B00F0D786 /* Language.swift */; }; 211989C41B2EC40500F0D786 /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989911B2EC38B00F0D786 /* Parser.swift */; }; 211989C51B2EC40500F0D786 /* Pattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989921B2EC38B00F0D786 /* Pattern.swift */; }; 211989C61B2EC40500F0D786 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989931B2EC38B00F0D786 /* Result.swift */; }; 211989C71B2EC40500F0D786 /* ResultSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989941B2EC38B00F0D786 /* ResultSet.swift */; }; 211989C81B2EC40500F0D786 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989961B2EC38B00F0D786 /* Theme.swift */; }; 211989C91B2EC40900F0D786 /* Tomorrow.tmTheme in Resources */ = {isa = PBXBuildFile; fileRef = 2119897E1B2EAF0900F0D786 /* Tomorrow.tmTheme */; }; - 211989CA1B2EC40900F0D786 /* YAML.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 2119897F1B2EAF0900F0D786 /* YAML.tmLanguage */; }; + 211989CA1B2EC40900F0D786 /* Yaml.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 2119897F1B2EAF0900F0D786 /* Yaml.tmLanguage */; }; 211989CB1B2EC40C00F0D786 /* TestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989821B2EB18000F0D786 /* TestHelper.swift */; }; 211989CC1B2EC40C00F0D786 /* ParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989881B2EB8D400F0D786 /* ParserTests.swift */; }; 211989CD1B2EC40C00F0D786 /* AttributedParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 210299D01B2E8924009C61EE /* AttributedParserTests.swift */; }; 211989CE1B2EC40C00F0D786 /* LanguageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 210299CF1B2E8924009C61EE /* LanguageTests.swift */; }; 211989CF1B2EC40C00F0D786 /* ThemeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898A1B2EBA2C00F0D786 /* ThemeTests.swift */; }; 2122A6EA1B22B9320006409B /* SyntaxKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2122A6DE1B22B9320006409B /* SyntaxKit.framework */; }; - 2132B6201B7BFFA700C2F25B /* X.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F28DDC1B7AC802009DD1E9 /* X.framework */; }; - 2132B6211B7BFFAD00C2F25B /* X.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F28DDA1B7AC7F8009DD1E9 /* X.framework */; }; - 2132B6231B7BFFFD00C2F25B /* X.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 21F28DDC1B7AC802009DD1E9 /* X.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 2132B6251B7C000A00C2F25B /* X.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 21F28DDA1B7AC7F8009DD1E9 /* X.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 2198CED21B36D5DE00BD463F /* AttributedParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898C1B2EC38B00F0D786 /* AttributedParser.swift */; }; 2198CED31B36D5DE00BD463F /* Capture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898D1B2EC38B00F0D786 /* Capture.swift */; }; 2198CED41B36D5DE00BD463F /* CaptureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2119898E1B2EC38B00F0D786 /* CaptureCollection.swift */; }; - 2198CED61B36D5DE00BD463F /* Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989901B2EC38B00F0D786 /* Language.swift */; }; 2198CED71B36D5DE00BD463F /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989911B2EC38B00F0D786 /* Parser.swift */; }; 2198CED81B36D5DE00BD463F /* Pattern.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989921B2EC38B00F0D786 /* Pattern.swift */; }; 2198CED91B36D5DE00BD463F /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989931B2EC38B00F0D786 /* Result.swift */; }; 2198CEDA1B36D5DE00BD463F /* ResultSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989941B2EC38B00F0D786 /* ResultSet.swift */; }; 2198CEDB1B36D5DE00BD463F /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211989961B2EC38B00F0D786 /* Theme.swift */; }; 2198CEDC1B36D5E100BD463F /* SyntaxKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 211989951B2EC38B00F0D786 /* SyntaxKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 21F28DDB1B7AC7F8009DD1E9 /* X.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F28DDA1B7AC7F8009DD1E9 /* X.framework */; }; - 21F28DDD1B7AC802009DD1E9 /* X.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F28DDC1B7AC802009DD1E9 /* X.framework */; }; - 21F28DDF1B7AC80B009DD1E9 /* X.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F28DDE1B7AC80B009DD1E9 /* X.framework */; }; - 92EC79D41CC9060600E058ED /* JavaScript.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 92EC79D31CC9060600E058ED /* JavaScript.tmLanguage */; }; - 92EC79D51CC9060600E058ED /* JavaScript.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 92EC79D31CC9060600E058ED /* JavaScript.tmLanguage */; }; - 92EC79D71CC9061D00E058ED /* test.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 92EC79D61CC9061D00E058ED /* test.js.txt */; }; - 92EC79D81CC9061D00E058ED /* test.js.txt in Resources */ = {isa = PBXBuildFile; fileRef = 92EC79D61CC9061D00E058ED /* test.js.txt */; }; + 8C08C3C71C36FD6D00D8548F /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C08C3C61C36FD6D00D8548F /* Color.swift */; }; + 8C10B6441CC38E5200740E00 /* AttributedParsingOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C10B6431CC38E5200740E00 /* AttributedParsingOperation.swift */; }; + 8C10B6451CC38E5200740E00 /* AttributedParsingOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C10B6431CC38E5200740E00 /* AttributedParsingOperation.swift */; }; + 8C10B6461CC38E5200740E00 /* AttributedParsingOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C10B6431CC38E5200740E00 /* AttributedParsingOperation.swift */; }; + 8C10B6471CC3937F00740E00 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C08C3C61C36FD6D00D8548F /* Color.swift */; }; + 8C10B6481CC3938100740E00 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C08C3C61C36FD6D00D8548F /* Color.swift */; }; + 8C10B6491CC393E700740E00 /* ScopedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C9003321C5C0B0D00CBA5B0 /* ScopedString.swift */; }; + 8C2EB3571D4B50EE005ECE2B /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C08C3C61C36FD6D00D8548F /* Color.swift */; }; + 8C2EB3581D4B510F005ECE2B /* Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE64FE21C74B48D0007BA57 /* Language.swift */; }; + 8C2EB3591D4B5126005ECE2B /* AttributedParsingOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C10B6431CC38E5200740E00 /* AttributedParsingOperation.swift */; }; + 8C2EB35A1D4B5126005ECE2B /* ScopedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C9003321C5C0B0D00CBA5B0 /* ScopedString.swift */; }; + 8C2EB35B1D4B5126005ECE2B /* BundleManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CDD6F1A1C71594B0063915A /* BundleManager.swift */; }; + 8C2EB35C1D4B5126005ECE2B /* Repository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CEEC0E11C411F9700BF3E85 /* Repository.swift */; }; + 8C2EB35D1D4B5126005ECE2B /* ReferenceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CEEC0DD1C411C8600BF3E85 /* ReferenceManager.swift */; }; + 8C2EB35E1D4B524F005ECE2B /* SwiftBaselineHighlightingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE8D1161C4EBF8F005A86B3 /* SwiftBaselineHighlightingTests.swift */; }; + 8C2EB35F1D4B524F005ECE2B /* IncrementalParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C71A05C1C59587700041EC6 /* IncrementalParsingTests.swift */; }; + 8C2EB3601D4B524F005ECE2B /* ScopedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE6BE2D1C5D1BBA002676BD /* ScopedStringTests.swift */; }; + 8C2EB3611D4B525A005ECE2B /* Swift.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 8CE8D1131C4EBF58005A86B3 /* Swift.tmLanguage */; }; + 8C2EB3621D4B525A005ECE2B /* swifttest.swift.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8CB2FD221C4D877D008ECD6D /* swifttest.swift.txt */; }; + 8C2EB3631D4B525A005ECE2B /* Solarized.tmTheme in Resources */ = {isa = PBXBuildFile; fileRef = 8CB2FD251C4D87D6008ECD6D /* Solarized.tmTheme */; }; + 8C4D09C01E1EAF750034974A /* PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C4D09BF1E1EAF750034974A /* PerformanceTests.swift */; }; + 8C4D09C11E1EAF750034974A /* PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C4D09BF1E1EAF750034974A /* PerformanceTests.swift */; }; + 8C4D09C21E1EAF750034974A /* PerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C4D09BF1E1EAF750034974A /* PerformanceTests.swift */; }; + 8C4D09C41E1EB0670034974A /* Latex.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 8C4D09C31E1EB0670034974A /* Latex.tmLanguage */; }; + 8C4D09C51E1EB0670034974A /* Latex.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 8C4D09C31E1EB0670034974A /* Latex.tmLanguage */; }; + 8C4D09C61E1EB0670034974A /* Latex.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 8C4D09C31E1EB0670034974A /* Latex.tmLanguage */; }; + 8C4D09C81E1EB07D0034974A /* Tex.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 8C4D09C71E1EB07D0034974A /* Tex.tmLanguage */; }; + 8C4D09C91E1EB07D0034974A /* Tex.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 8C4D09C71E1EB07D0034974A /* Tex.tmLanguage */; }; + 8C4D09CA1E1EB07D0034974A /* Tex.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 8C4D09C71E1EB07D0034974A /* Tex.tmLanguage */; }; + 8C4D09CC1E1EB16C0034974A /* textest.tex.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8C4D09CB1E1EB16C0034974A /* textest.tex.txt */; }; + 8C4D09CD1E1EB16C0034974A /* textest.tex.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8C4D09CB1E1EB16C0034974A /* textest.tex.txt */; }; + 8C4D09CE1E1EB16C0034974A /* textest.tex.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8C4D09CB1E1EB16C0034974A /* textest.tex.txt */; }; + 8C71A05D1C59587700041EC6 /* IncrementalParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C71A05C1C59587700041EC6 /* IncrementalParsingTests.swift */; }; + 8C71A05E1C59587700041EC6 /* IncrementalParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C71A05C1C59587700041EC6 /* IncrementalParsingTests.swift */; }; + 8C9003331C5C0B0D00CBA5B0 /* ScopedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C9003321C5C0B0D00CBA5B0 /* ScopedString.swift */; }; + 8C9003341C5C0B0D00CBA5B0 /* ScopedString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C9003321C5C0B0D00CBA5B0 /* ScopedString.swift */; }; + 8CAEC6BA1D3BB297001C57D3 /* swifttest.swift.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8CB2FD221C4D877D008ECD6D /* swifttest.swift.txt */; }; + 8CB2FD261C4D87D6008ECD6D /* Solarized.tmTheme in Resources */ = {isa = PBXBuildFile; fileRef = 8CB2FD251C4D87D6008ECD6D /* Solarized.tmTheme */; }; + 8CB2FD271C4D87D6008ECD6D /* Solarized.tmTheme in Resources */ = {isa = PBXBuildFile; fileRef = 8CB2FD251C4D87D6008ECD6D /* Solarized.tmTheme */; }; + 8CB2FD281C4D891A008ECD6D /* swifttest.swift.txt in Resources */ = {isa = PBXBuildFile; fileRef = 8CB2FD221C4D877D008ECD6D /* swifttest.swift.txt */; }; + 8CDD6F1B1C71594B0063915A /* BundleManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CDD6F1A1C71594B0063915A /* BundleManager.swift */; }; + 8CDD6F1C1C71594B0063915A /* BundleManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CDD6F1A1C71594B0063915A /* BundleManager.swift */; }; + 8CDD6F1D1C71594B0063915A /* BundleManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CDD6F1A1C71594B0063915A /* BundleManager.swift */; }; + 8CE64FE31C74B48D0007BA57 /* Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE64FE21C74B48D0007BA57 /* Language.swift */; }; + 8CE64FE41C74B48D0007BA57 /* Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE64FE21C74B48D0007BA57 /* Language.swift */; }; + 8CE64FE51C74B48D0007BA57 /* Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE64FE21C74B48D0007BA57 /* Language.swift */; }; + 8CE6BE2E1C5D1BBA002676BD /* ScopedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE6BE2D1C5D1BBA002676BD /* ScopedStringTests.swift */; }; + 8CE6BE2F1C5D1BBA002676BD /* ScopedStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE6BE2D1C5D1BBA002676BD /* ScopedStringTests.swift */; }; + 8CE8D1141C4EBF58005A86B3 /* Swift.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 8CE8D1131C4EBF58005A86B3 /* Swift.tmLanguage */; }; + 8CE8D1151C4EBF58005A86B3 /* Swift.tmLanguage in Resources */ = {isa = PBXBuildFile; fileRef = 8CE8D1131C4EBF58005A86B3 /* Swift.tmLanguage */; }; + 8CE8D1171C4EBF8F005A86B3 /* SwiftBaselineHighlightingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE8D1161C4EBF8F005A86B3 /* SwiftBaselineHighlightingTests.swift */; }; + 8CE8D1181C4EBF8F005A86B3 /* SwiftBaselineHighlightingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE8D1161C4EBF8F005A86B3 /* SwiftBaselineHighlightingTests.swift */; }; + 8CEEC0DE1C411C8600BF3E85 /* ReferenceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CEEC0DD1C411C8600BF3E85 /* ReferenceManager.swift */; }; + 8CEEC0DF1C411C8600BF3E85 /* ReferenceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CEEC0DD1C411C8600BF3E85 /* ReferenceManager.swift */; }; + 8CEEC0E01C411C8600BF3E85 /* ReferenceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CEEC0DD1C411C8600BF3E85 /* ReferenceManager.swift */; }; + 8CEEC0E21C411F9700BF3E85 /* Repository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CEEC0E11C411F9700BF3E85 /* Repository.swift */; }; + 8CEEC0E31C411F9700BF3E85 /* Repository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CEEC0E11C411F9700BF3E85 /* Repository.swift */; }; + 8CEEC0E41C411F9700BF3E85 /* Repository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CEEC0E11C411F9700BF3E85 /* Repository.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -124,7 +164,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 211827BE1D258068003F2BF2 /* X.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -135,7 +174,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 2132B6231B7BFFFD00C2F25B /* X.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -146,7 +184,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 2132B6251B7C000A00C2F25B /* X.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -162,18 +199,16 @@ 210BF26F1B37C0A2008AA4F0 /* Ruby.tmLanguage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Ruby.tmLanguage; sourceTree = ""; }; 211826DA1D257A71003F2BF2 /* SyntaxKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SyntaxKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 211826E31D257A71003F2BF2 /* SyntaxKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SyntaxKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 211827051D257B3C003F2BF2 /* X.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = X.framework; path = Carthage/Build/tvOS/X.framework; sourceTree = ""; }; 2119897E1B2EAF0900F0D786 /* Tomorrow.tmTheme */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Tomorrow.tmTheme; sourceTree = ""; }; - 2119897F1B2EAF0900F0D786 /* YAML.tmLanguage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = YAML.tmLanguage; sourceTree = ""; }; + 2119897F1B2EAF0900F0D786 /* Yaml.tmLanguage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Yaml.tmLanguage; sourceTree = ""; }; 211989821B2EB18000F0D786 /* TestHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestHelper.swift; sourceTree = ""; }; 211989881B2EB8D400F0D786 /* ParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParserTests.swift; sourceTree = ""; }; 2119898A1B2EBA2C00F0D786 /* ThemeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThemeTests.swift; sourceTree = ""; }; 2119898C1B2EC38B00F0D786 /* AttributedParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttributedParser.swift; sourceTree = ""; }; 2119898D1B2EC38B00F0D786 /* Capture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Capture.swift; sourceTree = ""; }; 2119898E1B2EC38B00F0D786 /* CaptureCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaptureCollection.swift; sourceTree = ""; }; - 211989901B2EC38B00F0D786 /* Language.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Language.swift; sourceTree = ""; }; - 211989911B2EC38B00F0D786 /* Parser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = ""; }; - 211989921B2EC38B00F0D786 /* Pattern.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Pattern.swift; sourceTree = ""; }; + 211989911B2EC38B00F0D786 /* Parser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Parser.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 211989921B2EC38B00F0D786 /* Pattern.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Pattern.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 211989931B2EC38B00F0D786 /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = ""; }; 211989941B2EC38B00F0D786 /* ResultSet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultSet.swift; sourceTree = ""; }; 211989951B2EC38B00F0D786 /* SyntaxKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SyntaxKit.h; sourceTree = ""; }; @@ -183,11 +218,23 @@ 2122A6DE1B22B9320006409B /* SyntaxKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SyntaxKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2122A6E91B22B9320006409B /* SyntaxKitTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SyntaxKitTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 2198CECA1B36D5D700BD463F /* SyntaxKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SyntaxKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 21F28DDA1B7AC7F8009DD1E9 /* X.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = X.framework; path = Carthage/Build/iOS/X.framework; sourceTree = ""; }; - 21F28DDC1B7AC802009DD1E9 /* X.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = X.framework; path = Carthage/Build/Mac/X.framework; sourceTree = ""; }; - 21F28DDE1B7AC80B009DD1E9 /* X.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = X.framework; path = Carthage/Build/watchOS/X.framework; sourceTree = ""; }; - 92EC79D31CC9060600E058ED /* JavaScript.tmLanguage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = JavaScript.tmLanguage; sourceTree = ""; }; - 92EC79D61CC9061D00E058ED /* test.js.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = test.js.txt; sourceTree = ""; }; + 8C08C3C61C36FD6D00D8548F /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Color.swift; path = ../Color.swift; sourceTree = ""; }; + 8C10B6431CC38E5200740E00 /* AttributedParsingOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AttributedParsingOperation.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 8C4D09BF1E1EAF750034974A /* PerformanceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PerformanceTests.swift; sourceTree = ""; }; + 8C4D09C31E1EB0670034974A /* Latex.tmLanguage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Latex.tmLanguage; sourceTree = ""; }; + 8C4D09C71E1EB07D0034974A /* Tex.tmLanguage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Tex.tmLanguage; sourceTree = ""; }; + 8C4D09CB1E1EB16C0034974A /* textest.tex.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = textest.tex.txt; sourceTree = ""; }; + 8C71A05C1C59587700041EC6 /* IncrementalParsingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IncrementalParsingTests.swift; sourceTree = ""; }; + 8C9003321C5C0B0D00CBA5B0 /* ScopedString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScopedString.swift; sourceTree = ""; }; + 8CB2FD221C4D877D008ECD6D /* swifttest.swift.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = swifttest.swift.txt; sourceTree = ""; }; + 8CB2FD251C4D87D6008ECD6D /* Solarized.tmTheme */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Solarized.tmTheme; sourceTree = ""; }; + 8CDD6F1A1C71594B0063915A /* BundleManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BundleManager.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 8CE64FE21C74B48D0007BA57 /* Language.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Language.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 8CE6BE2D1C5D1BBA002676BD /* ScopedStringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScopedStringTests.swift; sourceTree = ""; }; + 8CE8D1131C4EBF58005A86B3 /* Swift.tmLanguage */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Swift.tmLanguage; sourceTree = ""; }; + 8CE8D1161C4EBF8F005A86B3 /* SwiftBaselineHighlightingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftBaselineHighlightingTests.swift; sourceTree = ""; }; + 8CEEC0DD1C411C8600BF3E85 /* ReferenceManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ReferenceManager.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 8CEEC0E11C411F9700BF3E85 /* Repository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Repository.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -195,7 +242,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 211827071D257B3F003F2BF2 /* X.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -204,7 +250,6 @@ buildActionMask = 2147483647; files = ( 211826E41D257A71003F2BF2 /* SyntaxKit.framework in Frameworks */, - 211827BF1D2580A8003F2BF2 /* X.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -212,7 +257,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 21F28DDB1B7AC7F8009DD1E9 /* X.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -221,7 +265,6 @@ buildActionMask = 2147483647; files = ( 211989B11B2EC3B600F0D786 /* SyntaxKit.framework in Frameworks */, - 2132B6211B7BFFAD00C2F25B /* X.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -229,7 +272,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 21F28DDD1B7AC802009DD1E9 /* X.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -238,7 +280,6 @@ buildActionMask = 2147483647; files = ( 2122A6EA1B22B9320006409B /* SyntaxKit.framework in Frameworks */, - 2132B6201B7BFFA700C2F25B /* X.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -246,7 +287,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 21F28DDF1B7AC80B009DD1E9 /* X.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -256,6 +296,7 @@ 210299C11B2E8924009C61EE /* Resources */ = { isa = PBXGroup; children = ( + 8C08C3C61C36FD6D00D8548F /* Color.swift */, 210299C21B2E8924009C61EE /* Info.plist */, ); path = Resources; @@ -268,6 +309,10 @@ 211989821B2EB18000F0D786 /* TestHelper.swift */, 211989881B2EB8D400F0D786 /* ParserTests.swift */, 210299D01B2E8924009C61EE /* AttributedParserTests.swift */, + 8C4D09BF1E1EAF750034974A /* PerformanceTests.swift */, + 8CE8D1161C4EBF8F005A86B3 /* SwiftBaselineHighlightingTests.swift */, + 8C71A05C1C59587700041EC6 /* IncrementalParsingTests.swift */, + 8CE6BE2D1C5D1BBA002676BD /* ScopedStringTests.swift */, 210299CF1B2E8924009C61EE /* LanguageTests.swift */, 2119898A1B2EBA2C00F0D786 /* ThemeTests.swift */, ); @@ -287,28 +332,23 @@ isa = PBXGroup; children = ( 210BF26F1B37C0A2008AA4F0 /* Ruby.tmLanguage */, + 8CE8D1131C4EBF58005A86B3 /* Swift.tmLanguage */, + 8C4D09C31E1EB0670034974A /* Latex.tmLanguage */, + 8C4D09C71E1EB07D0034974A /* Tex.tmLanguage */, + 8CB2FD221C4D877D008ECD6D /* swifttest.swift.txt */, + 8C4D09CB1E1EB16C0034974A /* textest.tex.txt */, 210BF26C1B37C04E008AA4F0 /* test.rb.txt */, + 8CB2FD251C4D87D6008ECD6D /* Solarized.tmTheme */, 2119897E1B2EAF0900F0D786 /* Tomorrow.tmTheme */, - 2119897F1B2EAF0900F0D786 /* YAML.tmLanguage */, - 92EC79D31CC9060600E058ED /* JavaScript.tmLanguage */, - 92EC79D61CC9061D00E058ED /* test.js.txt */, + 2119897F1B2EAF0900F0D786 /* Yaml.tmLanguage */, ); path = Fixtures; sourceTree = ""; }; - 211827041D257B2D003F2BF2 /* tvOS */ = { - isa = PBXGroup; - children = ( - 211827051D257B3C003F2BF2 /* X.framework */, - ); - name = tvOS; - sourceTree = ""; - }; 2122A6D41B22B9320006409B = { isa = PBXGroup; children = ( 2122A6E01B22B9320006409B /* SyntaxKit */, - 21F28DD61B7AC7D0009DD1E9 /* Frameworks */, 2122A6DF1B22B9320006409B /* Products */, ); sourceTree = ""; @@ -331,56 +371,26 @@ isa = PBXGroup; children = ( 211989951B2EC38B00F0D786 /* SyntaxKit.h */, + 8C10B6431CC38E5200740E00 /* AttributedParsingOperation.swift */, 2119898C1B2EC38B00F0D786 /* AttributedParser.swift */, - 2119898D1B2EC38B00F0D786 /* Capture.swift */, - 2119898E1B2EC38B00F0D786 /* CaptureCollection.swift */, - 211989901B2EC38B00F0D786 /* Language.swift */, 211989911B2EC38B00F0D786 /* Parser.swift */, - 211989921B2EC38B00F0D786 /* Pattern.swift */, - 211989931B2EC38B00F0D786 /* Result.swift */, + 8C9003321C5C0B0D00CBA5B0 /* ScopedString.swift */, 211989941B2EC38B00F0D786 /* ResultSet.swift */, + 211989931B2EC38B00F0D786 /* Result.swift */, + 8CDD6F1A1C71594B0063915A /* BundleManager.swift */, 211989961B2EC38B00F0D786 /* Theme.swift */, + 8CE64FE21C74B48D0007BA57 /* Language.swift */, + 8CEEC0E11C411F9700BF3E85 /* Repository.swift */, + 8CEEC0DD1C411C8600BF3E85 /* ReferenceManager.swift */, + 211989921B2EC38B00F0D786 /* Pattern.swift */, + 2119898E1B2EC38B00F0D786 /* CaptureCollection.swift */, + 2119898D1B2EC38B00F0D786 /* Capture.swift */, 210299C11B2E8924009C61EE /* Resources */, 210299CD1B2E8924009C61EE /* Tests */, ); path = SyntaxKit; sourceTree = ""; }; - 21F28DD61B7AC7D0009DD1E9 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 21F28DD71B7AC7D6009DD1E9 /* macOS */, - 21F28DD81B7AC7DC009DD1E9 /* iOS */, - 21F28DD91B7AC7DF009DD1E9 /* watchOS */, - 211827041D257B2D003F2BF2 /* tvOS */, - ); - name = Frameworks; - sourceTree = ""; - }; - 21F28DD71B7AC7D6009DD1E9 /* macOS */ = { - isa = PBXGroup; - children = ( - 21F28DDC1B7AC802009DD1E9 /* X.framework */, - ); - name = macOS; - sourceTree = ""; - }; - 21F28DD81B7AC7DC009DD1E9 /* iOS */ = { - isa = PBXGroup; - children = ( - 21F28DDA1B7AC7F8009DD1E9 /* X.framework */, - ); - name = iOS; - sourceTree = ""; - }; - 21F28DD91B7AC7DF009DD1E9 /* watchOS */ = { - isa = PBXGroup; - children = ( - 21F28DDE1B7AC80B009DD1E9 /* X.framework */, - ); - name = watchOS; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -501,6 +511,7 @@ 2122A6DA1B22B9320006409B /* Frameworks */, 2122A6DB1B22B9320006409B /* Headers */, 2122A6DC1B22B9320006409B /* Resources */, + 8CDFB7351EE5BA1200CBB1D1 /* ShellScript */, ); buildRules = ( ); @@ -555,7 +566,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0730; - LastUpgradeCheck = 0700; + LastUpgradeCheck = 1030; ORGANIZATIONNAME = "Sam Soffes"; TargetAttributes = { 211826D91D257A71003F2BF2 = { @@ -566,9 +577,11 @@ }; 211989A61B2EC3B600F0D786 = { CreatedOnToolsVersion = 7.0; + LastSwiftMigration = 1030; }; 211989AF1B2EC3B600F0D786 = { CreatedOnToolsVersion = 7.0; + LastSwiftMigration = 1030; }; 2122A6DD1B22B9320006409B = { CreatedOnToolsVersion = 6.3.2; @@ -583,10 +596,11 @@ }; buildConfigurationList = 2122A6D81B22B9320006409B /* Build configuration list for PBXProject "SyntaxKit" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 2122A6D41B22B9320006409B; productRefGroup = 2122A6DF1B22B9320006409B /* Products */; @@ -616,10 +630,16 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8C2EB3611D4B525A005ECE2B /* Swift.tmLanguage in Resources */, + 8C2EB3621D4B525A005ECE2B /* swifttest.swift.txt in Resources */, + 8C2EB3631D4B525A005ECE2B /* Solarized.tmTheme in Resources */, + 8C4D09CA1E1EB07D0034974A /* Tex.tmLanguage in Resources */, 211826FF1D257A8A003F2BF2 /* Ruby.tmLanguage in Resources */, - 211827021D257A8A003F2BF2 /* YAML.tmLanguage in Resources */, + 8C4D09C61E1EB0670034974A /* Latex.tmLanguage in Resources */, + 211827021D257A8A003F2BF2 /* Yaml.tmLanguage in Resources */, 211827001D257A8A003F2BF2 /* test.rb.txt in Resources */, 211827011D257A8A003F2BF2 /* Tomorrow.tmTheme in Resources */, + 8C4D09CE1E1EB16C0034974A /* textest.tex.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -634,12 +654,16 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8CE8D1151C4EBF58005A86B3 /* Swift.tmLanguage in Resources */, 210BF2711B37C0A2008AA4F0 /* Ruby.tmLanguage in Resources */, + 211989CA1B2EC40900F0D786 /* Yaml.tmLanguage in Resources */, + 8C4D09C91E1EB07D0034974A /* Tex.tmLanguage in Resources */, 211989C91B2EC40900F0D786 /* Tomorrow.tmTheme in Resources */, - 92EC79D81CC9061D00E058ED /* test.js.txt in Resources */, + 8C4D09C51E1EB0670034974A /* Latex.tmLanguage in Resources */, + 8CB2FD271C4D87D6008ECD6D /* Solarized.tmTheme in Resources */, 210BF26E1B37C04E008AA4F0 /* test.rb.txt in Resources */, - 211989CA1B2EC40900F0D786 /* YAML.tmLanguage in Resources */, - 92EC79D51CC9060600E058ED /* JavaScript.tmLanguage in Resources */, + 8CB2FD281C4D891A008ECD6D /* swifttest.swift.txt in Resources */, + 8C4D09CD1E1EB16C0034974A /* textest.tex.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -654,12 +678,16 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8CE8D1141C4EBF58005A86B3 /* Swift.tmLanguage in Resources */, 210BF2701B37C0A2008AA4F0 /* Ruby.tmLanguage in Resources */, + 211989811B2EAF0900F0D786 /* Yaml.tmLanguage in Resources */, + 8C4D09C81E1EB07D0034974A /* Tex.tmLanguage in Resources */, 211989801B2EAF0900F0D786 /* Tomorrow.tmTheme in Resources */, - 92EC79D71CC9061D00E058ED /* test.js.txt in Resources */, + 8C4D09C41E1EB0670034974A /* Latex.tmLanguage in Resources */, + 8CB2FD261C4D87D6008ECD6D /* Solarized.tmTheme in Resources */, 210BF26D1B37C04E008AA4F0 /* test.rb.txt in Resources */, - 211989811B2EAF0900F0D786 /* YAML.tmLanguage in Resources */, - 92EC79D41CC9060600E058ED /* JavaScript.tmLanguage in Resources */, + 8CAEC6BA1D3BB297001C57D3 /* swifttest.swift.txt in Resources */, + 8C4D09CC1E1EB16C0034974A /* textest.tex.txt in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -672,15 +700,37 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 8CDFB7351EE5BA1200CBB1D1 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ $CLANG_STATIC_ANALYZER_MODE ]; then\n if which swiftlint >/dev/null; then\n swiftlint\n else\n echo \"Please install SwiftLint\"\n fi\nfi"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 211826D51D257A71003F2BF2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8C2EB3591D4B5126005ECE2B /* AttributedParsingOperation.swift in Sources */, + 8C2EB35A1D4B5126005ECE2B /* ScopedString.swift in Sources */, + 8C2EB35B1D4B5126005ECE2B /* BundleManager.swift in Sources */, + 8C2EB35C1D4B5126005ECE2B /* Repository.swift in Sources */, + 8C2EB35D1D4B5126005ECE2B /* ReferenceManager.swift in Sources */, + 8C2EB3581D4B510F005ECE2B /* Language.swift in Sources */, + 8C2EB3571D4B50EE005ECE2B /* Color.swift in Sources */, 211826F91D257A7E003F2BF2 /* Theme.swift in Sources */, 211826F61D257A7E003F2BF2 /* Pattern.swift in Sources */, 211826F21D257A7E003F2BF2 /* Capture.swift in Sources */, - 211826F41D257A7E003F2BF2 /* Language.swift in Sources */, 211826F51D257A7E003F2BF2 /* Parser.swift in Sources */, 211826F71D257A7E003F2BF2 /* Result.swift in Sources */, 211826F81D257A7E003F2BF2 /* ResultSet.swift in Sources */, @@ -693,11 +743,15 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8C2EB35E1D4B524F005ECE2B /* SwiftBaselineHighlightingTests.swift in Sources */, + 8C2EB35F1D4B524F005ECE2B /* IncrementalParsingTests.swift in Sources */, + 8C2EB3601D4B524F005ECE2B /* ScopedStringTests.swift in Sources */, 211826FD1D257A84003F2BF2 /* LanguageTests.swift in Sources */, 211826FA1D257A84003F2BF2 /* TestHelper.swift in Sources */, 211826FC1D257A84003F2BF2 /* AttributedParserTests.swift in Sources */, 211826FB1D257A84003F2BF2 /* ParserTests.swift in Sources */, 211826FE1D257A84003F2BF2 /* ThemeTests.swift in Sources */, + 8C4D09C21E1EAF750034974A /* PerformanceTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -706,14 +760,20 @@ buildActionMask = 2147483647; files = ( 211989C01B2EC40500F0D786 /* Capture.swift in Sources */, - 211989C31B2EC40500F0D786 /* Language.swift in Sources */, 211989C41B2EC40500F0D786 /* Parser.swift in Sources */, + 8C08C3C71C36FD6D00D8548F /* Color.swift in Sources */, + 8C9003341C5C0B0D00CBA5B0 /* ScopedString.swift in Sources */, 211989C11B2EC40500F0D786 /* CaptureCollection.swift in Sources */, + 8CEEC0DF1C411C8600BF3E85 /* ReferenceManager.swift in Sources */, 211989C71B2EC40500F0D786 /* ResultSet.swift in Sources */, + 8C10B6451CC38E5200740E00 /* AttributedParsingOperation.swift in Sources */, + 8CDD6F1C1C71594B0063915A /* BundleManager.swift in Sources */, 211989C51B2EC40500F0D786 /* Pattern.swift in Sources */, 211989C81B2EC40500F0D786 /* Theme.swift in Sources */, 211989C61B2EC40500F0D786 /* Result.swift in Sources */, + 8CE64FE41C74B48D0007BA57 /* Language.swift in Sources */, 211989BF1B2EC40500F0D786 /* AttributedParser.swift in Sources */, + 8CEEC0E31C411F9700BF3E85 /* Repository.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -723,9 +783,13 @@ files = ( 211989CF1B2EC40C00F0D786 /* ThemeTests.swift in Sources */, 211989CC1B2EC40C00F0D786 /* ParserTests.swift in Sources */, + 8CE6BE2F1C5D1BBA002676BD /* ScopedStringTests.swift in Sources */, + 8C71A05E1C59587700041EC6 /* IncrementalParsingTests.swift in Sources */, 211989CE1B2EC40C00F0D786 /* LanguageTests.swift in Sources */, 211989CB1B2EC40C00F0D786 /* TestHelper.swift in Sources */, + 8CE8D1181C4EBF8F005A86B3 /* SwiftBaselineHighlightingTests.swift in Sources */, 211989CD1B2EC40C00F0D786 /* AttributedParserTests.swift in Sources */, + 8C4D09C11E1EAF750034974A /* PerformanceTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -734,14 +798,20 @@ buildActionMask = 2147483647; files = ( 211989981B2EC38B00F0D786 /* Capture.swift in Sources */, - 2119899B1B2EC38B00F0D786 /* Language.swift in Sources */, + 8CDD6F1B1C71594B0063915A /* BundleManager.swift in Sources */, 2119899C1B2EC38B00F0D786 /* Parser.swift in Sources */, 211989991B2EC38B00F0D786 /* CaptureCollection.swift in Sources */, + 8C10B6441CC38E5200740E00 /* AttributedParsingOperation.swift in Sources */, + 8CEEC0DE1C411C8600BF3E85 /* ReferenceManager.swift in Sources */, + 8CEEC0E21C411F9700BF3E85 /* Repository.swift in Sources */, 2119899F1B2EC38B00F0D786 /* ResultSet.swift in Sources */, + 8C10B6471CC3937F00740E00 /* Color.swift in Sources */, 2119899D1B2EC38B00F0D786 /* Pattern.swift in Sources */, 211989A11B2EC38B00F0D786 /* Theme.swift in Sources */, 2119899E1B2EC38B00F0D786 /* Result.swift in Sources */, + 8C9003331C5C0B0D00CBA5B0 /* ScopedString.swift in Sources */, 211989971B2EC38B00F0D786 /* AttributedParser.swift in Sources */, + 8CE64FE31C74B48D0007BA57 /* Language.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -750,10 +820,14 @@ buildActionMask = 2147483647; files = ( 211989841B2EB18600F0D786 /* TestHelper.swift in Sources */, + 8C71A05D1C59587700041EC6 /* IncrementalParsingTests.swift in Sources */, 211989891B2EB8D400F0D786 /* ParserTests.swift in Sources */, 210299DF1B2E892E009C61EE /* AttributedParserTests.swift in Sources */, + 8CE6BE2E1C5D1BBA002676BD /* ScopedStringTests.swift in Sources */, 210299DE1B2E892E009C61EE /* LanguageTests.swift in Sources */, + 8CE8D1171C4EBF8F005A86B3 /* SwiftBaselineHighlightingTests.swift in Sources */, 2119898B1B2EBA2C00F0D786 /* ThemeTests.swift in Sources */, + 8C4D09C01E1EAF750034974A /* PerformanceTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -762,10 +836,16 @@ buildActionMask = 2147483647; files = ( 2198CED31B36D5DE00BD463F /* Capture.swift in Sources */, - 2198CED61B36D5DE00BD463F /* Language.swift in Sources */, + 8CDD6F1D1C71594B0063915A /* BundleManager.swift in Sources */, 2198CED71B36D5DE00BD463F /* Parser.swift in Sources */, + 8CE64FE51C74B48D0007BA57 /* Language.swift in Sources */, 2198CED41B36D5DE00BD463F /* CaptureCollection.swift in Sources */, + 8CEEC0E01C411C8600BF3E85 /* ReferenceManager.swift in Sources */, + 8C10B6461CC38E5200740E00 /* AttributedParsingOperation.swift in Sources */, + 8CEEC0E41C411F9700BF3E85 /* Repository.swift in Sources */, 2198CEDA1B36D5DE00BD463F /* ResultSet.swift in Sources */, + 8C10B6481CC3938100740E00 /* Color.swift in Sources */, + 8C10B6491CC393E700740E00 /* ScopedString.swift in Sources */, 2198CED81B36D5DE00BD463F /* Pattern.swift in Sources */, 2198CEDB1B36D5DE00BD463F /* Theme.swift in Sources */, 2198CED91B36D5DE00BD463F /* Result.swift in Sources */, @@ -798,14 +878,12 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ANALYZER_NONNULL = YES; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SyntaxKit/Resources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -813,6 +891,7 @@ PRODUCT_NAME = SyntaxKit; SDKROOT = appletvos; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; }; @@ -822,14 +901,12 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ANALYZER_NONNULL = YES; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SyntaxKit/Resources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -837,6 +914,7 @@ PRODUCT_NAME = SyntaxKit; SDKROOT = appletvos; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; VALIDATE_PRODUCT = YES; @@ -848,15 +926,13 @@ buildSettings = { APPLICATION_EXTENSION_API_ONLY = NO; CLANG_ANALYZER_NONNULL = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = SyntaxKit/Tests/Resources/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.samsoffes.syntaxkit.tvos.tests; PRODUCT_NAME = SyntaxKitTests; SDKROOT = appletvos; + SWIFT_VERSION = 4.0; TVOS_DEPLOYMENT_TARGET = 9.2; }; name = Debug; @@ -866,15 +942,13 @@ buildSettings = { APPLICATION_EXTENSION_API_ONLY = NO; CLANG_ANALYZER_NONNULL = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = SyntaxKit/Tests/Resources/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.samsoffes.syntaxkit.tvos.tests; PRODUCT_NAME = SyntaxKitTests; SDKROOT = appletvos; + SWIFT_VERSION = 4.0; TVOS_DEPLOYMENT_TARGET = 9.2; VALIDATE_PRODUCT = YES; }; @@ -883,15 +957,13 @@ 211989B91B2EC3B600F0D786 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SyntaxKit/Resources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -900,6 +972,7 @@ PRODUCT_NAME = SyntaxKit; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -907,15 +980,13 @@ 211989BA1B2EC3B600F0D786 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SyntaxKit/Resources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -924,6 +995,7 @@ PRODUCT_NAME = SyntaxKit; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -934,16 +1006,14 @@ buildSettings = { APPLICATION_EXTENSION_API_ONLY = NO; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = SyntaxKit/Tests/Resources/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.samsoffes.syntaxkit-ios.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -952,16 +1022,14 @@ buildSettings = { APPLICATION_EXTENSION_API_ONLY = NO; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = SyntaxKit/Tests/Resources/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.samsoffes.syntaxkit-ios.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; + SWIFT_VERSION = 5.0; VALIDATE_PRODUCT = YES; }; name = Release; @@ -971,22 +1039,34 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_BITCODE = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; @@ -1010,6 +1090,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -1020,26 +1101,39 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_BITCODE = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = s; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -1050,6 +1144,8 @@ MACOSX_DEPLOYMENT_TARGET = 10.9; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -1058,17 +1154,15 @@ 2122A6F51B22B9320006409B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_VERSION = A; INFOPLIST_FILE = "$(SRCROOT)/SyntaxKit/Resources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -1077,23 +1171,22 @@ PRODUCT_NAME = SyntaxKit; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; }; name = Debug; }; 2122A6F61B22B9320006409B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; FRAMEWORK_VERSION = A; INFOPLIST_FILE = "$(SRCROOT)/SyntaxKit/Resources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -1101,6 +1194,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.samsoffes.syntaxkit; PRODUCT_NAME = SyntaxKit; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -1109,10 +1203,10 @@ buildSettings = { APPLICATION_EXTENSION_API_ONLY = NO; COMBINE_HIDPI_IMAGES = YES; + ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", ); GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -1122,6 +1216,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.samsoffes.syntaxkit-macos.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -1130,15 +1225,16 @@ buildSettings = { APPLICATION_EXTENSION_API_ONLY = NO; COMBINE_HIDPI_IMAGES = YES; + ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", ); INFOPLIST_FILE = SyntaxKit/Tests/Resources/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.samsoffes.syntaxkit-macos.tests"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -1146,14 +1242,12 @@ isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/watchOS", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SyntaxKit/Resources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -1161,6 +1255,7 @@ PRODUCT_NAME = SyntaxKit; SDKROOT = watchos; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 4; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; @@ -1170,14 +1265,12 @@ isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/watchOS", - ); + FRAMEWORK_SEARCH_PATHS = "$(inherited)"; INFOPLIST_FILE = "$(SRCROOT)/SyntaxKit/Resources/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -1185,6 +1278,7 @@ PRODUCT_NAME = SyntaxKit; SDKROOT = watchos; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 4; VALIDATE_PRODUCT = YES; WATCHOS_DEPLOYMENT_TARGET = 2.0; @@ -1201,6 +1295,7 @@ 211826ED1D257A71003F2BF2 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 211826EE1D257A71003F2BF2 /* Build configuration list for PBXNativeTarget "SyntaxKitTests-tvOS" */ = { isa = XCConfigurationList; @@ -1209,6 +1304,7 @@ 211826F01D257A71003F2BF2 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 211989B81B2EC3B600F0D786 /* Build configuration list for PBXNativeTarget "SyntaxKit-iOS" */ = { isa = XCConfigurationList; diff --git a/SyntaxKit.xcodeproj/xcshareddata/xcbaselines/211989AF1B2EC3B600F0D786.xcbaseline/36C0E679-EC89-495E-854F-FFBDEA1A4F58.plist b/SyntaxKit.xcodeproj/xcshareddata/xcbaselines/211989AF1B2EC3B600F0D786.xcbaseline/36C0E679-EC89-495E-854F-FFBDEA1A4F58.plist new file mode 100644 index 0000000..92d73e9 --- /dev/null +++ b/SyntaxKit.xcodeproj/xcshareddata/xcbaselines/211989AF1B2EC3B600F0D786.xcbaseline/36C0E679-EC89-495E-854F-FFBDEA1A4F58.plist @@ -0,0 +1,75 @@ + + + + + classNames + + IncrementalParsingTests + + testPerformanceBeginEnd() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.003 + baselineIntegrationDisplayName + Local Baseline + + + testPerformanceEdgeCases() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.002 + baselineIntegrationDisplayName + Local Baseline + + + testPerformanceExample() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.002 + baselineIntegrationDisplayName + Local Baseline + + + testPerformanceInScope() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.002 + baselineIntegrationDisplayName + Local Baseline + + + testPerformanceSingleLine() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.003 + baselineIntegrationDisplayName + Local Baseline + + + + SwiftBaselineHighlightingTests + + testHighlightingPerformance() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.065 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/SyntaxKit.xcodeproj/xcshareddata/xcbaselines/211989AF1B2EC3B600F0D786.xcbaseline/39CEC1B4-ED87-4CDB-A7E7-9A4ED4F3BEC8.plist b/SyntaxKit.xcodeproj/xcshareddata/xcbaselines/211989AF1B2EC3B600F0D786.xcbaseline/39CEC1B4-ED87-4CDB-A7E7-9A4ED4F3BEC8.plist new file mode 100644 index 0000000..a00fdb7 --- /dev/null +++ b/SyntaxKit.xcodeproj/xcshareddata/xcbaselines/211989AF1B2EC3B600F0D786.xcbaseline/39CEC1B4-ED87-4CDB-A7E7-9A4ED4F3BEC8.plist @@ -0,0 +1,45 @@ + + + + + classNames + + IncrementalParsingTests + + testPerformanceEdgeCases() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0023728 + baselineIntegrationDisplayName + Local Baseline + + + testPerformanceInScope() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.0030039 + baselineIntegrationDisplayName + Local Baseline + + + + SwiftBaselineHighlightingTests + + testHighlightingPerformance() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 0.085269 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/SyntaxKit.xcodeproj/xcshareddata/xcbaselines/211989AF1B2EC3B600F0D786.xcbaseline/Info.plist b/SyntaxKit.xcodeproj/xcshareddata/xcbaselines/211989AF1B2EC3B600F0D786.xcbaseline/Info.plist new file mode 100644 index 0000000..cb975cb --- /dev/null +++ b/SyntaxKit.xcodeproj/xcshareddata/xcbaselines/211989AF1B2EC3B600F0D786.xcbaseline/Info.plist @@ -0,0 +1,71 @@ + + + + + runDestinationsByUUID + + 36C0E679-EC89-495E-854F-FFBDEA1A4F58 + + localComputer + + busSpeedInMHz + 100 + cpuCount + 1 + cpuKind + 6-Core Intel Xeon E5 + cpuSpeedInMHz + 3500 + logicalCPUCoresPerPackage + 12 + modelCode + MacPro6,1 + physicalCPUCoresPerPackage + 6 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + i386 + targetDevice + + modelCode + iPad2,1 + platformIdentifier + com.apple.platform.iphonesimulator + + + 39CEC1B4-ED87-4CDB-A7E7-9A4ED4F3BEC8 + + localComputer + + busSpeedInMHz + 100 + cpuCount + 1 + cpuKind + 6-Core Intel Xeon E5 + cpuSpeedInMHz + 3500 + logicalCPUCoresPerPackage + 12 + modelCode + MacPro6,1 + physicalCPUCoresPerPackage + 6 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + x86_64 + targetDevice + + modelCode + iPhone8,2 + platformIdentifier + com.apple.platform.iphonesimulator + + + + + diff --git a/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-iOS.xcscheme b/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-iOS.xcscheme index e630ca1..36486f5 100644 --- a/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-iOS.xcscheme +++ b/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-iOS.xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -80,15 +79,6 @@ savedToolIdentifier = "" useCustomWorkingDirectory = "NO" debugDocumentVersioning = "YES"> - - - - diff --git a/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-macOS.xcscheme b/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-macOS.xcscheme index 3490ea1..2947d9a 100644 --- a/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-macOS.xcscheme +++ b/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-macOS.xcscheme @@ -1,6 +1,6 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> diff --git a/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-tvOS.xcscheme b/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-tvOS.xcscheme index 566e79a..b3a82fe 100644 --- a/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-tvOS.xcscheme +++ b/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-tvOS.xcscheme @@ -1,6 +1,6 @@ @@ -33,7 +33,7 @@ @@ -43,7 +43,7 @@ @@ -65,7 +65,7 @@ @@ -83,7 +83,7 @@ diff --git a/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-watchOS.xcscheme b/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-watchOS.xcscheme index b1c2c1a..a8ac452 100644 --- a/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-watchOS.xcscheme +++ b/SyntaxKit.xcodeproj/xcshareddata/xcschemes/SyntaxKit-watchOS.xcscheme @@ -1,6 +1,6 @@ Void - - - // MARK: - Properties - - public let theme: Theme - - - // MARK: - Initializers - - public required init(language: Language, theme: Theme) { - self.theme = theme - super.init(language: language) - } - - - // MARK: - Parsing - - public func parse(string: String, match callback: AttributedCallback) { - parse(string) { scope, range in - callback(scope: scope, range: range, attributes: self.attributesForScope(scope)) - } - } - - public func attributedStringForString(string: String, baseAttributes: Attributes? = nil) -> NSAttributedString { - let output = NSMutableAttributedString(string: string, attributes: baseAttributes) - parse(string) { _, range, attributes in - if let attributes = attributes { - output.addAttributes(attributes, range: range) - } - } - return output - } - - - // MARK: - Private - - private func attributesForScope(scope: String) -> Attributes? { - let components = scope.componentsSeparatedByString(".") as NSArray - let count = components.count - if count == 0 { - return nil - } - - var attributes = Attributes() - for i in 0.. Void + + // MARK: - Properties + + public let theme: Theme + + // MARK: - Initializers + + public required init(language: Language, theme: Theme) { + self.theme = theme + super.init(language: language) + } + + // MARK: - Parsing + + open func parse(_ string: String, match callback: AttributedCallback) { + parse(string) { scope, range in + callback(scope, range, self.attributes(forScope: scope)) + } + } + + func parse(in range: NSRange?, match callback: AttributedCallback) { + parse(in: range) { scope, range in + callback(scope, range, self.attributes(forScope: scope)) + } + } + + open func attributedString(for string: String, base: Attributes? = nil) -> NSAttributedString { + let output = NSMutableAttributedString(string: string, attributes: base) + output.beginEditing() + parse(string) { _, range, attributes in + if let attributes = attributes { + output.addAttributes(attributes, range: range) + } + } + output.endEditing() + return output + } + + // MARK: - Private + + private func attributes(forScope scope: String) -> Attributes? { + let components = scope.components(separatedBy: ".") + if components.isEmpty { + return nil + } + + var attributes = Attributes() + for i in 0.. Bool { + return newString == (oldString as NSString).replacingCharacters(in: range, with: change) + && self.change == (newString as NSString).substring(with: self.rangeInNewString()) + } + + /// - returns: the range of the change in the new string + func rangeInNewString() -> NSRange { + return NSRange(location: self.range.location, length: isInsertion() ? (self.change as NSString).length : 0) + } + + /// - returns: true if the change is an insertion + func isInsertion() -> Bool { + return self.range.length == 0 + } +} + +open class AttributedParsingOperation: Operation { + + // MARK: - Types + + /// Asynchronous or synchronous callback to which the results are passed + /// + /// The sender is passed in so it can be used to check if the operation was + /// cancelled after the call. + public typealias OperationCallback = ([(range: NSRange, attributes: Attributes?)], AttributedParsingOperation) -> Void + + // MARK: - Properties + + private let parser: AttributedParser + private let operationCallback: OperationCallback + private var parsedRange: NSRange? + + // MARK: - Initializers + + /// Initializer for the first instance in the NSOperationQueue + /// + /// Can also be used if no incremental parsing is desired + public init(string: String, language: Language, theme: Theme, callback: @escaping OperationCallback) { + parser = AttributedParser(language: language, theme: theme) + parser.toParse = ScopedString(string: string) + operationCallback = callback + super.init() + } + + /// Initializer for operations that allow incremental parsing + /// + /// The given change has to match the change in the string between the two + /// operations. Otherwise the entire string will be reparsed. If newCallback + /// is nil the callback from the previous operation will be used. + /// + /// - parameter string: The new String to parse. + /// - parameter previousOperation: The preceding operation in the queue. + /// - parameter insertion: True if the change was an insertion. + /// - parameter range: Either the range in the old string that + /// was deleted or the range in the new + /// string that was added. + /// - parameter callback: The callback to call with results. + public init(string: String, previousOperation: AttributedParsingOperation, changeIsInsertion insertion: Bool, changedRange range: NSRange, newCallback callback: OperationCallback? = nil) { + parser = previousOperation.parser + operationCallback = callback ?? previousOperation.operationCallback + + super.init() + + let diff: Diff + if insertion { + diff = Diff(change: (string as NSString).substring(with: range), range: NSRange(location: range.location, length: 0)) + } else { + diff = Diff(change: "", range: range) + } + + if diff.representsChanges(from: parser.toParse.string, to: string) { + self.parsedRange = AttributedParsingOperation.outdatedRange(in: string as NSString, forChange: diff, updatingPreviousResult: &self.parser.toParse) + } else { + self.parser.toParse = ScopedString(string: string) + } + } + + // MARK: - NSOperation Implementation + + open override func main() { + var resultsArray: [(range: NSRange, attributes: Attributes?)] = [] + let callback = { (_: String, range: NSRange, attributes: Attributes?) in + if let attributes = attributes { + resultsArray.append((range, attributes)) + } + } + + parser.parse(in: self.parsedRange, match: callback) + + if !parser.aborted { + operationCallback(resultsArray, self) + } + } + + open override func cancel() { + parser.aborted = true + super.cancel() + } + + // MARK: - Change Processing + + // Implementation notes: + // If change occurred in a block reparse the lines in which the change + // happened and the range of the block from this point on. If the change + // occurred in the global scope just reparse the lines that changed. + + /// Returns the range in the given string that should be re-parsed after the + /// given change. + /// + /// This method returns a range that can be safely passed into parse so that + /// only a part of the string has to be reparsed. + /// In fact passing anything other than this range to parse might lead to + /// uninteded results but is not prohibited. + /// + /// - parameter newString: The string that will be parsed next. + /// - parameter diff: A diff representing the changes from + /// previous.string to newString. + /// - parameter previous: The result of the previous parsing pass. + /// + /// - returns: A range in newString that can be safely re-parsed. Or nil if + /// everything has to be reparsed. + class func outdatedRange(in newString: NSString, forChange diff: Diff, updatingPreviousResult previous: inout ScopedString) -> NSRange? { + let linesRange: NSRange + let range: NSRange + if diff.isInsertion() { + range = diff.rangeInNewString() + previous.insert(diff.change, atIndex: range.location) + linesRange = newString.lineRange(for: range) + } else { + range = diff.range + previous.deleteCharacters(in: range) + linesRange = newString.lineRange(for: NSRange(location: range.location, length: 0)) + } + + let scopeAtIndex = previous.topmostScope(atIndex: NSMaxRange(linesRange) - 1) + if scopeAtIndex == previous.baseScope { + return linesRange + } else { + let endOfCurrentScope = NSMaxRange(scopeAtIndex.range) + return NSUnionRange(linesRange, NSRange(location: range.location, length: endOfCurrentScope - range.location)) + } + } +} diff --git a/SyntaxKit/BundleManager.swift b/SyntaxKit/BundleManager.swift new file mode 100644 index 0000000..b33d109 --- /dev/null +++ b/SyntaxKit/BundleManager.swift @@ -0,0 +1,125 @@ +// +// BundleManager.swift +// SyntaxKit +// +// Used to get access to SyntaxKit representations of TextMate bundle files. +// This class is used as a gateway for both internal and external use. +// Alternatively a global instace can be used for convenience. It is +// initialized with a callback that tells the bundle manager where to find the +// files. +// +// Created by Alexander Hedges on 15/02/16. +// Copyright © 2016 Alexander Hedges. All rights reserved. +// + +open class BundleManager { + + public enum TextMateFileType { + case language, theme + } + + // MARK: - Types + + /// Given an identifier of a grammar file and the format returns a url to + /// the resource. + /// + /// - parameter identifier: The identifier of the file. Used to map it to + /// the name of the file. + /// - parameter kind: The kind of file requested + /// - returns: A URL pointing to the resource, if found + public typealias BundleLocationCallback = (_ identifier: String, _ kind: TextMateFileType) -> (URL?) + + // MARK: - Properties + + /// You probably want to leave the languageCaching property set to true. + /// + /// - note: Setting it to false will not invalidate or purge the cache. This + /// has to be done separately using clearLanguageCache. + open var languageCaching: Bool = true + + public static var defaultManager: BundleManager? + + private var bundleCallback: BundleLocationCallback + private var dependencies: [Language] = [] + private var cachedLanguages: [String: Language] = [:] + private var cachedThemes: [String: Theme] = [:] + + // MARK: - Initializers + + /// Used to initialize the default manager. Unless this is called the + /// defaultManager property will be set to nil. + /// + /// - parameter callback: The callback used to find the location of the + /// textmate files. + open class func initializeDefaultManager(with callback: @escaping BundleLocationCallback) { + if let manager = defaultManager { + manager.bundleCallback = callback + } else { + defaultManager = BundleManager(callback: callback) + } + } + + public init(callback: @escaping BundleLocationCallback) { + self.bundleCallback = callback + } + + // MARK: - Public + + open func language(withIdentifier identifier: String) -> Language? { + if let language = self.cachedLanguages[identifier] { + return language + } + + self.dependencies = [] + var language = self.loadRawLanguage(withIdentifier: identifier) + language?.validate(with: self.dependencies) + + if languageCaching && language != nil { + self.cachedLanguages[identifier] = language + } + + self.dependencies = [] + return language + } + + open func theme(withIdentifier identifier: String) -> Theme? { + if let theme = cachedThemes[identifier] { + return theme + } + + guard let dictURL = self.bundleCallback(identifier, .theme), + let plist = NSDictionary(contentsOf: dictURL) as? [String: Any], + let newTheme = Theme(dictionary: plist) else { + return nil + } + + cachedThemes[identifier] = newTheme + return newTheme + } + + /// Clears the language cache. Use if low on memory. + open func clearLanguageCache() { + self.cachedLanguages = [:] + } + + // MARK: - Internal Interface + + /// - parameter identifier: The identifier of the requested language. + /// - returns: The Language with unresolved extenal references, if found + func loadRawLanguage(withIdentifier identifier: String) -> Language? { + let indexOfStoredLanguage = self.dependencies.firstIndex { (lang: Language) in lang.scopeName == identifier } + + if let index = indexOfStoredLanguage { + return self.dependencies[index] + } else { + guard let dictURL = self.bundleCallback(identifier, .language), + let plist = NSDictionary(contentsOf: dictURL) as? [String: Any], + let newLanguage = Language(dictionary: plist, manager: self) else { + return nil + } + + self.dependencies.append(newLanguage) + return newLanguage + } + } +} diff --git a/SyntaxKit/Capture.swift b/SyntaxKit/Capture.swift index 368b104..839f771 100644 --- a/SyntaxKit/Capture.swift +++ b/SyntaxKit/Capture.swift @@ -2,23 +2,25 @@ // Capture.swift // SyntaxKit // +// Represents a capture in a TextMate grammar. +// // Created by Sam Soffes on 9/18/14. // Copyright © 2014-2015 Sam Soffes. All rights reserved. // -import Foundation +internal struct Capture { -struct Capture { + // MARK: - Properties - // MARK: - Properties + let name: String - let name: String + // MARK: - Initializers + init?(dictionary: [AnyHashable: Any]) { + guard let name = dictionary["name"] as? String else { + return nil + } - // MARK: - Initializers - - init?(dictionary: [NSObject: AnyObject]) { - guard let name = dictionary["name"] as? String else { return nil } - self.name = name - } + self.name = name + } } diff --git a/SyntaxKit/CaptureCollection.swift b/SyntaxKit/CaptureCollection.swift index 17ab305..0aedf7d 100644 --- a/SyntaxKit/CaptureCollection.swift +++ b/SyntaxKit/CaptureCollection.swift @@ -2,43 +2,43 @@ // CaptureCollection.swift // SyntaxKit // +// Represents the captures attribute in a TextMate grammar. +// // Created by Sam Soffes on 9/19/14. // Copyright © 2014-2015 Sam Soffes. All rights reserved. // -import Foundation - -struct CaptureCollection { - - // MARK: - Properties - - private let captures: [UInt: Capture] +internal struct CaptureCollection { - var captureIndexes: [UInt] { - var keys = Array(captures.keys) - keys.sortInPlace() { $0 < $1 } - return keys - } + // MARK: - Properties + private let captures: [UInt: Capture] - // MARK: - Initializers + var captureIndexes: [UInt] { + var keys = Array(captures.keys) + keys.sort { $0 < $1 } + return keys + } - init?(dictionary: [NSObject: AnyObject]) { - guard let dictionary = dictionary as? [String: [String: String]] else { return nil } + // MARK: - Initializers - var captures = [UInt: Capture]() - for (key, value) in dictionary { - if let key = UInt(key), capture = Capture(dictionary: value) { - captures[key] = capture - } - } - self.captures = captures - } + init?(dictionary: [AnyHashable: Any]) { + guard let dictionary = dictionary as? [String: [String: String]] else { + return nil + } + var captures = [UInt: Capture]() + for (key, value) in dictionary { + if let key = UInt(key), let capture = Capture(dictionary: value) { + captures[key] = capture + } + } + self.captures = captures + } - // MARK: - Accessing Captures + // MARK: - Accessing Captures - subscript(index: UInt) -> Capture? { - return captures[index] - } + subscript(index: UInt) -> Capture? { + return captures[index] + } } diff --git a/SyntaxKit/Color.swift b/SyntaxKit/Color.swift new file mode 100644 index 0000000..36326f4 --- /dev/null +++ b/SyntaxKit/Color.swift @@ -0,0 +1,91 @@ +// +// Color.swift +// SyntaxKit +// +// Created by Sam Soffes on 4/28/15. +// Copyright © 2015 Sam Soffes. All rights reserved. +// + +#if os(OSX) + import AppKit.NSColor + public typealias ColorType = NSColor + + extension NSColor { + convenience init(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { + self.init(srgbRed: red, green: green, blue: blue, alpha: alpha) + } + } +#else + import UIKit.UIColor + public typealias ColorType = UIColor + + extension Color { + var redComponent: CGFloat { + var value: CGFloat = 0.0 + getRed(&value, green: nil, blue: nil, alpha: nil) + return value + } + + var greenComponent: CGFloat { + var value: CGFloat = 0.0 + getRed(nil, green: &value, blue: nil, alpha: nil) + return value + } + + var blueComponent: CGFloat { + var value: CGFloat = 0.0 + getRed(nil, green: nil, blue: &value, alpha: nil) + return value + } + + var alphaComponent: CGFloat { + var value: CGFloat = 0.0 + getRed(nil, green: nil, blue: nil, alpha: &value) + return value + } + } +#endif + +public typealias Color = ColorType + +extension Color { + convenience init?(hex representation: String) { + var hex = representation as NSString + + // Remove `#` and `0x` + if hex.hasPrefix("#") { + hex = hex.substring(from: 1) as NSString + } else if hex.hasPrefix("0x") { + hex = hex.substring(from: 2) as NSString + } + + // Invalid if not 3, 6, or 8 characters + let length = hex.length + if length != 3 && length != 6 && length != 8 { + return nil + } + + // Make the string 8 characters long for easier parsing + if length == 3 { + let r = hex.substring(with: NSRange(location: 0, length: 1)) + let g = hex.substring(with: NSRange(location: 1, length: 1)) + let b = hex.substring(with: NSRange(location: 2, length: 1)) + hex = "\(r)\(r)\(g)\(g)\(b)\(b)ff" as NSString + } else if length == 6 { + hex = "\(hex)ff" as NSString + } + + // Convert 2 character strings to CGFloats + func hexValue(_ string: String) -> CGFloat { + let value = Double(strtoul(string, nil, 16)) + return CGFloat(value / 255.0) + } + + let red = hexValue(hex.substring(with: NSRange(location: 0, length: 2))) + let green = hexValue(hex.substring(with: NSRange(location: 2, length: 2))) + let blue = hexValue(hex.substring(with: NSRange(location: 4, length: 2))) + let alpha = hexValue(hex.substring(with: NSRange(location: 6, length: 2))) + + self.init(red: red, green: green, blue: blue, alpha: alpha) + } +} diff --git a/SyntaxKit/Language.swift b/SyntaxKit/Language.swift index cbb5dba..b23b9ee 100644 --- a/SyntaxKit/Language.swift +++ b/SyntaxKit/Language.swift @@ -2,59 +2,54 @@ // Language.swift // SyntaxKit // +// Represents a textmate syntax file (.tmLanguage). Before use the +// validate method has to be called on it. +// // Created by Sam Soffes on 9/18/14. // Copyright © 2014-2015 Sam Soffes. All rights reserved. // -import Foundation - public struct Language { - // MARK: - Properties - - public let UUID: String - public let name: String - public let scopeName: String - let patterns: [Pattern] - - - // MARK: - Initializers - - public init?(dictionary: [NSObject: AnyObject]) { - guard let UUID = dictionary["uuid"] as? String, - name = dictionary["name"] as? String, - scopeName = dictionary["scopeName"] as? String - else { return nil } - - self.UUID = UUID - self.name = name - self.scopeName = scopeName - - var repository = [String: Pattern]() - if let repo = dictionary["repository"] as? [String: [NSObject: AnyObject]] { - for (key, value) in repo { - if let pattern = Pattern(dictionary: value) { - repository[key] = pattern - } - } - } - - var patterns = [Pattern]() - if let array = dictionary["patterns"] as? [[NSObject: AnyObject]] { - for value in array { - if let include = value["include"] as? String { - let key = include.substringFromIndex(include.startIndex.successor()) - if let pattern = repository[key] { - patterns.append(pattern) - continue - } - } - - if let pattern = Pattern(dictionary: value) { - patterns.append(pattern) - } - } - } - self.patterns = patterns - } + // MARK: - Properties + + public let uuid: UUID + public let name: String + public let scopeName: String + + let pattern: Pattern = Pattern() + let referenceManager: ReferenceManager + let repository: Repository + + static let globalScope: String = "GLOBAL" + + // MARK: - Initializers + + init?(dictionary: [String: Any], manager: BundleManager) { + guard let uuidString = dictionary["uuid"] as? String, + let uuid = UUID(uuidString: uuidString), + let name = dictionary["name"] as? String, + let scopeName = dictionary["scopeName"] as? String, + let array = dictionary["patterns"] as? [[String: Any]] + else { return nil } + + self.uuid = uuid + self.name = name + self.scopeName = scopeName + self.referenceManager = ReferenceManager(bundleManager: manager) + + self.pattern.subpatterns = referenceManager.patterns(for: array, in: nil, caller: nil) + self.repository = Repository(repo: dictionary["repository"] as? [String: [AnyHashable: Any]] ?? [:], inParent: nil, with: referenceManager) + referenceManager.resolveInternalReferences(with: repository, in: self) + } + + /// Resolves all external reference the language has to the given languages. + /// Only after a call to this method the Language is fit for general use. + /// + /// - parameter helperLanguages: The languages that the language has + /// references to resolve against. This should at least contain the + /// language itself. + mutating func validate(with helperLanguages: [Language]) { + ReferenceManager.resolveExternalReferences(between: helperLanguages, basename: self.scopeName) + } } diff --git a/SyntaxKit/Parser.swift b/SyntaxKit/Parser.swift index 4500b8a..f0cdba4 100644 --- a/SyntaxKit/Parser.swift +++ b/SyntaxKit/Parser.swift @@ -2,142 +2,305 @@ // Parser.swift // SyntaxKit // +// This class is in charge of the painful task of recognizing the syntax +// patterns. It tries to match parsing behavior of TextMate as closely as +// possible. +// // Created by Sam Soffes on 9/19/14. // Copyright © 2014-2015 Sam Soffes. All rights reserved. // -import Foundation - -public class Parser { - - // MARK: - Types - - public typealias Callback = (scope: String, range: NSRange) -> Void - - - // MARK: - Properties - - public let language: Language - - - // MARK: - Initializers - - public init(language: Language) { - self.language = language - } - - - // MARK: - Parsing - - public func parse(string: String, match callback: Callback) { - // Loop through paragraphs - let s: NSString = string - let length = s.length - var paragraphEnd = 0 - - while paragraphEnd < length { - var paragraphStart = 0 - var contentsEnd = 0 - s.getParagraphStart(¶graphStart, end: ¶graphEnd, contentsEnd: &contentsEnd, forRange: NSMakeRange(paragraphEnd, 0)) - - let paragraphRange = NSMakeRange(paragraphStart, contentsEnd - paragraphStart) - let limit = NSMaxRange(paragraphRange) - var range = paragraphRange - - // Loop through the line until we reach the end - while range.length > 0 && range.location < limit { - let location = parse(string, inRange: range, callback: callback) - range.location = Int(location) - range.length = max(0, range.length - paragraphRange.location - range.location) - } - } - } - - - // MARK: - Private - - /// Returns new location - private func parse(string: String, inRange bounds: NSRange, callback: Callback) -> UInt { - for pattern in language.patterns { - // Single pattern - if let match = pattern.match { - if let resultSet = parse(string, inRange: bounds, scope: pattern.name, expression: match, captures: pattern.captures) { - return applyResults(resultSet, callback: callback) - } else { - continue - } - } - - // Begin & end - if let begin = pattern.begin, end = pattern.end { - guard let beginResults = parse(string, inRange: bounds, expression: begin, captures: pattern.beginCaptures), - beginRange = beginResults.range else { continue } - - let location = NSMaxRange(beginRange) - let endBounds = NSMakeRange(location, NSMaxRange(bounds) - location) - - guard let endResults = parse(string, inRange: endBounds, expression: end, captures: pattern.endCaptures), - endRange = endResults.range else { /* TODO: Rewind? */ continue } - - // Add whole scope before start and end - var results = ResultSet() - if let name = pattern.name { - results.addResult(Result(scope: name, range: NSUnionRange(beginRange, endRange))) - } - - results.addResults(beginResults) - results.addResults(endResults) - - return applyResults(results, callback: callback) - } - } - - return UInt(NSMaxRange(bounds)) - } - - /// Parse an expression with captures - private func parse(string: String, inRange bounds: NSRange, scope: String? = nil, expression expressionString: String, captures: CaptureCollection?) -> ResultSet? { - let matches: [NSTextCheckingResult] - do { - let expression = try NSRegularExpression(pattern: expressionString, options: [.CaseInsensitive]) - matches = expression.matchesInString(string, options: [], range: bounds) - } catch { - return nil - } - - guard let result = matches.first else { return nil } - - var resultSet = ResultSet() - if let scope = scope where result.range.location != NSNotFound { - resultSet.addResult(Result(scope: scope, range: result.range)) - } - - if let captures = captures { - for index in captures.captureIndexes { - let range = result.rangeAtIndex(Int(index)) - if range.location == NSNotFound { - continue - } - - if let scope = captures[index]?.name { - resultSet.addResult(Result(scope: scope, range: range)) - } - } - } - - if !resultSet.isEmpty { - return resultSet - } - - return nil - } - - private func applyResults(resultSet: ResultSet, callback: Callback) -> UInt { - var i = 0 - for result in resultSet.results { - callback(scope: result.scope, range: result.range) - i = max(NSMaxRange(result.range), i) - } - return UInt(i) - } +open class Parser { + + // MARK: - Types + + public typealias Callback = (_ scope: String, _ range: NSRange) -> Void + + // MARK: - Properties + + /// The Language that the parser recognizes + public let language: Language + + /// String that is used in parse(in:). May already contain lexical + /// information from previous calls to parse for incremental parsing. + /// Stores the recognized lexical scopes after a successful call to parse. + var toParse: ScopedString = ScopedString(string: "") + /// Set to true to abort the parsing pass + var aborted: Bool = false + + // MARK: - Initializers + + public init(language: Language) { + self.language = language + } + + // MARK: - Public + + open func parse(_ string: String, match callback: Callback) { + if aborted { + return + } + self.toParse = ScopedString(string: string) + parse(match: callback) + } + + // MARK: - Private + + /// Parses the string in toParse. Supports incremental parsing. + /// + /// - parameter range: The range that should be re-parsed or nil if the + /// entire string should be parsed. It may be exceeded + /// if necessary to match a pattern entirely. For + /// calculation of such a range take a look at + /// outdatedRange(in: forChange:). + /// - parameter match: The callback to call on every match of a pattern + /// identifier of the language. + func parse(in range: NSRange? = nil, match: Callback) { + + let bounds: NSRange = range ?? NSRange(location: 0, length: (toParse.string as NSString).length) + assert((toParse.string as NSString).length >= NSMaxRange(bounds)) + var endScope = toParse.topmostScope(atIndex: bounds.location) + var startIndex = bounds.location + var endIndex = NSMaxRange(bounds) + let allResults = ResultSet(startingRange: bounds) + + while startIndex < endIndex { + let endPattern = endScope.attribute as? Pattern ?? language.pattern + guard let results = self.matchSubpatterns(of: endPattern, in: NSRange(location: startIndex, length: endIndex - startIndex)) else { + return + } + + allResults.add(Result(identifier: endScope.patternIdentifier, range: results.range)) + + if results.range.length != 0 { + allResults.add(results) + startIndex = NSMaxRange(results.range) + endScope = toParse.lowerScope(for: endScope, atIndex: startIndex) + } else { + startIndex = endIndex + } + + if startIndex > endIndex && toParse.isInString(index: startIndex + 1) { + let scopeAtIndex = toParse.topmostScope(atIndex: startIndex + 1) + if toParse.level(for: scopeAtIndex) > toParse.level(for: endScope) { + endIndex = NSMaxRange(scopeAtIndex.range) + } + } + } + + if aborted { + return + } + toParse.removeScopes(in: allResults.range) + self.apply(allResults, callback: match) + } + + // Algorithmic notes: + // A pattern expression can not match a substring spanning multiple lines + // so in the outer loop the string is decomposed into its lines. + // In the inner loop it tries to repeatedly match a pattern followed by the + // end pattern until either the line is consumed or it has found the end. + // This procedure is repeated with the subsequent lines until it has either + // matched the end pattern or the string is consumed entirely. + // If it can find neither in a line it moves to the next one. + + // Implementation note: + // The matching of the middle part may return a match that goes beyond the + // given range. This is intentional. + + /// Matches subpatterns of the given pattern in the input. + /// + /// - parameter pattern: The patterns whose subpatterns should be matched + /// - parameter range: The range in which the matching should occur. + /// + /// - returns: The result set containing the lexical scope names with range + /// information or nil if aborted. May exceed range. + private func matchSubpatterns(of pattern: Pattern, in range: NSRange) -> ResultSet? { + let stop = range.location + range.length + var lineStart = range.location + var lineEnd = range.location + let result = ResultSet(startingRange: NSRange(location: range.location, length: 0)) + + while lineEnd < stop { + (toParse.string as NSString).getLineStart(nil, end: &lineEnd, contentsEnd: nil, for: NSRange(location: lineEnd, length: 0)) + var range = NSRange(location: lineStart, length: lineEnd - lineStart) + + while range.length > 0 { + if aborted { + return nil + } + + let bestMatchForMiddle = match(pattern.subpatterns, in: range) + + if let patternEnd = pattern.end, + let endMatchResult = self.match(patternEnd, in: range, captures: pattern.endCaptures) { + if let middleMatch = bestMatchForMiddle { + if !pattern.applyEndPatternLast && endMatchResult.range.location <= middleMatch.match.range.location || endMatchResult.range.location < middleMatch.match.range.location { + result.add(endMatchResult) + return result + } + } else { + result.add(endMatchResult) + return result + } + } + + guard let middleMatch = bestMatchForMiddle, + let middleResult = middleMatch.pattern.match != nil ? middleMatch.match : matchAfterBegin(of: middleMatch.pattern, beginResults: middleMatch.match) else { + break + } + if middleResult.range.length == 0 { + break + } + result.add(middleResult) + let newStart = NSMaxRange(middleResult.range) + range = NSRange(location: newStart, length: max(0, range.length - (newStart - range.location))) + lineEnd = max(lineEnd, newStart) + } + + lineStart = lineEnd + } + + result.extend(with: range) + return result + } + + /// Helper method that iterates over the given patterns and tries to match + /// them. Returns the matched pattern with the highest priority + /// (first criterion: matched sooner, second: higher up the list). + /// + /// - parameter patterns: The patterns that can be matched + /// - parameter range: The range in which the matching should happen. + /// + /// - returns: The matched pattern and the matching result. Nil on failure. + /// The results range may exceed the passed in range. + private func match(_ patterns: [Pattern], in range: NSRange) -> (pattern: Pattern, match: ResultSet)? { + var interestingBounds = range + var bestResult: (pattern: Pattern, match: ResultSet)? + for pattern in patterns { + let currentMatch = self.firstMatch(of: pattern, in: range) + if currentMatch?.match.range.location == range.location { + return currentMatch + } else if let currMatch = currentMatch { + if let best = bestResult { + if currMatch.match.range.location < best.match.range.location { + bestResult = currentMatch + interestingBounds.length = currMatch.match.range.location - interestingBounds.location + } + } else { + bestResult = currentMatch + interestingBounds.length = currMatch.match.range.location - interestingBounds.location + } + } + } + return bestResult + } + + /// Matches a single pattern in the string in the given range + /// + /// - parameter pattern: The Pattern to match in the string + /// - parameter range: The range in which to match the pattern + /// + /// - returns: The matched pattern and the matching result. Nil on failure. + private func firstMatch(of pattern: Pattern, in range: NSRange) -> (pattern: Pattern, match: ResultSet)? { + if let expression = pattern.match { + if let resultSet = match(expression, in: range, captures: pattern.captures, baseSelector: pattern.name) { + if resultSet.range.length != 0 { + return (pattern, resultSet) + } + } + } else if let begin = pattern.begin { + if let beginResults = match(begin, in: range, captures: pattern.beginCaptures) { + return (pattern, beginResults) + } + } else if pattern.subpatterns.count >= 1 { + return match(pattern.subpatterns, in: range) + } + return nil + } + + // Implementation note: + // The order in which the beginning middle and end are added to the final + // result matters. + + /// Matches the middle and end of the given pattern + /// + /// - parameter pattern: The pattern whose subpatterns and end pattern + /// has to be matched + /// - parameter begin: The match result of the beginning + /// - returns: The result of matching the given pattern or nil on abortion. + private func matchAfterBegin(of pattern: Pattern, beginResults begin: ResultSet) -> ResultSet? { + let newLocation = NSMaxRange(begin.range) + guard let endResults = matchSubpatterns(of: pattern, in: NSRange(location: newLocation, length: (toParse.string as NSString).length - newLocation)) else { + return nil + } + + let result = ResultSet(startingRange: endResults.range) + if let patternName = pattern.name { + result.add(Result(identifier: patternName, range: NSUnionRange(begin.range, endResults.range))) + } + result.add(Scope(identifier: pattern.name ?? "", range: NSRange(location: begin.range.location + begin.range.length, length: NSUnionRange(begin.range, endResults.range).length - begin.range.length), attribute: pattern)) + result.add(begin) + result.add(endResults) + return result + } + + /// Matches a given regular expression in the String and returns range + /// information for the captures + /// + /// - parameter expression: The regular expression to match + /// - parameter range: The range to which to restrict the match + /// - parameter captures: A collection of captures that can be used to + /// add extra information to parts of the match. + /// - parameter baseSelector: String to associate with the entire range of + /// the match + /// + /// - returns: The set containing the results. May be nil if the expression + /// could not match any part of the string. It may also be empty + /// and only contain range information to show what it matched. + private func match(_ expression: NSRegularExpression, in range: NSRange, captures: CaptureCollection?, baseSelector: String? = nil) -> ResultSet? { + guard let result = expression.firstMatch(in: toParse.string, options: [.withTransparentBounds], range: range) else { + return nil + } + + let resultSet = ResultSet(startingRange: result.range) + if let base = baseSelector { + resultSet.add(Result(identifier: base, range: result.range)) + } + + if let captures = captures { + for index in captures.captureIndexes { + if result.numberOfRanges <= Int(index) { + print("Attention unexpected capture (\(index) to \(result.numberOfRanges)): \(expression.pattern)") + continue + } + let range = result.range(at: Int(index)) + if range.location == NSNotFound { + continue + } + + if let scope = captures[index]?.name { + resultSet.add(Result(identifier: scope, range: range)) + } + } + } + + return resultSet + } + + /// Uses the callback to communicate the results of the parsing pass back to + /// the caller of parse. The scopes are stored in toParse. + /// + /// - parameter results: The results of the parsing pass + /// - parameter callback: The method to call on every successful match + private func apply(_ results: ResultSet, callback: Callback) { + callback(Language.globalScope, results.range) + for result in results.results where result.range.length > 0 { + if result.attribute != nil { + toParse.addAtTop(result as Scope) + } else if result.patternIdentifier != "" { + callback(result.patternIdentifier, result.range) + } + } + } } diff --git a/SyntaxKit/Pattern.swift b/SyntaxKit/Pattern.swift index fa2453f..4e27605 100644 --- a/SyntaxKit/Pattern.swift +++ b/SyntaxKit/Pattern.swift @@ -2,69 +2,222 @@ // Pattern.swift // SyntaxKit // +// Represents a pattern from a TextMate grammar +// +// The Include class represents a Pattern that is a reference to another part +// in the same or another grammar. It is only usable as a pattern after it has +// been resolved via the provided method (and has type .resolved). +// +// A pattern may be one of three types: +// * A single pattern in match which should be matched +// * A begin and an end pattern containing an optional body of patterns +// (subpatterns) which should be matched between the begin and the end +// * Only a body of patterns without the begin and end. Any pattern may be +// matched successfully +// // Created by Sam Soffes on 9/18/14. // Copyright © 2014-2015 Sam Soffes. All rights reserved. // -import Foundation - -final class Pattern { - - // MARK: - Properties - - let name: String? - let match: String? - let captures: CaptureCollection? - let begin: String? - let beginCaptures: CaptureCollection? - let end: String? - let endCaptures: CaptureCollection? - private weak var parent: Pattern? - private let patterns: [Pattern] - - var superpattern: Pattern? { - return parent - } - - var subpatterns: [Pattern] { - return patterns - } - - // MARK: - Initializers - - init?(dictionary: [NSObject: AnyObject], parent: Pattern? = nil) { - self.parent = parent - self.name = dictionary["name"] as? String - self.match = dictionary["match"] as? String - self.begin = dictionary["begin"] as? String - self.end = dictionary["end"] as? String - - if let dictionary = dictionary["beginCaptures"] as? [NSObject: AnyObject] { - self.beginCaptures = CaptureCollection(dictionary: dictionary) - } else { - self.beginCaptures = nil - } - - if let dictionary = dictionary["captures"] as? [NSObject: AnyObject] { - self.captures = CaptureCollection(dictionary: dictionary) - } else { - self.captures = nil - } - - if let dictionary = dictionary["endCaptures"] as? [NSObject: AnyObject] { - self.endCaptures = CaptureCollection(dictionary: dictionary) - } else { - self.endCaptures = nil - } - - var patterns = [Pattern]() - if let array = dictionary["patterns"] as? [[NSObject: AnyObject]] { - for value in array { - if let pattern = Pattern(dictionary: value, parent: parent) { - patterns.append(pattern) - } - } - } - self.patterns = patterns - } +@objc(SKPattern) +internal class Pattern: NSObject { + + // MARK: - Properties + + var name: String? { return _name } + var match: NSRegularExpression? { return _match } + var captures: CaptureCollection? { return _captures } + var begin: NSRegularExpression? { return _begin } + var beginCaptures: CaptureCollection? { return _beginCaptures } + var end: NSRegularExpression? { return _end } + var endCaptures: CaptureCollection? { return _endCaptures } + var applyEndPatternLast: Bool { return _applyEndPatternLast } + var parent: Pattern? { return _parent } + var subpatterns: [Pattern] = [] + + // swiftlint:disable strict_fileprivate + fileprivate var _name: String? + fileprivate var _match: NSRegularExpression? + fileprivate var _captures: CaptureCollection? + fileprivate var _begin: NSRegularExpression? + fileprivate var _beginCaptures: CaptureCollection? + fileprivate var _end: NSRegularExpression? + fileprivate var _endCaptures: CaptureCollection? + fileprivate var _applyEndPatternLast: Bool = false + fileprivate weak var _parent: Pattern? + // swiftlint:enable strict_fileprivate + + // MARK: - Initializers + + init?(dictionary: [AnyHashable: Any], parent: Pattern?, with repository: Repository?, with manager: ReferenceManager) { + super.init() + _parent = parent + _name = dictionary["name"] as? String + + if let matchExpr = dictionary["match"] as? String { + _match = try? NSRegularExpression(pattern: matchExpr, options: [.anchorsMatchLines]) + } + + if let beginExpr = dictionary["begin"] as? String { + _begin = try? NSRegularExpression(pattern: beginExpr, options: [.anchorsMatchLines]) + } + + if let endExpr = dictionary["end"] as? String { + _end = try? NSRegularExpression(pattern: endExpr, options: [.anchorsMatchLines]) + } + + _applyEndPatternLast = dictionary["applyEndPatternLast"] as? Bool ?? false + + if let dictionary = dictionary["beginCaptures"] as? [AnyHashable: Any] { + _beginCaptures = CaptureCollection(dictionary: dictionary) + } + + if let dictionary = dictionary["captures"] as? [AnyHashable: Any] { + if match != nil { + _captures = CaptureCollection(dictionary: dictionary) + } else if begin != nil && end != nil { + _beginCaptures = CaptureCollection(dictionary: dictionary) + _endCaptures = self.beginCaptures + } + } + + if let dictionary = dictionary["endCaptures"] as? [AnyHashable: Any] { + _endCaptures = CaptureCollection(dictionary: dictionary) + } + + if dictionary["match"] as? String != nil && self.match == nil || + dictionary["begin"] as? String != nil && (self.begin == nil || self.end == nil) || + self.match == nil && self.begin == nil && self.end == nil && ((dictionary["patterns"] as? [[AnyHashable: Any]])?.isEmpty ?? true) { + return nil + } + + if let array = dictionary["patterns"] as? [[AnyHashable: Any]] { + self.subpatterns = manager.patterns(for: array, in: repository, caller: self) + } + } + + init(pattern: Pattern, parent: Pattern?) { + super.init() + _name = pattern.name + _match = pattern.match + _captures = pattern.captures + _begin = pattern.begin + _beginCaptures = pattern.beginCaptures + _end = pattern.end + _endCaptures = pattern.endCaptures + _parent = parent + self.subpatterns = [] + } + + /// For most cases does not create a usable pattern. + override init() { + super.init() + } +} + +internal class Include: Pattern { + + // MARK: - Properties + + enum ReferenceType { + case toRepository (repositoryRef: String) + case toSelf + case toBase + case toForeign (languageRef: String) + case toForeignRepository (repositoryRef: String, languageRef: String) + case resolved + } + + private var type: ReferenceType + private var associatedRepository: Repository? + + // MARK: - Initializers + + init(reference: String, in repository: Repository? = nil, parent: Pattern?, manager: BundleManager) { + self.associatedRepository = repository + if reference.hasPrefix("#") { + self.type = .toRepository(repositoryRef: String(reference[reference.index(after: reference.startIndex)...])) + } else if reference == "$self" { + self.type = .toSelf + } else if reference == "$base" { + self.type = .toBase + } else if reference.contains("#") { + if let hashRange = reference.range(of: "#") { + let languagePart = String(reference[.. [Pattern] { + guard let manager = bundleManager else { + assert(false) + return [] + } + var results: [Pattern] = [] + for rawPattern in patterns { + if let include = rawPattern["include"] as? String { + let reference = Include(reference: include, in: repository, parent: caller, manager: manager) + self.includes.append(reference) + results.append(reference) + } else if let pattern = Pattern(dictionary: rawPattern, parent: caller, with: repository, with: self) { + results.append(pattern) + } + } + return results + } + + func resolveInternalReferences(with repository: Repository, in language: Language) { + for include in includes { + include.resolveInternalReference(with: repository, in: language) + } + } + + class func resolveExternalReferences(between languages: [Language], basename: String) { + var otherLanguages: [String: Language] = [:] + for language in languages { + otherLanguages[language.scopeName] = language + } + for language in languages { + let includes = language.referenceManager.includes + for include in includes { + include.resolveExternalReference(from: language, in: otherLanguages, baseName: basename) + } + } + } +} diff --git a/SyntaxKit/Repository.swift b/SyntaxKit/Repository.swift new file mode 100644 index 0000000..a2f72ff --- /dev/null +++ b/SyntaxKit/Repository.swift @@ -0,0 +1,43 @@ +// +// Repository.swift +// SyntaxKit +// +// Represents a repository dictionary from a TextMate grammar. This class +// supports nested repositories as found in some grammars. +// +// Created by Alexander Hedges on 09/01/16. +// Copyright © 2016 Alexander Hedges. All rights reserved. +// + +internal class Repository { + + // MARK: - Properties + + private var entries: [String: Pattern] = [:] + private weak var parentRepository: Repository? + + // MARK: - Initializers + + init(repo: [String: [AnyHashable: Any]], inParent parent: Repository?, with manager: ReferenceManager) { + self.parentRepository = parent + + for (key, value) in repo { + var subRepo: Repository? + if let containedRepo = value["repository"] as? [String: [AnyHashable: Any]] { + subRepo = Repository(repo: containedRepo, inParent: self, with: manager) + } + if let pattern = Pattern(dictionary: value, parent: nil, with: subRepo, with: manager) { + self.entries[key] = pattern + } + } + } + + // MARK: - Accessing Patterns + + subscript(index: String) -> Pattern? { + if let resultAtLevel = entries[index] { + return resultAtLevel + } + return parentRepository?[index] + } +} diff --git a/SyntaxKit/Resources/Info.plist b/SyntaxKit/Resources/Info.plist index c568766..17dee6f 100644 --- a/SyntaxKit/Resources/Info.plist +++ b/SyntaxKit/Resources/Info.plist @@ -15,13 +15,13 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 0.1.2 + 1.0 CFBundleSignature ???? CFBundleVersion $(CURRENT_PROJECT_VERSION) NSHumanReadableCopyright - Copyright © 2015 Sam Soffes. All rights reserved. + Copyright © 2015-2016 Sam Soffes. Copyright © 2016 Alexander Hedges. All rights reserved. NSPrincipalClass diff --git a/SyntaxKit/Result.swift b/SyntaxKit/Result.swift index be1a604..ba1442f 100644 --- a/SyntaxKit/Result.swift +++ b/SyntaxKit/Result.swift @@ -2,24 +2,30 @@ // Result.swift // SyntaxKit // +// Represents a match by the parser. +// // Created by Sam Soffes on 10/11/14. // Copyright © 2014-2015 Sam Soffes. All rights reserved. // -import Foundation - -struct Result { +internal struct Result: Equatable { - // MARK: - Properties + // MARK: - Properties - let scope: String - let range: NSRange + let patternIdentifier: String + var range: NSRange + let attribute: AnyObject? + // MARK: - Initializers - // MARK: - Initializers + init(identifier: String, range: NSRange, attribute: AnyObject? = nil) { + self.patternIdentifier = identifier + self.range = range + self.attribute = attribute + } +} - init(scope: String, range: NSRange) { - self.scope = scope - self.range = range - } +internal func == (lhs: Result, rhs: Result) -> Bool { + return lhs.patternIdentifier == rhs.patternIdentifier && + Range(lhs.range) == Range(rhs.range) } diff --git a/SyntaxKit/ResultSet.swift b/SyntaxKit/ResultSet.swift index 839d6d0..0f379b3 100644 --- a/SyntaxKit/ResultSet.swift +++ b/SyntaxKit/ResultSet.swift @@ -2,44 +2,45 @@ // ResultSet.swift // SyntaxKit // +// Stores a set of results generated by the parser. +// // Created by Sam Soffes on 10/11/14. // Copyright © 2014-2015 Sam Soffes. All rights reserved. // -import Foundation - -struct ResultSet { - - // MARK: - Properties +internal class ResultSet { - private var _results = [Result]() - var results: [Result] { - return _results - } + // MARK: - Properties - var range: NSRange? + var results: [Result] { return _results } + /// Guaranteed to be larger or equal to the union of all the ranges + /// associated with the contained results. + var range: NSRange { return _range } - var isEmpty: Bool { - return results.isEmpty - } + private var _results: [Result] = [] + private var _range: NSRange + // MARK: - Initializers - // MARK: - Adding + init(startingRange range: NSRange) { + _range = range + } - mutating func addResult(result: Result) { - _results.append(result) + // MARK: - Adding - guard let range = range else { - self.range = result.range - return - } + func extend(with range: NSRange) { + _range = NSUnionRange(self.range, range) + } - self.range = NSUnionRange(range, result.range) - } + func add(_ result: Result) { + extend(with: result.range) + _results.append(result) + } - mutating func addResults(resultSet: ResultSet) { - for result in resultSet.results { - addResult(result) - } - } + func add(_ resultSet: ResultSet) { + extend(with: resultSet.range) + for result in resultSet.results { + _results.append(result) + } + } } diff --git a/SyntaxKit/ScopedString.swift b/SyntaxKit/ScopedString.swift new file mode 100644 index 0000000..5d6f612 --- /dev/null +++ b/SyntaxKit/ScopedString.swift @@ -0,0 +1,301 @@ +// +// ScopedString.swift +// SyntaxKit +// +// A datastructure that facilitates working with strings that have nested +// scopes associated with them. A scope being a named range that can have an +// attribute assciated with it for the callers convenience. +// The ranges can be nested. The datastructure could be visualized like this: +// In fact, something like this is returned by the prettyPrint function. +// +// Top: ---- +// ------------- +// ------- ----------------------------- +// Bottom: ------------------------------------------ +// String: "(This is) (string (with (nest)ed) scopes)!" +// +// Note: +// In the picture above the parens are not actually in the string, they serve +// visualization purposes. The bottom-most layer is implicit and is not stored. +// A new layer is added if no layer can hold the inserted scope without +// creating intersections. +// +// In the future the datastructure could be optimized by using binary search +// for insertions at the individual levels. +// +// Created by Alexander Hedges on 29/01/16. +// Copyright © 2016 Alexander Hedges. All rights reserved. +// + +import Foundation + +extension NSRange { + + func isEmpty() -> Bool { + return length == 0 + } + + func contains(index: Int) -> Bool { + return length == 0 && index == location || index >= location && index < location + length + } + + func partiallyContains(_ otherRange: NSRange) -> Bool { + return otherRange.location + otherRange.length >= location && otherRange.location < location + length + } + + func entirelyContains(_ otherRange: NSRange) -> Bool { + return location <= otherRange.location && location + length >= otherRange.location + otherRange.length + } + + /// Removes the indexes contained in range from self and shifts itself as + /// needed to not leave a gap in the domain. + mutating func removeIndexes(from range: NSRange) { + length -= NSIntersectionRange(range, NSRange(location: location, length: length)).length + if range.location < self.location { + self.location -= NSIntersectionRange(range, NSRange(location: 0, length: self.location)).length + } + } + + /// Inserts the indexes contained in range into self. Grows as needed. + mutating func insertIndexes(from range: NSRange) { + if self.contains(index: range.location) && range.location < NSMaxRange(self) { + length += range.length + } else if location > range.location { + location += range.length + } + } +} + +/// In this project the difference between a Result and a Scope is that the +/// scope has the attribute set while the Result does not. This is an implicit +/// agreement, please respect ;). +typealias Scope = Result + +internal struct ScopedString { + + // MARK: - Properties + + var string: String + + private var levels: [[Scope]] = [] + + /// The inplicit scope at the base of each ScopedString + var baseScope: Scope { + return Scope(identifier: "BaseNameString", range: NSRange(location: 0, length: (string as NSString).length), attribute: nil) + } + + // MARK: - Initializers + + init(string: String) { + self.string = string + } + + // MARK: - Interface + + func numberOfScopes() -> Int { + var sum = 1 + for level in levels { + sum += level.count + } + return sum + } + + func numberOfLevels() -> Int { + return levels.count + 1 + } + + func isInString(index: Int) -> Bool { + return index >= 0 && index <= baseScope.range.length + } + + mutating func addAtTop(_ scope: Scope) { + assert(scope.range.length != 0) + assert(NSIntersectionRange(scope.range, baseScope.range).length == scope.range.length) + + var added = false + for level in 0.. Scope { + let indexRange = NSRange(location: index, length: 0) + for i in stride(from: (levels.count - 1), through: 0, by: -1) { + let level = levels[i] + if let theScope = findScopeIntersection(with: indexRange, at: level) { + return theScope + } + } + return baseScope + } + + func lowerScope(for scope: Scope, atIndex index: Int) -> Scope { + assert(index >= 0 && index <= baseScope.range.length) + + var foundScope = false + let indexRange = NSRange(location: index, length: 0) + for i in stride(from: (levels.count - 1), through: 0, by: -1) { + let level = levels[i] + if let theScope = findScopeIntersection(with: indexRange, at: level) { + if foundScope { + return scope + } else if theScope == scope { + foundScope = true + } + } + } + return baseScope + } + + func level(for scope: Scope) -> Int { + for i in 0 ..< levels.count { + let level = levels[i] + if level.contains(scope) { + return i + 1 + } + } + if scope == baseScope { + return 0 + } + return -1 + } + + /// Removes all scopes that are entirely contained in the spcified range. + mutating func removeScopes(in range: NSRange) { + assert(NSIntersectionRange(range, baseScope.range).length == range.length) + + for level in stride(from: (levels.count - 1), through: 0, by: -1) { + for scope in stride(from: (levels[level].count - 1), through: 0, by: -1) { + let theScope = levels[level][scope] + if range.entirelyContains(theScope.range) { + levels[level].remove(at: scope) + } + } + if levels[level].isEmpty { + levels.remove(at: level) + } + } + } + + /// Inserts the given string into the underlying string, stretching and + /// shifting ranges as needed. If the range starts before and ends after the + /// insertion point, it is stretched. + mutating func insert(_ string: String, atIndex index: Int) { + assert(index >= 0 && index <= baseScope.range.length) + + let s = self.string as NSString + let length = (string as NSString).length + let mutableString = s.mutableCopy() as? NSMutableString + mutableString?.insert(string, at: index) + self.string = mutableString?.copy() as? String ?? "" + for level in 0.. String { + var result = "" + var printableUnderlyingString = string.replacingOccurrences(of: "\n", with: "¬") + printableUnderlyingString = printableUnderlyingString.replacingOccurrences(of: "\t", with: "»") + result += printableUnderlyingString + "\n" + for level in stride(from: (levels.count - 1), through: 0, by: -1) { + var levelString = String(repeating: " ", count: (string as NSString).length) + for pattern in levels[level] { + let range = pattern.range + if range.length == 0 { + assert(false) + } else if range.length == 1 { + levelString = (levelString as NSString).replacingCharacters(in: range, with: "|") + } else { + let dashes = String(repeating: "-", count: range.length - 2) + levelString = (levelString as NSString).replacingCharacters(in: range, with: "[\(dashes)]") + } + } + result += levelString + "\n" + } + var numberString = "" + for i in 0...(string as NSString).length / 10 { + let numDigits = ("\(i * 10)" as NSString).length + let dashes = String(repeating: "-", count: 9 - numDigits) + numberString += "\(i * 10)\(dashes)|" + } + result += numberString + "\n" + return result + } + + // MARK: - Private + + private func findScopeIntersection(with range: NSRange, at level: [Scope]) -> Scope? { + for scope in level { + if scope.range.partiallyContains(range) { + return scope + } + } + return nil + } + + private func insertionPoint(for range: NSRange, at level: [Scope]) -> Int { + var i = 0 + for scope in level { + if range.location < scope.range.location { + return i + } + i += 1 + } + return i + } +} diff --git a/SyntaxKit/Tests/AttributedParserTests.swift b/SyntaxKit/Tests/AttributedParserTests.swift index 605d2d2..e4b2754 100644 --- a/SyntaxKit/Tests/AttributedParserTests.swift +++ b/SyntaxKit/Tests/AttributedParserTests.swift @@ -1,29 +1,40 @@ // // AttributedParserTests.swift -// SyntaxKitTests +// SyntaxKit // // Created by Sam Soffes on 9/19/14. // Copyright © 2014-2015 Sam Soffes. All rights reserved. // -import XCTest import SyntaxKit +import XCTest + +internal class AttributedParserTests: XCTestCase { -class AttributedParserTests: XCTestCase { + // MARK: - Properties - // MARK: - Properties + private let manager: BundleManager = getBundleManager() + private var parser: AttributedParser? - let parser = AttributedParser(language: language("YAML"), theme: simpleTheme()) + // MARK: - Tests + override func setUp() { + super.setUp() + if let yaml = manager.language(withIdentifier: "source.YAML"), + let theme = simpleTheme() { + parser = AttributedParser(language: yaml, theme: theme) + } else { + XCTFail("Should be able to load yaml") + } - // MARK: - Tests + } - func testParsing() { - let string = parser.attributedStringForString("title: Hello World\ncount: 42\n") + func testParsing() { + let string = parser?.attributedString(for: "title: Hello World\ncount: 42\n") - XCTAssertEqual(["color": "blue"] as NSDictionary, string.attributesAtIndex(0, effectiveRange: nil) as NSDictionary) - XCTAssertEqual(["color": "red"] as NSDictionary, string.attributesAtIndex(7, effectiveRange: nil) as NSDictionary) - XCTAssertEqual(["color": "blue"] as NSDictionary, string.attributesAtIndex(19, effectiveRange: nil) as NSDictionary) - XCTAssertEqual(["color": "purple"] as NSDictionary, string.attributesAtIndex(25, effectiveRange: nil) as NSDictionary) - } + XCTAssertEqual(["color": "blue"], string?.attributes(at: 0, effectiveRange: nil) as NSDictionary?) + XCTAssertEqual(["color": "red"], string?.attributes(at: 7, effectiveRange: nil) as NSDictionary?) + XCTAssertEqual(["color": "blue"], string?.attributes(at: 19, effectiveRange: nil) as NSDictionary?) + XCTAssertEqual(["color": "purple"], string?.attributes(at: 25, effectiveRange: nil) as NSDictionary?) + } } diff --git a/SyntaxKit/Tests/IncrementalParsingTests.swift b/SyntaxKit/Tests/IncrementalParsingTests.swift new file mode 100644 index 0000000..29028fb --- /dev/null +++ b/SyntaxKit/Tests/IncrementalParsingTests.swift @@ -0,0 +1,135 @@ +// +// IncrementalParsingTests.swift +// SyntaxKit +// +// Created by Alexander Hedges on 27/01/16. +// Copyright © 2016 Alexander Hedges. All rights reserved. +// + +import SyntaxKit +import XCTest + +internal class IncrementalParsingTests: XCTestCase { + + // MARK: - Properties + + private let manager: BundleManager = getBundleManager() + private var parsingOperation: AttributedParsingOperation? + private var totalRange: NSRange? + private var input: String = "" + + // MARK: - Tests + + override func setUp() { + super.setUp() + } + + func testEdits() { + input = fixture("swifttest.swift", "txt") + parsingOperation = getParsingOperation() + + parsingOperation?.main() + XCTAssertEqual(totalRange, NSRange(location: 0, length: (input as NSString).length)) + + assertInsertion("i", location: 162, expectedRange: NSRange(location: 159, length: 5)) + + assertDeletion(NSRange(location: 162, length: 1), expectedRange: NSRange(location: 159, length: 4)) + + assertInsertion("756", location: 160, expectedRange: NSRange(location: 159, length: 7)) + } + + func testDeletion() { + input = "Only this!" + parsingOperation = getParsingOperation() + + parsingOperation?.main() + + assertDeletion(NSRange(location: 9, length: 1), expectedRange: NSRange(location: 0, length: 9)) + } + + func testEdgeCase() { + input = "// test.swift\n/**" + parsingOperation = getParsingOperation() + + parsingOperation?.main() + XCTAssertEqual(totalRange, NSRange(location: 0, length: 17)) + + assertDeletion(NSRange(location: 2, length: 1), expectedRange: NSRange(location: 0, length: 13)) + + assertInsertion(" ", location: 2, expectedRange: NSRange(location: 0, length: 14)) + + assertInsertion("\n", location: 17, expectedRange: NSRange(location: 14, length: 4)) + } + + func testPerformanceInScope() { + input = fixture("swifttest.swift", "txt") + parsingOperation = getParsingOperation() + + parsingOperation?.main() + + self.measure { + self.assertInsertion("Tests", location: 239, expectedRange: NSRange(location: 230, length: 24)) + + self.assertDeletion(NSRange(location: 239, length: 5), expectedRange: NSRange(location: 230, length: 19)) + } + } + + func testPerformanceEdgeCases() { + input = fixture("swifttest.swift", "txt") + parsingOperation = getParsingOperation() + + parsingOperation?.main() + + self.measure { + self.assertDeletion(NSRange(location: 139, length: 1), expectedRange: NSRange(location: 139, length: 22)) + + self.assertInsertion("/", location: 139, expectedRange: NSRange(location: 139, length: 23)) + } + } + + // MARK: - Helpers + + private func getParsingOperation() -> AttributedParsingOperation? { + if let language = manager.language(withIdentifier: "Source.swift"), + let theme = manager.theme(withIdentifier: "tomorrow") { + return AttributedParsingOperation(string: input, language: language, theme: theme) { (results: [(range: NSRange, attributes: Attributes?)], _: AttributedParsingOperation) in + for result in results { + if let range = self.totalRange { + self.totalRange = NSUnionRange(range, result.range) + } else { + self.totalRange = result.range + } + } + } + } else { + XCTFail("Should be able to load swift language fixture") + return nil + } + } + + private func assertInsertion(_ string: String, location: Int, expectedRange expected: NSRange) { + input = replace(NSRange(location: location, length: 0), in: input, with: string) + if let previousOperation = parsingOperation { + parsingOperation = AttributedParsingOperation(string: input, previousOperation: previousOperation, changeIsInsertion: true, changedRange: NSRange(location: location, length: (string as NSString).length)) + + totalRange = nil + parsingOperation?.main() + XCTAssertEqual(totalRange, expected) + } else { + XCTFail("Should have been able to get parsing operation") + } + } + + private func assertDeletion(_ range: NSRange, expectedRange expected: NSRange) { + input = replace(range, in: input, with: "") + if let previousOperation = parsingOperation { + parsingOperation = AttributedParsingOperation(string: input, previousOperation: previousOperation, changeIsInsertion: false, changedRange: range) + + totalRange = nil + parsingOperation?.main() + XCTAssertEqual(totalRange, expected) + } else { + XCTFail("Should have been able to get parsing operation") + } + } +} diff --git a/SyntaxKit/Tests/LanguageTests.swift b/SyntaxKit/Tests/LanguageTests.swift index 4eb0662..69e592b 100644 --- a/SyntaxKit/Tests/LanguageTests.swift +++ b/SyntaxKit/Tests/LanguageTests.swift @@ -6,29 +6,51 @@ // Copyright © 2014-2015 Sam Soffes. All rights reserved. // -import XCTest @testable import SyntaxKit +import XCTest -class LanguageTests: XCTestCase { - - // MARK: - Properties - - let yaml = language("YAML") - - - // MARK: - Tests - - func testLoading() { - XCTAssertEqual("B0C44228-4F1F-11DA-AFF2-000A95AF0064", yaml.UUID) - XCTAssertEqual("YAML", yaml.name) - XCTAssertEqual("source.yaml", yaml.scopeName) - - XCTAssertEqual("meta.embedded.line.ruby", yaml.patterns[0].name!) - XCTAssertEqual("string.unquoted.block.yaml", yaml.patterns[1].name!) - XCTAssertEqual("constant.numeric.yaml", yaml.patterns[2].name!) - - let pattern = yaml.patterns[3] - XCTAssertEqual("string.unquoted.yaml", pattern.name!) - XCTAssertEqual("punctuation.definition.entry.yaml", pattern.captures![1]!.name) - } +internal class LanguageTests: XCTestCase { + + // MARK: - Properties + + private let manager: BundleManager = getBundleManager() + + // MARK: - Tests + + func testYaml() { + if let yaml = manager.language(withIdentifier: "source.YAML") { + XCTAssertEqual(UUID(uuidString: "B0C44228-4F1F-11DA-AFF2-000A95AF0064"), yaml.uuid) + XCTAssertEqual("YAML", yaml.name) + XCTAssertEqual("source.yaml", yaml.scopeName) + + XCTAssertEqual("meta.embedded.line.ruby", yaml.pattern.subpatterns[0].name) + XCTAssertEqual("punctuation.definition.embedded.begin.ruby", yaml.pattern.subpatterns[0].beginCaptures?[0]?.name) + XCTAssertEqual("punctuation.definition.embedded.end.ruby", yaml.pattern.subpatterns[0].endCaptures?[0]?.name) + XCTAssertEqual("punctuation.definition.comment.ruby", yaml.pattern.subpatterns[0].subpatterns[0].captures?[1]?.name) + XCTAssertEqual("string.unquoted.block.yaml", yaml.pattern.subpatterns[1].name) + XCTAssertEqual("punctuation.definition.entry.yaml", yaml.pattern.subpatterns[1].beginCaptures?[2]?.name) + XCTAssertEqual("punctuation.separator.key-value.yaml", yaml.pattern.subpatterns[1].beginCaptures?[5]?.name) + XCTAssertEqual("constant.numeric.yaml", yaml.pattern.subpatterns[2].name) + + let pattern = yaml.pattern.subpatterns[3] + XCTAssertEqual("string.unquoted.yaml", pattern.name) + XCTAssertEqual("punctuation.definition.entry.yaml", pattern.captures?[1]?.name) + } else { + XCTFail("Should be able to load yaml language fixture") + } + } + + func testSwift() { + if let swift = manager.language(withIdentifier: "source.swift") { + XCTAssertEqual(UUID(uuidString: "D133338A-DEED-4ECC-9852-A392C44D10AC"), swift.uuid) + XCTAssertEqual("Swift", swift.name) + XCTAssertEqual("source.swift", swift.scopeName) + + XCTAssertEqual("comment.line.shebang.swift", swift.pattern.subpatterns[0].name) + XCTAssertEqual(4, swift.pattern.subpatterns[1].subpatterns.count) + XCTAssertEqual("comment.line.double-slash.swift", swift.pattern.subpatterns[1].subpatterns[3].subpatterns[0].name) + } else { + XCTFail("Should be able to load swift language fixture") + } + } } diff --git a/SyntaxKit/Tests/ParserTests.swift b/SyntaxKit/Tests/ParserTests.swift index 49c0483..efe73c2 100644 --- a/SyntaxKit/Tests/ParserTests.swift +++ b/SyntaxKit/Tests/ParserTests.swift @@ -6,63 +6,75 @@ // Copyright © 2015 Sam Soffes. All rights reserved. // -import XCTest import SyntaxKit +import XCTest + +internal class ParserTests: XCTestCase { + + // MARK: - Properties + + private var parser: Parser? + private let manager: BundleManager = getBundleManager() + + // MARK: - Tests + + override func setUp() { + super.setUp() + if let yaml = manager.language(withIdentifier: "source.YAML") { + parser = Parser(language: yaml) + } else { + XCTFail("Should be able to load yaml language fixture") + } + } + + func testParsingBeginEnd() { + var stringQuoted: NSRange? + var punctuationBegin: NSRange? + var punctuationEnd: NSRange? + + parser?.parse("title: \"Hello World\"\n") { (scope: String, range: NSRange) in + if stringQuoted == nil && scope.hasPrefix("string.quoted.double") { + stringQuoted = range + } + + if punctuationBegin == nil && scope.hasPrefix("punctuation.definition.string.begin") { + punctuationBegin = range + } + + if punctuationEnd == nil && scope.hasPrefix("punctuation.definition.string.end") { + punctuationEnd = range + } + } + + XCTAssertEqual(NSRange(location: 7, length: 13), stringQuoted) + XCTAssertEqual(NSRange(location: 7, length: 1), punctuationBegin) + XCTAssertEqual(NSRange(location: 19, length: 1), punctuationEnd) + } + + func testParsingBeginEndGarbage() { + var stringQuoted: NSRange? + + parser?.parse("title: Hello World\ncomments: 24\nposts: \"12\"zz\n") { (scope: String, range: NSRange) in + if stringQuoted == nil && scope.hasPrefix("string.quoted.double") { + stringQuoted = range + } + } + + XCTAssertEqual(NSRange(location: 39, length: 4), stringQuoted) + } + + func testParsingGarbage() { + parser?.parse("") { _, _ in } + parser?.parse("ainod adlkf ac\nv a;skcja\nsd flaksdfj [awiefasdvxzc\\vzxcx c\n\n\nx \ncvas\ndv\nas \ndf as]pkdfa \nsd\nfa sdos[a \n\n a\ns cvsa\ncd\n a \ncd\n \n\n\n asdcp[vk sa\n\ndd'; \nssv[ das \n\n\nlkjs") { _, _ in } + } -class ParserTests: XCTestCase { - - // MARK: - Properties - - let parser = Parser(language: language("YAML")) - - - // MARK: - Tests - - func testParsingBeginEnd() { - var stringQuoted: NSRange? - var punctuationBegin: NSRange? - var punctuationEnd: NSRange? - - parser.parse("title: \"Hello World\"\n") { scope, range in - if stringQuoted == nil && scope.hasPrefix("string.quoted.double") { - stringQuoted = range - } - - if punctuationBegin == nil && scope.hasPrefix("punctuation.definition.string.begin") { - punctuationBegin = range - } - - if punctuationEnd == nil && scope.hasPrefix("punctuation.definition.string.end") { - punctuationEnd = range - } - } - - XCTAssertEqual(NSMakeRange(7, 13), stringQuoted!) - XCTAssertEqual(NSMakeRange(7, 1), punctuationBegin!) - XCTAssertEqual(NSMakeRange(19, 1), punctuationEnd!) - } - - func testParsingBeginEndCrap() { - var stringQuoted: NSRange? - - parser.parse("title: Hello World\ncomments: 24\nposts: \"12\"zz\n") { scope, range in - if stringQuoted == nil && scope.hasPrefix("string.quoted.double") { - stringQuoted = range - } - } - - XCTAssertEqual(NSMakeRange(39, 4), stringQuoted!) - } - - func testRuby() { - let parser = Parser(language: language("Ruby")) - let input = fixture("test.rb", "txt") - parser.parse(input, match: { _, _ in return }) - } - - func testJavaScript() { - let parser = Parser(language: language("JavaScript")) - let input = fixture("test.js", "txt") - parser.parse(input, match: { _, _ in return }) + func testRuby() { + if let ruby = manager.language(withIdentifier: "source.Ruby") { + parser = Parser(language: ruby) + let input = fixture("test.rb", "txt") + parser?.parse(input) { _, _ in return } + } else { + XCTFail("Should be able to load ruby language fixture") + } } } diff --git a/SyntaxKit/Tests/PerformanceTests.swift b/SyntaxKit/Tests/PerformanceTests.swift new file mode 100644 index 0000000..17849c4 --- /dev/null +++ b/SyntaxKit/Tests/PerformanceTests.swift @@ -0,0 +1,36 @@ +// +// PerformanceTests.swift +// SyntaxKit +// +// Created by Alexander Hedges on 05/01/17. +// Copyright © 2017 Sam Soffes. All rights reserved. +// + +import SyntaxKit +import XCTest + +internal class PerformanceTests: XCTestCase { + + // MARK: - Properties + + private let manager: BundleManager = getBundleManager() + private var parser: AttributedParser? + + override func setUp() { + super.setUp() + if let latex = manager.language(withIdentifier: "source.Latex"), + let solarized = manager.theme(withIdentifier: "Solarized") { + parser = AttributedParser(language: latex, theme: solarized) + } else { + XCTFail("Should be able to load latex language fixture") + } + } + + func testLongTexFilePerformance() { + let input = fixture("textest.tex", "txt") + self.measure { + _ = self.parser?.attributedString(for: input) + } + } + +} diff --git a/SyntaxKit/Tests/Resources/Fixtures/JavaScript.tmLanguage b/SyntaxKit/Tests/Resources/Fixtures/JavaScript.tmLanguage deleted file mode 100644 index 3fd1b4f..0000000 --- a/SyntaxKit/Tests/Resources/Fixtures/JavaScript.tmLanguage +++ /dev/null @@ -1,676 +0,0 @@ - - - - - comment - JavaScript Syntax: version 2.0 - fileTypes - - js - htc - jsx - - injections - - source.js - meta.ternary-if.js - string - comment - - patterns - - - match - (?<!\w)[\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?=\s*:\s*function\b) - name - entity.name.function.js - - - match - (?<!\w)[\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?=\s*:) - name - entity.name.attribute-name.js - - - - - keyEquivalent - ^~J - name - JavaScript - patterns - - - captures - - 1 - - name - punctuation.definition.comment.js - - - comment - Match the shebang for JavaScript executables - match - \A(#!).*$\n - name - comment.line.number-sign.shebang.js - - - begin - (?x) - (?: - (?<!\w) # Ensure word boundry - ([\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*) # Identifier - \s*(=)\s* - )? # Optional - \b(function) - (?:\s* - (\*) # Optional generator notation - )? # (ECMAScript 6) - (?:\s* - (?<=[\s\*]) - ([\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*) # Optional Name - )? - \s*(\() - - beginCaptures - - 1 - - name - meta.function.variable.js - - 2 - - name - keyword.operator.js - - 3 - - name - storage.type.function.js - - 4 - - name - storage.modifier.js - - 5 - - name - entity.name.function.js - - 6 - - name - punctuation.definition.parameters.begin.js - - - comment - Match function, optional function name and optional function arguments - end - (\)) - endCaptures - - 1 - - name - punctuation.definition.parameters.end.js - - - name - meta.function.js - patterns - - - include - #function-params - - - - - match - \b0[xX]\h+\b - name - constant.numeric.hex.js - - - match - (?x) - (?<!\w) # Ensure word boundry - (?> - ( - (0|[1-9][0-9]*)(\.[0-9]*)? # 0 or 1 or 1. or 1.0 - | \.[0-9]+ # .1 - ) - ([eE][+-]?[0-9]+)? # Exponent - ) - (?!\w) # Ensure word boundry - - name - constant.numeric.js - - - begin - ' - beginCaptures - - 0 - - name - punctuation.definition.string.begin.js - - - end - ' - endCaptures - - 0 - - name - punctuation.definition.string.end.js - - - name - string.quoted.single.js - patterns - - - match - \\(x\h{2}|[0-2][0-7]{0,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.) - name - constant.character.escape.js - - - - - begin - " - beginCaptures - - 0 - - name - punctuation.definition.string.begin.js - - - end - " - endCaptures - - 0 - - name - punctuation.definition.string.end.js - - - name - string.quoted.double.js - patterns - - - match - \\(x\h{2}|[0-2][0-7]{0,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.) - name - constant.character.escape.js - - - - - begin - /\* - captures - - 0 - - name - punctuation.definition.comment.js - - - end - \*/ - name - comment.block.js - - - begin - (^[ \t]+)?(?=//) - beginCaptures - - 1 - - name - punctuation.whitespace.comment.leading.js - - - end - (?!\G) - patterns - - - begin - // - beginCaptures - - 0 - - name - punctuation.definition.comment.js - - - end - \n - name - comment.line.double-slash.js - - - - - match - (?<!\.|\$)\b(let|var)\b(?!\$) - name - storage.type.js - - - match - (?<!\.|\$)\b(get|set)\b(?!\$) - name - storage.modifier.js - - - match - (?<!\.|\$)\b(break|case|catch|continue|default|do|else|finally|for|if|return|switch|throw|try|while|yield)\b(?!\$) - name - keyword.control.js - - - match - (?<!\.|\$)\b(delete|in|instanceof|new|typeof|void|with)\b(?!\$) - name - keyword.operator.js - - - match - !|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^= - name - keyword.operator.js - - - match - (?<!\.|\$)\b(debugger)\b(?!\$) - name - keyword.other.js - - - match - (?<!\.|\$)\b(Array|Boolean|Date|Error|EvalError|Function|Number|Object|RangeError|ReferenceError|RegExp|String|SyntaxError|TypeError|URIError)\b(?!\$) - name - support.class.js - - - comment - DOM Core Level 4 (http://www.w3.org/TR/domcore/) and DOM Events Level 3 (http://www.w3.org/TR/DOM-Level-3-Events/) - match - (?<!\.|\$)\b(Attr|CharacterData|Comment|CompositionEvent|CustomEvent|Document|DocumentFragment|DocumentType|DOMError|DOMException|DOMImplementation|DOMParser|DOMString|DOMTimestamp|DOMSettableTokenList|DOMStringList|DOMTokenList|Element|Event|EventTarget|FocusEvent|HTMLCollection|KeyboardEvent|MouseEvent|MutationObserver|MutationRecord|Node|NodeFilter|NodeIterator|NodeList|ProcessingInstruction|Range|Text|TextEvent|TreeWalker|UIEvent|WheelEvent|XMLDocument)\b(?!\$) - name - support.class.dom.js - - - comment - DOM Core Level 4 (http://www.w3.org/TR/domcore/) and DOM Events Level 3 (http://www.w3.org/TR/DOM-Level-3-Events/) - match - (?<!\.|\$)\b(CDATASection|DOMConfiguration|DOMErrorHandler|DOMImplementationList|DOMImplementationSource|DOMLocator|DOMObject|DOMUserData|Entity|EntityReference|MutationEvent|NamedNodeMap|NameList|Notation|TypeInfo|UserDataHandler)\b(?!\$) - name - invalid.deprecated.dom.js - - - comment - TypedArray specification used by HTML 5 (http://www.khronos.org/registry/typedarray/specs/latest/) - match - (?<!\.|\$)\b(ArrayBuffer|DataView|Float32Array|Float64Array|Int8Array|Int16Array|Int32Array|TypedArray|Uint8Array|Uint16Array|Uint32Array|Uint8ClampedArray)\b(?!\$) - name - support.class.dom.js - - - comment - File specification used by HTML 5 (http://dev.w3.org/2006/webapi/FileAPI/) - match - (?<!\.|\$)\b(Blob|File|FileList|FileReader)\b(?!\$) - name - support.class.dom.js - - - comment - XMLHttpRequest specification used by HTML 5 (http://xhr.spec.whatwg.org/) - match - (?<!\.|\$)\b(FormData|ProgressEvent|XMLHttpRequest|XMLHttpRequestUpload)\b(?!\$) - name - support.class.dom.js - - - comment - EventSource specification used by HTML 5 (http://www.w3.org/TR/eventsource/) - match - (?<!\.|\$)\b(EventSource)\b(?!\$) - name - support.class.dom.js - - - comment - CSSOM specification used by HTML 5 (http://dev.w3.org/csswg/cssom/) - match - (?<!\.|\$)\b(CSS|CSSCharsetRule|CSSImportRule|CSSPageRule|CSSRule|CSSRuleList|CSSStyleDeclaration|CSSStyleRule|CSSStyleSheet|MediaList|Stylesheet|StyleSheetList)\b(?!\$) - name - support.class.dom.js - - - comment - CSSOM View specification used by HTML 5 (http://dev.w3.org/csswg/cssom-view/) - match - (?<!\.|\$)\b(Screen)\b(?!\$) - name - support.class.dom.js - - - comment - CSS Font specification used by HTML 5 (http://dev.w3.org/csswg/css-fonts/) - match - (?<!\.|\$)\b(CSSFontFaceRule)\b(?!\$) - name - support.class.dom.js - - - comment - SVG specification used by HTML 5 (http://www.w3.org/TR/SVG/single-page.html) - match - (?<!\.|\$)\b(SVGAElement|SVGAltGlyphDefElement|SVGAltGlyphElement|SVGAltGlyphItemElement|SVGAngle|SVGAnimateColorElement|SVGAnimateElement|SVGAnimateMotionElement|SVGAnimateTransformElement|SVGAnimatedAngle|SVGAnimatedBoolean|SVGAnimatedEnumeration|SVGAnimatedInteger|SVGAnimatedLength|SVGAnimatedLengthList|SVGAnimatedNumber|SVGAnimatedNumberList|SVGAnimatedPreserveAspectRatio|SVGAnimatedRect|SVGAnimatedString|SVGAnimatedTransformList|SVGAnimationElement|SVGCircleElement|SVGClipPathElement|SVGColor|SVGComponentTransferFunctionElement|SVGCursorElement|SVGDefsElement|SVGDescElement|SVGDocument|SVGElement|SVGElementInstance|SVGElementInstanceList|SVGEllipseElement|SVGFEBlendElement|SVGFEColorMatrixElement|SVGFEComponentTransferElement|SVGFECompositeElement|SVGFEConvolveMatrixElement|SVGFEDiffuseLightingElement|SVGFEDisplacementMapElement|SVGFEDistantLightElement|SVGFEFloodElement|SVGFEFuncAElement|SVGFEFuncBElement|SVGFEFuncGElement|SVGFEFuncRElement|SVGFEGaussianBlurElement|SVGFEImageElement|SVGFEMergeElement|SVGFEMergeNodeElement|SVGFEMorphologyElement|SVGFEOffsetElement|SVGFEPointLightElement|SVGFESpecularLightingElement|SVGFESpotLightElement|SVGFETileElement|SVGFETurbulenceElement|SVGFilterElement|SVGFontElement|SVGFontFaceElement|SVGFontFaceFormatElement|SVGFontFaceNameElement|SVGFontFaceSrcElement|SVGFontFaceUriElement|SVGForeignObjectElement|SVGGElement|SVGGlyphElement|SVGGlyphRefElement|SVGGradientElement|SVGHKernElement|SVGImageElement|SVGLength|SVGLengthList|SVGLineElement|SVGLinearGradientElement|SVGMPathElement|SVGMarkerElement|SVGMaskElement|SVGMatrix|SVGMetadataElement|SVGMissingGlyphElement|SVGNumber|SVGNumberList|SVGPaint|SVGPathElement|SVGPathSeg|SVGPathSegArcAbs|SVGPathSegArcRel|SVGPathSegClosePath|SVGPathSegCurvetoCubicAbs|SVGPathSegCurvetoCubicRel|SVGPathSegCurvetoCubicSmoothAbs|SVGPathSegCurvetoCubicSmoothRel|SVGPathSegCurvetoQuadraticAbs|SVGPathSegCurvetoQuadraticRel|SVGPathSegCurvetoQuadraticSmoothAbs|SVGPathSegCurvetoQuadraticSmoothRel|SVGPathSegLinetoAbs|SVGPathSegLinetoHorizontalAbs|SVGPathSegLinetoHorizontalRel|SVGPathSegLinetoRel|SVGPathSegLinetoVerticalAbs|SVGPathSegLinetoVerticalRel|SVGPathSegList|SVGPathSegMovetoAbs|SVGPathSegMovetoRel|SVGPatternElement|SVGPoint|SVGPointList|SVGPolygonElement|SVGPolylineElement|SVGPreserveAspectRatio|SVGRadialGradientElement|SVGRect|SVGRectElement|SVGRenderingIntent|SVGSVGElement|SVGScriptElement|SVGSetElement|SVGStopElement|SVGStringList|SVGStyleElement|SVGSwitchElement|SVGSymbolElement|SVGTRefElement|SVGTSpanElement|SVGTextContentElement|SVGTextElement|SVGTextPathElement|SVGTextPositioningElement|SVGTitleElement|SVGTransform|SVGTransformList|SVGUnitTypes|SVGUseElement|SVGUseElement|SVGVKernElement|SVGViewElement|SVGViewSpec|SVGZoomEvent)\b(?!\$) - name - support.class.dom.js - - - comment - WebGL specification used by HTML 5 (http://www.khronos.org/registry/webgl/specs/latest/1.0/) - match - (?<!\.|\$)\b(WebGLActiveInfo|WebGLBuffer|WebGLContextEvent|WebGLFramebuffer|WebGLProgram|WebGLRenderbuffer|WebGLRenderingContext|WebGLShader|WebGLShaderPrecisionFormat|WebGLTexture|WebGLUniformLocation)\b(?!\$) - name - support.class.dom.js - - - comment - HTML 5 (http://www.w3.org/TR/html5/single-page.html) - match - (?<!\.|\$)\b(Audio|BarProp|DOMStringMap|ErrorEvent|FileError|HTMLAllCollection|HTMLAnchorElement|HTMLAppletElement|HTMLAreaElement|HTMLAudioElement|HTMLBRElement|HTMLBaseElement|HTMLBodyElement|HTMLButtonElement|HTMLCanvasElement|HTMLDListElement|HTMLDataElement|HTMLDataListElement|HTMLDetailsElement|HTMLDialogElement|HTMLDirectoryElement|HTMLDivElement|HTMLEmbedElement|HTMLFieldSetElement|HTMLFontElement|HTMLFormControlsCollection|HTMLFormElement|HTMLFrameElement|HTMLFrameSetElement|HTMLHRElement|HTMLHeadElement|HTMLHeadingElement|HTMLHtmlElement|HTMLIFrameElement|HTMLImageElement|HTMLInputElement|HTMLKeygenElement|HTMLLIElement|HTMLLabelElement|HTMLLegendElement|HTMLLinkElement|HTMLMapElement|HTMLMarqueeElement|HTMLMediaElement|HTMLMetaElement|HTMLMeterElement|HTMLModElement|HTMLOListElement|HTMLObjectElement|HTMLOptGroupElement|HTMLOptionElement|HTMLOptionsCollection|HTMLOutputElement|HTMLParagraphElement|HTMLParamElement|HTMLPreElement|HTMLProgressElement|HTMLQuoteElement|HTMLScriptElement|HTMLSelectElement|HTMLSour|HTMLSpanElement|HTMLStyleElement|HTMLTableCaptionElement|HTMLTableCellElement|HTMLTableColElement|HTMLTableDataCellElement|HTMLTableElement|HTMLTableHeaderCellElement|HTMLTableRowElement|HTMLTableSectionElement|HTMLTextAreaElement|HTMLTimeElement|HTMLTitleElement|HTMLTrackElement|HTMLUListElement|HTMLUnknownElement|HTMLVideoElement|HashChangeEvent|History|Image|Location|MediaController|MediaError|MouseEvent|Navigator|Option|PageTransitionEvent|PopStateEvent|TextTrack|TextTrackCue|TextTrackCueList|TextTrackList|TimeRanges|TrackEvent|UIEvent|ValidityState|Window)\b(?!\$) - name - support.class.dom.js - - - comment - HTML 5 (http://www.w3.org/TR/html5/single-page.html#window) - match - (?<!\.|\$)\b(applicationCache|closed|console|crypto|document|external|frameElement|frames|history|innerHeight|innerWidth|length|location|locationbar|menubar|name|navigator|offscreenBuffering|onabort|onafterprint|onbeforeprint|onbeforeunload|onblur|oncancel|oncanplay|oncanplaythrough|onchange|onclick|onclose|oncuechange|ondblclick|ondrag|ondragend|ondragenter|ondragexit|ondragleave|ondragover|ondragstart|ondrop|ondurationchange|onemptied|onended|onerror|onfocus|onhashchange|oninput|oninvalid|onkeydown|onkeypress|onkeyup|onload|onloadeddata|onloadedmetadata|onloadstart|onmessage|onmousedown|onmouseenter|onmouseleave|onmousemove|onmouseout|onmouseover|onmouseup|onmousewheel|onoffline|ononline|onpagehide|onpageshow|onpause|onplay|onplaying|onpopstate|onprogress|onratechange|onreset|onresize|onscroll|onseeked|onseeking|onselect|onshow|onstalled|onstorage|onsubmit|onsuspend|ontimeupdate|onunload|onvolumechange|onwaiting|opener|outerHeight|outerWidth|pageXOffset|pageYOffset|parent|personalbar|postMessage|screen|screenX|screenY|scrollbars|scrollX|scrollY|self|status|statusbar|toolbar|top|window)\b(?!\$) - name - support.constant.dom.js - - - comment - HTML 5 (http://www.w3.org/TR/html5/single-page.html#window) - match - (?<!\.|\$)\b(addEventListener|alert|atob|blur|btoa|clearInterval|clearTimeout|close|confirm|dispatchEvent|doNotTrack|find|focus|getComputedStyle|getMatchedCSSRules|getSelection|matchMedia|moveBy|moveTo|open|openDatabase|print|prompt|removeEventListener|resizeBy|resizeTo|scroll|scrollBy|scrollTo|setInterval|setTimeout|showModalDialog|stop)\b(?!\$) - name - support.function.dom.js - - - match - (?<!\.|\$)\b(captureEvents|defaultStatus|defaultstatus|releaseEvents)\b(?!\$) - name - invalid.deprecated.dom.js - - - match - (?<!\.|\$)\b(JSON|Math)\b(?!\$) - name - support.constant.js - - - match - (?<!\.|\$)\b(decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|uneval)\b(?!\$) - name - support.function.js - - - comment - Keywords reserved for future use but now are unused. - match - (?<!\.|\$)\b(class|const|enum|export|extends|import|super)\b(?!\$) - name - invalid.illegal.js - - - comment - Keywords reserved for future use in strict mode but now are unused. - match - (?<!\.|\$)\b(implements|interface|package|private|protected|public|static)\b(?!\$) - name - invalid.deprecated.js - - - match - \b(false|Infinity|NaN|null|true|undefined)\b - name - constant.language.js - - - match - (?<!\.|\$)\b(this)\b(?!\$) - name - variable.language.js - - - begin - (?<=[=(:,]|^|return|&&|\|\||!|\?)\s*(?=/[^/*+?]) - comment - Dont scope preceding whitespace as string.regex - end - (?<=[/igm]) - patterns - - - begin - / - beginCaptures - - 1 - - name - punctuation.definition.string.begin.js - - - end - (/)[igm]* - endCaptures - - 1 - - name - punctuation.definition.string.end.js - - - name - string.regexp.js - patterns - - - include - source.js.regexp - - - - - - - match - \; - name - punctuation.terminator.statement.js - - - captures - - 1 - - name - punctuation.section.scope.begin.js - - 2 - - name - punctuation.section.scope.end.js - - - comment - Allows the special return snippet to fire. - match - (\{)(\}) - - - captures - - 1 - - name - punctuation.section.scope.begin.js - - 2 - - name - punctuation.section.scope.end.js - - - comment - Allows the special return snippet to fire. - match - (\()(\)) - - - captures - - 1 - - name - punctuation.section.scope.begin.js - - 2 - - name - punctuation.section.scope.end.js - - - comment - Allows the special return snippet to fire. - match - (\[)(\]) - - - match - \{|\} - name - meta.brace.curly.js - - - match - \(|\) - name - meta.brace.round.js - - - match - \[|\] - name - meta.brace.square.js - - - begin - \? - end - : - name - meta.ternary-if.js - patterns - - - include - $self - - - - - comment - Match classes based on the usage of the "new" operator. - match - (?<=new )([\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*)(?!\w) - name - support.class.js - - - comment - Match classes based on the usage of the "instanceof" operator. - match - (?<= instanceof )([\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*)(?!\w) - name - support.class.js - - - comment - Match classes based on the usage of the "prototype" property. - match - (?<!\w)([\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*)(?=\.prototype\b) - name - support.class.js - - - comment - Matches the "prototype" keyword. Even though it is not a valid keyword, it is a special constant of sorts. - match - (?<=\.)(prototype)\b - name - keyword.other.js - - - comment - Matches the function calls. - match - (?<!\w)([\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*)(?=\() - name - meta.function-call.js - - - repository - - function-params - - patterns - - - begin - (?=[\p{L}\p{Nl}$_]) - comment - Matches valid argument, function and variable names. To be thorough: https://github.com/mathiasbynens/mothereff.in/tree/master/js-variables - end - (?=[,)]) - patterns - - - match - \G[\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]* - name - variable.parameter.function.js - - - - - - - scopeName - source.js - uuid - 93E017CC-6F27-11D9-90EB-000D93589AF6 - - \ No newline at end of file diff --git a/SyntaxKit/Tests/Resources/Fixtures/Latex.tmLanguage b/SyntaxKit/Tests/Resources/Fixtures/Latex.tmLanguage new file mode 100644 index 0000000..dafc016 --- /dev/null +++ b/SyntaxKit/Tests/Resources/Fixtures/Latex.tmLanguage @@ -0,0 +1,1529 @@ + + + + + fileTypes + + tex + + firstLineMatch + ^\\documentclass(?!.*\{beamer\}) + keyEquivalent + ^~L + name + LaTeX + patterns + + + comment + This scope identifies partially typed commands such as `\tab`. We use this to trigger “Command Completion” only when it makes sense. + match + (?<=\\[\w@]|\\[\w@]{2}|\\[\w@]{3}|\\[\w@]{4}|\\[\w@]{5}|\\[\w@]{6})\s + name + meta.space-after-command.latex + + + begin + ((\\)(?:usepackage|documentclass))(?:(\[)([^\]]*)(\]))?(\{) + beginCaptures + + 1 + + name + keyword.control.preamble.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.arguments.begin.latex + + 4 + + name + variable.parameter.latex + + 5 + + name + punctuation.definition.arguments.end.latex + + 6 + + name + punctuation.definition.arguments.begin.latex + + + contentName + support.class.latex + end + \} + endCaptures + + 0 + + name + punctuation.definition.arguments.end.latex + + + name + meta.preamble.latex + patterns + + + include + $self + + + + + begin + ((\\)(?:include|input))(\{) + beginCaptures + + 1 + + name + keyword.control.include.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.arguments.begin.latex + + + contentName + support.class.latex + end + \} + endCaptures + + 0 + + name + punctuation.definition.arguments.end.latex + + + name + meta.include.latex + patterns + + + include + $self + + + + + begin + (?x) + ( # Capture 1 + (\\) # Marker + ( + (?:sub){0,2}section # Functions + | (?:sub)?paragraph + | chapter|part|addpart + | addchap|addsec|minisec + ) + (?:\*)? # Optional Unnumbered + ) + (?: + (\[)([^\[]*?)(\]) # Optional Title + )?? + (\{) # Opening Bracket + + beginCaptures + + 1 + + name + support.function.section.latex + + 2 + + name + punctuation.definition.function.latex + + 4 + + name + punctuation.definition.arguments.optional.begin.latex + + 5 + + name + entity.name.section.latex + + 6 + + name + punctuation.definition.arguments.optional.end.latex + + 7 + + name + punctuation.definition.arguments.begin.latex + + + comment + this works OK with all kinds of crazy stuff as long as section is one line + contentName + entity.name.section.latex + end + \} + endCaptures + + 0 + + name + punctuation.definition.arguments.end.latex + + + name + meta.function.section.$3.latex + patterns + + + include + $self + + + + + begin + (^\s*)?(?=\\begin\{lstlisting\}) + beginCaptures + + 0 + + name + punctuation.whitespace.embedded.leading.latex + + + end + (?!\G)(\s*$\n?)? + endCaptures + + 0 + + name + punctuation.whitespace.embedded.trailing.latex + + + patterns + + + begin + ((\\)begin)(\{)(lstlisting)(\})(?:(\[).*(\]))?(\s*%.*\n?)? + captures + + 1 + + name + meta.function.embedded.latex + + 2 + + name + support.function.be.latex + + 3 + + name + punctuation.definition.function.latex + + 4 + + name + punctuation.definition.arguments.begin.latex + + 5 + + name + variable.parameter.function.latex + + 6 + + name + punctuation.definition.arguments.end.latex + + 7 + + name + punctuation.definition.arguments.optional.begin.latex + + 8 + + name + punctuation.definition.arguments.optional.end.latex + + 9 + + name + comment.line.percentage.latex + + + contentName + meta.function.embedded.latex + end + (((\\)end)(\{)(lstlisting)(\})) + name + meta.embedded.block.generic + + + + + begin + (?:\s*)((\\)begin)(\{)((?:V|v)erbatim|alltt)(\}) + captures + + 1 + + name + support.function.be.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.arguments.begin.latex + + 4 + + name + variable.parameter.function.latex + + 5 + + name + punctuation.definition.arguments.end.latex + + + contentName + markup.raw.verbatim.latex + end + ((\\)end)(\{)(\4)(\}) + name + meta.function.verbatim.latex + + + captures + + 1 + + name + support.function.url.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.arguments.begin.latex + + 4 + + name + markup.underline.link.latex + + 5 + + name + punctuation.definition.arguments.end.latex + + + match + (?:\s*)((\\)(?:url|href))(\{)([^}]*)(\}) + name + meta.function.link.url.latex + + + captures + + 1 + + name + support.function.be.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.arguments.begin.latex + + 4 + + name + variable.parameter.function.latex + + 5 + + name + punctuation.definition.arguments.end.latex + + + comment + These two patterns match the \begin{document} and \end{document} commands, so that the environment matching pattern following them will ignore those commands. + match + (?:\s*)((\\)begin)(\{)(document)(\}) + name + meta.function.begin-document.latex + + + captures + + 1 + + name + support.function.be.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.arguments.begin.latex + + 4 + + name + variable.parameter.function.latex + + 5 + + name + punctuation.definition.arguments.end.latex + + + match + (?:\s*)((\\)end)(\{)(document)(\}) + name + meta.function.end-document.latex + + + begin + (?x) + (?:\s*) # Optional whitespace + ((\\)begin) # Marker - Function + (\{) # Open Bracket + ( + (?: + align|equation|eqnarray # Argument + | multline|aligned|alignat + | split|gather|gathered + ) + (?:\*)? # Optional Unnumbered + ) + (\}) # Close Bracket + (\s*\n)? # Match to end of line absent of content + + captures + + 1 + + name + support.function.be.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.arguments.begin.latex + + 4 + + name + variable.parameter.function.latex + + 5 + + name + punctuation.definition.arguments.end.latex + + + contentName + string.other.math.block.environment.latex + end + (?x) + (?:\s*) # Optional whitespace + ((\\)end) # Marker - Function + (\{) # Open Bracket + (\4) # Previous capture from begin + (\}) # Close Bracket + (?:\s*\n)? # Match to end of line absent of content + + name + meta.function.environment.math.latex + patterns + + + include + $base + + + + + begin + (?x) + (?:\s*) # Optional whitespace + ((\\)begin) # Marker - Function + (\{) # Open Bracket + (array|tabular[xy*]?) + (\}) # Close Bracket + (\s*\n)? # Match to end of line absent of content + + captures + + 1 + + name + support.function.be.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.arguments.begin.latex + + 4 + + name + variable.parameter.function.latex + + 5 + + name + punctuation.definition.arguments.end.latex + + + contentName + meta.data.environment.tabular.latex + end + (?x) + (?:\s*) # Optional whitespace + ((\\)end) # Marker - Function + (\{) # Open Bracket + (\4) # Previous capture from begin + (\}) # Close Bracket + (?:\s*\n)? # Match to end of line absent of content + + name + meta.function.environment.tabular.latex + patterns + + + match + \\\\ + name + punctuation.definition.table.row.latex + + + begin + (?:^|(?<=\\\\))(?!\\\\|\s*\\end\{(?:tabular|array)) + end + (?=\\\\|\s*\\end\{(?:tabular|array)) + name + meta.row.environment.tabular.latex + patterns + + + match + & + name + punctuation.definition.table.cell.latex + + + begin + (?:^|(?<=&))((?!&|\\\\|$)) + end + (?=&|\\\\|\s*\\end\{(?:tabular|array)) + name + meta.cell.environment.tabular.latex + patterns + + + include + $base + + + + + include + $base + + + + + include + $base + + + + + begin + (?:\s*)((\\)begin)(\{)(itemize|enumerate|description|list)(\}) + captures + + 1 + + name + support.function.be.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.arguments.latex + + 4 + + name + variable.parameter.function.latex + + 5 + + name + punctuation.definition.arguments.latex + + + end + ((\\)end)(\{)(\4)(\})(?:\s*\n)? + name + meta.function.environment.list.latex + patterns + + + include + $base + + + + + begin + (?:\s*)((\\)begin)(\{)(tikzpicture)(\}) + captures + + 1 + + name + support.function.be.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.arguments.latex + + 4 + + name + variable.parameter.function.latex + + 5 + + name + punctuation.definition.arguments.latex + + + end + ((\\)end)(\{)(tikzpicture)(\})(?:\s*\n)? + name + meta.function.environment.latex.tikz + patterns + + + include + $self + + + + + begin + (?:\s*)((\\)begin)(\{)(\w+[*]?)(\}) + captures + + 1 + + name + support.function.be.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.arguments.latex + + 4 + + name + variable.parameter.function.latex + + 5 + + name + punctuation.definition.arguments.latex + + + end + ((\\)end)(\{)(\4)(\})(?:\s*\n)? + name + meta.function.environment.general.latex + patterns + + + include + $base + + + + + captures + + 1 + + name + punctuation.definition.function.latex + + + match + (\\)(newcommand|renewcommand)\b + name + storage.type.function.latex + + + begin + ((\\)marginpar)(\{) + beginCaptures + + 1 + + name + support.function.marginpar.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.marginpar.begin.latex + + + contentName + meta.paragraph.margin.latex + end + \} + endCaptures + + 0 + + name + punctuation.definition.marginpar.end.latex + + + patterns + + + include + $base + + + + + begin + ((\\)footnote)((?:\[[^\[]*?\])*)(\{) + beginCaptures + + 1 + + name + support.function.footnote.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + patterns + + + captures + + 1 + + name + punctuation.definition.arguments.begin.latex + + 2 + + name + variable.parameter.latex + + 3 + + name + punctuation.definition.arguments.end.latex + + + match + (\[)([^\[]*?)(\]) + + + + 4 + + name + punctuation.definition.footnote.begin.latex + + + contentName + meta.footnote.latex + end + \} + endCaptures + + 0 + + name + punctuation.definition.footnote.end.latex + + + patterns + + + include + $base + + + + + begin + ((\\)emph)(\{) + beginCaptures + + 1 + + name + support.function.emph.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.emph.begin.latex + + + contentName + markup.italic.emph.latex + end + \} + endCaptures + + 0 + + name + punctuation.definition.emph.end.latex + + + name + meta.function.emph.latex + patterns + + + include + $base + + + + + begin + ((\\)textit)(\{) + captures + + 1 + + name + support.function.textit.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.textit.begin.latex + + + comment + We put the keyword in a capture and name this capture, so that disabling spell checking for “keyword” won't be inherited by the argument to \textit{...}. + +Put specific matches for particular LaTeX keyword.functions before the last two more general functions + contentName + markup.italic.textit.latex + end + \} + endCaptures + + 0 + + name + punctuation.definition.textit.end.latex + + + name + meta.function.textit.latex + patterns + + + include + $base + + + + + begin + ((\\)textbf)(\{) + captures + + 1 + + name + support.function.textbf.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.textbf.begin.latex + + + contentName + markup.bold.textbf.latex + end + \} + endCaptures + + 0 + + name + punctuation.definition.textbf.end.latex + + + name + meta.function.textbf.latex + patterns + + + include + $base + + + + + begin + ((\\)texttt)(\{) + captures + + 1 + + name + support.function.texttt.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.texttt.begin.latex + + + contentName + markup.raw.texttt.latex + end + \} + endCaptures + + 0 + + name + punctuation.definition.texttt.end.latex + + + name + meta.function.texttt.latex + patterns + + + include + $base + + + + + captures + + 0 + + name + keyword.other.item.latex + + 1 + + name + punctuation.definition.keyword.latex + + + match + (\\)item\b + name + meta.scope.item.latex + + + begin + (?x) + ( + (\\) # Marker + (?:auto)?(?:foot)?(?:full)?(?:no)?(?:short)? # Function Name + [cC]ite + (?:al)?(?:t|p|author|year(?:par)?|title)?[ANP]* + \*? # Optional Unabreviated + ) + (?:(\[)[^\]]*(\]))? # Optional + (?:(\[)[^\]]*(\]))? # Arguments + (\{) # Opening Bracket + + captures + + 1 + + name + keyword.control.cite.latex + + 2 + + name + punctuation.definition.keyword.latex + + 3 + + name + punctuation.definition.arguments.optional.begin.latex + + 4 + + name + punctuation.definition.arguments.optional.end.latex + + 5 + + name + punctuation.definition.arguments.optional.begin.latex + + 6 + + name + punctuation.definition.arguments.optional.end.latex + + 7 + + name + punctuation.definition.arguments.latex + + + end + \} + endCaptures + + 0 + + name + punctuation.definition.arguments.latex + + + name + meta.citation.latex + patterns + + + match + [\w:.]+ + name + constant.other.reference.citation.latex + + + + + begin + ((\\)(?:\w*[r|R]ef\*?))(\{) + beginCaptures + + 1 + + name + keyword.control.ref.latex + + 2 + + name + punctuation.definition.keyword.latex + + 3 + + name + punctuation.definition.arguments.begin.latex + + + end + \} + endCaptures + + 0 + + name + punctuation.definition.arguments.begin.latex + + + name + meta.reference.label.latex + patterns + + + match + [a-zA-Z0-9\.,:/*!^_-] + name + constant.other.reference.label.latex + + + + + begin + ((\\)label)(\{) + beginCaptures + + 1 + + name + keyword.control.label.latex + + 2 + + name + punctuation.definition.keyword.latex + + 3 + + name + punctuation.definition.arguments.begin.latex + + + end + \} + endCaptures + + 0 + + name + punctuation.definition.arguments.end.latex + + + name + meta.definition.label.latex + patterns + + + match + [a-zA-Z0-9\.,:/*!^_-] + name + variable.parameter.definition.label.latex + + + + + begin + ((\\)(?:verb|lstinline)[\*]?)\s*((\\)scantokens)(\{) + beginCaptures + + 1 + + name + support.function.verb.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + support.function.verb.latex + + 4 + + name + punctuation.definition.verb.latex + + 5 + + name + punctuation.definition.begin.latex + + + contentName + markup.raw.verb.latex + end + (\}) + endCaptures + + 1 + + name + punctuation.definition.end.latex + + + name + meta.function.verb.latex + patterns + + + include + $self + + + + + captures + + 1 + + name + support.function.verb.latex + + 2 + + name + punctuation.definition.function.latex + + 3 + + name + punctuation.definition.verb.latex + + 4 + + name + markup.raw.verb.latex + + 5 + + name + punctuation.definition.verb.latex + + + match + ((\\)(?:verb|lstinline)[\*]?)\s*((?<=\s)\S|[^a-zA-Z])(.*?)(\3|$) + name + meta.function.verb.latex + + + begin + "` + beginCaptures + + 0 + + name + punctuation.definition.string.begin.latex + + + end + "' + endCaptures + + 0 + + name + punctuation.definition.string.end.latex + + + name + string.quoted.double.european.latex + patterns + + + include + $base + + + + + begin + `` + beginCaptures + + 0 + + name + punctuation.definition.string.begin.latex + + + end + ''|" + endCaptures + + 0 + + name + punctuation.definition.string.end.latex + + + name + string.quoted.double.latex + patterns + + + include + $base + + + + + begin + "> + beginCaptures + + 0 + + name + punctuation.definition.string.begin.latex + + + end + "< + endCaptures + + 0 + + name + punctuation.definition.string.end.latex + + + name + string.quoted.double.guillemot.latex + patterns + + + include + $base + + + + + begin + "< + beginCaptures + + 0 + + name + punctuation.definition.string.begin.latex + + + end + "> + endCaptures + + 0 + + name + punctuation.definition.string.end.latex + + + name + string.quoted.double.guillemot.latex + patterns + + + include + $base + + + + + begin + \\\( + beginCaptures + + 0 + + name + punctuation.definition.string.begin.latex + + + end + \\\) + endCaptures + + 0 + + name + punctuation.definition.string.end.latex + + + name + string.other.math.latex + patterns + + + include + $base + + + + + begin + \\\[ + beginCaptures + + 0 + + name + punctuation.definition.string.begin.latex + + + end + \\\] + endCaptures + + 0 + + name + punctuation.definition.string.end.latex + + + name + string.other.math.latex + patterns + + + include + $base + + + + + match + (?<!\S)'.*?' + name + invalid.illegal.string.quoted.single.latex + + + match + (?<!\S)".*?" + name + invalid.illegal.string.quoted.double.latex + + + captures + + 1 + + name + punctuation.definition.constant.latex + + + match + (\\)(text(s(terling|ixoldstyle|urd|e(ction|venoldstyle|rvicemark))|yen|n(ineoldstyle|umero|aira)|c(ircledP|o(py(left|right)|lonmonetary)|urrency|e(nt(oldstyle)?|lsius))|t(hree(superior|oldstyle|quarters(emdash)?)|i(ldelow|mes)|w(o(superior|oldstyle)|elveudash)|rademark)|interrobang(down)?|zerooldstyle|o(hm|ne(superior|half|oldstyle|quarter)|penbullet|rd(feminine|masculine))|d(i(scount|ed|v(orced)?)|o(ng|wnarrow|llar(oldstyle)?)|egree|agger(dbl)?|blhyphen(char)?)|uparrow|p(ilcrow|e(so|r(t(housand|enthousand)|iodcentered))|aragraph|m)|e(stimated|ightoldstyle|uro)|quotes(traight(dblbase|base)|ingle)|f(iveoldstyle|ouroldstyle|lorin|ractionsolidus)|won|l(not|ira|e(ftarrow|af)|quill|angle|brackdbl)|a(s(cii(caron|dieresis|acute|grave|macron|breve)|teriskcentered)|cutedbl)|r(ightarrow|e(cipe|ferencemark|gistered)|quill|angle|brackdbl)|g(uarani|ravedbl)|m(ho|inus|u(sicalnote)?|arried)|b(igcircle|orn|ullet|lank|a(ht|rdbl)|rokenbar)))\b + name + constant.character.latex + + + captures + + 1 + + name + punctuation.definition.column-specials.begin.latex + + 2 + + name + punctuation.definition.column-specials.end.latex + + + match + (?:<|>)(\{)\$(\}) + name + meta.column-specials.latex + + + include + text.tex + + + scopeName + text.tex.latex + uuid + 3BEEA00C-6B1D-11D9-B8AD-000D93589AF6 + + diff --git a/SyntaxKit/Tests/Resources/Fixtures/Ruby.tmLanguage b/SyntaxKit/Tests/Resources/Fixtures/Ruby.tmLanguage index ece00af..5a53e74 100644 --- a/SyntaxKit/Tests/Resources/Fixtures/Ruby.tmLanguage +++ b/SyntaxKit/Tests/Resources/Fixtures/Ruby.tmLanguage @@ -455,7 +455,7 @@ (?>[a-zA-Z_]\w*(?>[?!]|=(?!>))? # the method name |===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?) ) # …or an operator method [ \t] # the space separating the arguments - (?=[ \t]*[^\s#;]) # make sure arguments and not a comment follow + (?=[ \t]*[^\s\#;]) # make sure arguments and not a comment follow beginCaptures diff --git a/SyntaxKit/Tests/Resources/Fixtures/Solarized.tmTheme b/SyntaxKit/Tests/Resources/Fixtures/Solarized.tmTheme new file mode 100644 index 0000000..8e85ba1 --- /dev/null +++ b/SyntaxKit/Tests/Resources/Fixtures/Solarized.tmTheme @@ -0,0 +1,2148 @@ + + + + + name + Solarized (light) + semanticClass + solarized.light + gutterSettings + + background + #EEE8D5 + divider + #EEE8D5 + foreground + #93A1A1 + selectionBackground + #EEE8D5 + selectionForeground + #93A1A1 + + settings + + + settings + + background + #FDF6E3 + caret + #000000 + foreground + #586E75 + invisibles + #EAE3C9 + lineHighlight + #EEE8D5 + selection + #EEE8D5 + + + + name + Comment + scope + comment + settings + + fontStyle + + foreground + #93A1A1 + + + + name + String + scope + string + settings + + foreground + #2aa198 + + + + name + StringNumber + scope + string + settings + + foreground + #586E75 + + + + name + Regexp + scope + string.regexp + settings + + foreground + #dc322f + + + + name + Number + scope + constant.numeric + settings + + foreground + #d33682 + + + + name + Variable + scope + variable.language, variable.other + settings + + foreground + #268bd2 + + + + name + Keyword + scope + keyword + settings + + foreground + #859900 + + + + name + Storage + scope + storage + settings + + fontStyle + bold + foreground + #073642 + + + + name + Class name + scope + entity.name.class, entity.name.type.class + settings + + foreground + #268bd2 + + + + name + Function name + scope + entity.name.function + settings + + foreground + #268bd2 + + + + name + Variable start + scope + punctuation.definition.variable + settings + + foreground + #859900 + + + + name + Embedded code markers + scope + punctuation.section.embedded.begin, punctuation.section.embedded.end + settings + + foreground + #dc322f + + + + name + Built-in constant + scope + constant.language, meta.preprocessor + settings + + foreground + #B58900 + + + + name + Support.construct + scope + support.function.construct, keyword.other.new + settings + + foreground + #dc322f + + + + name + User-defined constant + scope + constant.character, constant.other + settings + + foreground + #CB4B16 + + + + name + Inherited class + scope + entity.other.inherited-class + settings + + + + name + Function argument + scope + variable.parameter + settings + + + + name + Tag name + scope + entity.name.tag + settings + + fontStyle + bold + foreground + #268bd2 + + + + name + Tag start/end + scope + punctuation.definition.tag.html, punctuation.definition.tag.begin, punctuation.definition.tag.end + settings + + foreground + #93A1A1 + + + + name + Tag attribute + scope + entity.other.attribute-name + settings + + foreground + #93A1A1 + + + + name + Library function + scope + support.function + settings + + foreground + #268bd2 + + + + name + Continuation + scope + punctuation.separator.continuation + settings + + foreground + #dc322f + + + + name + Library constant + scope + support.constant + settings + + + + name + Library class/type + scope + support.type, support.class + settings + + foreground + #859900 + + + + name + Library Exception + scope + support.type.exception + settings + + foreground + #CB4B16 + + + + name + Special + scope + keyword.other.special-method + settings + + foreground + #CB4B16 + + + + name + Library variable + scope + support.other.variable + settings + + + + name + Invalid + scope + invalid + settings + + + + name + Quoted String + scope + string.quoted.double, string.quoted.single + settings + + foreground + #2aa198 + + + + name + Quotes + scope + punctuation.definition.string.begin, punctuation.definition.string.end + settings + + foreground + #dc322f + + + + name + CSS: Property + scope + entity.name.tag.css, support.type.property-name.css, meta.property-name.css + settings + + fontStyle + + foreground + #b58900 + + + + name + CSS: @font-face + scope + source.css + settings + + foreground + #dc322f + + + + name + CSS: Selector + scope + meta.selector.css + settings + + fontStyle + + foreground + #586e75 + + + + name + CSS: {} + scope + punctuation.section.property-list.css + settings + + foreground + #6c71c4 + + + + name + CSS: Numeric Value + scope + meta.property-value.css constant.numeric.css, keyword.other.unit.css,constant.other.color.rgb-value.css + settings + + fontStyle + + foreground + #2aa198 + + + + name + CSS: Value + scope + meta.property-value.css + settings + + fontStyle + + foreground + #2aa198 + + + + name + CSS: !Important + scope + keyword.other.important.css + settings + + foreground + #dc322f + + + + name + CSS: Standard Value + scope + support.constant.color + settings + + foreground + #2aa198 + + + + name + CSS: Tag + scope + entity.name.tag.css + settings + + foreground + #859900 + + + + name + CSS: : , + scope + punctuation.separator.key-value.css, punctuation.terminator.rule.css + settings + + fontStyle + + foreground + #586e75 + + + + name + CSS .class + scope + entity.other.attribute-name.class.css + settings + + fontStyle + + foreground + #268bd2 + + + + name + CSS :pseudo + scope + entity.other.attribute-name.pseudo-element.css, entity.other.attribute-name.pseudo-class.css + settings + + fontStyle + + foreground + #cb4b16 + + + + name + CSS: #id + scope + entity.other.attribute-name.id.css + settings + + fontStyle + + foreground + #268bd2 + + + + name + JS: Function Name + scope + meta.function.js, entity.name.function.js, support.function.dom.js + settings + + foreground + #b58900 + + + + name + JS: Source + scope + text.html.basic source.js.embedded.html + settings + + fontStyle + + foreground + #b58900 + + + + name + JS: Function + scope + storage.type.function.js + settings + + foreground + #268bd2 + + + + name + JS: Numeric Constant + scope + constant.numeric.js + settings + + foreground + #2aa198 + + + + name + JS: [] + scope + meta.brace.square.js + settings + + foreground + #268bd2 + + + + name + JS: Storage Type + scope + storage.type.js + settings + + foreground + #268bd2 + + + + name + () + scope + meta.brace.round, punctuation.definition.parameters.begin.js, punctuation.definition.parameters.end.js + settings + + foreground + #93A1A1 + + + + name + {} + scope + meta.brace.curly.js + settings + + foreground + #268bd2 + + + + name + HTML: Doctype + scope + entity.name.tag.doctype.html, meta.tag.sgml.html, string.quoted.double.doctype.identifiers-and-DTDs.html + settings + + fontStyle + italic + foreground + #93a1a1 + + + + name + HTML: Comment Block + scope + comment.block.html + settings + + fontStyle + italic + foreground + #839496 + + + + name + HTML: Script + scope + entity.name.tag.script.html + settings + + fontStyle + italic + + + + name + HTML: Style + scope + source.css.embedded.html string.quoted.double.html + settings + + fontStyle + + foreground + #2aa198 + + + + name + HTML: Text + scope + text.html.ruby + settings + + fontStyle + bold + foreground + #cb4b16 + + + + name + HTML: = + scope + text.html.basic meta.tag.other.html, text.html.basic meta.tag.any.html, text.html.basic meta.tag.block.any, text.html.basic meta.tag.inline.any, text.html.basic meta.tag.structure.any.html, text.html.basic source.js.embedded.html, punctuation.separator.key-value.html + settings + + fontStyle + + foreground + #657b83 + + + + name + HTML: something= + scope + text.html.basic entity.other.attribute-name.html + settings + + foreground + #657b83 + + + + name + HTML: " + scope + text.html.basic meta.tag.structure.any.html punctuation.definition.string.begin.html, punctuation.definition.string.begin.html, punctuation.definition.string.end.html + settings + + fontStyle + + foreground + #2aa198 + + + + name + HTML: <tag> + scope + entity.name.tag.block.any.html + settings + + fontStyle + bold + foreground + #268bd2 + + + + name + HTML: style + scope + source.css.embedded.html entity.name.tag.style.html + settings + + fontStyle + italic + + + + name + HTML: <style> + scope + entity.name.tag.style.html + settings + + fontStyle + + + + + name + HTML: {} + scope + text.html.basic punctuation.section.property-list.css + settings + + fontStyle + + + + + name + HTML: Embeddable + scope + source.css.embedded.html, comment.block.html + settings + + fontStyle + italic + foreground + #839496 + + + + name + Ruby: Variable definition + scope + punctuation.definition.variable.ruby + settings + + fontStyle + + foreground + #268bd2 + + + + name + Ruby: Function Name + scope + meta.function.method.with-arguments.ruby + settings + + foreground + #657b83 + + + + name + Ruby: Variable + scope + variable.language.ruby + settings + + foreground + #2aa198 + + + + name + Ruby: Function + scope + entity.name.function.ruby + settings + + foreground + #268bd2 + + + + name + Ruby: Keyword Control + scope + keyword.control.ruby, keyword.control.def.ruby + settings + + fontStyle + bold + foreground + #859900 + + + + name + Ruby: Class + scope + keyword.control.class.ruby, meta.class.ruby + settings + + foreground + #859900 + + + + name + Ruby: Class Name + scope + entity.name.type.class.ruby + settings + + fontStyle + + foreground + #b58900 + + + + name + Ruby: Keyword + scope + keyword.control.ruby + settings + + fontStyle + + foreground + #859900 + + + + name + Ruby: Support Class + scope + support.class.ruby + settings + + fontStyle + + foreground + #b58900 + + + + name + Ruby: Special Method + scope + keyword.other.special-method.ruby + settings + + foreground + #859900 + + + + name + Ruby: Constant + scope + constant.language.ruby, constant.numeric.ruby + settings + + foreground + #2aa198 + + + + name + Ruby: Constant Other + scope + variable.other.constant.ruby + settings + + fontStyle + + foreground + #b58900 + + + + name + Ruby: :symbol + scope + constant.other.symbol.ruby + settings + + fontStyle + + foreground + #2aa198 + + + + name + Ruby: Punctuation Section '' + scope + punctuation.section.embedded.ruby, punctuation.definition.string.begin.ruby, punctuation.definition.string.end.ruby + settings + + foreground + #dc322f + + + + name + Ruby: Special Method + scope + keyword.other.special-method.ruby + settings + + foreground + #cb4b16 + + + + name + PHP: Include + scope + keyword.control.import.include.php + settings + + foreground + #cb4b16 + + + + name + Ruby: erb = + scope + text.html.ruby meta.tag.inline.any.html + settings + + fontStyle + + foreground + #839496 + + + + name + Ruby: erb "" + scope + text.html.ruby punctuation.definition.string.begin, text.html.ruby punctuation.definition.string.end + settings + + fontStyle + + foreground + #2aa198 + + + + name + PHP: Quoted Single + scope + punctuation.definition.string.begin, punctuation.definition.string.end + settings + + foreground + #839496 + + + + name + PHP: [] + scope + keyword.operator.index-start.php, keyword.operator.index-end.php + settings + + foreground + #dc322f + + + + name + PHP: Array + scope + meta.array.php + settings + + foreground + #586e75 + + + + name + PHP: Array() + scope + meta.array.php support.function.construct.php, meta.array.empty.php support.function.construct.php + settings + + fontStyle + + foreground + #b58900 + + + + name + PHP: Array Construct + scope + support.function.construct.php + settings + + foreground + #b58900 + + + + name + PHP: Array Begin + scope + punctuation.definition.array.begin, punctuation.definition.array.end + settings + + foreground + #dc322f + + + + name + PHP: Numeric Constant + scope + constant.numeric.php + settings + + foreground + #2aa198 + + + + name + PHP: New + scope + keyword.other.new.php + settings + + foreground + #CB4B16 + + + + name + PHP: :: + scope + support.class.php, keyword.operator.class + settings + + fontStyle + + foreground + #586e75 + + + + name + PHP: Other Property + scope + variable.other.property.php + settings + + foreground + #93a1a1 + + + + name + PHP: Class + scope + storage.modifier.extends.php, storage.type.class.php, keyword.operator.class.php + settings + + foreground + #b58900 + + + + name + PHP: Class Function + settings + + + + name + PHP: Inherited Class + scope + meta.other.inherited-class.php + settings + + fontStyle + + foreground + #586e75 + + + + name + PHP: Storage Type + scope + storage.type.php + settings + + foreground + #859900 + + + + name + PHP: Function + scope + entity.name.function.php + settings + + foreground + #93a1a1 + + + + name + PHP: Function Construct + scope + support.function.construct.php + settings + + foreground + #859900 + + + + name + PHP: Function Call + scope + entity.name.type.class.php, meta.function-call.php, meta.function-call.static.php, meta.function-call.object.php + settings + + foreground + #839496 + + + + name + PHP: Comment + scope + keyword.other.phpdoc + settings + + fontStyle + + foreground + #93a1a1 + + + + name + PHP: Source Emebedded + scope + source.php.embedded.block.html + settings + + foreground + #cb4b16 + + + + name + PHP: Storage Type Function + scope + storage.type.function.php + settings + + foreground + #cb4b16 + + + + name + C: constant + scope + constant.numeric.c + settings + + fontStyle + + foreground + #2aa198 + + + + name + C: Meta Preprocessor + scope + meta.preprocessor.c.include, meta.preprocessor.macro.c + settings + + fontStyle + + foreground + #cb4b16 + + + + name + C: Keyword + scope + keyword.control.import.define.c, keyword.control.import.include.c + settings + + fontStyle + + foreground + #cb4b16 + + + + name + C: Function Preprocessor + scope + entity.name.function.preprocessor.c + settings + + fontStyle + + foreground + #cb4b16 + + + + name + C: include <something.c> + scope + meta.preprocessor.c.include string.quoted.other.lt-gt.include.c, meta.preprocessor.c.include punctuation.definition.string.begin.c, meta.preprocessor.c.include punctuation.definition.string.end.c + settings + + fontStyle + + foreground + #2aa198 + + + + name + C: Function + scope + support.function.C99.c, support.function.any-method.c, entity.name.function.c + settings + + fontStyle + + foreground + #586e75 + + + + name + C: " + scope + punctuation.definition.string.begin.c, punctuation.definition.string.end.c + settings + + fontStyle + + foreground + #2aa198 + + + + name + C: Storage Type + scope + storage.type.c + settings + + fontStyle + + foreground + #b58900 + + + + name + diff: header + scope + meta.diff, meta.diff.header + settings + + background + #b58900 + fontStyle + italic + foreground + #E0EDDD + + + + name + diff: deleted + scope + markup.deleted + settings + + background + #eee8d5 + fontStyle + + foreground + #dc322f + + + + name + diff: changed + scope + markup.changed + settings + + background + #eee8d5 + fontStyle + + foreground + #cb4b16 + + + + name + diff: inserted + scope + markup.inserted + settings + + background + #eee8d5 + foreground + #219186 + + + + name + Markdown: Linebreak + scope + text.html.markdown meta.dummy.line-break + settings + + background + #A57706 + foreground + #E0EDDD + + + + name + Markdown: Raw + scope + text.html.markdown markup.raw.inline + settings + + foreground + #2aa198 + + + + name + reST raw + scope + text.restructuredtext markup.raw + settings + + foreground + #2aa198 + + + + name + Other: Removal + scope + other.package.exclude, other.remove + settings + + fontStyle + + foreground + #dc322f + + + + name + Other: Add + scope + other.add + settings + + foreground + #2aa198 + + + + name + Tex: {} + scope + punctuation.section.group.tex , punctuation.definition.arguments.begin.latex, punctuation.definition.arguments.end.latex, punctuation.definition.arguments.latex + settings + + fontStyle + + foreground + #dc322f + + + + name + Tex: {text} + scope + meta.group.braces.tex + settings + + fontStyle + + foreground + #b58900 + + + + name + Tex: Other Math + scope + string.other.math.tex + settings + + fontStyle + + foreground + #b58900 + + + + name + Tex: {var} + scope + variable.parameter.function.latex + settings + + fontStyle + + foreground + #cb4b16 + + + + name + Tex: Math \\ + scope + punctuation.definition.constant.math.tex + settings + + fontStyle + + foreground + #dc322f + + + + name + Tex: Constant Math + scope + text.tex.latex constant.other.math.tex, constant.other.general.math.tex, constant.other.general.math.tex, constant.character.math.tex + settings + + fontStyle + + foreground + #2aa198 + + + + name + Tex: Other Math String + scope + string.other.math.tex + settings + + fontStyle + + foreground + #b58900 + + + + name + Tex: $ + scope + punctuation.definition.string.begin.tex, punctuation.definition.string.end.tex + settings + + fontStyle + + foreground + #dc322f + + + + name + Tex: \label + scope + keyword.control.label.latex, text.tex.latex constant.other.general.math.tex + settings + + fontStyle + + foreground + #2aa198 + + + + name + Tex: \label { } + scope + variable.parameter.definition.label.latex + settings + + fontStyle + + foreground + #dc322f + + + + name + Tex: Function + scope + support.function.be.latex + settings + + fontStyle + + foreground + #859900 + + + + name + Tex: Support Function Section + scope + support.function.section.latex + settings + + fontStyle + + foreground + #cb4b16 + + + + name + Tex: Support Function + scope + support.function.general.tex + settings + + fontStyle + + foreground + #2aa198 + + + + name + Tex: Comment + scope + punctuation.definition.comment.tex, comment.line.percentage.tex + settings + + fontStyle + italic + + + + name + Tex: Reference Label + scope + keyword.control.ref.latex + settings + + fontStyle + + foreground + #2aa198 + + + + name + Python: docstring + scope + string.quoted.double.block.python + settings + + fontStyle + + foreground + #586e75 + + + + name + Python: storage + scope + storage.type.class.python, storage.type.function.python, storage.modifier.global.python + settings + + fontStyle + + foreground + #859900 + + + + name + Python: import + scope + keyword.control.import.python, keyword.control.import.from.python + settings + + foreground + #cb4b16 + + + + name + Python: Support.exception + scope + support.type.exception.python + settings + + foreground + #b58900 + + + + name + Shell: builtin + scope + support.function.builtin.shell + settings + + foreground + #859900 + + + + name + Shell: variable + scope + variable.other.normal.shell + settings + + foreground + #cb4b16 + + + + name + Shell: DOT_FILES + scope + source.shell + settings + + fontStyle + + foreground + #268bd2 + + + + name + Shell: meta scope in loop + scope + meta.scope.for-in-loop.shell, variable.other.loop.shell + settings + + fontStyle + + foreground + #586e75 + + + + name + Shell: "" + scope + punctuation.definition.string.end.shell, punctuation.definition.string.begin.shell + settings + + fontStyle + + foreground + #859900 + + + + name + Shell: Meta Block + scope + meta.scope.case-block.shell, meta.scope.case-body.shell + settings + + fontStyle + + foreground + #586e75 + + + + name + Shell: [] + scope + punctuation.definition.logical-expression.shell + settings + + fontStyle + + foreground + #dc322f + + + + name + Shell: Comment + scope + comment.line.number-sign.shell + settings + + fontStyle + italic + + + + name + Java: import + scope + keyword.other.import.java + settings + + fontStyle + + foreground + #cb4b16 + + + + name + Java: meta-import + scope + storage.modifier.import.java + settings + + fontStyle + + foreground + #586E75 + + + + name + Java: Class + scope + meta.class.java storage.modifier.java + settings + + fontStyle + + foreground + #b58900 + + + + name + Java: /* comment */ + scope + source.java comment.block + settings + + fontStyle + + foreground + #586e75 + + + + name + Java: /* @param */ + scope + comment.block meta.documentation.tag.param.javadoc keyword.other.documentation.param.javadoc + settings + + fontStyle + + foreground + #586e75 + + + + name + Perl: variables + scope + punctuation.definition.variable.perl, variable.other.readwrite.global.perl, variable.other.predefined.perl, keyword.operator.comparison.perl + settings + + foreground + #b58900 + + + + name + Perl: functions + scope + support.function.perl + settings + + foreground + #859900 + + + + name + Perl: comments + scope + comment.line.number-sign.perl + settings + + fontStyle + italic + foreground + #586E75 + + + + name + Perl: quotes + scope + punctuation.definition.string.begin.perl, punctuation.definition.string.end.perl + settings + + foreground + #2aa198 + + + + name + Perl: \char + scope + constant.character.escape.perl + settings + + foreground + #DC322F + + + + + name + Markdown: Headings + scope + markup.heading.markdown, markup.heading.1.markdown, markup.heading.2.markdown, markup.heading.3.markdown, markup.heading.4.markdown, markup.heading.5.markdown, markup.heading.6.markdown + settings + + foreground + #268bd2 + + + + name + Markdown: Bold + scope + markup.bold.markdown + settings + + fontStyle + bold + foreground + #586E75 + + + + name + Markdown: Italic + scope + markup.italic.markdown + settings + + fontStyle + italic + foreground + #586E75 + + + + name + Markdown: Punctuation for Bold, Italic, and Inline Block + scope + punctuation.definition.bold.markdown, punctuation.definition.italic.markdown, punctuation.definition.raw.markdown + settings + + foreground + #DC322F + + + + name + Markdown: Bulleted List + scope + markup.list.unnumbered.markdown + settings + + foreground + #B58900 + + + + name + Markdown: Numbered List + scope + markup.list.numbered.markdown + settings + + foreground + #859900 + + + + name + Markdown: Block and Inline Block + scope + markup.raw.block.markdown, markup.raw.inline.markdown + settings + + foreground + #2aa198 + + + + name + markup.quote.markdown + scope + markup.quote.markdown + settings + + foreground + #6c71c4 + + + + + name + punctuation.definition.blockquote.markdown + scope + punctuation.definition.blockquote.markdown + settings + + foreground + #6c71c4 + + + + + name + Markdown: Seperator + scope + meta.separator.markdown + settings + + foreground + #d33682 + + + + + name + Markdown: Link URL, Reference + scope + markup.underline.link.markdown + settings + + foreground + #839496 + + + + + name + Markdown: Link Title + scope + markup.underline.link.markdown + settings + + foreground + #839496 + + + + + name + Markdown: Link Punctuation + scope + meta.link.inet.markdown, meta.link.email.lt-gt.markdown, punctuation.definition.string.begin.markdown, punctuation.definition.string.end.markdown, punctuation.definition.link.markdown + settings + + foreground + #DC322F + + + + + name + text plain + scope + text.plain + settings + + foreground + #6a8187 + + + + name + SublimeLinter Annotations + scope + sublimelinter.notes + settings + + background + #eee8d5 + foreground + #eee8d5 + + + + name + SublimeLinter Error Outline + scope + sublimelinter.outline.illegal + settings + + background + #93a1a1 + foreground + #93a1a1 + + + + name + SublimeLinter Error Underline + scope + sublimelinter.underline.illegal + settings + + background + #dc322f + + + + name + SublimeLinter Warning Outline + scope + sublimelinter.outline.warning + settings + + background + #839496 + foreground + #839496 + + + + name + SublimeLinter Warning Underline + scope + sublimelinter.underline.warning + settings + + background + #b58900 + + + + name + SublimeLinter Violation Outline + scope + sublimelinter.outline.violation + settings + + background + #657b83 + foreground + #657b83 + + + + name + SublimeLinter Violation Underline + scope + sublimelinter.underline.violation + settings + + background + #cb4b16 + + + + + uuid + 38E819D9-AE02-452F-9231-ECC3B204AFD7 + colorSpaceName + sRGB + + diff --git a/SyntaxKit/Tests/Resources/Fixtures/Swift.tmLanguage b/SyntaxKit/Tests/Resources/Fixtures/Swift.tmLanguage new file mode 100644 index 0000000..2ce68ba --- /dev/null +++ b/SyntaxKit/Tests/Resources/Fixtures/Swift.tmLanguage @@ -0,0 +1,1522 @@ + + + + + fileTypes + + swift + + firstLineMatch + ^#!/.*\bswift + keyEquivalent + ^~S + name + Swift + patterns + + + include + #shebang-line + + + include + #comment + + + include + #attribute + + + include + #literal + + + include + #operator + + + include + #declaration + + + include + #storage-type + + + include + #keyword + + + include + #type + + + include + #builtin-global-function + + + include + #builtin-function + + + include + #builtin-property + + + include + #builtin-static-property + + + include + #builtin-constant + + + include + #section-punctuation + + + repository + + arithmetic-operator + + match + (?<![/=\-+!*%<>&|\^~.])(\+|\-|\*|\/)(?![/=\-+!*%<>&|\^~.]) + name + keyword.operator.arithmetic.swift + + array-type + + begin + \b(Array)(\[) + beginCaptures + + 1 + + name + support.type.array.swift + + 2 + + name + punctuation.definition.array.begin.swift + + + end + (\]) + endCaptures + + 1 + + name + punctuation.definition.array.end.swift + + + name + meta.array.swift + patterns + + + include + $self + + + + assignment-operator + + match + (?<![/=\-+!*%<>&|\^~.])(\+|\-|\*|\/|%|<<|>>|&|\^|\||&&|\|\|)?=(?![/=\-+!*%<>&|\^~.]) + name + keyword.operator.assignment.swift + + attribute + + comment + attribute + name + meta.attribute.swift + patterns + + + begin + ((@)(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B))(\() + beginCaptures + + 1 + + name + storage.modifier.attribute.swift + + 2 + + name + punctuation.definition.attribute.swift + + 3 + + name + punctuation.definition.attribute-arguments.begin.swift + + + contentName + meta.attribute.arguments.swift + end + \) + endCaptures + + 0 + + name + punctuation.definition.attribute-arguments.end.swift + + + patterns + + + include + $self + + + + + captures + + 1 + + name + storage.modifier.attribute.swift + + 2 + + name + punctuation.definition.attribute.swift + + + match + ((@)(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B)) + + + + bitwise-operator + + match + (?<![/=\-+!*%<>&|\^~.])(&|\||\^|<<|>>)(?![/=\-+!*%<>&|\^~.]) + name + keyword.operator.bitwise.swift + + boolean-literal + + match + \b(true|false)\b + name + constant.language.boolean.swift + + branch-statement-keyword + + name + keyword.control.branch.swift + patterns + + + include + #if-statement-keyword + + + include + #switch-statement-keyword + + + + builtin-class-type + + comment + Builtin class types + match + \b(Managed(Buffer|ProtoBuffer)|NonObjectiveCBase|AnyGenerator)\b + name + support.class.swift + + builtin-constant + + comment + Process is really an enum, but it acts like a constant + match + \bProcess\b + name + support.constant.swift + + builtin-enum-type + + comment + Builtin enum types + match + \b(MirrorDisposition|Bit|ImplicitlyUnwrappedOptional|Optional|UnicodeDecodingResult|QuickLookObject|FloatingPointClassification)\b + name + support.type.swift + + builtin-function + + comment + Functions provided in the standard library; found by searching ^[ \t]+func\s+(\w+?)[<(] + match + (?<=\.)(s(tartsWith|ort|u(ccessor|perclassMirror|btract)|amePositionIn)|has(Suffix|Prefix)|next(Object)?|c(haracterAtIndex|o(ntains|untByEnumeratingWithState|pyWithZone)|ustom(Mirror|PlaygroundQuickLook)|lamp)|t(o(IntMax|Opaque|UIntMax)|ake(RetainedValue|UnretainedValue))|i(s(S(trictSu(persetOf|bsetOf)|u(persetOf|bsetOf))|DisjointWith|EmptyInput|ASCII)|n(tersect|itialize(From)?|dex(Of|ForKey)))|object(Enumerator|ForKey|AtIndex)|d(istanceTo|e(s(cendant|troy)|alloc))|un(ion|derestimateCount)|join|p(ut|redecessor)|e(scape|numerate|lementsEqual|xclusiveOr)|keyEnumerator|f(ilter|latMap)|w(ith(CString|U(nsafe(MutablePointer(s|To(Elements|Value))|BufferPointer)|TF8Buffer))|riteTo)|le(ngth|xicographicalCompare)|a(ssign(BackwardFrom|From)|dvancedBy|utorelease)|re(tain|duce|verse|questNativeBuffer|lease)|ge(nerate|t(Mirror|Objects))|m(inElement|ove(Initialize(BackwardFrom|From)|AssignFrom)?|ember|a(p|xElement)))\b + name + support.function.swift + + builtin-global-function + + comment + Global functions provided in the standard library; found by searching ^func\s+(\w+?)[<(] + match + \b(s(tride(of(Value)?)?|izeof(Value)?|ort|uffix|pli(ce|t)|wap)|numericCast|transcode|i(sUniquelyReferenced(NonObjC)?|nsert)|zip|overlaps|d(istance|ump|ebugPrint|rop(First|Last))|unsafe(BitCast|Downcast|Unwrap|AddressOf)|join|pr(int|e(condition|fix))|extend|with(Unsafe(MutablePointer(s)?|Pointer(s)?)|ExtendedLifetime|VaList)|lazy|a(ssert(ionFailure)?|nyGenerator|dvance|lignof(Value)?|bs)|re(flect|adLine|move(Range|Last|A(tIndex|ll)))|getVaList|m(in|ax))\b + name + support.function.swift + + builtin-property + + comment + Properties provided in the standard library; found by searching ^\s+var\s+(\w+?)\W + match + (?<=\.)(s(t(art(Index)?|ringValue)|ummary)|has(hValue|PointerRepresentation)|nulTerminatedUTF8|c(haracters|ount|apacity)|i(s(S(ign(Minus|aling)|ubnormal)|N(ormal|aN)|Infinite|Zero|Empty|Finite|ASCII)|ndices|dentity)|o(wner|bjectIdentifier)|d(isposition|e(scription|bugDescription))|u(nicodeScalar(s)?|tf(16|8(Start)?)|intValue|ppercaseString)|end(Index)?|value(s|Type)?|keys|quickLookObject|f(irst|loatingPointClass)|l(ittleEndian|owercaseString|ast)|a(llocatedElementCount|rray)|rawValue|memory|b(yteS(ize|wapped)|igEndian|oolValue|uffer|aseAddress))\b + name + support.variable.swift + + builtin-protocol-type + + comment + Builtin protocol types + match + \b(Ra(n(domAccessIndexType|geReplaceableCollectionType)|wRepresentable)|GeneratorType|M(irror(Type|PathType)|utable(Sliceable|CollectionType))|B(i(twiseOperationsType|directionalIndexType)|oolean(Type|LiteralConvertible))|S(tr(i(ng(InterpolationConvertible|LiteralConvertible)|deable)|eamable)|i(nkType|gned(NumberType|IntegerType))|e(tAlgebraType|quenceType)|liceable)|Hashable|NilLiteralConvertible|C(o(llectionType|mparable)|ustom(Reflectable|StringConvertible|DebugStringConvertible|PlaygroundQuickLookable|LeafReflectable)|VarArgType)|Inte(rvalType|ger(Type|LiteralConvertible|ArithmeticType))|O(utputStreamType|ptionSetType)|DictionaryLiteralConvertible|Un(signedIntegerType|icode(ScalarLiteralConvertible|CodecType))|E(quatable|rrorType|xten(sibleCollectionType|dedGraphemeClusterLiteralConvertible))|F(orwardIndexType|loat(ingPointType|LiteralConvertible))|A(ny(CollectionType|Object)|rrayLiteralConvertible|bsoluteValuable))\b + name + support.type.swift + + builtin-static-property + + comment + Static properties provided in the standard library; found by searching ^\s*(class|static)\s+var\s+(\w+?)\W + match + (?<=\.)(infinity|NaN|quietNaN|allZeros|m(in|ax))\b|(?<=\bProcess\.)(arguments|argc|unsafeArgv)\b + name + support.variable.swift + + builtin-struct-type + + comment + Builtin struct types + match + \b(R(e(peat|verse(RandomAccess(Collection|Index)|Collection|Index))|a(nge(Generator)?|wByte))|Generator(Sequence|OfOne)|M(irror|a(nagedBufferPointer|p(Generator|Sequence|Collection)))|Bool|S(t(aticString|ri(ng|deT(hrough(Generator)?|o(Generator)?)))|inkOf|et(Generator|Index)?)|HalfOpenInterval|C(haracter|o(ntiguousArray|llectionOfOne)|OpaquePointer|losedInterval|VaListPointer)|In(t(16|8|32|64)?|dexingGenerator)|Zip2(Generator|Sequence)|ObjectIdentifier|D(ictionary(Generator|Index|Literal)?|ouble)|U(n(safe(Mutable(BufferPointer|Pointer)|BufferPointer(Generator)?|Pointer)|icodeScalar|managed)|TF(16|8|32)|Int(16|8|32|64)?)|PermutationGenerator|E(numerate(Generator|Sequence)|mpty(Generator|Collection))|F(ilter(Generator|Sequence|Collection(Index)?)|loat(80)?)|Lazy(RandomAccessCollection|BidirectionalCollection|Sequence|ForwardCollection)|A(ny(RandomAccess(Collection|Index)|Bidirectional(Collection|Index)|Sequence|Forward(Collection|Index))|utoreleasingUnsafeMutablePointer|rray(Slice)?))\b + name + support.type.swift + + builtin-type + + comment + Types provided in the standard library; found by searching ^(@objc\s+)?(struct|protocol|class|enum)\s+(\w+)[\s<].+$ + patterns + + + include + #builtin-class-type + + + include + #builtin-enum-type + + + include + #builtin-protocol-type + + + include + #builtin-struct-type + + + include + #builtin-typealias + + + + builtin-typealias + + comment + Builtin typealiases + match + \b(BooleanLiteralType|StringLiteralType|C(Bool|S(hort|ignedChar)|Char(16|32)?|Int|Double|Unsigned(Short|Char|Int|Long(Long)?)|Float|WideChar|Long(Long)?)|Int(Max|egerLiteralType)|U(nicodeScalarType|IntMax|Word)|PlaygroundQuickLook|ExtendedGraphemeClusterType|Void|Float(32|LiteralType|64)|Word|Any(Class)?)\b + name + support.type.swift + + capture-specifier + + comment + matches weak, unowned, unowned(safe), unowned(unsafe) + match + \b(weak|unowned(?:\((?:un)?safe\))?) + name + keyword.other.capture-specifier.swift + + coalescing-operator + + match + (?<![?/=\-+!*%<>&|\^~.])\?\?(?![?/=\-+!*%<>&|\^~.]) + name + keyword.operator.coalescing.swift + + code-block + + begin + (\{) + beginCaptures + + 1 + + name + punctuation.definition.code-block.begin.swift + + + comment + code-block + end + (\}) + endCaptures + + 1 + + name + punctuation.definition.code-block.end.swift + + + patterns + + + include + $self + + + + collection-type + + comment + Collection types + patterns + + + include + #array-type + + + include + #dictionary-type + + + + comment + + comment + All comment types + patterns + + + include + #block-doc + + + include + #block + + + include + #inline-doc + + + include + #inline + + + repository + + block + + begin + /\* + beginCaptures + + 0 + + name + punctuation.definition.comment.block.begin.swift + + + end + \*/ + endCaptures + + 0 + + name + punctuation.definition.comment.block.end.swift + + + name + comment.block.swift + patterns + + + include + #nested + + + repository + + nested + + begin + /\* + end + \*/ + patterns + + + include + #block-nested + + + + + + block-doc + + begin + /\*\* + beginCaptures + + 0 + + name + punctuation.definition.comment.block.documentation.begin.swift + + + end + \*/ + endCaptures + + 0 + + name + punctuation.definition.comment.block.documentation.end.swift + + + name + comment.block.documentation.swift + patterns + + + include + #nested + + + include + text.restructuredtext#tags + + + repository + + nested + + begin + /\* + end + \*/ + patterns + + + include + #block-nested + + + include + text.restructuredtext#tags + + + + + + inline + + begin + (^[ \t]+)?(?=//) + beginCaptures + + 1 + + name + punctuation.whitespace.comment.leading.swift + + + end + \n + patterns + + + begin + // + beginCaptures + + 0 + + name + punctuation.definition.comment.swift + + + end + (?=\n) + name + comment.line.double-slash.swift + + + + inline-doc + + begin + (^[ \t]+)?(?=///) + beginCaptures + + 1 + + name + punctuation.whitespace.comment.leading.swift + + + end + \n + patterns + + + begin + /// + beginCaptures + + 0 + + name + punctuation.definition.comment.swift + + + end + (?=\n) + name + comment.line.triple-slash.swift + + + + + + comparative-operator + + match + (?<![/=\-+!*%<>&|\^~.])((=|!)==?|(<|>)=?|~=)(?![/=\-+!*%<>&|\^~.]) + name + keyword.operator.comparative.swift + + control-transfer-statement-keyword + + comment + control-transfer-statement + match + \b(continue|break|fallthrough|return)\b + name + keyword.control.transfer.swift + + custom-operator + + patterns + + + match + (?<=[\s(\[{,;:])([/=\-+!*%<>&|\^~.]++)(?![\s)\]},;:]) + name + keyword.operator.custom.prefix.unary.swift + + + match + (?<![\s(\[{,;:])([/=\-+!*%<>&|\^~.]++)(?![\s)\]},;:\.]) + name + keyword.operator.custom.postfix.unary.swift + + + match + (?<=[\s(\[{,;:])([/=\-+!*%<>&|\^~.]++)(?=[\s)\]},;:]) + name + keyword.operator.custom.binary.swift + + + + declaration + + comment + declaration + name + meta.declaration.swift + patterns + + + include + #import-declaration + + + include + #function-declaration + + + + declaration-specifier + + comment + declaration-specifier + match + \b(class|deinit|enum|extension|func|import|init|inout|internal|let|operator|private|protocol|public|static|struct|subscript|typealias|var)\b + name + keyword.other.declaration-specifier.swift + + dictionary-type + + begin + \b(Dictionary)(\[) + beginCaptures + + 1 + + name + support.type.dictionary.swift + + 2 + + name + punctuation.definition.dictionary.begin.swift + + + end + (\]) + endCaptures + + 1 + + name + punctuation.definition.dictionary.end.swift + + + name + meta.dictionary.swift + patterns + + + include + $self + + + + floating-point-literal + + name + constant.numeric.floating-point.swift + patterns + + + comment + floating-point-literal -> (decimal-literal)(decimal-fraction)?(decimal-exponent)? + match + \b([0-9][0-9_]*)(\.([0-9][0-9_]*))?([eE][+\-]?([0-9][0-9_]*))?\b + + + comment + floating-point-literal -> (hexadecimal-literal)(hexadecimal-fraction)?(hexadecimal-exponent) + match + \b(0x\h[\h_]*)(\.(0x\h[\h_]*))?([pP][+\-]?(0x\h[\h_]*))\b + + + + function-declaration + + begin + \b(func)\s+(\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B|[/=\-+!*%<>&|\^~.]+)\s*(?=\(|<) + beginCaptures + + 1 + + name + storage.type.function.swift + + 2 + + name + entity.name.function.swift + + + comment + function-declaration + end + (?<=\})|$ + name + meta.function-declaration.swift + patterns + + + include + #generic-parameter-clause + + + include + #parameter-clause + + + include + #function-result + + + begin + (\{) + beginCaptures + + 1 + + name + punctuation.section.function.begin.swift + + + end + (\}) + endCaptures + + 1 + + name + punctuation.section.function.end.swift + + + name + meta.function-declaration.body.swift + patterns + + + include + $self + + + + + + function-result + + begin + (?<![/=\-+!*%<>&|\^~.])(\->)(?![/=\-+!*%<>&|\^~.])\s* + beginCaptures + + 1 + + name + keyword.operator.function-result.swift + + + comment + function-result + end + (?=\{)|$ + name + meta.function-result.swift + patterns + + + include + #type + + + + generic-parameter-clause + + begin + (<) + beginCaptures + + 1 + + name + punctuation.definition.generic-parameter-clause.begin.swift + + + comment + generic-parameter-clause + end + (>) + endCaptures + + 1 + + name + punctuation.definition.generic-parameter-clause.end.swift + + + name + meta.generic-parameter-clause.swift + patterns + + + include + $self + + + + identifier + + comment + identifier + match + (\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B) + name + meta.identifier.swift + + if-statement-keyword + + comment + if-statement + match + \b(if|else)\b + name + keyword.control.if.swift + + import-declaration + + captures + + 1 + + name + keyword.other.import.swift + + 2 + + name + storage.modifier.swift + + 3 + + name + support.type.module.import.swift + + + comment + import-declaration + match + \b(import)\s+(?:(typealias|struct|class|enum|protocol|var|func)\s+)?((?:\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B|[/=\-+!*%<>&|\^~.]+)(?:\.(?:\B\$[0-9]+|\b[\w^\d][\w\d]*\b|\B`[\w^\d][\w\d]*`\B|[/=\-+!*%<>&|\^~.]+))*) + name + meta.import.swift + + increment-decrement-operator + + match + (?<![/=\-+!*%<>&|\^~.])(\+\+|\-\-)(?![/=\-+!*%<>&|\^~.]) + name + keyword.operator.increment-or-decrement.swift + + integer-literal + + name + constant.numeric.integer.swift + patterns + + + comment + binary-literal + match + (\B\-|\b)(0b[01][01_]*)\b + name + constant.numeric.integer.binary.swift + + + comment + octal-literal + match + (\B\-|\b)(0o[0-7][0-7_]*)\b + name + constant.numeric.integer.octal.swift + + + comment + decimal-literal + match + (\B\-|\b)([0-9][0-9_]*)\b + name + constant.numeric.integer.decimal.swift + + + comment + hexadecimal-literal + match + (\B\-|\b)(0x\h[\h_]*)\b + name + constant.numeric.integer.hexadecimal.swift + + + + keyword + + patterns + + + include + #branch-statement-keyword + + + include + #control-transfer-statement-keyword + + + include + #loop-statement-keyword + + + include + #declaration-specifier + + + include + #capture-specifier + + + include + #operator-declaration-keyword + + + comment + declaration keyword + match + \b(class|deinit|enum|extension|func|import|init|inout|internal|let|operator|private|protocol|public|static|struct|subscript|typealias|var)\b + name + storage.type.declaration.swift + + + comment + statement keyword + match + \b(break|case|continue|default|defer|do|else|fallthrough|for|guard|if|in|repeat|return|switch|where|while)\b + name + keyword.control.statement.swift + + + comment + expression and type keyword + match + \b(as|catch|dynamicType|false|is|nil|rethrows|super|self|Self|throw|throws|true|try|__COLUMN__|__FILE__|__FUNCTION__|__LINE__)\b + name + keyword.other.statement.swift + + + comment + other keyword + match + \b(associativity|convenience|dynamic|didSet|final|get|infix|indirect|lazy|left|mutating|none|nonmutating|optional|override|postfix|precedence|prefix|Protocol|required|right|set|Type|unowned|weak|willSet)\b + name + keyword.other.swift + + + + literal + + patterns + + + include + #integer-literal + + + include + #floating-point-literal + + + include + #string-literal + + + include + #special-literal + + + include + #boolean-literal + + + include + #nil-literal + + + + logical-operator + + match + (?<![/=\-+!*%<>&|\^~.])(!|&&|\|\|)(?![/=\-+!*%<>&|\^~.]) + name + keyword.operator.logical.swift + + loop-statement-keyword + + comment + loop-statement + match + \b(while|do|for|in)\b + name + keyword.control.loop.swift + + nil-literal + + match + \bnil\b + name + constant.language.nil.swift + + operator + + patterns + + + include + #comparative-operator + + + include + #assignment-operator + + + include + #logical-operator + + + include + #remainder-operator + + + include + #increment-decrement-operator + + + include + #overflow-operator + + + include + #range-operator + + + include + #bitwise-operator + + + include + #arithmetic-operator + + + include + #ternary-operator + + + include + #type-casting-operator + + + include + #coalescing-operator + + + include + #custom-operator + + + + operator-declaration-keyword + + comment + operator-declaration + match + \b(operator|prefix|infix|postfix)\b + name + keyword.other.operator.swift + + optional-type + + beginCaptures + + 1 + + name + support.type.optional.swift + + 2 + + name + punctuation.definition.optional.begin.swift + + + end + (>) + endCaptures + + 1 + + name + punctuation.definition.optional.end.swift + + + match + \b(Optional)(<) + name + meta.optional.swift + patterns + + + include + $self + + + + overflow-operator + + match + (?<![/=\-+!*%<>&|\^~.])\&(\+|\-|\*|\/|%)(?![/=\-+!*%<>&|\^~.]) + name + keyword.operator.overflow.swift + + parameter-clause + + begin + (\() + beginCaptures + + 1 + + name + punctuation.definition.function-arguments.begin.swift + + + comment + parameter-clause + end + (\)) + endCaptures + + 1 + + name + punctuation.definition.function-arguments.end.swift + + + name + meta.parameter-clause.swift + patterns + + + captures + + 2 + + name + variable.parameter.function.swift + + + comment + named parameters + match + \b([\w^\d][\w\d]*)\b\s+\b([\w^\d][\w\d]*)\b + + + include + $self + + + + protocol-composition-type + + beginCaptures + + 1 + + name + support.type.protocol.swift + + 2 + + name + punctuation.definition.protocol.begin.swift + + + end + (>) + endCaptures + + 1 + + name + punctuation.definition.protocol.end.swift + + + match + \b(protocol)(<) + name + meta.protocol.swift + patterns + + + include + $self + + + + range-operator + + match + (?<![/=\-+!*%<>&|\^~.])\.\.[.<]?(?![/=\-+!*%<>&|\^~.]) + name + keyword.operator.range.swift + + remainder-operator + + match + (?<![/=\-+!*%<>&|\^~.])\%(?![/=\-+!*%<>&|\^~.]) + name + keyword.operator.remainder.swift + + section-punctuation + + patterns + + + captures + + 1 + + name + punctuation.section.scope.begin.swift + + 2 + + name + punctuation.section.scope.end.swift + + + comment + Allows the special return snippet to fire. + match + (\{)(\}) + + + captures + + 1 + + name + punctuation.section.scope.begin.swift + + 2 + + name + punctuation.section.scope.end.swift + + + comment + Allows the special return snippet to fire. + match + (\()(\)) + + + captures + + 1 + + name + punctuation.section.scope.begin.swift + + 2 + + name + punctuation.section.scope.end.swift + + + comment + Allows the special return snippet to fire. + match + (\[)(\]) + + + + shebang-line + + captures + + 1 + + name + punctuation.definition.comment.line.shebang.swift + + + comment + Shebang line + match + ^(#!).*$ + name + comment.line.shebang.swift + + special-literal + + match + \b__(FILE|LINE|COLUMN|FUNCTION)__\b + name + keyword.other.literal.swift + + storage-type + + match + \b(var|func|let|class|enum|struct|protocol|extension|typealias)\b + name + storage.type.swift + + string-literal + + begin + " + beginCaptures + + 0 + + name + punctuation.definition.string.begin.swift + + + end + " + endCaptures + + 0 + + name + punctuation.definition.string.end.swift + + + name + string.quoted.double.swift + patterns + + + match + \\[0\\tnr"'] + name + constant.character.escape.swift + + + match + \\u\{\h{1,8}\} + name + constant.character.escape.swift + + + begin + \\\( + beginCaptures + + 0 + + name + punctuation.section.embedded.begin.swift + + + contentName + source.swift + end + \) + endCaptures + + 0 + + name + punctuation.section.embedded.end.swift + + 1 + + name + source.swift + + + name + meta.embedded.line.swift + patterns + + + include + $self + + + begin + \( + comment + Nested parens + end + \) + + + + + match + \\. + name + invalid.illegal.unrecognized-escape.swift + + + + switch-statement-keyword + + comment + switch-statement + match + \b(switch|case|default|where)\b + name + keyword.control.switch.swift + + ternary-operator + + match + (?<=[\s(\[{,;:])(\?|:)(?=[\s)\]},;:]) + name + keyword.operator.ternary.swift + + type + + comment + type + patterns + + + include + #builtin-type + + + include + #collection-type + + + include + #optional-type + + + include + #protocol-composition-type + + + + type-casting-operator + + match + \b(is\b|as([!?]\B|\b)) + name + keyword.operator.type-casting.swift + + + scopeName + source.swift + uuid + D133338A-DEED-4ECC-9852-A392C44D10AC + + diff --git a/SyntaxKit/Tests/Resources/Fixtures/Tex.tmLanguage b/SyntaxKit/Tests/Resources/Fixtures/Tex.tmLanguage new file mode 100644 index 0000000..403c8a6 --- /dev/null +++ b/SyntaxKit/Tests/Resources/Fixtures/Tex.tmLanguage @@ -0,0 +1,424 @@ + + + + + fileTypes + + sty + cls + bbx + cbx + + name + TeX + patterns + + + captures + + 1 + + name + punctuation.definition.keyword.tex + + + match + (\\)(backmatter|else|fi|frontmatter|ftrue|mainmatter|if(case|cat|dim|eof|false|hbox|hmode|inner|mmode|num|odd|undefined|vbox|vmode|void|x)?)\b + name + keyword.control.tex + + + captures + + 1 + + name + keyword.control.catcode.tex + + 2 + + name + punctuation.definition.keyword.tex + + 3 + + name + punctuation.separator.key-value.tex + + 4 + + name + constant.numeric.category.tex + + + match + ((\\)catcode)`(?:\\)?.(=)(\d+) + name + meta.catcode.tex + + + begin + (^[ \t]+)?(?=%) + beginCaptures + + 1 + + name + punctuation.whitespace.comment.leading.tex + + + end + $\n? + patterns + + + begin + %: + beginCaptures + + 0 + + name + punctuation.definition.comment.tex + + + end + (?=$\n?) + name + comment.line.percentage.semicolon.texshop.tex + + + begin + ^(%!TEX) (\S*) = + beginCaptures + + 1 + + name + punctuation.definition.comment.tex + + + end + (?=$\n?) + name + comment.line.percentage.directive.texshop.tex + + + begin + % + beginCaptures + + 0 + + name + punctuation.definition.comment.tex + + + end + (?=$\n?) + name + comment.line.percentage.tex + + + + + begin + \{ + beginCaptures + + 0 + + name + punctuation.section.group.begin.tex + + + end + \} + endCaptures + + 0 + + name + punctuation.section.group.end.tex + + + name + meta.group.braces.tex + patterns + + + include + $base + + + + + match + [\[\]] + name + punctuation.definition.brackets.tex + + + begin + \$\$ + beginCaptures + + 0 + + name + punctuation.definition.string.begin.tex + + + end + \$\$ + endCaptures + + 0 + + name + punctuation.definition.string.end.tex + + + name + string.other.math.block.tex + patterns + + + include + #math + + + include + $self + + + + + match + \\\\ + name + constant.character.newline.tex + + + begin + \$ + beginCaptures + + 0 + + name + punctuation.definition.string.begin.tex + + + end + \$ + endCaptures + + 0 + + name + punctuation.definition.string.end.tex + + + name + string.other.math.tex + patterns + + + match + \\\$ + name + constant.character.escape.tex + + + include + #math + + + include + $self + + + + + captures + + 1 + + name + punctuation.definition.function.tex + + + match + (\\)[A-Za-z@]+ + name + support.function.general.tex + + + captures + + 1 + + name + punctuation.definition.keyword.tex + + + match + (\\)[^a-zA-Z@] + name + constant.character.escape.tex + + + match + «press a-z and space for greek letter»[a-zA-Z]* + name + meta.placeholder.greek.tex + + + repository + + math + + patterns + + + captures + + 1 + + name + punctuation.definition.constant.math.tex + + + match + (\\)(s(s(earrow|warrow|lash)|h(ort(downarrow|uparrow|parallel|leftarrow|rightarrow|mid)|arp)|tar|i(gma|m(eq)?)|u(cc(sim|n(sim|approx)|curlyeq|eq|approx)?|pset(neq(q)?|plus(eq)?|eq(q)?)?|rd|m|bset(neq(q)?|plus(eq)?|eq(q)?)?)|p(hericalangle|adesuit)|e(tminus|arrow)|q(su(pset(eq)?|bset(eq)?)|c(up|ap)|uare)|warrow|m(ile|all(s(etminus|mile)|frown)))|h(slash|ook(leftarrow|rightarrow)|eartsuit|bar)|R(sh|ightarrow|e|bag)|Gam(e|ma)|n(s(hort(parallel|mid)|im|u(cc(eq)?|pseteq(q)?|bseteq))|Rightarrow|n(earrow|warrow)|cong|triangle(left(eq(slant)?)?|right(eq(slant)?)?)|i(plus)?|u|p(lus|arallel|rec(eq)?)|e(q|arrow|g|xists)|v(dash|Dash)|warrow|le(ss|q(slant|q)?|ft(arrow|rightarrow))|a(tural|bla)|VDash|rightarrow|g(tr|eq(slant|q)?)|mid|Left(arrow|rightarrow))|c(hi|irc(eq|le(d(circ|S|dash|ast)|arrow(left|right)))?|o(ng|prod|lon|mplement)|dot(s|p)?|u(p|r(vearrow(left|right)|ly(eq(succ|prec)|vee(downarrow|uparrow)?|wedge(downarrow|uparrow)?)))|enterdot|lubsuit|ap)|Xi|Maps(to(char)?|from(char)?)|B(ox|umpeq|bbk)|t(h(ick(sim|approx)|e(ta|refore))|imes|op|wohead(leftarrow|rightarrow)|a(u|lloblong)|riangle(down|q|left(eq(slant)?)?|right(eq(slant)?)?)?)|i(n(t(er(cal|leave))?|plus|fty)?|ota|math)|S(igma|u(pset|bset))|zeta|o(slash|times|int|dot|plus|vee|wedge|lessthan|greaterthan|m(inus|ega)|b(slash|long|ar))|d(i(v(ideontimes)?|a(g(down|up)|mond(suit)?)|gamma)|o(t(plus|eq(dot)?)|ublebarwedge|wn(harpoon(left|right)|downarrows|arrow))|d(ots|agger)|elta|a(sh(v|leftarrow|rightarrow)|leth|gger))|Y(down|up|left|right)|C(up|ap)|u(n(lhd|rhd)|p(silon|harpoon(left|right)|downarrow|uparrows|lus|arrow)|lcorner|rcorner)|jmath|Theta|Im|p(si|hi|i(tchfork)?|erp|ar(tial|allel)|r(ime|o(d|pto)|ec(sim|n(sim|approx)|curlyeq|eq|approx)?)|m)|e(t(h|a)|psilon|q(slant(less|gtr)|circ|uiv)|ll|xists|mptyset)|Omega|D(iamond|ownarrow|elta)|v(d(ots|ash)|ee(bar)?|Dash|ar(s(igma|u(psetneq(q)?|bsetneq(q)?))|nothing|curly(vee|wedge)|t(heta|imes|riangle(left|right)?)|o(slash|circle|times|dot|plus|vee|wedge|lessthan|ast|greaterthan|minus|b(slash|ar))|p(hi|i|ropto)|epsilon|kappa|rho|bigcirc))|kappa|Up(silon|downarrow|arrow)|Join|f(orall|lat|a(t(s(emi|lash)|bslash)|llingdotseq)|rown)|P(si|hi|i)|w(p|edge|r)|l(hd|n(sim|eq(q)?|approx)|ceil|times|ightning|o(ng(left(arrow|rightarrow)|rightarrow|maps(to|from))|zenge|oparrow(left|right))|dot(s|p)|e(ss(sim|dot|eq(qgtr|gtr)|approx|gtr)|q(slant|q)?|ft(slice|harpoon(down|up)|threetimes|leftarrows|arrow(t(ail|riangle))?|right(squigarrow|harpoons|arrow(s|triangle|eq)?))|adsto)|vertneqq|floor|l(c(orner|eil)|floor|l|bracket)?|a(ngle|mbda)|rcorner|bag)|a(s(ymp|t)|ngle|pprox(eq)?|l(pha|eph)|rrownot|malg)|V(dash|vdash)|r(h(o|d)|ceil|times|i(singdotseq|ght(s(quigarrow|lice)|harpoon(down|up)|threetimes|left(harpoons|arrows)|arrow(t(ail|riangle))?|rightarrows))|floor|angle|r(ceil|parenthesis|floor|bracket)|bag)|g(n(sim|eq(q)?|approx)|tr(sim|dot|eq(qless|less)|less|approx)|imel|eq(slant|q)?|vertneqq|amma|g(g)?)|Finv|xi|m(ho|i(nuso|d)|o(o|dels)|u(ltimap)?|p|e(asuredangle|rge)|aps(to|from(char)?))|b(i(n(dnasrepma|ampersand)|g(s(tar|qc(up|ap))|nplus|c(irc|u(p|rly(vee|wedge))|ap)|triangle(down|up)|interleave|o(times|dot|plus)|uplus|parallel|vee|wedge|box))|o(t|wtie|x(slash|circle|times|dot|plus|empty|ast|minus|b(slash|ox|ar)))|u(llet|mpeq)|e(cause|t(h|ween|a))|lack(square|triangle(down|left|right)?|lozenge)|a(ck(s(im(eq)?|lash)|prime|epsilon)|r(o|wedge))|bslash)|L(sh|ong(left(arrow|rightarrow)|rightarrow|maps(to|from))|eft(arrow|rightarrow)|leftarrow|ambda|bag)|Arrownot)\b + name + constant.character.math.tex + + + captures + + 1 + + name + punctuation.definition.constant.math.tex + + + match + (\\)(sum|prod|coprod|int|oint|bigcap|bigcup|bigsqcup|bigvee|bigwedge|bigodot|bigotimes|bogoplus|biguplus)\b + name + constant.character.math.tex + + + captures + + 1 + + name + punctuation.definition.constant.math.tex + + + match + (\\)(arccos|arcsin|arctan|arg|cos|cosh|cot|coth|csc|deg|det|dim|exp|gcd|hom|inf|ker|lg|lim|liminf|limsup|ln|log|max|min|pr|sec|sin|sinh|sup|tan|tanh)\b + name + constant.other.math.tex + + + begin + ((\\)Sexpr(\{)) + beginCaptures + + 1 + + name + support.function.sexpr.math.tex + + 2 + + name + punctuation.definition.function.math.tex + + 3 + + name + punctuation.section.embedded.begin.math.tex + + + contentName + support.function.sexpr.math.tex + end + (((\}))) + endCaptures + + 1 + + name + support.function.sexpr.math.tex + + 2 + + name + punctuation.section.embedded.end.math.tex + + 3 + + name + source.r + + + name + meta.embedded.line.r + patterns + + + begin + \G(?!\}) + end + (?=\}) + name + source.r + patterns + + + include + source.r + + + + + + + captures + + 1 + + name + punctuation.definition.constant.math.tex + + + match + (\\)([^a-zA-Z]|[A-Za-z]+)(?=\b|\}|\]|\^|\_) + name + constant.other.general.math.tex + + + match + (([0-9]*[\.][0-9]+)|[0-9]+) + name + constant.numeric.math.tex + + + match + «press a-z and space for greek letter»[a-zA-Z]* + name + meta.placeholder.greek.math.tex + + + + + scopeName + text.tex + uuid + 6BC8DE6F-9360-4C7E-AC3C-971385945346 + + diff --git a/SyntaxKit/Tests/Resources/Fixtures/YAML.tmLanguage b/SyntaxKit/Tests/Resources/Fixtures/Yaml.tmLanguage similarity index 100% rename from SyntaxKit/Tests/Resources/Fixtures/YAML.tmLanguage rename to SyntaxKit/Tests/Resources/Fixtures/Yaml.tmLanguage diff --git a/SyntaxKit/Tests/Resources/Fixtures/swifttest.swift.txt b/SyntaxKit/Tests/Resources/Fixtures/swifttest.swift.txt new file mode 100644 index 0000000..12e7413 --- /dev/null +++ b/SyntaxKit/Tests/Resources/Fixtures/swifttest.swift.txt @@ -0,0 +1,75 @@ +// +// Pattern.swift +// SyntaxKit +// +// Created by Sam Soffes on 9/18/14. +// Copyright © 2014-2015 Sam Soffes. All rights reserved. +// + +/** + * Test comment + */ + +import Foundation + +final class Pattern { + + // MARK: - Properties + + let name: String? + let match: String? + let captures: CaptureCollection? + let begin: String? + let beginCaptures: CaptureCollection? + let end: String? + let endCaptures: CaptureCollection? + private weak var parent: Pattern? + private let patterns: [Pattern] + + var superpattern: Pattern? { + return parent + } + + var subpatterns: [Pattern] { + return patterns + } + + // MARK: - Initializers + + init?(dictionary: [NSObject: AnyObject], parent: Pattern? = nil) { + self.parent = parent + let i = 0.9 + self.name = dictionary["name"] as? String + self.match = dictionary["match"] as? String + self.begin = dictionary["begin"] as? String + self.end = dictionary["end"] as? String + + if let dictionary = dictionary["beginCaptures"] as? [NSObject: AnyObject] { + self.beginCaptures = CaptureCollection(dictionary: dictionary) + } else { + self.beginCaptures = nil + } + + if let dictionary = dictionary["captures"] as? [NSObject: AnyObject] { + self.captures = CaptureCollection(dictionary: dictionary) + } else { + self.captures = nil + } + + if let dictionary = dictionary["endCaptures"] as? [NSObject: AnyObject] { + self.endCaptures = CaptureCollection(dictionary: dictionary) + } else { + self.endCaptures = nil + } + + var patterns = [Pattern]() + if let array = dictionary["patterns"] as? [[NSObject: AnyObject]] { + for value in array { + if let pattern = Pattern(dictionary: value, parent: parent) { + patterns.append(pattern) + } + } + } + self.patterns = patterns + } +} \ No newline at end of file diff --git a/SyntaxKit/Tests/Resources/Fixtures/test.js.txt b/SyntaxKit/Tests/Resources/Fixtures/test.js.txt deleted file mode 100644 index a92c267..0000000 --- a/SyntaxKit/Tests/Resources/Fixtures/test.js.txt +++ /dev/null @@ -1,21 +0,0 @@ -var global = "test"; - -function foo() { - var a = 1; - - if (a != null) { - bar(a); - } - - for (var i = 0; i < 10; i++) { - // Comment - } -} - -function bar(abc) { - var b = abc; - - while (true) { - doSomething(); - } -} \ No newline at end of file diff --git a/SyntaxKit/Tests/Resources/Fixtures/textest.tex.txt b/SyntaxKit/Tests/Resources/Fixtures/textest.tex.txt new file mode 100644 index 0000000..77613ee --- /dev/null +++ b/SyntaxKit/Tests/Resources/Fixtures/textest.tex.txt @@ -0,0 +1,644 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% This is my macro files +%% +%% Feel free to use it or to delete it +%% +%% Anyway, this is where you put your own macros +%% (in addition to these ones +%% or in replacement as you want) +%% +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%% Fonctions, notations usuelles %%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\newcommand{\CoeffBinom}[2]{\binom{#1}{#2}} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%% Ensembles classiques %%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\def\N{\mathbb{N}} +\def\Z{\mathbb{Z}} +\def\Q{\mathbb{Q}} +\def\R{\mathbb{R}} +\def\C{\mathbb{C}} +\def\U{\mathbb{U}} +\def\K{\mathbb{K}} +\def\vide{\varnothing} +\def\Premiers{\mathcal{P}} + + + + + + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%% Notations pour les probas %%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\def\P{P} %\def\P{\mathbb{P}} +\newcommand{\Pcond}[2]{\P_{#1}\left ( #2\right )} +\def\E{\mathbb{E}} +\def\V{\mathbb{V}} +\newcommand{\covar}[2]{\mathrm{cov}\left (#1, #2 \right)} +\newcommand{\Correlation}[2]{\mathrm{cor}\left (#1, #2 \right )} + +\newcommand{\Bernoulli}[1]{\mathcal{B}(#1)} +\newcommand{\Binomiale}[2]{\mathcal{B}(#1, #2)} +\newcommand{\Poisson}[1]{\mathcal{P}(#1)} +\newcommand{\Geometrique}[1]{\mathcal{G}(#1)} +\newcommand{\Uniforme}[1]{\mathcal{U}(#1)} +\newcommand{\Exponentielle}[1]{\mathcal{E}(#1)} +\newcommand{\Normale}[2]{\mathscr{N}(#1, #2)} + +\newcommand{\loiSuit}{\rightsquigarrow} +\def\suitVA{\hookrightarrow} + + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%% Matrices %%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%% Espaces vectoriels %%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\def\GLcore{\mathrm{GL}} +\def\SLcore{\mathrm{SL}} +\def\SOcore{\mathrm{SO}} + + +% cf. http://stackoverflow.com/a/1812314/1670830 +\DeclareDocumentCommand\GL{ m g }{% +{\IfNoValueTF {#2} {\GLcore\left (#1 \right )} {\GLcore_{#1}\left (#2 \right )} +}% +} + +\DeclareDocumentCommand\SL{ m g }{% +{\IfNoValueTF {#2} {\SLcore\left (#1 \right )} {\SLcore_{#1}\left (#2 \right )} +}% +} + +\DeclareDocumentCommand\SO{ m g }{% +{\IfNoValueTF {#2} {\SOcore\left (#1 \right )} {\SOcore_{#1}\left (#2 \right )} +}% +} + +\newcommand{\Mat}[2]{\mathrm{M}_{#1}\left ( #2\right)} +\newcommand{\MatRectangle}[3]{\mathrm{M}_{#1\, #2}\left ( #3\right)} +\DeclareMathOperator{\tr}{tr} + +%\newcommand{\AppliLin}[2]{\mathscr{L}\left (#1, #2\right)} +%\newcommand{\Endo}[1]{\mathscr{L}\left (#1\right)} +\newcommand{\AppliLin}[2]{\mathrm{L}\left (#1, #2\right)} +\newcommand{\Endo}[1]{\mathrm{L}\left (#1\right)} + + +\newcommand{\Orth}[1]{\mathrm{O}\left (#1\right)} +\newcommand{\MatOrth}[1]{\mathrm{O}_{#1}\left (\R\right)} + +\newcommand{\MatSym}[1]{\mathrm{S}_{#1}(\R)} +\newcommand{\MatSymPos}[1]{\mathrm{S}_{#1}^+(\R)} +\newcommand{\MatSymDefPos}[1]{\mathrm{S}_{#1}^{++}(\R)} + + +%% old way +%%\newcommand{\Transposee}[1]{\prescript{\mathrm t}{}{#1}} +\newcommand{\Transposee}[1]{\transp{#1}} +\newcommand{\TransposeeParenth}[1]{\transp{\left (#1\right )}} +\newcommand*{\transp}[2][-3mu]{\ensuremath{\mskip1mu\prescript{\smash{\mathrm t\mkern#1}}{}{\mathstrut#2}}}% + +%% new way +\newcommand{\TransposeeNew}[1]{\transpNew{#1}} +\newcommand{\TransposeeNewParenth}[1]{\transpNew{\left (#1\right )}} +\newcommand*{\transpNew}[1]{{#1}^\mathsf{T}}% + + +\newcommand{\MatApplLin}[2]{\mathrm{Mat}_{#1}\left ( #2\right)} + +\DeclareMathOperator{\Spec}{Sp} + + + +\def\Id{\mathrm{Id}} + +\DeclareMathOperator{\Vect}{Vect} + +\DeclareMathOperator{\Matt}{Mat} + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%% Guillemets %%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%% Accolades %%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\guillemets}[1]{\enquote{#1}} + +\newcommand{\accolades}[1]{\left \{#1\right \}} +\newcommand{\accoladesB}[1]{\big \{#1\big \}} +\newcommand{\accoladesBB}[1]{\Big \{#1\Big \}} +\newcommand{\accoladesBBB}[1]{\bigg \{#1\bigg \}} +\newcommand{\accoladesBBBB}[1]{\Bigg \{#1\Bigg \}} + +\newcommand{\crochets}[1]{\left [#1\right ]} +\newcommand{\crochetsB}[1]{\big [#1\big ]} +\newcommand{\crochetsBB}[1]{\Big [#1\Big ]} +\newcommand{\crochetsBBB}[1]{\bigg [#1\bigg ]} + +\newcommand{\crochetsOuv}[1]{\left ]#1\right [} +\newcommand{\crochetsOuvB}[1]{\big ]#1\big [} +\newcommand{\crochetsOuvBB}[1]{\Big ]#1\Big [} +\newcommand{\crochetsOuvBBB}[1]{\bigg ]#1\bigg [} + +\def\tq{\mathrel{}\middle|\mathrel{}} +\def\tqN{\mathrel{}|\mathrel{}} +\def\tqB{\mathrel{}\big|\mathrel{}} +\def\tqBB{\mathrel{}\Big|\mathrel{}} +\def\tqBBB{\mathrel{}\bigg|\mathrel{}} + +\newcommand{\parenth}[1]{\left (#1\right )} +\newcommand{\parenthB}[1]{\big (#1\big )} +\newcommand{\parenthBB}[1]{\Big (#1\Big )} +\newcommand{\parenthBBB}[1]{\bigg (#1\bigg )} + +\newcommand{\accoladesForAnd}[2]{\left \{\begin{array}{ll}#1\\[1mm]#2\end{array}\right.} + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%% Produit scalaire %%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\prodScal}[2]{\left(#1\,\middle\vert\,#2\right)} +\newcommand{\prodScalB}[2]{\big(#1\,\big\vert\,#2\big)} +\newcommand{\prodScalBB}[2]{\Big(#1\,\Big\vert\,#2\Big)} + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%% Intervalles %%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\intervalle}[2]{\left [#1, #2 \right ]} +\newcommand{\intervalleOF}[2]{\left ]#1, #2 \right ]} +\newcommand{\intervalleFO}[2]{\left [#1, #2 \right [} +\newcommand{\intervalleN}[2]{\left \llbracket #1, #2 \right \rrbracket} + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%% Mon propre style de listes %%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% +% ex : \begin{myItemize}[2mm] \myItem Bonjour \myItem Hello \end{myItemize} +% + + +\usepackage{xifthen}% provides \isempty test + +\newcommand{\optarg}[1][]{% +\ifthenelse{\isempty{#1}}% +{}% if #1 is empty +{(((#1)))}% if #1 is not empty +} + +\newenvironment{myItemize}[1][] +{% +\begin{itemize}% +\ifthenelse{\isempty{#1}}% +{}% if #1 is empty +{\setlength{\itemsep}{#1}}% if #1 is not empty +} +{% +\end{itemize}% +} + + + +\def\myItem{\item[•]} +\def\myItemLong{\item[---]} +\def\myItemShort{\item[--]} + + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%% Valeur absolue %%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\va}[1]{\left | #1 \right |} +\newcommand{\vaB}[1]{\big | #1 \big |} +\newcommand{\vaBB}[1]{\Big | #1 \Big |} +\newcommand{\vaBBB}[1]{\bigg | #1 \bigg |} + +\newcommand{\norm}[1]{\left \| #1 \right \|} +\newcommand{\normB}[1]{\big \| #1 \big \|} +\newcommand{\normBB}[1]{\Big \| #1 \Big \|} +\newcommand{\normBBB}[1]{\bigg \| #1 \bigg \|} + +\newcommand{\normetriple}[1]{\left | \! \left | \! \left | #1 \right | \! \right | \! \right |} +\newcommand{\normetripleB}[1]{\big | \! \big | \! \big | #1 \big | \! \big | \! \big |} +\newcommand{\normetripleBB}[1]{\Big | \! \Big| \! \Big | #1 \Big | \! \Big | \! \Big |} +\newcommand{\normetripleBBB}[1]{\bigg | \! \bigg | \! \bigg | #1 \bigg | \! \bigg | \! \bigg |} + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%% Le d de dx dans les intégrales %%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\renewcommand{\d}[1]{\ensuremath{\operatorname{d}\!{#1}}} + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%% Modulo %%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\modd}[1]{\ (#1)} + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%% Petits mots français qu'on trouve dans les formules (ou pas) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\newcommand{\ie}{\emph{ie} } +\newcommand{\et}{\text{ et }} +\newcommand{\donc}{\text{ donc }} +\newcommand{\ou}{\text{ ou }} +\newcommand{\cf}{\emph{cf.} } + + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%% Quantificateurs %%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\def\fa{\forall} +\def\xt{\exists} + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%% Raccourcis et petites commandes %%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\def\longto{\mathop{\longrightarrow}} +\def\impl{\Longrightarrow} +\def\implInverse{\Longleftarrow} +\def\ssi{\iff} +\def\ssivert{\Updownarrow} + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%% Modification de \Im (et ker) %%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\renewcommand{\Im}{\mathrm{Im}} +\newcommand{\im}{\mathrm{Im}} +\newcommand{\Ker}{\mathrm{Ker}} +\renewcommand{\ker}{\mathrm{Ker}} +\newcommand{\rg}{\mathrm{rg}} + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%% Compléments xy-pic %%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%% Pour centrer les diagrammes et autres +% +% ex : \boite{} +% +\newlength\longueurdelaboite +\newcommand{\boite}[1] +{ +\settowidth{\longueurdelaboite}{#1} +\begin{minipage}{\longueurdelaboite} +#1 +\end{minipage} +} + + + +%%%%%%% Pour écrire des fonctions +% +% ex : \fonction{\R}{\R}{x}{x^2} +% +\newcommand{\fonction}[4]{ +\begin{tabular}{r@{~}c@{~}l} +$#1$&$\longrightarrow$&$#2$ \\ +$#3$&$\longmapsto$&$#4$ \\ +\end{tabular}} + + + +%%%%%%% Pour écrire des fonctions bis +% +% ex : \fonction{\R}{\R}{x}{x^2} +% +\makeatother +\newlength\longueurdudiagramme +\newcommand{\fonctionb}[4] +{% +\settowidth{\longueurdudiagramme} +{% +$\xymatrix@R=0mm{ +#1 \ar[r] & #2 \\ +#3 \ar@{|->}[r] & #4}$ +} +\begin{minipage}{\longueurdudiagramme} +$\xymatrix@R=0mm{ +#1 \ar[r] & #2 \\ +#3 \ar@{|->}[r] & #4}$ +\end{minipage} +} +\makeatletter + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%% Quotients %%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%% Une commande pour les gros quotients +% +% ancienne commande +%%%%\newcommand{\quotient}[2]{\raisebox{4pt}{$#1$} \Big/ \raisebox{-4pt}{$#2$}} +% +% +% ex : \quotient{Z}{nZ} +% +\newcommand{\quotient}[2]{\left. \raisebox{.2em}{$#1$}\middle/\raisebox{-.2em}{$#2$}\right.} + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%% Canonical matrixes %%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% +% +% example +% \canonicalmatrix{2\text{-ième ligne}}{3\text{-ième colonne}}{A} +% +% + +\NewDocumentCommand{\canonicalmatrix}{mmm}{% +\begin{array}{@{}c@{}} +\vphantom{ +\begin{array}{@{}c@{}}\text{$#2$}\\\downarrow\end{array} +} +\\ +\hphantom{#3={}\enspace +} +\begin{pmatrix} +& & \smash[t]{ +\begin{array}[b]{@{}c@{}} +\makebox[0pt]{$#2$}\\ +\downarrow\\[-.5ex] +\vdots +\end{array} +} +\\ +& & 0 +\\ +\llap{$#3={}$\quad} +\cdots & 0 & 1 & 0 & \cdots\rlap{\quad$\leftarrow$ $#1$} +\\ +& & 0 +\\ +& & \vdots +\end{pmatrix} +\end{array}%\hphantom{\text{\enspace$\leftarrow$ $#1$-#2 row}} +} + + +\newcommand{\vecteurCanonique}[1]{% +\left ( +\begin{array}{c} +\vdots \\ +0 \\ +1 \\ +0 \\ +\vdots +\end{array} +\right ) \text{\small $\gets$ $#1$-ième ligne} +} + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%% Démo %%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\newcommand{\demo}[1]{\noindent \textit{Démonstration.\,---\!--} #1 $\blacksquare$} +\newcommand{\demoOf}[2]{\noindent \textit{Démonstration #1.\,---\!--} #2 $\blacksquare$} + +\newcommand{\solution}[1]{\noindent \textit{Solution.\,---\!--} #1 $\blacksquare$} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%% Fonctions continues %%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\def\Cont{\mathscr{C}} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%% Petit o %%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\petito}[1]{ o\left ( #1\right)} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%% Topologie %%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\bouleO}[2]{\mathring{B}\left ( #1, #2\right )} +\newcommand{\bouleF}[2]{\overline{B}\left ( #1, #2\right )} +\DeclareMathOperator{\diam}{diam} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%% Récurrence %%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\Heredite{$\text{HR}_n \impl \text{HR}_{n+1}$} +\def\HerediteForte{$(\text{HR}_k)_{k\leq n} \impl \text{HR}_{n+1}$} +\newcommand{\initRecurrence}[1]{$n=#1$} +\newcommand{\HerediteWithArgument}[1]{$\text{HR}_{#1} \impl \text{HR}_{#1+1}$} +\newcommand{\HerediteForteWithArgument}[1]{$(\text{HR}_\ell)_{\ell\leq #1} \impl \text{HR}_{#1+1}$} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%% Partie réelle et imaginaire %%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\renewcommand{\Re}{\operatorname{Re}} +\renewcommand{\Im}{\operatorname{Im}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%% Cardinal %%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\DeclareMathOperator{\Card}{Card} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%% Groupes %%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\DeclareMathOperator{\Stab}{Stab} +\def\Orb{\mathscr{O}} +\newcommand{\GroupeSym}[1]{\mathfrak{S}_{#1}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% pgcd et ppcm %%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\DeclareMathOperator{\pgcd}{pgcd} +\DeclareMathOperator{\ppcm}{ppcm} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Better underbraces for matrices %%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\newcommand{\underbracedmatrix}[2]{% +\left(\; +\smash[b]{\underbrace{ +\begin{matrix}#1\end{matrix} +}_{#2}} +\;\right) +\vphantom{\underbrace{\begin{matrix}#1\end{matrix}}_{#2}} +} + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% Equivalence %%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\DeclareMathOperator{\equivaut}{\sim} + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%% Signe %%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\DeclareMathOperator{\signe}{\mathrm{sign}} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%% Vertical symbols %%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\verticalEquals{\rotatebox[origin=c]{90}{$=$}} +\def\verticalDefines{\rotatebox[origin=c]{-90}{$:=$}} +\def\verticalSsi{\big\Updownarrow} +\def\verticalImpl{\big\Downarrow} +\def\verticalLongto{\rotatebox[origin=c]{-90}{$\longto$}} +\def\verticalLeadsto{\rotatebox[origin=c]{-90}{$\leadsto$}} + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%% Better inf, max and min %%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\let\inf\relax \DeclareMathOperator*\inf{\vphantom{p}inf} +\let\max\relax \DeclareMathOperator*\max{\vphantom{p}max} +\let\min\relax \DeclareMathOperator*\min{\vphantom{p}min} + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%% Nice symbol for \leq and \geq %%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\renewcommand\leq{\leqslant} +\renewcommand\geq{\geqslant} + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%% Extra thin space %%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% cf. http://tex.stackexchange.com/a/332158/8323 + +\protected\def\miniSpace{% +\ifmmode +\mskip0.5\thinmuskip +\else +\ifhmode +\kern0.08334em +\fi +\fi +} \ No newline at end of file diff --git a/SyntaxKit/Tests/ScopedStringTests.swift b/SyntaxKit/Tests/ScopedStringTests.swift new file mode 100644 index 0000000..15a3baf --- /dev/null +++ b/SyntaxKit/Tests/ScopedStringTests.swift @@ -0,0 +1,102 @@ +// +// ScopedStringTests.swift +// SyntaxKit +// +// Created by Alexander Hedges on 30/01/16. +// Copyright © 2016 Alexander Hedges. All rights reserved. +// + +@testable import SyntaxKit +import XCTest + +internal class ScopedStringTests: XCTestCase { + + func testScopesString() { + var newScopedString = ScopedString(string: "Test") + XCTAssertEqual(newScopedString.numberOfScopes(), 1) + XCTAssertEqual(newScopedString.numberOfLevels(), 1) + + XCTAssertEqual(newScopedString.topmostScope(atIndex: 2), newScopedString.baseScope) + + let newScope1 = Scope(identifier: "bogus", range: NSRange(location: 1, length: 3), attribute: nil) + newScopedString.addAtTop(newScope1) +// print(newScopedString.prettyRepresentation()) + + XCTAssertEqual(newScopedString.numberOfScopes(), 2) + XCTAssertEqual(newScopedString.numberOfLevels(), 2) + + XCTAssertEqual(newScopedString.topmostScope(atIndex: 0), newScopedString.baseScope) + XCTAssertEqual(newScopedString.topmostScope(atIndex: 1), newScope1) + XCTAssertEqual(newScopedString.lowerScope(for: newScope1, atIndex: 1), newScopedString.baseScope) + + let newScope2 = Scope(identifier: "bogus2", range: NSRange(location: 2, length: 1), attribute: nil) + newScopedString.addAtTop(newScope2) +// print(newScopedString.prettyRepresentation()) + + XCTAssertEqual(newScopedString.numberOfScopes(), 3) + XCTAssertEqual(newScopedString.numberOfLevels(), 3) + + XCTAssertEqual(newScopedString.topmostScope(atIndex: 1), newScope1) + XCTAssertEqual(newScopedString.topmostScope(atIndex: 2), newScope2) + XCTAssertNotEqual(newScopedString.numberOfScopes(), 1) + + newScopedString.deleteCharacters(in: NSRange(location: 2, length: 1)) +// print(newScopedString.prettyRepresentation()) + XCTAssertEqual(newScopedString.string, "Tet") + XCTAssertEqual(newScopedString.numberOfScopes(), 2) + XCTAssertEqual(newScopedString.numberOfLevels(), 2) + + XCTAssertEqual(newScopedString.topmostScope(atIndex: 1).range, NSRange(location: 1, length: 2)) + + newScopedString.insert("ssssss", atIndex: 2) +// print(newScopedString.prettyRepresentation()) + XCTAssertEqual(newScopedString.string, "Tesssssst") + XCTAssertEqual(newScopedString.numberOfScopes(), 2) + + newScopedString.removeScopes(in: NSRange(location: 0, length: 1)) + XCTAssertEqual(newScopedString.numberOfScopes(), 2) + + XCTAssertEqual(newScopedString.topmostScope(atIndex: 2).range, NSRange(location: 1, length: 8)) + } + + func testRangeExtension() { + var someRange = NSRange(location: 0, length: 24) + XCTAssertFalse(someRange.isEmpty()) + + someRange = NSRange(location: 49, length: 0) + XCTAssertTrue(someRange.isEmpty()) + + someRange = NSRange(location: 4, length: 2) + XCTAssertTrue(someRange.contains(index: 4)) + XCTAssertFalse(someRange.contains(index: 1)) + XCTAssertFalse(someRange.contains(index: 23)) + + someRange = NSRange(location: 0, length: 24) + someRange.removeIndexes(from: NSRange(location: 2, length: 4)) + XCTAssertEqual(someRange, NSRange(location: 0, length: 20)) + + someRange = NSRange(location: 20, length: 40) + someRange.removeIndexes(from: NSRange(location: 4, length: 12)) + XCTAssertEqual(someRange, NSRange(location: 8, length: 40)) + + someRange = NSRange(location: 23, length: 11) + someRange.removeIndexes(from: NSRange(location: 20, length: 5)) + XCTAssertEqual(someRange, NSRange(location: 20, length: 9)) + + someRange = NSRange(location: 10, length: 14) + someRange.removeIndexes(from: NSRange(location: 5, length: 40)) + XCTAssertTrue(someRange.isEmpty()) + + someRange = NSRange(location: 23, length: 11) + someRange.insertIndexes(from: NSRange(location: 20, length: 5)) + XCTAssertEqual(someRange, NSRange(location: 28, length: 11)) + + someRange = NSRange(location: 14, length: 2) + someRange.insertIndexes(from: NSRange(location: 15, length: 7)) + XCTAssertEqual(someRange, NSRange(location: 14, length: 9)) + + someRange = NSRange(location: 26, length: 36) + someRange.insertIndexes(from: NSRange(location: 62, length: 5)) + XCTAssertEqual(someRange, NSRange(location: 26, length: 36)) + } +} diff --git a/SyntaxKit/Tests/SwiftBaselineHighlightingTests.swift b/SyntaxKit/Tests/SwiftBaselineHighlightingTests.swift new file mode 100644 index 0000000..a5be91c --- /dev/null +++ b/SyntaxKit/Tests/SwiftBaselineHighlightingTests.swift @@ -0,0 +1,67 @@ +// +// SwiftBaselineHighlightingTests.swift +// SyntaxKit +// +// Created by Alexander Hedges on 19/01/16. +// Copyright © 2016 Alexander Hedges. All rights reserved. +// + +import Foundation +@testable import SyntaxKit +import XCTest + +internal class SwiftBaselineHighlightingTests: XCTestCase { + + // MARK: - Properties + + let manager: BundleManager = getBundleManager() + var parser: AttributedParser? + + // MARK: - Tests + + override func setUp() { + super.setUp() + if let swift = manager.language(withIdentifier: "source.Swift"), + let solarized = manager.theme(withIdentifier: "Solarized") { + parser = AttributedParser(language: swift, theme: solarized) + } else { + XCTFail("Should be able to load swift language fixture") + } + } + + func testColors() { + let input = fixture("swifttest.swift", "txt") + if let string = parser?.attributedString(for: input) { + // line comment + assertEqualColors(Color(hex: "#93A1A1"), string.attributes(at: 10, effectiveRange: nil)[NSAttributedString.Key.foregroundColor] as? Color) + assertEqualColors(Color(hex: "#93A1A1"), string.attributes(at: 135, effectiveRange: nil)[NSAttributedString.Key.foregroundColor] as? Color) + + // block comment + // print((string.string as NSString).substringWithRange(NSRange(location: 157, length: 20))) + assertEqualColors(Color(hex: "#93A1A1"), string.attributes(at: 157, effectiveRange: nil)[NSAttributedString.Key.foregroundColor] as? Color) + + // string literal + // print((string.string as NSString).substringWithRange(NSRange(location: 744, length: 6))) + assertEqualColors(Color(hex: "#839496"), string.attributes(at: 744, effectiveRange: nil)[NSAttributedString.Key.foregroundColor] as? Color) + var stringRange = NSRange() + assertEqualColors(Color(hex: "#2aa198"), string.attributes(at: 745, effectiveRange: &stringRange)[NSAttributedString.Key.foregroundColor] as? Color) + XCTAssertEqual(stringRange.length, 4) + assertEqualColors(Color(hex: "#839496"), string.attributes(at: 749, effectiveRange: nil)[NSAttributedString.Key.foregroundColor] as? Color) + + // number literal + var numberRange = NSRange() + // print((string.string as NSString).substringWithRange(NSRange(location: 715, length: 3))) + assertEqualColors(Color(hex: "#d33682"), string.attributes(at: 715, effectiveRange: &numberRange)[NSAttributedString.Key.foregroundColor] as? Color) + XCTAssertEqual(numberRange, NSRange(location: 715, length: 1)) + } else { + XCTFail("Parser loading should have succeeded") + } + } + + func testHighlightingPerformance() { + let input = fixture("swifttest.swift", "txt") + self.measure { + _ = self.parser?.attributedString(for: input) + } + } +} diff --git a/SyntaxKit/Tests/TestHelper.swift b/SyntaxKit/Tests/TestHelper.swift index cf93e8e..facf4d6 100644 --- a/SyntaxKit/Tests/TestHelper.swift +++ b/SyntaxKit/Tests/TestHelper.swift @@ -7,63 +7,68 @@ // import Foundation -import XCTest -import X @testable import SyntaxKit +import XCTest -func fixture(name: String, _ type: String) -> String! { - let path = NSBundle(forClass: LanguageTests.self).pathForResource(name, ofType: type)! - return try! String(contentsOfFile: path) -} - -func language(name: String) -> Language! { - let path = NSBundle(forClass: LanguageTests.self).pathForResource(name, ofType: "tmLanguage")! - let plist = NSDictionary(contentsOfFile: path)! as [NSObject: AnyObject] - return Language(dictionary: plist)! +internal func fixture(_ name: String, _ type: String) -> String { + if let path = Bundle(for: LanguageTests.self).path(forResource: name, ofType: type) { + do { + return try String(contentsOfFile: path) + } catch { + return "" + } + } + return "" } -func theme(name: String) -> Theme! { - let path = NSBundle(forClass: LanguageTests.self).pathForResource(name, ofType: "tmTheme")! - let plist = NSDictionary(contentsOfFile: path)! as [NSObject: AnyObject] - return Theme(dictionary: plist)! +internal func getBundleManager() -> BundleManager { + return BundleManager { identifier, kind in + let name = kind == .language ? String(identifier.split(separator: ".")[1]) : identifier + let ext = kind == .language ? ".tmLanguage" : ".tmTheme" + return Bundle(for: LanguageTests.self).url(forResource: name.capitalized, withExtension: ext) ?? URL(fileURLWithPath: "") + } } -func simpleTheme() -> Theme! { - return Theme(dictionary: [ - "uuid": "7", - "name": "Simple", - "settings": [ - [ - "scope": "entity.name", - "settings": [ - "color": "blue" - ] - ], - [ - "scope": "string", - "settings": [ - "color": "red" - ] - ], - [ - "scope": "constant.numeric", - "settings": [ - "color": "purple" - ] - ] - ] - ]) +internal func simpleTheme() -> Theme? { + return Theme(dictionary: [ + "uuid": "123e4567-e89b-12d3-a456-426655440000", + "name": "Simple", + "settings": [ + [ + "scope": "entity.name", + "settings": [ + "color": "blue" + ] + ], + [ + "scope": "string", + "settings": [ + "color": "red" + ] + ], + [ + "scope": "constant.numeric", + "settings": [ + "color": "purple" + ] + ] + ] + ]) } -func assertEqualColors(color1: Color, _ color2: Color, accuracy: CGFloat = 0.005) { - XCTAssertEqualWithAccuracy(color1.redComponent, color2.redComponent, accuracy: accuracy) - XCTAssertEqualWithAccuracy(color1.greenComponent, color2.greenComponent, accuracy: accuracy) - XCTAssertEqualWithAccuracy(color1.blueComponent, color2.blueComponent, accuracy: accuracy) - XCTAssertEqualWithAccuracy(color1.alphaComponent, color2.alphaComponent, accuracy: accuracy) +internal func replace(_ range: NSRange, in string: String, with inserted: String) -> String { + let newInput = string.mutableCopy() as? NSMutableString + newInput?.replaceCharacters(in: range, with: inserted) + return newInput?.copy() as? String ?? "" } -extension NSRange: Equatable { } - -public func ==(lhs: NSRange, rhs: NSRange) -> Bool { - return lhs.location == rhs.location && lhs.length == rhs.length +internal func assertEqualColors(_ color1: Color?, _ color2: Color?, accuracy: CGFloat = 0.005) { + guard let lhColor = color1, let rhColor = color2 else { + XCTAssert(false, "colors have to be non-nil") + return + } + XCTAssertEqual(lhColor.redComponent, rhColor.redComponent, accuracy: accuracy) + XCTAssertEqual(lhColor.greenComponent, rhColor.greenComponent, accuracy: accuracy) + XCTAssertEqual(lhColor.blueComponent, rhColor.blueComponent, accuracy: accuracy) + XCTAssertEqual(lhColor.alphaComponent, rhColor.alphaComponent, accuracy: accuracy) } diff --git a/SyntaxKit/Tests/ThemeTests.swift b/SyntaxKit/Tests/ThemeTests.swift index fa8471d..5c7a41e 100644 --- a/SyntaxKit/Tests/ThemeTests.swift +++ b/SyntaxKit/Tests/ThemeTests.swift @@ -6,22 +6,36 @@ // Copyright © 2015 Sam Soffes. All rights reserved. // -import XCTest -import X @testable import SyntaxKit +import XCTest -class ThemeTests: XCTestCase { +internal class ThemeTests: XCTestCase { - // MARK: - Properties + // MARK: - Properties - let tomorrow = theme("Tomorrow") + private let manager: BundleManager = getBundleManager() + // MARK: - Tests - // MARK: - Tests + func testLoading() { + if let tomorrow = manager.theme(withIdentifier: "Tomorrow") { + XCTAssertEqual(UUID(uuidString: "82CCD69C-F1B1-4529-B39E-780F91F07604"), tomorrow.uuid) + XCTAssertEqual("Tomorrow", tomorrow.name) + assertEqualColors(Color(hex: "#666969"), tomorrow.attributes["constant.other"]?[NSAttributedString.Key.foregroundColor] as? Color) + assertEqualColors(Color(hex: "#4271AE"), tomorrow.attributes["keyword.other.special-method"]?[NSAttributedString.Key.foregroundColor] as? Color) + } else { + XCTFail("Should be able to load tomorrow theme fixture") + } + } - func testLoading() { - XCTAssertEqual("82CCD69C-F1B1-4529-B39E-780F91F07604", tomorrow.UUID) - XCTAssertEqual("Tomorrow", tomorrow.name) - assertEqualColors(Color(hex: "#666969")!, tomorrow.attributes["constant.other"]![NSForegroundColorAttributeName] as! Color) - } + func testComplexTheme() { + if let solarized = manager.theme(withIdentifier: "Solarized") { + XCTAssertEqual(UUID(uuidString: "38E819D9-AE02-452F-9231-ECC3B204AFD7"), solarized.uuid) + XCTAssertEqual("Solarized (light)", solarized.name) + assertEqualColors(Color(hex: "#2aa198"), solarized.attributes["string.quoted.double"]?[NSAttributedString.Key.foregroundColor] as? Color) + assertEqualColors(Color(hex: "#2aa198"), solarized.attributes["string.quoted.single"]?[NSAttributedString.Key.foregroundColor] as? Color) + } else { + XCTFail("Should be able to load solarized theme fixture") + } + } } diff --git a/SyntaxKit/Theme.swift b/SyntaxKit/Theme.swift index a665939..1a76903 100644 --- a/SyntaxKit/Theme.swift +++ b/SyntaxKit/Theme.swift @@ -2,59 +2,70 @@ // Theme.swift // SyntaxKit // +// Represents a TextMate theme file (.tmTheme). Currently only supports the +// foreground text color attribute on a local scope. +// // Created by Sam Soffes on 10/11/14. // Copyright © 2014-2015 Sam Soffes. All rights reserved. // -import Foundation -import X - -#if !os(OSX) - import UIKit +#if os(OSX) + import AppKit +#else + import UIKit #endif -public typealias Attributes = [String: AnyObject] +public typealias Attributes = [NSAttributedString.Key: Any] public struct Theme { - // MARK: - Properties + // MARK: - Properties - public let UUID: String - public let name: String - public let attributes: [String: Attributes] + public let uuid: UUID + public let name: String + public let attributes: [String: Attributes] + public var backgroundColor: Color { + return attributes[Language.globalScope]?[NSAttributedString.Key.backgroundColor] as? Color ?? Color.white + } - // MARK: - Initializers + public var foregroundColor: Color { + return attributes[Language.globalScope]?[NSAttributedString.Key.foregroundColor] as? Color ?? Color.black + } - public init?(dictionary: [NSObject: AnyObject]) { - guard let UUID = dictionary["uuid"] as? String, - name = dictionary["name"] as? String, - rawSettings = dictionary["settings"] as? [[String: AnyObject]] - else { return nil } + // MARK: - Initializers - self.UUID = UUID - self.name = name + init?(dictionary: [String: Any]) { + guard let uuidString = dictionary["uuid"] as? String, + let uuid = UUID(uuidString: uuidString), + let name = dictionary["name"] as? String, + let rawSettings = dictionary["settings"] as? [[String: AnyObject]] + else { return nil } - var attributes = [String: Attributes]() - for raw in rawSettings { - guard let scopes = raw["scope"] as? String else { continue } - guard var setting = raw["settings"] as? [String: AnyObject] else { continue } + self.uuid = uuid + self.name = name - if let value = setting.removeValueForKey("foreground") as? String { - setting[NSForegroundColorAttributeName] = Color(hex: value) - } + var attributes = [String: Attributes]() + for raw in rawSettings { + guard var setting = raw["settings"] as? [NSAttributedString.Key: Any] else { continue } - if let value = setting.removeValueForKey("background") as? String { - setting[NSBackgroundColorAttributeName] = Color(hex: value) - } + if let value = setting.removeValue(forKey: NSAttributedString.Key(rawValue: "foreground")) as? String { + setting[NSAttributedString.Key.foregroundColor] = Color(hex: value) + } - // TODO: caret, invisibles, lightHighlight, selection, font style + if let value = setting.removeValue(forKey: NSAttributedString.Key(rawValue: "background")) as? String { + setting[NSAttributedString.Key.backgroundColor] = Color(hex: value) + } - for scope in scopes.componentsSeparatedByString(",") { - let key = scope.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) - attributes[key] = setting - } - } - self.attributes = attributes - } + if let patternIdentifiers = raw["scope"] as? String { + for patternIdentifier in patternIdentifiers.components(separatedBy: ",") { + let key = patternIdentifier.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) + attributes[key] = setting + } + } else if !setting.isEmpty { + attributes[Language.globalScope] = setting + } + } + self.attributes = attributes + } }