├── .github
├── ISSUE_TEMPLATE.md
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ └── swift.yml
├── .gitignore
├── .swift-version
├── .swiftlint.yml
├── .swiftpm
└── xcode
│ ├── package.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDETemplateMacros.plist
│ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ └── xcschemes
│ ├── Scout-Package.xcscheme
│ ├── Scout.xcscheme
│ ├── ScoutCLT.xcscheme
│ └── ScoutCLTCore.xcscheme
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Highlight-presets
├── Colors-Homebrew.plist
├── Colors-Novel.plist
├── Colors-Ocean.plist
└── README.md
├── LICENSE
├── Package.resolved
├── Package.swift
├── Playground
├── Commands.md
├── People.json
├── People.plist
├── People.xml
└── People.yml
├── README.md
├── Resources
├── scout-logo.png
├── syntax-highlight.png
└── syntax-highlighting-2.png
├── Sources
├── Parsing
│ ├── Character+Extensions.swift
│ ├── Parser+Operators.swift
│ ├── Parser+Types.swift
│ └── Parser.swift
├── Scout
│ ├── Constants
│ │ ├── DataFormat.swift
│ │ ├── Folding.swift
│ │ └── ScoutVersion.swift
│ ├── ExplorerValue
│ │ ├── CRUD
│ │ │ ├── ExplorerValue+Add.swift
│ │ │ ├── ExplorerValue+Delete.swift
│ │ │ ├── ExplorerValue+Get.swift
│ │ │ └── ExplorerValue+Set.swift
│ │ ├── CSV
│ │ │ ├── ExplorerValue+CSVExport.swift
│ │ │ └── ExplorerValue+CSVImport.swift
│ │ ├── ExplorerValue.swift
│ │ └── Other
│ │ │ ├── ExplorerValue+Codable.swift
│ │ │ ├── ExplorerValue+Convenience.swift
│ │ │ ├── ExplorerValue+CustomStringConvertible.swift
│ │ │ ├── ExplorerValue+ExpressibleBy.swift
│ │ │ ├── ExplorerValue+Folded.swift
│ │ │ ├── ExplorerValue+Helpers.swift
│ │ │ └── ExplorerValue+PathsListing.swift
│ ├── ExplorerValueSerialization
│ │ ├── ExplorerValueConvertible+Codable
│ │ │ ├── CodableFormat
│ │ │ │ ├── CodableFormat.swift
│ │ │ │ ├── CodableFormats+JsonDateIso8601.swift
│ │ │ │ ├── CodableFormats+JsonDefault.swift
│ │ │ │ ├── CodableFormats+Namespace.swift
│ │ │ │ ├── CodableFormats+PlistDefault.swift
│ │ │ │ └── CodableFormats+YamlDefault.swift
│ │ │ ├── Decoding
│ │ │ │ ├── ExplorerValueDecoder.swift
│ │ │ │ ├── ExplorerValueDecodingContainer.swift
│ │ │ │ ├── ExplorerValueSingleDecodingContainer.swift
│ │ │ │ └── ExplorerValueUnkeyedDecodingContainer.swift
│ │ │ ├── DecodingError+Extensions.swift
│ │ │ └── Encoding
│ │ │ │ ├── ExplorerValueEncoder.swift
│ │ │ │ ├── ExplorerValueEncodingContainer.swift
│ │ │ │ ├── ExplorerValueSingleEncodingContainer.swift
│ │ │ │ └── ExplorerValueUnkeyedEncodingContainer.swift
│ │ ├── ExplorerValueConvertible+Primitive.swift
│ │ ├── ExplorerValueConvertible.swift
│ │ └── SerializationError.swift
│ ├── ExplorerXML
│ │ ├── ExplorerXML+Add.swift
│ │ ├── ExplorerXML+CSVExport.swift
│ │ ├── ExplorerXML+CSVImport.swift
│ │ ├── ExplorerXML+Delete.swift
│ │ ├── ExplorerXML+ExplorerValue.swift
│ │ ├── ExplorerXML+Fold.swift
│ │ ├── ExplorerXML+Get.swift
│ │ ├── ExplorerXML+PathsListing.swift
│ │ ├── ExplorerXML+Serialization.swift
│ │ ├── ExplorerXML+Set.swift
│ │ ├── ExplorerXML+SingleChildStrategy.swift
│ │ ├── ExplorerXML+ValueSetter.swift
│ │ └── ExplorerXML.swift
│ ├── Extensions
│ │ ├── AEXML
│ │ │ ├── AEXMLElement+Children.swift
│ │ │ ├── AEXMLElement+Equal.swift
│ │ │ └── AEXMLElement+Group.swift
│ │ ├── Array+Extensions.swift
│ │ ├── CodingKey+Extensions.swift
│ │ ├── Collection+Extensions.swift
│ │ ├── Collection+Path.swift
│ │ ├── Dictionary+Extensions.swift
│ │ ├── Int+LastIndex.swift
│ │ ├── NSRegularExpression+Extensions.swift
│ │ ├── Optional+Extensions.swift
│ │ ├── Slice+Etensions.swift
│ │ ├── String+Extension.swift
│ │ └── String+Jaro-Winkler.swift
│ ├── Models
│ │ ├── Error
│ │ │ ├── ExplorerError.swift
│ │ │ └── PathError.swift
│ │ ├── Path
│ │ │ ├── Bounds+Bound.swift
│ │ │ ├── Bounds+IntWrapper.swift
│ │ │ ├── Bounds.swift
│ │ │ ├── Path+Flattening.swift
│ │ │ ├── Path+Miscellaneous.swift
│ │ │ ├── Path+StringConvertible.swift
│ │ │ ├── Path.swift
│ │ │ ├── PathElement+Convenience.swift
│ │ │ ├── PathElement.swift
│ │ │ ├── PathElementRepresentable.swift
│ │ │ ├── PathTree+ValueType.swift
│ │ │ └── PathTree.swift
│ │ ├── PathExplorer
│ │ │ ├── CodablePathExplorer+Serialization.swift
│ │ │ ├── CodablePathExplorer.swift
│ │ │ ├── EquatablePathExplorer.swift
│ │ │ ├── PathExplorer+Convenience.swift
│ │ │ ├── PathExplorer+ExploreWithMemory.swift
│ │ │ ├── PathExplorer+Helpers.swift
│ │ │ ├── PathExplorer.swift
│ │ │ ├── PathExplorers.swift
│ │ │ └── SerializablePathExplorer.swift
│ │ ├── PathParser
│ │ │ └── Path+Parsing.swift
│ │ └── PathsFilter
│ │ │ ├── PathsFilter+ExpressionPredicate.swift
│ │ │ ├── PathsFilter+FunctionPredicate.swift
│ │ │ ├── PathsFilter.swift
│ │ │ ├── ValuePredicate.swift
│ │ │ └── ValueTarget.swift
│ └── Scout.docc
│ │ ├── Articles
│ │ ├── custom-types-explorerValue.md
│ │ ├── getting-started.md
│ │ ├── mastering-paths.md
│ │ ├── new-4.0.0.md
│ │ └── paths-listing.md
│ │ ├── Extensions
│ │ ├── explorer-value.md
│ │ ├── path-element.md
│ │ ├── path-explorer.md
│ │ ├── path.md
│ │ ├── paths-filter.md
│ │ ├── serializable-path-explorer-export-folder.md
│ │ └── serializable-path-explorer.md
│ │ └── Scout.md
├── ScoutCLT
│ ├── AdvancedTopicsDoc
│ │ ├── AdvancedTopic.swift
│ │ └── AdvandedPredicates.swift
│ ├── CRUD
│ │ ├── Add
│ │ │ ├── AddCommand.swift
│ │ │ └── AddDocumentation.swift
│ │ ├── Delete
│ │ │ ├── DeleteCommand.swift
│ │ │ ├── DeleteDocumentation.swift
│ │ │ └── DeleteKeyCommand.swift
│ │ ├── Read
│ │ │ ├── ReadCommand.swift
│ │ │ └── ReadDocumentation.swift
│ │ └── Set
│ │ │ ├── SetCommand.swift
│ │ │ └── SetDocumentation.swift
│ ├── CSVCommand.swift
│ ├── ColorDelegates
│ │ ├── ColorFile.swift
│ │ ├── JSONInjectorDelegate.swift
│ │ ├── PlistInjectorColorDelegate.swift
│ │ ├── XMLInjectorColorDelegate.swift
│ │ └── YAMLInjectorColorDelegate.swift
│ ├── Extensions
│ │ ├── ArgumentHelp+Extensions.swift
│ │ ├── ArgumentParserConformance
│ │ │ ├── DataFormat+ArgumentParser.swift
│ │ │ ├── ExportFormat+ArgumentParser.swift
│ │ │ ├── ParsableCommand+Extensions.swift
│ │ │ ├── ParsableCommand+PathCompletion.swift
│ │ │ └── PathAndValue+ArgumentParser.swift
│ │ ├── FileHandle+Extensions.swift
│ │ ├── Optional+Extensions.swift
│ │ ├── Path+Extensions.swift
│ │ └── String+Extensions.swift
│ ├── Main
│ │ ├── CommandsRecords.swift
│ │ ├── DocCommand.swift
│ │ ├── InstallCompletionScriptCommand.swift
│ │ ├── PathExplorerInputCommand.swift
│ │ └── ScoutMainCommand.swift
│ ├── Models
│ │ ├── ColorFlag.swift
│ │ ├── Command.swift
│ │ ├── Documentation.swift
│ │ ├── PathExplorer+Alias.swift
│ │ ├── RuntimeError.swift
│ │ ├── SADCommand.swift
│ │ └── ValidationError.swift
│ └── Paths
│ │ ├── PathsCommand.swift
│ │ └── PathsDocumentation.swift
└── ScoutCLTCore
│ ├── Extensions
│ ├── Collection+Extensions.swift
│ ├── ExplorerValue+Extensions.swift
│ └── URL+Extensions.swift
│ └── Models
│ ├── CLTCoreError.swift
│ ├── ExportCommand.swift
│ ├── ExportFormat.swift
│ ├── GroupExportValue.swift
│ ├── PathAndValue+Parser.swift
│ ├── PathAndValue.swift
│ └── ValueType.swift
├── Tests
├── ScoutCLTCoreTests
│ ├── ExportCommandTests.swift
│ └── ValueParserTests.swift
└── ScoutTests
│ ├── Definitions
│ ├── ParserTests.swift
│ ├── Path
│ │ ├── PathTests+Flattening.swift
│ │ ├── PathTests+Miscellaneous.swift
│ │ └── PathTests.swift
│ └── ValueTypeTests+Codable.swift
│ ├── ExplorerValueCoder
│ ├── ExplorerValueDecoderTests.swift
│ └── ExplorerValueEncoderTests.swift
│ ├── ExplorerXML
│ ├── PathExplorerXMLTests+COW.swift
│ └── PathExplorerXMLTests+ExplorerValue.swift
│ ├── Extensions
│ ├── PathExplorers+Alias.swift
│ ├── URL+Extensions.swift
│ └── XCTestCase+Extensions.swift
│ ├── ExtensionsTests
│ ├── AEXMLExtensionsTests.swift
│ ├── ArrayTests.swift
│ ├── NSRegularExpressionExtensionsTests.swift
│ ├── PathExplorerHelperTests.swift
│ ├── String+Jaro-WinklerTests.swift
│ └── StringExtensionsTests.swift
│ ├── Models
│ ├── BoundsTests.swift
│ └── PathsFilterTests.swift
│ ├── PathExplorerTestsSuite
│ ├── PathExplorer+CSVImport.swift
│ ├── PathExplorerTests+Add.swift
│ ├── PathExplorerTests+CSVExport.swift
│ ├── PathExplorerTests+Delete.swift
│ ├── PathExplorerTests+Fold.swift
│ ├── PathExplorerTests+Get.swift
│ ├── PathExplorerTests+PathsListing.swift
│ └── PathExplorerTests+Set.swift
│ └── PathTree
│ └── PathTreeTests.swift
├── clt-test.sh
├── codecov.yml
└── docs
├── css
├── chunk-c0335d80.10a2f091.css
├── documentation-topic.1d1eec04.css
├── documentation-topic~topic.b6287bcf.css
├── documentation-topic~topic~tutorials-overview.d6f5411c.css
├── index.038e887c.css
├── topic.d8c126f3.css
└── tutorials-overview.c249c765.css
├── data
└── documentation
│ ├── scout.json
│ └── scout
│ ├── bounds.json
│ ├── bounds
│ ├── !=(_:_:).json
│ ├── bound.json
│ ├── bound
│ │ ├── !=(_:_:).json
│ │ ├── equatable-implementations.json
│ │ ├── first.json
│ │ ├── init(_:).json
│ │ ├── init(integerliteral:).json
│ │ ├── integerliteraltype.json
│ │ └── last.json
│ ├── equatable-implementations.json
│ ├── init(lower:upper:).json
│ └── range(arraycount:).json
│ ├── codableformat.json
│ ├── codableformat
│ ├── dataformat.json
│ ├── decode(_:from:).json
│ ├── encode(_:).json
│ ├── encode(_:rootname:).json
│ └── foldedregexpattern.json
│ ├── codableformats.json
│ ├── codableformats
│ ├── jsondateiso8601.json
│ ├── jsondateiso8601
│ │ ├── codableformat-implementations.json
│ │ ├── dataformat.json
│ │ ├── decode(_:from:).json
│ │ ├── encode(_:).json
│ │ ├── encode(_:rootname:).json
│ │ └── foldedregexpattern.json
│ ├── jsondefault.json
│ ├── jsondefault
│ │ ├── codableformat-implementations.json
│ │ ├── dataformat.json
│ │ ├── decode(_:from:).json
│ │ ├── encode(_:).json
│ │ ├── encode(_:rootname:).json
│ │ └── foldedregexpattern.json
│ ├── plistdefault.json
│ ├── plistdefault
│ │ ├── codableformat-implementations.json
│ │ ├── dataformat.json
│ │ ├── decode(_:from:).json
│ │ ├── encode(_:).json
│ │ ├── encode(_:rootname:).json
│ │ └── foldedregexpattern.json
│ ├── yamldefault.json
│ └── yamldefault
│ │ ├── codableformat-implementations.json
│ │ ├── dataformat.json
│ │ ├── decode(_:from:).json
│ │ ├── encode(_:).json
│ │ ├── encode(_:rootname:).json
│ │ └── foldedregexpattern.json
│ ├── codablepathexplorer.json
│ ├── codablepathexplorer
│ ├── add(_:at:)-13yei.json
│ ├── add(_:at:)-1mpqn.json
│ ├── add(_:at:)-9ka70.json
│ ├── add(_:at:)-w76g.json
│ ├── adding(_:at:).json
│ ├── array(of:).json
│ ├── bool.json
│ ├── data.json
│ ├── date.json
│ ├── debugdescription.json
│ ├── delete(_:).json
│ ├── delete(_:deleteifempty:)-1iwci.json
│ ├── delete(_:deleteifempty:)-3e7af.json
│ ├── delete(_:deleteifempty:)-8sq6g.json
│ ├── deleting(_:deleteifempty:).json
│ ├── description.json
│ ├── dictionary(of:).json
│ ├── double.json
│ ├── exportcsv().json
│ ├── exportcsv(separator:).json
│ ├── exportdata().json
│ ├── exportdata(to:).json
│ ├── exportdata(to:rootname:).json
│ ├── exportfoldedstring(upto:).json
│ ├── exportstring().json
│ ├── exportstring(to:).json
│ ├── exportstring(to:rootname:).json
│ ├── expressiblebyextendedgraphemeclusterliteral-implementations.json
│ ├── expressiblebyunicodescalarliteral-implementations.json
│ ├── folded(upto:).json
│ ├── format.json
│ ├── fromcsv(string:separator:hasheaders:).json
│ ├── get(_:).json
│ ├── init(booleanliteral:).json
│ ├── init(data:).json
│ ├── init(extendedgraphemeclusterliteral:).json
│ ├── init(floatliteral:).json
│ ├── init(integerliteral:).json
│ ├── init(stringliteral:).json
│ ├── init(unicodescalarliteral:).json
│ ├── init(value:).json
│ ├── init(value:name:).json
│ ├── int.json
│ ├── isgroup.json
│ ├── issingle.json
│ ├── listpaths(startingat:).json
│ ├── listpaths(startingat:filter:).json
│ ├── pathexplorer-implementations.json
│ ├── real.json
│ ├── serializablepathexplorer-implementations.json
│ ├── set(_:keynameto:)-1z5hp.json
│ ├── set(_:keynameto:)-40f4n.json
│ ├── set(_:keynameto:)-6dvwq.json
│ ├── set(_:to:)-15dj0.json
│ ├── set(_:to:)-40ro5.json
│ ├── set(_:to:)-61aqz.json
│ ├── set(_:to:)-7lp6u.json
│ ├── setting(_:keynameto:).json
│ ├── setting(_:to:).json
│ └── string.json
│ ├── custom-types-explorervalue.json
│ ├── dataformat.json
│ ├── dataformat
│ ├── !=(_:_:).json
│ ├── equatable-implementations.json
│ ├── hash(into:).json
│ ├── hashvalue.json
│ ├── init(rawvalue:).json
│ ├── json.json
│ ├── plist.json
│ ├── rawrepresentable-implementations.json
│ ├── xml.json
│ └── yaml.json
│ ├── explorererror.json
│ ├── explorererror
│ ├── !=(_:_:).json
│ ├── equatable-implementations.json
│ ├── error-implementations.json
│ ├── errordescription.json
│ ├── failurereason.json
│ ├── helpanchor.json
│ ├── invalid(value:).json
│ ├── localizeddescription.json
│ ├── localizederror-implementations.json
│ ├── mismatchingtype(_:value:).json
│ ├── missing(key:bestmatch:).json
│ ├── path.json
│ ├── predicatenotevaluatable(_:description:).json
│ ├── recoverysuggestion.json
│ ├── subscriptindexnoarray.json
│ ├── subscriptkeynodict.json
│ ├── wrong(bounds:arraycount:).json
│ ├── wrong(index:arraycount:).json
│ ├── wrong(regexpattern:).json
│ └── wrongusage(of:).json
│ ├── explorervalue.json
│ ├── explorervalue
│ ├── !=(_:_:).json
│ ├── add(_:at:)-4gmuo.json
│ ├── add(_:at:)-5gilx.json
│ ├── add(_:at:)-8223h.json
│ ├── add(_:at:)-8r71p.json
│ ├── adding(_:at:).json
│ ├── array(_:).json
│ ├── array(of:).json
│ ├── array.json
│ ├── arrayvalue.json
│ ├── bool(_:).json
│ ├── bool.json
│ ├── customdebugstringconvertible-implementations.json
│ ├── customstringconvertible-implementations.json
│ ├── data(_:).json
│ ├── data.json
│ ├── date(_:).json
│ ├── date.json
│ ├── debugdescription.json
│ ├── decodable-implementations.json
│ ├── delete(_:).json
│ ├── delete(_:deleteifempty:)-215jh.json
│ ├── delete(_:deleteifempty:)-55slk.json
│ ├── delete(_:deleteifempty:)-5j8qh.json
│ ├── deleting(_:deleteifempty:).json
│ ├── description.json
│ ├── dictionary(_:).json
│ ├── dictionary(of:).json
│ ├── dictionary.json
│ ├── dictionaryvalue.json
│ ├── double(_:).json
│ ├── double.json
│ ├── encodable-implementations.json
│ ├── encode(to:).json
│ ├── equatable-implementations.json
│ ├── expressiblebyarrayliteral-implementations.json
│ ├── expressiblebybooleanliteral-implementations.json
│ ├── expressiblebydictionaryliteral-implementations.json
│ ├── expressiblebyextendedgraphemeclusterliteral-implementations.json
│ ├── expressiblebyfloatliteral-implementations.json
│ ├── expressiblebyintegerliteral-implementations.json
│ ├── expressiblebystringliteral-implementations.json
│ ├── expressiblebyunicodescalarliteral-implementations.json
│ ├── get(_:).json
│ ├── init(arrayliteral:).json
│ ├── init(booleanliteral:).json
│ ├── init(dictionaryliteral:).json
│ ├── init(extendedgraphemeclusterliteral:).json
│ ├── init(floatliteral:).json
│ ├── init(from:).json
│ ├── init(integerliteral:).json
│ ├── init(stringliteral:).json
│ ├── init(unicodescalarliteral:).json
│ ├── init(value:).json
│ ├── init(value:name:).json
│ ├── int(_:).json
│ ├── int.json
│ ├── isgroup.json
│ ├── issingle.json
│ ├── listpaths(startingat:).json
│ ├── listpaths(startingat:filter:).json
│ ├── pathexplorer-implementations.json
│ ├── real.json
│ ├── set(_:keynameto:)-71khn.json
│ ├── set(_:keynameto:)-7cmde.json
│ ├── set(_:keynameto:)-9elrr.json
│ ├── set(_:to:)-1osuj.json
│ ├── set(_:to:)-1p08w.json
│ ├── set(_:to:)-85z1n.json
│ ├── set(_:to:)-neu9.json
│ ├── setting(_:keynameto:).json
│ ├── setting(_:to:).json
│ ├── string(_:).json
│ └── string.json
│ ├── explorervalueconvertible.json
│ ├── explorervaluecreatable.json
│ ├── explorervaluecreatable
│ ├── init(from:)-2m6tw.json
│ └── init(from:)-7khyl.json
│ ├── explorervaluerepresentable.json
│ ├── explorervaluerepresentable
│ ├── explorervalue()-1gz0u.json
│ └── explorervalue()-9wvc3.json
│ ├── explorerxml.json
│ ├── explorerxml
│ ├── add(_:at:)-1bcbx.json
│ ├── add(_:at:)-1pzz6.json
│ ├── add(_:at:)-1vd0k.json
│ ├── add(_:at:)-4t6ia.json
│ ├── add(_:at:)-4y7o0.json
│ ├── add(_:at:)-5c99x.json
│ ├── adding(_:at:)-1pus.json
│ ├── adding(_:at:)-3bl3a.json
│ ├── adding(_:at:)-4y55p.json
│ ├── adding(_:at:)-5hn92.json
│ ├── adding(_:at:)-9e3bi.json
│ ├── adding(_:at:)-cwm8.json
│ ├── array(of:).json
│ ├── array(of:keepingattributes:singlechildstrategy:).json
│ ├── bool.json
│ ├── data.json
│ ├── date.json
│ ├── debugdescription.json
│ ├── delete(_:).json
│ ├── delete(_:deleteifempty:)-3fqmj.json
│ ├── delete(_:deleteifempty:)-9oiah.json
│ ├── delete(_:deleteifempty:)-9pz8.json
│ ├── deleting(_:deleteifempty:).json
│ ├── description.json
│ ├── dictionary(of:).json
│ ├── dictionary(of:keepingattributes:singlechildstrategy:).json
│ ├── double.json
│ ├── element.json
│ ├── explorervalue(keepingattributes:singlechildstrategy:).json
│ ├── exportcsv().json
│ ├── exportcsv(separator:).json
│ ├── exportdata().json
│ ├── exportdata(to:).json
│ ├── exportdata(to:rootname:).json
│ ├── exportfoldedstring(upto:).json
│ ├── exportstring().json
│ ├── exportstring(to:).json
│ ├── exportstring(to:rootname:).json
│ ├── expressiblebyextendedgraphemeclusterliteral-implementations.json
│ ├── expressiblebyunicodescalarliteral-implementations.json
│ ├── folded(upto:).json
│ ├── format.json
│ ├── fromcsv(string:separator:hasheaders:).json
│ ├── get(_:).json
│ ├── init(booleanliteral:).json
│ ├── init(data:).json
│ ├── init(extendedgraphemeclusterliteral:).json
│ ├── init(floatliteral:).json
│ ├── init(integerliteral:).json
│ ├── init(stringliteral:).json
│ ├── init(unicodescalarliteral:).json
│ ├── init(value:).json
│ ├── init(value:name:).json
│ ├── int.json
│ ├── isgroup.json
│ ├── issingle.json
│ ├── listpaths(startingat:).json
│ ├── listpaths(startingat:filter:).json
│ ├── pathexplorer-implementations.json
│ ├── real.json
│ ├── serializablepathexplorer-implementations.json
│ ├── set(_:keynameto:)-1bi3d.json
│ ├── set(_:keynameto:)-3whe6.json
│ ├── set(_:keynameto:)-8bycm.json
│ ├── set(_:to:)-2wq5w.json
│ ├── set(_:to:)-3d1tv.json
│ ├── set(_:to:)-45huy.json
│ ├── set(_:to:)-54j6g.json
│ ├── set(_:to:)-8wtzf.json
│ ├── set(_:to:)-ofo9.json
│ ├── setting(_:keynameto:).json
│ ├── setting(_:to:)-1eczh.json
│ ├── setting(_:to:)-2pw3q.json
│ ├── setting(_:to:)-4m6ll.json
│ ├── setting(_:to:)-4xlv9.json
│ ├── setting(_:to:)-5h22p.json
│ ├── setting(_:to:)-7elcu.json
│ ├── singlechildstrategy.json
│ ├── singlechildstrategy
│ │ ├── array.json
│ │ ├── custom(_:).json
│ │ ├── default.json
│ │ ├── dictionary.json
│ │ └── transform.json
│ └── string.json
│ ├── getting-started.json
│ ├── mastering-paths.json
│ ├── new-4.0.0.json
│ ├── path.json
│ ├── path
│ ├── !=(_:_:).json
│ ├── +(_:_:)-1mpyt.json
│ ├── +(_:_:)-4knou.json
│ ├── +(_:_:)-wurs.json
│ ├── +=(_:_:).json
│ ├── allsatisfy(_:).json
│ ├── append(_:)-6mddf.json
│ ├── append(_:)-9l194.json
│ ├── append(contentsof:).json
│ ├── appending(_:)-2ptn6.json
│ ├── appending(_:)-3mvwq.json
│ ├── applying(_:).json
│ ├── arrayliteralelement.json
│ ├── bidirectionalcollection-implementations.json
│ ├── collection-implementations.json
│ ├── commonprefix(with:).json
│ ├── compactmap(_:).json
│ ├── compactmapfilter.json
│ ├── compactmapindexes.json
│ ├── compactmapkeys.json
│ ├── compactmapslices.json
│ ├── compare(_:_:).json
│ ├── comparedbykeyandindexes(with:).json
│ ├── contains(_:).json
│ ├── contains(where:).json
│ ├── count.json
│ ├── debugdescription.json
│ ├── defaultseparator.json
│ ├── description.json
│ ├── difference(from:).json
│ ├── difference(from:by:).json
│ ├── drop(while:).json
│ ├── dropfirst(_:).json
│ ├── droplast(_:).json
│ ├── elementsequal(_:).json
│ ├── elementsequal(_:by:).json
│ ├── empty.json
│ ├── endindex.json
│ ├── enumerated().json
│ ├── equatable-implementations.json
│ ├── expressiblebyarrayliteral-implementations.json
│ ├── filter(_:).json
│ ├── first(where:).json
│ ├── first.json
│ ├── firstindex(of:).json
│ ├── firstindex(where:).json
│ ├── firstrange(of:).json
│ ├── flatmap(_:)-4dfav.json
│ ├── flatmap(_:)-658d.json
│ ├── flattened().json
│ ├── foreach(_:).json
│ ├── formatted(_:).json
│ ├── formindex(_:offsetby:).json
│ ├── formindex(_:offsetby:limitedby:).json
│ ├── formindex(after:).json
│ ├── formindex(before:).json
│ ├── index(_:offsetby:limitedby:).json
│ ├── index(after:).json
│ ├── index(of:).json
│ ├── init().json
│ ├── init(_:)-1b2iy.json
│ ├── init(_:)-3ayg2.json
│ ├── init(_:)-cgb7.json
│ ├── init(arrayliteral:).json
│ ├── init(elements:)-8dch4.json
│ ├── init(elements:)-9i64v.json
│ ├── init(repeating:count:).json
│ ├── init(string:separator:).json
│ ├── insert(_:at:).json
│ ├── insert(contentsof:at:).json
│ ├── isempty.json
│ ├── last(where:).json
│ ├── last.json
│ ├── lastindex(of:).json
│ ├── lastindex(where:).json
│ ├── lazy.json
│ ├── lexicographicallyprecedes(_:by:).json
│ ├── makeiterator().json
│ ├── map(_:)-1pyvn.json
│ ├── map(_:)-3bvvx.json
│ ├── max(by:).json
│ ├── min(by:).json
│ ├── mutablecollection-implementations.json
│ ├── parser(separator:keyforbiddencharacters:).json
│ ├── partition(by:)-5mp72.json
│ ├── partition(by:)-70krf.json
│ ├── poplast().json
│ ├── prefix(_:).json
│ ├── prefix(through:).json
│ ├── prefix(upto:).json
│ ├── prefix(while:).json
│ ├── publisher.json
│ ├── randomaccesscollection-implementations.json
│ ├── randomelement().json
│ ├── randomelement(using:).json
│ ├── rangereplaceablecollection-implementations.json
│ ├── ranges(of:).json
│ ├── reduce(_:_:).json
│ ├── reduce(into:_:).json
│ ├── remove(at:).json
│ ├── removeall(keepingcapacity:).json
│ ├── removeall(where:)-13bwz.json
│ ├── removeall(where:)-6oyg2.json
│ ├── removefirst().json
│ ├── removefirst(_:).json
│ ├── removelast().json
│ ├── removelast(_:).json
│ ├── removesubrange(_:)-28mkd.json
│ ├── removesubrange(_:)-3w6oh.json
│ ├── replace(_:with:maxreplacements:).json
│ ├── replacesubrange(_:with:)-69vd1.json
│ ├── replacesubrange(_:with:)-8jwu3.json
│ ├── replacesubrange(_:with:)-8v4n8.json
│ ├── replacing(_:with:maxreplacements:).json
│ ├── replacing(_:with:subrange:maxreplacements:).json
│ ├── reservecapacity(_:).json
│ ├── reverse().json
│ ├── reversed().json
│ ├── sequence-implementations.json
│ ├── shuffle().json
│ ├── shuffle(using:).json
│ ├── shuffled().json
│ ├── shuffled(using:).json
│ ├── sort(by:).json
│ ├── sort(using:)-20eip.json
│ ├── sort(using:)-7hq1j.json
│ ├── sorted(by:).json
│ ├── sorted(using:)-1q9xt.json
│ ├── sorted(using:)-2epe7.json
│ ├── split(maxsplits:omittingemptysubsequences:whereseparator:).json
│ ├── split(separator:maxsplits:omittingemptysubsequences:).json
│ ├── startindex.json
│ ├── starts(with:).json
│ ├── starts(with:by:).json
│ ├── subscript(_:).json
│ ├── suffix(_:).json
│ ├── suffix(from:).json
│ ├── swapat(_:_:).json
│ ├── trimmingprefix(_:).json
│ ├── trimmingprefix(while:).json
│ ├── trimprefix(_:).json
│ ├── trimprefix(while:).json
│ ├── underestimatedcount.json
│ ├── withcontiguousmutablestorageifavailable(_:).json
│ └── withcontiguousstorageifavailable(_:).json
│ ├── pathelement.json
│ ├── pathelement
│ ├── !=(_:_:).json
│ ├── count.json
│ ├── customstringconvertible-implementations.json
│ ├── description.json
│ ├── equatable-implementations.json
│ ├── expressiblebyextendedgraphemeclusterliteral-implementations.json
│ ├── expressiblebyintegerliteral-implementations.json
│ ├── expressiblebystringliteral-implementations.json
│ ├── expressiblebyunicodescalarliteral-implementations.json
│ ├── filter(_:).json
│ ├── index(_:).json
│ ├── init(extendedgraphemeclusterliteral:).json
│ ├── init(integerliteral:).json
│ ├── init(stringliteral:).json
│ ├── init(unicodescalarliteral:).json
│ ├── integerliteraltype.json
│ ├── key(_:).json
│ ├── keyslist.json
│ ├── pathelementrepresentable-implementations.json
│ ├── pathvalue.json
│ ├── slice(_:).json
│ ├── slice(_:_:).json
│ └── stringliteraltype.json
│ ├── pathelementrepresentable.json
│ ├── pathelementrepresentable
│ └── pathvalue.json
│ ├── pathexplorer.json
│ ├── pathexplorer
│ ├── add(_:at:)-2kii6.json
│ ├── add(_:at:)-2zxor.json
│ ├── add(_:at:)-6wo3i.json
│ ├── add(_:at:)-861h4.json
│ ├── adding(_:at:)-4ju9b.json
│ ├── adding(_:at:)-5uv86.json
│ ├── adding(_:at:)-68mxp.json
│ ├── adding(_:at:)-7fd9c.json
│ ├── array(of:).json
│ ├── bool.json
│ ├── data.json
│ ├── date.json
│ ├── delete(_:).json
│ ├── delete(_:deleteifempty:)-2uxwq.json
│ ├── delete(_:deleteifempty:)-40w9g.json
│ ├── delete(_:deleteifempty:)-g45f.json
│ ├── deleting(_:deleteifempty:)-1byw9.json
│ ├── deleting(_:deleteifempty:)-2u4ud.json
│ ├── deleting(_:deleteifempty:)-32ufs.json
│ ├── dictionary(of:).json
│ ├── double.json
│ ├── get(_:)-2ghf1.json
│ ├── get(_:)-6pa9h.json
│ ├── get(_:)-8vyte.json
│ ├── init(value:).json
│ ├── init(value:name:).json
│ ├── int.json
│ ├── isgroup.json
│ ├── issingle.json
│ ├── listpaths(startingat:).json
│ ├── listpaths(startingat:filter:)-4tkeq.json
│ ├── listpaths(startingat:filter:)-8y0x2.json
│ ├── real.json
│ ├── set(_:keynameto:)-1zwfv.json
│ ├── set(_:keynameto:)-5j60r.json
│ ├── set(_:keynameto:)-9i6hd.json
│ ├── set(_:to:)-376n0.json
│ ├── set(_:to:)-5fgny.json
│ ├── set(_:to:)-6yk0i.json
│ ├── set(_:to:)-9d877.json
│ ├── setting(_:keynameto:)-1fmyp.json
│ ├── setting(_:keynameto:)-1vrh.json
│ ├── setting(_:keynameto:)-7ar89.json
│ ├── setting(_:to:)-5tdzy.json
│ ├── setting(_:to:)-7q3g.json
│ ├── setting(_:to:)-9vtr8.json
│ ├── setting(_:to:)-n2ij.json
│ └── string.json
│ ├── pathexplorers.json
│ ├── pathexplorers
│ ├── json.json
│ ├── plist.json
│ ├── xml.json
│ └── yaml.json
│ ├── paths-listing.json
│ ├── pathsfilter.json
│ ├── pathsfilter
│ ├── expressionpredicate.json
│ ├── expressionpredicate
│ │ ├── evaluate(with:).json
│ │ └── init(format:).json
│ ├── functionpredicate.json
│ ├── functionpredicate
│ │ ├── evaluate(with:).json
│ │ ├── evaluation-swift.property.json
│ │ ├── evaluation-swift.typealias.json
│ │ └── init(evaluation:).json
│ ├── key(pattern:target:).json
│ ├── key(regex:).json
│ ├── key(regex:target:).json
│ ├── keyandvalue(keyregex:valuepredicate:).json
│ ├── keyandvalue(keyregex:valuepredicates:).json
│ ├── keyandvalue(keyregex:valuepredicates:_:).json
│ ├── keyandvalue(pattern:valuepredicate:).json
│ ├── keyandvalue(pattern:valuepredicatesformat:_:).json
│ ├── nofilter.json
│ ├── targetonly(_:).json
│ ├── value(_:).json
│ ├── value(_:_:)-2wxh0.json
│ ├── value(_:_:)-8tfx1.json
│ ├── valuetarget.json
│ └── valuetarget
│ │ ├── !=(_:_:).json
│ │ ├── equatable-implementations.json
│ │ ├── group.json
│ │ ├── hash(into:).json
│ │ ├── hashvalue.json
│ │ ├── init(rawvalue:).json
│ │ ├── rawrepresentable-implementations.json
│ │ ├── single.json
│ │ └── singleandgroup.json
│ ├── serializablepathexplorer.json
│ ├── serializablepathexplorer
│ ├── exportcsv().json
│ ├── exportcsv(separator:).json
│ ├── exportdata().json
│ ├── exportdata(to:).json
│ ├── exportdata(to:rootname:).json
│ ├── exportfoldedstring(upto:).json
│ ├── exportstring().json
│ ├── exportstring(to:).json
│ ├── exportstring(to:rootname:).json
│ ├── folded(upto:).json
│ ├── format.json
│ ├── fromcsv(string:separator:hasheaders:).json
│ └── init(data:).json
│ ├── serializationerror.json
│ ├── serializationerror
│ ├── datatostring.json
│ ├── error-implementations.json
│ ├── errordescription.json
│ ├── failurereason.json
│ ├── helpanchor.json
│ ├── localizeddescription.json
│ ├── localizederror-implementations.json
│ ├── notcsvexportable(description:).json
│ ├── recoverysuggestion.json
│ └── stringtodata.json
│ ├── valuepredicate.json
│ └── valuepredicate
│ └── evaluate(with:).json
├── developer-og-twitter.jpg
├── developer-og.jpg
├── documentation
└── scout
│ ├── bounds
│ ├── !=(_:_:)
│ │ └── index.html
│ ├── bound
│ │ ├── !=(_:_:)
│ │ │ └── index.html
│ │ ├── equatable-implementations
│ │ │ └── index.html
│ │ ├── first
│ │ │ └── index.html
│ │ ├── index.html
│ │ ├── init(_:)
│ │ │ └── index.html
│ │ ├── init(integerliteral:)
│ │ │ └── index.html
│ │ ├── integerliteraltype
│ │ │ └── index.html
│ │ └── last
│ │ │ └── index.html
│ ├── equatable-implementations
│ │ └── index.html
│ ├── index.html
│ ├── init(lower:upper:)
│ │ └── index.html
│ └── range(arraycount:)
│ │ └── index.html
│ ├── codableformat
│ ├── dataformat
│ │ └── index.html
│ ├── decode(_:from:)
│ │ └── index.html
│ ├── encode(_:)
│ │ └── index.html
│ ├── encode(_:rootname:)
│ │ └── index.html
│ ├── foldedregexpattern
│ │ └── index.html
│ └── index.html
│ ├── codableformats
│ ├── index.html
│ ├── jsondateiso8601
│ │ ├── codableformat-implementations
│ │ │ └── index.html
│ │ ├── dataformat
│ │ │ └── index.html
│ │ ├── decode(_:from:)
│ │ │ └── index.html
│ │ ├── encode(_:)
│ │ │ └── index.html
│ │ ├── encode(_:rootname:)
│ │ │ └── index.html
│ │ ├── foldedregexpattern
│ │ │ └── index.html
│ │ └── index.html
│ ├── jsondefault
│ │ ├── codableformat-implementations
│ │ │ └── index.html
│ │ ├── dataformat
│ │ │ └── index.html
│ │ ├── decode(_:from:)
│ │ │ └── index.html
│ │ ├── encode(_:)
│ │ │ └── index.html
│ │ ├── encode(_:rootname:)
│ │ │ └── index.html
│ │ ├── foldedregexpattern
│ │ │ └── index.html
│ │ └── index.html
│ ├── plistdefault
│ │ ├── codableformat-implementations
│ │ │ └── index.html
│ │ ├── dataformat
│ │ │ └── index.html
│ │ ├── decode(_:from:)
│ │ │ └── index.html
│ │ ├── encode(_:)
│ │ │ └── index.html
│ │ ├── encode(_:rootname:)
│ │ │ └── index.html
│ │ ├── foldedregexpattern
│ │ │ └── index.html
│ │ └── index.html
│ └── yamldefault
│ │ ├── codableformat-implementations
│ │ └── index.html
│ │ ├── dataformat
│ │ └── index.html
│ │ ├── decode(_:from:)
│ │ └── index.html
│ │ ├── encode(_:)
│ │ └── index.html
│ │ ├── encode(_:rootname:)
│ │ └── index.html
│ │ ├── foldedregexpattern
│ │ └── index.html
│ │ └── index.html
│ ├── codablepathexplorer
│ ├── add(_:at:)-13yei
│ │ └── index.html
│ ├── add(_:at:)-1mpqn
│ │ └── index.html
│ ├── add(_:at:)-9ka70
│ │ └── index.html
│ ├── add(_:at:)-w76g
│ │ └── index.html
│ ├── adding(_:at:)
│ │ └── index.html
│ ├── array(of:)
│ │ └── index.html
│ ├── bool
│ │ └── index.html
│ ├── data
│ │ └── index.html
│ ├── date
│ │ └── index.html
│ ├── debugdescription
│ │ └── index.html
│ ├── delete(_:)
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-1iwci
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-3e7af
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-8sq6g
│ │ └── index.html
│ ├── deleting(_:deleteifempty:)
│ │ └── index.html
│ ├── description
│ │ └── index.html
│ ├── dictionary(of:)
│ │ └── index.html
│ ├── double
│ │ └── index.html
│ ├── exportcsv()
│ │ └── index.html
│ ├── exportcsv(separator:)
│ │ └── index.html
│ ├── exportdata()
│ │ └── index.html
│ ├── exportdata(to:)
│ │ └── index.html
│ ├── exportdata(to:rootname:)
│ │ └── index.html
│ ├── exportfoldedstring(upto:)
│ │ └── index.html
│ ├── exportstring()
│ │ └── index.html
│ ├── exportstring(to:)
│ │ └── index.html
│ ├── exportstring(to:rootname:)
│ │ └── index.html
│ ├── expressiblebyextendedgraphemeclusterliteral-implementations
│ │ └── index.html
│ ├── expressiblebyunicodescalarliteral-implementations
│ │ └── index.html
│ ├── folded(upto:)
│ │ └── index.html
│ ├── format
│ │ └── index.html
│ ├── fromcsv(string:separator:hasheaders:)
│ │ └── index.html
│ ├── get(_:)
│ │ └── index.html
│ ├── index.html
│ ├── init(booleanliteral:)
│ │ └── index.html
│ ├── init(data:)
│ │ └── index.html
│ ├── init(extendedgraphemeclusterliteral:)
│ │ └── index.html
│ ├── init(floatliteral:)
│ │ └── index.html
│ ├── init(integerliteral:)
│ │ └── index.html
│ ├── init(stringliteral:)
│ │ └── index.html
│ ├── init(unicodescalarliteral:)
│ │ └── index.html
│ ├── init(value:)
│ │ └── index.html
│ ├── init(value:name:)
│ │ └── index.html
│ ├── int
│ │ └── index.html
│ ├── isgroup
│ │ └── index.html
│ ├── issingle
│ │ └── index.html
│ ├── listpaths(startingat:)
│ │ └── index.html
│ ├── listpaths(startingat:filter:)
│ │ └── index.html
│ ├── pathexplorer-implementations
│ │ └── index.html
│ ├── real
│ │ └── index.html
│ ├── serializablepathexplorer-implementations
│ │ └── index.html
│ ├── set(_:keynameto:)-1z5hp
│ │ └── index.html
│ ├── set(_:keynameto:)-40f4n
│ │ └── index.html
│ ├── set(_:keynameto:)-6dvwq
│ │ └── index.html
│ ├── set(_:to:)-15dj0
│ │ └── index.html
│ ├── set(_:to:)-40ro5
│ │ └── index.html
│ ├── set(_:to:)-61aqz
│ │ └── index.html
│ ├── set(_:to:)-7lp6u
│ │ └── index.html
│ ├── setting(_:keynameto:)
│ │ └── index.html
│ ├── setting(_:to:)
│ │ └── index.html
│ └── string
│ │ └── index.html
│ ├── custom-types-explorervalue
│ └── index.html
│ ├── dataformat
│ ├── !=(_:_:)
│ │ └── index.html
│ ├── equatable-implementations
│ │ └── index.html
│ ├── hash(into:)
│ │ └── index.html
│ ├── hashvalue
│ │ └── index.html
│ ├── index.html
│ ├── init(rawvalue:)
│ │ └── index.html
│ ├── json
│ │ └── index.html
│ ├── plist
│ │ └── index.html
│ ├── rawrepresentable-implementations
│ │ └── index.html
│ ├── xml
│ │ └── index.html
│ └── yaml
│ │ └── index.html
│ ├── explorererror
│ ├── !=(_:_:)
│ │ └── index.html
│ ├── equatable-implementations
│ │ └── index.html
│ ├── error-implementations
│ │ └── index.html
│ ├── errordescription
│ │ └── index.html
│ ├── failurereason
│ │ └── index.html
│ ├── helpanchor
│ │ └── index.html
│ ├── index.html
│ ├── invalid(value:)
│ │ └── index.html
│ ├── localizeddescription
│ │ └── index.html
│ ├── localizederror-implementations
│ │ └── index.html
│ ├── mismatchingtype(_:value:)
│ │ └── index.html
│ ├── missing(key:bestmatch:)
│ │ └── index.html
│ ├── path
│ │ └── index.html
│ ├── predicatenotevaluatable(_:description:)
│ │ └── index.html
│ ├── recoverysuggestion
│ │ └── index.html
│ ├── subscriptindexnoarray
│ │ └── index.html
│ ├── subscriptkeynodict
│ │ └── index.html
│ ├── wrong(bounds:arraycount:)
│ │ └── index.html
│ ├── wrong(index:arraycount:)
│ │ └── index.html
│ ├── wrong(regexpattern:)
│ │ └── index.html
│ └── wrongusage(of:)
│ │ └── index.html
│ ├── explorervalue
│ ├── !=(_:_:)
│ │ └── index.html
│ ├── add(_:at:)-4gmuo
│ │ └── index.html
│ ├── add(_:at:)-5gilx
│ │ └── index.html
│ ├── add(_:at:)-8223h
│ │ └── index.html
│ ├── add(_:at:)-8r71p
│ │ └── index.html
│ ├── adding(_:at:)
│ │ └── index.html
│ ├── array(_:)
│ │ └── index.html
│ ├── array(of:)
│ │ └── index.html
│ ├── array
│ │ └── index.html
│ ├── arrayvalue
│ │ └── index.html
│ ├── bool(_:)
│ │ └── index.html
│ ├── bool
│ │ └── index.html
│ ├── customdebugstringconvertible-implementations
│ │ └── index.html
│ ├── customstringconvertible-implementations
│ │ └── index.html
│ ├── data(_:)
│ │ └── index.html
│ ├── data
│ │ └── index.html
│ ├── date(_:)
│ │ └── index.html
│ ├── date
│ │ └── index.html
│ ├── debugdescription
│ │ └── index.html
│ ├── decodable-implementations
│ │ └── index.html
│ ├── delete(_:)
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-215jh
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-55slk
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-5j8qh
│ │ └── index.html
│ ├── deleting(_:deleteifempty:)
│ │ └── index.html
│ ├── description
│ │ └── index.html
│ ├── dictionary(_:)
│ │ └── index.html
│ ├── dictionary(of:)
│ │ └── index.html
│ ├── dictionary
│ │ └── index.html
│ ├── dictionaryvalue
│ │ └── index.html
│ ├── double(_:)
│ │ └── index.html
│ ├── double
│ │ └── index.html
│ ├── encodable-implementations
│ │ └── index.html
│ ├── encode(to:)
│ │ └── index.html
│ ├── equatable-implementations
│ │ └── index.html
│ ├── expressiblebyarrayliteral-implementations
│ │ └── index.html
│ ├── expressiblebybooleanliteral-implementations
│ │ └── index.html
│ ├── expressiblebydictionaryliteral-implementations
│ │ └── index.html
│ ├── expressiblebyextendedgraphemeclusterliteral-implementations
│ │ └── index.html
│ ├── expressiblebyfloatliteral-implementations
│ │ └── index.html
│ ├── expressiblebyintegerliteral-implementations
│ │ └── index.html
│ ├── expressiblebystringliteral-implementations
│ │ └── index.html
│ ├── expressiblebyunicodescalarliteral-implementations
│ │ └── index.html
│ ├── get(_:)
│ │ └── index.html
│ ├── index.html
│ ├── init(arrayliteral:)
│ │ └── index.html
│ ├── init(booleanliteral:)
│ │ └── index.html
│ ├── init(dictionaryliteral:)
│ │ └── index.html
│ ├── init(extendedgraphemeclusterliteral:)
│ │ └── index.html
│ ├── init(floatliteral:)
│ │ └── index.html
│ ├── init(from:)
│ │ └── index.html
│ ├── init(integerliteral:)
│ │ └── index.html
│ ├── init(stringliteral:)
│ │ └── index.html
│ ├── init(unicodescalarliteral:)
│ │ └── index.html
│ ├── init(value:)
│ │ └── index.html
│ ├── init(value:name:)
│ │ └── index.html
│ ├── int(_:)
│ │ └── index.html
│ ├── int
│ │ └── index.html
│ ├── isgroup
│ │ └── index.html
│ ├── issingle
│ │ └── index.html
│ ├── listpaths(startingat:)
│ │ └── index.html
│ ├── listpaths(startingat:filter:)
│ │ └── index.html
│ ├── pathexplorer-implementations
│ │ └── index.html
│ ├── real
│ │ └── index.html
│ ├── set(_:keynameto:)-71khn
│ │ └── index.html
│ ├── set(_:keynameto:)-7cmde
│ │ └── index.html
│ ├── set(_:keynameto:)-9elrr
│ │ └── index.html
│ ├── set(_:to:)-1osuj
│ │ └── index.html
│ ├── set(_:to:)-1p08w
│ │ └── index.html
│ ├── set(_:to:)-85z1n
│ │ └── index.html
│ ├── set(_:to:)-neu9
│ │ └── index.html
│ ├── setting(_:keynameto:)
│ │ └── index.html
│ ├── setting(_:to:)
│ │ └── index.html
│ ├── string(_:)
│ │ └── index.html
│ └── string
│ │ └── index.html
│ ├── explorervalueconvertible
│ └── index.html
│ ├── explorervaluecreatable
│ ├── index.html
│ ├── init(from:)-2m6tw
│ │ └── index.html
│ └── init(from:)-7khyl
│ │ └── index.html
│ ├── explorervaluerepresentable
│ ├── explorervalue()-1gz0u
│ │ └── index.html
│ ├── explorervalue()-9wvc3
│ │ └── index.html
│ └── index.html
│ ├── explorerxml
│ ├── add(_:at:)-1bcbx
│ │ └── index.html
│ ├── add(_:at:)-1pzz6
│ │ └── index.html
│ ├── add(_:at:)-1vd0k
│ │ └── index.html
│ ├── add(_:at:)-4t6ia
│ │ └── index.html
│ ├── add(_:at:)-4y7o0
│ │ └── index.html
│ ├── add(_:at:)-5c99x
│ │ └── index.html
│ ├── adding(_:at:)-1pus
│ │ └── index.html
│ ├── adding(_:at:)-3bl3a
│ │ └── index.html
│ ├── adding(_:at:)-4y55p
│ │ └── index.html
│ ├── adding(_:at:)-5hn92
│ │ └── index.html
│ ├── adding(_:at:)-9e3bi
│ │ └── index.html
│ ├── adding(_:at:)-cwm8
│ │ └── index.html
│ ├── array(of:)
│ │ └── index.html
│ ├── array(of:keepingattributes:singlechildstrategy:)
│ │ └── index.html
│ ├── bool
│ │ └── index.html
│ ├── data
│ │ └── index.html
│ ├── date
│ │ └── index.html
│ ├── debugdescription
│ │ └── index.html
│ ├── delete(_:)
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-3fqmj
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-9oiah
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-9pz8
│ │ └── index.html
│ ├── deleting(_:deleteifempty:)
│ │ └── index.html
│ ├── description
│ │ └── index.html
│ ├── dictionary(of:)
│ │ └── index.html
│ ├── dictionary(of:keepingattributes:singlechildstrategy:)
│ │ └── index.html
│ ├── double
│ │ └── index.html
│ ├── element
│ │ └── index.html
│ ├── explorervalue(keepingattributes:singlechildstrategy:)
│ │ └── index.html
│ ├── exportcsv()
│ │ └── index.html
│ ├── exportcsv(separator:)
│ │ └── index.html
│ ├── exportdata()
│ │ └── index.html
│ ├── exportdata(to:)
│ │ └── index.html
│ ├── exportdata(to:rootname:)
│ │ └── index.html
│ ├── exportfoldedstring(upto:)
│ │ └── index.html
│ ├── exportstring()
│ │ └── index.html
│ ├── exportstring(to:)
│ │ └── index.html
│ ├── exportstring(to:rootname:)
│ │ └── index.html
│ ├── expressiblebyextendedgraphemeclusterliteral-implementations
│ │ └── index.html
│ ├── expressiblebyunicodescalarliteral-implementations
│ │ └── index.html
│ ├── folded(upto:)
│ │ └── index.html
│ ├── format
│ │ └── index.html
│ ├── fromcsv(string:separator:hasheaders:)
│ │ └── index.html
│ ├── get(_:)
│ │ └── index.html
│ ├── index.html
│ ├── init(booleanliteral:)
│ │ └── index.html
│ ├── init(data:)
│ │ └── index.html
│ ├── init(extendedgraphemeclusterliteral:)
│ │ └── index.html
│ ├── init(floatliteral:)
│ │ └── index.html
│ ├── init(integerliteral:)
│ │ └── index.html
│ ├── init(stringliteral:)
│ │ └── index.html
│ ├── init(unicodescalarliteral:)
│ │ └── index.html
│ ├── init(value:)
│ │ └── index.html
│ ├── init(value:name:)
│ │ └── index.html
│ ├── int
│ │ └── index.html
│ ├── isgroup
│ │ └── index.html
│ ├── issingle
│ │ └── index.html
│ ├── listpaths(startingat:)
│ │ └── index.html
│ ├── listpaths(startingat:filter:)
│ │ └── index.html
│ ├── pathexplorer-implementations
│ │ └── index.html
│ ├── real
│ │ └── index.html
│ ├── serializablepathexplorer-implementations
│ │ └── index.html
│ ├── set(_:keynameto:)-1bi3d
│ │ └── index.html
│ ├── set(_:keynameto:)-3whe6
│ │ └── index.html
│ ├── set(_:keynameto:)-8bycm
│ │ └── index.html
│ ├── set(_:to:)-2wq5w
│ │ └── index.html
│ ├── set(_:to:)-3d1tv
│ │ └── index.html
│ ├── set(_:to:)-45huy
│ │ └── index.html
│ ├── set(_:to:)-54j6g
│ │ └── index.html
│ ├── set(_:to:)-8wtzf
│ │ └── index.html
│ ├── set(_:to:)-ofo9
│ │ └── index.html
│ ├── setting(_:keynameto:)
│ │ └── index.html
│ ├── setting(_:to:)-1eczh
│ │ └── index.html
│ ├── setting(_:to:)-2pw3q
│ │ └── index.html
│ ├── setting(_:to:)-4m6ll
│ │ └── index.html
│ ├── setting(_:to:)-4xlv9
│ │ └── index.html
│ ├── setting(_:to:)-5h22p
│ │ └── index.html
│ ├── setting(_:to:)-7elcu
│ │ └── index.html
│ ├── singlechildstrategy
│ │ ├── array
│ │ │ └── index.html
│ │ ├── custom(_:)
│ │ │ └── index.html
│ │ ├── default
│ │ │ └── index.html
│ │ ├── dictionary
│ │ │ └── index.html
│ │ ├── index.html
│ │ └── transform
│ │ │ └── index.html
│ └── string
│ │ └── index.html
│ ├── getting-started
│ └── index.html
│ ├── index.html
│ ├── mastering-paths
│ └── index.html
│ ├── new-4.0.0
│ └── index.html
│ ├── path
│ ├── !=(_:_:)
│ │ └── index.html
│ ├── +(_:_:)-1mpyt
│ │ └── index.html
│ ├── +(_:_:)-4knou
│ │ └── index.html
│ ├── +(_:_:)-wurs
│ │ └── index.html
│ ├── +=(_:_:)
│ │ └── index.html
│ ├── allsatisfy(_:)
│ │ └── index.html
│ ├── append(_:)-6mddf
│ │ └── index.html
│ ├── append(_:)-9l194
│ │ └── index.html
│ ├── append(contentsof:)
│ │ └── index.html
│ ├── appending(_:)-2ptn6
│ │ └── index.html
│ ├── appending(_:)-3mvwq
│ │ └── index.html
│ ├── applying(_:)
│ │ └── index.html
│ ├── arrayliteralelement
│ │ └── index.html
│ ├── bidirectionalcollection-implementations
│ │ └── index.html
│ ├── collection-implementations
│ │ └── index.html
│ ├── commonprefix(with:)
│ │ └── index.html
│ ├── compactmap(_:)
│ │ └── index.html
│ ├── compactmapfilter
│ │ └── index.html
│ ├── compactmapindexes
│ │ └── index.html
│ ├── compactmapkeys
│ │ └── index.html
│ ├── compactmapslices
│ │ └── index.html
│ ├── compare(_:_:)
│ │ └── index.html
│ ├── comparedbykeyandindexes(with:)
│ │ └── index.html
│ ├── contains(_:)
│ │ └── index.html
│ ├── contains(where:)
│ │ └── index.html
│ ├── count
│ │ └── index.html
│ ├── debugdescription
│ │ └── index.html
│ ├── defaultseparator
│ │ └── index.html
│ ├── description
│ │ └── index.html
│ ├── difference(from:)
│ │ └── index.html
│ ├── difference(from:by:)
│ │ └── index.html
│ ├── drop(while:)
│ │ └── index.html
│ ├── dropfirst(_:)
│ │ └── index.html
│ ├── droplast(_:)
│ │ └── index.html
│ ├── elementsequal(_:)
│ │ └── index.html
│ ├── elementsequal(_:by:)
│ │ └── index.html
│ ├── empty
│ │ └── index.html
│ ├── endindex
│ │ └── index.html
│ ├── enumerated()
│ │ └── index.html
│ ├── equatable-implementations
│ │ └── index.html
│ ├── expressiblebyarrayliteral-implementations
│ │ └── index.html
│ ├── filter(_:)
│ │ └── index.html
│ ├── first(where:)
│ │ └── index.html
│ ├── first
│ │ └── index.html
│ ├── firstindex(of:)
│ │ └── index.html
│ ├── firstindex(where:)
│ │ └── index.html
│ ├── firstrange(of:)
│ │ └── index.html
│ ├── flatmap(_:)-4dfav
│ │ └── index.html
│ ├── flatmap(_:)-658d
│ │ └── index.html
│ ├── flattened()
│ │ └── index.html
│ ├── foreach(_:)
│ │ └── index.html
│ ├── formatted(_:)
│ │ └── index.html
│ ├── formindex(_:offsetby:)
│ │ └── index.html
│ ├── formindex(_:offsetby:limitedby:)
│ │ └── index.html
│ ├── formindex(after:)
│ │ └── index.html
│ ├── formindex(before:)
│ │ └── index.html
│ ├── index(_:offsetby:limitedby:)
│ │ └── index.html
│ ├── index(after:)
│ │ └── index.html
│ ├── index(of:)
│ │ └── index.html
│ ├── index.html
│ ├── init()
│ │ └── index.html
│ ├── init(_:)-1b2iy
│ │ └── index.html
│ ├── init(_:)-3ayg2
│ │ └── index.html
│ ├── init(_:)-cgb7
│ │ └── index.html
│ ├── init(arrayliteral:)
│ │ └── index.html
│ ├── init(elements:)-8dch4
│ │ └── index.html
│ ├── init(elements:)-9i64v
│ │ └── index.html
│ ├── init(repeating:count:)
│ │ └── index.html
│ ├── init(string:separator:)
│ │ └── index.html
│ ├── insert(_:at:)
│ │ └── index.html
│ ├── insert(contentsof:at:)
│ │ └── index.html
│ ├── isempty
│ │ └── index.html
│ ├── last(where:)
│ │ └── index.html
│ ├── last
│ │ └── index.html
│ ├── lastindex(of:)
│ │ └── index.html
│ ├── lastindex(where:)
│ │ └── index.html
│ ├── lazy
│ │ └── index.html
│ ├── lexicographicallyprecedes(_:by:)
│ │ └── index.html
│ ├── makeiterator()
│ │ └── index.html
│ ├── map(_:)-1pyvn
│ │ └── index.html
│ ├── map(_:)-3bvvx
│ │ └── index.html
│ ├── max(by:)
│ │ └── index.html
│ ├── min(by:)
│ │ └── index.html
│ ├── mutablecollection-implementations
│ │ └── index.html
│ ├── parser(separator:keyforbiddencharacters:)
│ │ └── index.html
│ ├── partition(by:)-5mp72
│ │ └── index.html
│ ├── partition(by:)-70krf
│ │ └── index.html
│ ├── poplast()
│ │ └── index.html
│ ├── prefix(_:)
│ │ └── index.html
│ ├── prefix(through:)
│ │ └── index.html
│ ├── prefix(upto:)
│ │ └── index.html
│ ├── prefix(while:)
│ │ └── index.html
│ ├── publisher
│ │ └── index.html
│ ├── randomaccesscollection-implementations
│ │ └── index.html
│ ├── randomelement()
│ │ └── index.html
│ ├── randomelement(using:)
│ │ └── index.html
│ ├── rangereplaceablecollection-implementations
│ │ └── index.html
│ ├── ranges(of:)
│ │ └── index.html
│ ├── reduce(_:_:)
│ │ └── index.html
│ ├── reduce(into:_:)
│ │ └── index.html
│ ├── remove(at:)
│ │ └── index.html
│ ├── removeall(keepingcapacity:)
│ │ └── index.html
│ ├── removeall(where:)-13bwz
│ │ └── index.html
│ ├── removeall(where:)-6oyg2
│ │ └── index.html
│ ├── removefirst()
│ │ └── index.html
│ ├── removefirst(_:)
│ │ └── index.html
│ ├── removelast()
│ │ └── index.html
│ ├── removelast(_:)
│ │ └── index.html
│ ├── removesubrange(_:)-28mkd
│ │ └── index.html
│ ├── removesubrange(_:)-3w6oh
│ │ └── index.html
│ ├── replace(_:with:maxreplacements:)
│ │ └── index.html
│ ├── replacesubrange(_:with:)-69vd1
│ │ └── index.html
│ ├── replacesubrange(_:with:)-8jwu3
│ │ └── index.html
│ ├── replacesubrange(_:with:)-8v4n8
│ │ └── index.html
│ ├── replacing(_:with:maxreplacements:)
│ │ └── index.html
│ ├── replacing(_:with:subrange:maxreplacements:)
│ │ └── index.html
│ ├── reservecapacity(_:)
│ │ └── index.html
│ ├── reverse()
│ │ └── index.html
│ ├── reversed()
│ │ └── index.html
│ ├── sequence-implementations
│ │ └── index.html
│ ├── shuffle()
│ │ └── index.html
│ ├── shuffle(using:)
│ │ └── index.html
│ ├── shuffled()
│ │ └── index.html
│ ├── shuffled(using:)
│ │ └── index.html
│ ├── sort(by:)
│ │ └── index.html
│ ├── sort(using:)-20eip
│ │ └── index.html
│ ├── sort(using:)-7hq1j
│ │ └── index.html
│ ├── sorted(by:)
│ │ └── index.html
│ ├── sorted(using:)-1q9xt
│ │ └── index.html
│ ├── sorted(using:)-2epe7
│ │ └── index.html
│ ├── split(maxsplits:omittingemptysubsequences:whereseparator:)
│ │ └── index.html
│ ├── split(separator:maxsplits:omittingemptysubsequences:)
│ │ └── index.html
│ ├── startindex
│ │ └── index.html
│ ├── starts(with:)
│ │ └── index.html
│ ├── starts(with:by:)
│ │ └── index.html
│ ├── subscript(_:)
│ │ └── index.html
│ ├── suffix(_:)
│ │ └── index.html
│ ├── suffix(from:)
│ │ └── index.html
│ ├── swapat(_:_:)
│ │ └── index.html
│ ├── trimmingprefix(_:)
│ │ └── index.html
│ ├── trimmingprefix(while:)
│ │ └── index.html
│ ├── trimprefix(_:)
│ │ └── index.html
│ ├── trimprefix(while:)
│ │ └── index.html
│ ├── underestimatedcount
│ │ └── index.html
│ ├── withcontiguousmutablestorageifavailable(_:)
│ │ └── index.html
│ └── withcontiguousstorageifavailable(_:)
│ │ └── index.html
│ ├── pathelement
│ ├── !=(_:_:)
│ │ └── index.html
│ ├── count
│ │ └── index.html
│ ├── customstringconvertible-implementations
│ │ └── index.html
│ ├── description
│ │ └── index.html
│ ├── equatable-implementations
│ │ └── index.html
│ ├── expressiblebyextendedgraphemeclusterliteral-implementations
│ │ └── index.html
│ ├── expressiblebyintegerliteral-implementations
│ │ └── index.html
│ ├── expressiblebystringliteral-implementations
│ │ └── index.html
│ ├── expressiblebyunicodescalarliteral-implementations
│ │ └── index.html
│ ├── filter(_:)
│ │ └── index.html
│ ├── index(_:)
│ │ └── index.html
│ ├── index.html
│ ├── init(extendedgraphemeclusterliteral:)
│ │ └── index.html
│ ├── init(integerliteral:)
│ │ └── index.html
│ ├── init(stringliteral:)
│ │ └── index.html
│ ├── init(unicodescalarliteral:)
│ │ └── index.html
│ ├── integerliteraltype
│ │ └── index.html
│ ├── key(_:)
│ │ └── index.html
│ ├── keyslist
│ │ └── index.html
│ ├── pathelementrepresentable-implementations
│ │ └── index.html
│ ├── pathvalue
│ │ └── index.html
│ ├── slice(_:)
│ │ └── index.html
│ ├── slice(_:_:)
│ │ └── index.html
│ └── stringliteraltype
│ │ └── index.html
│ ├── pathelementrepresentable
│ ├── index.html
│ └── pathvalue
│ │ └── index.html
│ ├── pathexplorer
│ ├── add(_:at:)-2kii6
│ │ └── index.html
│ ├── add(_:at:)-2zxor
│ │ └── index.html
│ ├── add(_:at:)-6wo3i
│ │ └── index.html
│ ├── add(_:at:)-861h4
│ │ └── index.html
│ ├── adding(_:at:)-4ju9b
│ │ └── index.html
│ ├── adding(_:at:)-5uv86
│ │ └── index.html
│ ├── adding(_:at:)-68mxp
│ │ └── index.html
│ ├── adding(_:at:)-7fd9c
│ │ └── index.html
│ ├── array(of:)
│ │ └── index.html
│ ├── bool
│ │ └── index.html
│ ├── data
│ │ └── index.html
│ ├── date
│ │ └── index.html
│ ├── delete(_:)
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-2uxwq
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-40w9g
│ │ └── index.html
│ ├── delete(_:deleteifempty:)-g45f
│ │ └── index.html
│ ├── deleting(_:deleteifempty:)-1byw9
│ │ └── index.html
│ ├── deleting(_:deleteifempty:)-2u4ud
│ │ └── index.html
│ ├── deleting(_:deleteifempty:)-32ufs
│ │ └── index.html
│ ├── dictionary(of:)
│ │ └── index.html
│ ├── double
│ │ └── index.html
│ ├── get(_:)-2ghf1
│ │ └── index.html
│ ├── get(_:)-6pa9h
│ │ └── index.html
│ ├── get(_:)-8vyte
│ │ └── index.html
│ ├── index.html
│ ├── init(value:)
│ │ └── index.html
│ ├── init(value:name:)
│ │ └── index.html
│ ├── int
│ │ └── index.html
│ ├── isgroup
│ │ └── index.html
│ ├── issingle
│ │ └── index.html
│ ├── listpaths(startingat:)
│ │ └── index.html
│ ├── listpaths(startingat:filter:)-4tkeq
│ │ └── index.html
│ ├── listpaths(startingat:filter:)-8y0x2
│ │ └── index.html
│ ├── real
│ │ └── index.html
│ ├── set(_:keynameto:)-1zwfv
│ │ └── index.html
│ ├── set(_:keynameto:)-5j60r
│ │ └── index.html
│ ├── set(_:keynameto:)-9i6hd
│ │ └── index.html
│ ├── set(_:to:)-376n0
│ │ └── index.html
│ ├── set(_:to:)-5fgny
│ │ └── index.html
│ ├── set(_:to:)-6yk0i
│ │ └── index.html
│ ├── set(_:to:)-9d877
│ │ └── index.html
│ ├── setting(_:keynameto:)-1fmyp
│ │ └── index.html
│ ├── setting(_:keynameto:)-1vrh
│ │ └── index.html
│ ├── setting(_:keynameto:)-7ar89
│ │ └── index.html
│ ├── setting(_:to:)-5tdzy
│ │ └── index.html
│ ├── setting(_:to:)-7q3g
│ │ └── index.html
│ ├── setting(_:to:)-9vtr8
│ │ └── index.html
│ ├── setting(_:to:)-n2ij
│ │ └── index.html
│ └── string
│ │ └── index.html
│ ├── pathexplorers
│ ├── index.html
│ ├── json
│ │ └── index.html
│ ├── plist
│ │ └── index.html
│ ├── xml
│ │ └── index.html
│ └── yaml
│ │ └── index.html
│ ├── paths-listing
│ └── index.html
│ ├── pathsfilter
│ ├── expressionpredicate
│ │ ├── evaluate(with:)
│ │ │ └── index.html
│ │ ├── index.html
│ │ └── init(format:)
│ │ │ └── index.html
│ ├── functionpredicate
│ │ ├── evaluate(with:)
│ │ │ └── index.html
│ │ ├── evaluation-swift.property
│ │ │ └── index.html
│ │ ├── evaluation-swift.typealias
│ │ │ └── index.html
│ │ ├── index.html
│ │ └── init(evaluation:)
│ │ │ └── index.html
│ ├── index.html
│ ├── key(pattern:target:)
│ │ └── index.html
│ ├── key(regex:)
│ │ └── index.html
│ ├── key(regex:target:)
│ │ └── index.html
│ ├── keyandvalue(keyregex:valuepredicate:)
│ │ └── index.html
│ ├── keyandvalue(keyregex:valuepredicates:)
│ │ └── index.html
│ ├── keyandvalue(keyregex:valuepredicates:_:)
│ │ └── index.html
│ ├── keyandvalue(pattern:valuepredicate:)
│ │ └── index.html
│ ├── keyandvalue(pattern:valuepredicatesformat:_:)
│ │ └── index.html
│ ├── nofilter
│ │ └── index.html
│ ├── targetonly(_:)
│ │ └── index.html
│ ├── value(_:)
│ │ └── index.html
│ ├── value(_:_:)-2wxh0
│ │ └── index.html
│ ├── value(_:_:)-8tfx1
│ │ └── index.html
│ └── valuetarget
│ │ ├── !=(_:_:)
│ │ └── index.html
│ │ ├── equatable-implementations
│ │ └── index.html
│ │ ├── group
│ │ └── index.html
│ │ ├── hash(into:)
│ │ └── index.html
│ │ ├── hashvalue
│ │ └── index.html
│ │ ├── index.html
│ │ ├── init(rawvalue:)
│ │ └── index.html
│ │ ├── rawrepresentable-implementations
│ │ └── index.html
│ │ ├── single
│ │ └── index.html
│ │ └── singleandgroup
│ │ └── index.html
│ ├── serializablepathexplorer
│ ├── exportcsv()
│ │ └── index.html
│ ├── exportcsv(separator:)
│ │ └── index.html
│ ├── exportdata()
│ │ └── index.html
│ ├── exportdata(to:)
│ │ └── index.html
│ ├── exportdata(to:rootname:)
│ │ └── index.html
│ ├── exportfoldedstring(upto:)
│ │ └── index.html
│ ├── exportstring()
│ │ └── index.html
│ ├── exportstring(to:)
│ │ └── index.html
│ ├── exportstring(to:rootname:)
│ │ └── index.html
│ ├── folded(upto:)
│ │ └── index.html
│ ├── format
│ │ └── index.html
│ ├── fromcsv(string:separator:hasheaders:)
│ │ └── index.html
│ ├── index.html
│ └── init(data:)
│ │ └── index.html
│ ├── serializationerror
│ ├── datatostring
│ │ └── index.html
│ ├── error-implementations
│ │ └── index.html
│ ├── errordescription
│ │ └── index.html
│ ├── failurereason
│ │ └── index.html
│ ├── helpanchor
│ │ └── index.html
│ ├── index.html
│ ├── localizeddescription
│ │ └── index.html
│ ├── localizederror-implementations
│ │ └── index.html
│ ├── notcsvexportable(description:)
│ │ └── index.html
│ ├── recoverysuggestion
│ │ └── index.html
│ └── stringtodata
│ │ └── index.html
│ └── valuepredicate
│ ├── evaluate(with:)
│ └── index.html
│ └── index.html
├── favicon.ico
├── favicon.svg
├── img
├── added-icon.d6f7e47d.svg
├── deprecated-icon.015b4f17.svg
├── modified-icon.f496e73d.svg
└── no-image@2x.df2a0a50.png
├── index.html
├── index
└── index.json
├── js
├── chunk-2d0d3105.cd72cc8e.js
├── chunk-c0335d80.76a68cc5.js
├── chunk-vendors.ba2dd0cb.js
├── documentation-topic.57e91f8a.js
├── documentation-topic~topic.1679ec90.js
├── documentation-topic~topic~tutorials-overview.90c61522.js
├── highlight-js-bash.1b52852f.js
├── highlight-js-c.d1db3f17.js
├── highlight-js-cpp.eaddddbe.js
├── highlight-js-css.75eab1fe.js
├── highlight-js-custom-markdown.7cffc4b3.js
├── highlight-js-custom-swift.5cda5c20.js
├── highlight-js-diff.62d66733.js
├── highlight-js-http.163e45b6.js
├── highlight-js-java.8326d9d8.js
├── highlight-js-javascript.acb8a8eb.js
├── highlight-js-json.471128d2.js
├── highlight-js-llvm.6100b125.js
├── highlight-js-markdown.90077643.js
├── highlight-js-objectivec.bcdf5156.js
├── highlight-js-perl.757d7b6f.js
├── highlight-js-php.cc8d6c27.js
├── highlight-js-python.c214ed92.js
├── highlight-js-ruby.f889d392.js
├── highlight-js-scss.62ee18da.js
├── highlight-js-shell.dd7f411f.js
├── highlight-js-swift.84f3e88c.js
├── highlight-js-xml.9c3688c7.js
├── index.e8a5d294.js
├── topic.8cd0c0c4.js
└── tutorials-overview.2a32cd6f.js
└── metadata.json
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | :warning:
2 |
3 | New issue checklist:
4 |
5 | - [ ] Issue tracker does not already contain the same (or a very similar) issue
6 | - [ ] Title must be clear about what is the issue
7 | - [ ] All relevant fields of the description are filled
8 | - [ ] Issue is following the [CODE OF CONDUCT](https://github.com/ABridoux/scout/blob/master/CODE_OF_CONDUCT.md)
9 |
10 | **Please delete this section once you're ready to finally create the issue.**
11 |
12 | :warning:
13 |
14 | # Short description
15 |
16 | _Please fill this section with a short description of your issue / new feature._
17 |
18 | ---
19 |
20 | **If the ticket is about an issue, use the following sections to give more details about the issue you're facing.**
21 |
22 | ### Expected outcome
23 |
24 | _Please fill this section with a description of what you're expecting to happen._
25 |
26 | ### Actual outcome
27 |
28 | _Please fill the following section with a description of what is actually happening. Please add as much information as you can (how easy it is to reproduce, steps, etc.)._
29 |
30 | ---
31 |
32 | **If the ticket is about a new feature, use the following sections to give more details about the changes you ask for / want to implement.**
33 |
34 | ### Missing functionnality
35 |
36 | _Please fill this section with a description of what's missing for you._
37 |
38 | ### Implementation
39 |
40 | _Please fill this section with details of the implementation you expect or plan to do._
41 |
42 | ## Miscellaneous
43 |
44 | | Information | Value |
45 | | ---------------- | ---------------- |
46 | | Scout version | e.g. 1.0.0 |
47 | | Platform | e.g. macOS/linux |
48 | | Platform version | e.g. 9.0 |
49 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Report a bug with details
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior
15 |
16 | **Expected behavior**
17 | A clear and concise description of what you expected to happen.
18 |
19 | **Current behavior**
20 | What actually happened
21 |
22 | **Screenshots**
23 | If applicable, add screenshots to help explain your problem.
24 |
25 | **Additional context**
26 | Add any other context about the problem here.
27 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. *I'm always frustrated when [...]*
12 |
13 | **Describe your idea briefly.**
14 | A general idea of the new feature the program/library could offer.
15 |
16 | **Describe the solution you'd like**
17 | A clear and concise description of what you want to happen. Don't hesitate to give examples of possible usage.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | *Please fill this section with information related to the changes / fixes you introduced.*
4 |
5 | ## Miscellaneous
6 |
7 | *Please fill this section with anything else that can be relevant to the review of your pull request (benchmarks, blogs, StackOverflow threads, etc.).*
8 |
--------------------------------------------------------------------------------
/.github/workflows/swift.yml:
--------------------------------------------------------------------------------
1 | name: Swift
2 |
3 | on: [push, pull_request]
4 |
5 |
6 | jobs:
7 | build_and_test:
8 | runs-on: macos-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v2
12 | - name: Build
13 | run: xcodebuild -scheme Scout
14 | - name: Run tests
15 | run: xcodebuild test -scheme Scout
16 | - name: Code coverage
17 | run: bash <(curl -s https://codecov.io/bash)
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 |
--------------------------------------------------------------------------------
/.swift-version:
--------------------------------------------------------------------------------
1 | 5.2
2 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | included:
2 | - Sources
3 | - Tests
4 |
5 | disabled_rules:
6 | - xctfail_message
7 | line_length: 200
8 | identifier_name:
9 | # identifiers like id
10 | min_length: 2
11 | max_length: 50
12 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDETemplateMacros.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FILEHEADER
6 |
7 | // Scout
8 | // Copyright (c) 2020-present Alexis Bridoux
9 | // MIT license, see LICENSE file for details
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Highlight-presets/Colors-Homebrew.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | json
6 |
7 | keyName
8 | 187
9 |
10 | plist
11 |
12 | keyName
13 | 187
14 | tag
15 | 245
16 | header
17 | 239
18 |
19 | xml
20 |
21 | openingTag
22 | 187
23 | header
24 | 239
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Highlight-presets/Colors-Novel.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | json
6 |
7 | keyName
8 | 168
9 | punctuation
10 | 247
11 |
12 | plist
13 |
14 | keyName
15 | 168
16 | tag
17 | 247
18 | header
19 | 138
20 |
21 | xml
22 |
23 | openingTag
24 | 168
25 | header
26 | 138
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Highlight-presets/Colors-Ocean.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | json
6 |
7 | keyName
8 | 113
9 | punctuation
10 | 66
11 |
12 | plist
13 |
14 | keyName
15 | 113
16 | tag
17 | 68
18 | header
19 | 25
20 |
21 | xml
22 |
23 | openingTag
24 | 168
25 | header
26 | 138
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/Highlight-presets/README.md:
--------------------------------------------------------------------------------
1 | # Highlight presets
2 |
3 | Those files are highlight colors presets for **Scout**. I tried to make them useful for some macOS terminal default styles.
4 |
5 | To use a preset, download it and put it in the folder *~/.scout/*. Then change its name to *Colors.plist*. You can find more information about how to customise highlight colors [here](https://github.com/ABridoux/scout/wiki/%5B30%5D-Syntax-highlighting:-custom-colors).
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) [2020] Alexis Bridoux
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/Playground/People.json:
--------------------------------------------------------------------------------
1 | {
2 | "Tom" : {
3 | "age" : 68,
4 | "hobbies" : [
5 | "cooking",
6 | "guitar"
7 | ],
8 | "height" : 175
9 | },
10 | "Robert" : {
11 | "age" : 23,
12 | "hobbies" : [
13 | "video games",
14 | "party",
15 | "tennis"
16 | ],
17 | "running_records" : [
18 | [
19 | 10,
20 | 12,
21 | 9,
22 | 10
23 | ],
24 | [
25 | 9,
26 | 12,
27 | 11
28 | ]
29 | ],
30 | "height" : 181
31 | },
32 | "Suzanne" : {
33 | "job" : "actress",
34 | "movies" : [
35 | {
36 | "title" : "Tomorrow is so far",
37 | "awards" : "Best speech for a silent movie"
38 | },
39 | {
40 | "title" : "Yesterday will never go",
41 | "awards" : "Best title"
42 | },
43 | {
44 | "title" : "What about today?"
45 | }
46 | ]
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Playground/People.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Robert
6 |
7 | age
8 | 23
9 | height
10 | 181
11 | hobbies
12 |
13 | video games
14 | party
15 | tennis
16 |
17 | running_records
18 |
19 |
20 | 10
21 | 12
22 | 9
23 | 10
24 |
25 |
26 | 9
27 | 12
28 | 11
29 |
30 |
31 |
32 | Suzanne
33 |
34 | job
35 | actress
36 | movies
37 |
38 |
39 | awards
40 | Best speech for a silent movie
41 | title
42 | Tomorrow is so far
43 |
44 |
45 | awards
46 | Best title
47 | title
48 | Yesterday will never go
49 |
50 |
51 | title
52 | What about today?
53 |
54 |
55 |
56 | Tom
57 |
58 | age
59 | 68
60 | height
61 | 175
62 | hobbies
63 |
64 | cooking
65 | guitar
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/Playground/People.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 175
5 | 68
6 |
7 | cooking
8 | guitar
9 |
10 |
11 |
12 |
13 | 181
14 | 23
15 |
16 | video games
17 | party
18 | tennis
19 |
20 |
21 |
22 | 10
23 | 12
24 | 9
25 | 10
26 |
27 |
28 | 9
29 | 12
30 | 11
31 |
32 |
33 |
34 |
35 |
36 | actress
37 |
38 |
39 | Tomorrow is so far
40 | Best speech for a silent movie
41 |
42 |
43 | Yesterday will never go
44 | Best title
45 |
46 |
47 | What about today?
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/Playground/People.yml:
--------------------------------------------------------------------------------
1 | Robert:
2 | age: 23
3 | height: 181
4 | hobbies:
5 | - video games
6 | - party
7 | - tennis
8 | running_records:
9 | - - 10
10 | - 12
11 | - 9
12 | - 10
13 | - - 9
14 | - 12
15 | - 11
16 | Suzanne:
17 | job: actress
18 | movies:
19 | - awards: Best speech for a silent movie
20 | title: Tomorrow is so far
21 | - awards: Best title
22 | title: Yesterday will never go
23 | - title: What about today?
24 | Tom:
25 | age: 68
26 | height: 175
27 | hobbies:
28 | - cooking
29 | - guitar
30 |
31 |
--------------------------------------------------------------------------------
/Resources/scout-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ABridoux/scout/37453749ef2d3e81a542cc9dacf0d8f636f848c1/Resources/scout-logo.png
--------------------------------------------------------------------------------
/Resources/syntax-highlight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ABridoux/scout/37453749ef2d3e81a542cc9dacf0d8f636f848c1/Resources/syntax-highlight.png
--------------------------------------------------------------------------------
/Resources/syntax-highlighting-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ABridoux/scout/37453749ef2d3e81a542cc9dacf0d8f636f848c1/Resources/syntax-highlighting-2.png
--------------------------------------------------------------------------------
/Sources/Parsing/Character+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension Character {
9 |
10 | var isDecimalDigit: Bool {
11 | let zero: Character = "0"
12 | let nine: Character = "9"
13 | return (zero...nine).contains(self)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/Parsing/Parser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | /// Parse a string to an array of `PathElement`s
9 | ///
10 | /// - note: Inspired from [functional Swift](https://www.objc.io/books/functional-swift/)
11 | /// *Parser Combinators* chapter
12 | public struct Parser {
13 | let parse: (Substring) -> (R, Substring)?
14 |
15 | public init(parse: @escaping (Substring) -> (R, Substring)?) {
16 | self.parse = parse
17 | }
18 | }
19 |
20 | public extension Parser {
21 |
22 | func run(_ string: String) -> (result: R, remainder: String)? {
23 | guard let (result, remainder) = parse(Substring(string)) else { return nil }
24 | return (result, String(remainder))
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/Scout/Constants/DataFormat.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | /// Unique identifier of a data format.
7 | public enum DataFormat: String, CaseIterable {
8 | case json
9 | case plist
10 | case xml
11 | case yaml
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/Scout/Constants/Folding.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | // MARK: - Folding
7 |
8 | enum Folding {
9 |
10 | /// Used to name the single key when folding a dictionary
11 | static let foldedKey = "Folded"
12 |
13 | /// Used to replace the content of a dictionary or array when folding it
14 | static let foldedMark = "~~SCOUT_FOLDED~~"
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/Scout/Constants/ScoutVersion.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | // MARK: - ScoutVersion
7 |
8 | public enum ScoutVersion {
9 | public static let current = "4.1.0"
10 | }
11 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValue/CSV/ExplorerValue+CSVImport.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 | import SwiftCSV
8 |
9 | // MARK: - CSV import
10 |
11 | extension ExplorerValue {
12 |
13 | private typealias Tree = PathTree
14 |
15 | static func fromCSV(string: String, separator: Character, hasHeaders: Bool) throws -> ExplorerValue {
16 | let csv = try CSV(string: string, delimiter: separator, loadColumns: hasHeaders)
17 | return try from(csv: csv, headers: hasHeaders)
18 | }
19 |
20 | private static func from(csv: CSV, headers: Bool) throws -> ExplorerValue {
21 | if headers {
22 | return try fromArrayOfDictionaries(csv: csv)
23 | } else if csv.enumeratedRows.count == 1 {
24 | return .array(csv.enumeratedRows[0].map(ExplorerValue.singleFrom))
25 | } else {
26 | return array <^> ([csv.header] + csv.enumeratedRows).map { array <^> $0.map(ExplorerValue.singleFrom) }
27 | }
28 | }
29 |
30 | private static func fromArrayOfDictionaries(csv: CSV) throws -> ExplorerValue {
31 | let rootTree = Tree.root()
32 | let headers = try csv.header
33 | .map { try (key: $0, path: Path(string: $0)) } // transform keys to paths
34 | .sorted { $0.path.comparedByKeyAndIndexes(with: $1.path) } // sort by path
35 | .map { ($0.key, rootTree.insert(path: $0.path)) } // insert paths in the PathTree
36 |
37 | let dicts = try csv.namedRows.compactMap { row -> ExplorerValue? in
38 | try from(row: row, with: headers, rootTree: rootTree)
39 | }
40 |
41 | return .array(dicts)
42 | }
43 |
44 | private static func from(row: [String: String], with keysTrees: [(key: String, path: Tree)], rootTree: Tree) throws -> ExplorerValue? {
45 | keysTrees.forEach { (key, tree) in
46 | if let value = row[key] {
47 | tree.value = .leaf(value: .singleFrom(string: value))
48 | } else {
49 | tree.value = .leaf(value: nil)
50 | }
51 | }
52 |
53 | return try ExplorerValue.newValue(exploring: rootTree)
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValue/ExplorerValue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - ExplorerValue
9 |
10 | /// The values a `PathExplorer` can take
11 | public enum ExplorerValue: Sendable {
12 |
13 | // single
14 | case int(Int)
15 | case double(Double)
16 | case string(String)
17 | case bool(Bool)
18 | case data(Data)
19 | case date(Date)
20 |
21 | // group
22 | case array(ArrayValue)
23 | case dictionary(DictionaryValue)
24 | }
25 |
26 | // MARK: - Type aliases
27 |
28 | extension ExplorerValue {
29 |
30 | public typealias ArrayValue = [ExplorerValue]
31 | public typealias DictionaryValue = [String: ExplorerValue]
32 | typealias SlicePath = Slice
33 | }
34 |
35 | // MARK: - Hashable
36 |
37 | extension ExplorerValue: Hashable {}
38 |
39 | // MARK: - Special init
40 |
41 | extension ExplorerValue {
42 |
43 | init(value: Any) throws {
44 | if let int = value as? Int {
45 | self = .int(int)
46 | } else if let double = value as? Double {
47 | self = .double(double)
48 | } else if let string = value as? String {
49 | self = .string(string)
50 | } else if let bool = value as? Bool {
51 | self = .bool(bool)
52 | } else if let data = value as? Data {
53 | self = .data(data)
54 | } else if let date = value as? Date {
55 | self = .date(date)
56 | } else if let dict = value as? [String: Any] {
57 | self = try .dictionary(dict.mapValues { try ExplorerValue(value: $0) })
58 | } else if let array = value as? [Any] {
59 | self = try .array(array.map { try ExplorerValue(value: $0) })
60 | } else {
61 | throw ExplorerError.invalid(value: value)
62 | }
63 | }
64 |
65 | static func singleFrom(string: String) -> ExplorerValue {
66 | if let int = Int(string) {
67 | return .int(int)
68 | } else if let double = Double(string) {
69 | return .double(double)
70 | } else if let bool = Bool(string) {
71 | return .bool(bool)
72 | } else {
73 | return .string(string)
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValue/Other/ExplorerValue+CustomStringConvertible.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | // MARK: - CustomStringConvertible
7 |
8 | extension ExplorerValue: CustomStringConvertible {
9 |
10 | public var description: String {
11 | switch self {
12 | case .int(let int): return int.description
13 | case .double(let double): return double.description
14 | case .string(let string): return string
15 | case .bool(let bool): return bool.description
16 | case .data(let data): return data.base64EncodedString()
17 | case .date(let date): return date.description
18 | case .array(let array):
19 | let elements = array.map(\.description).joined(separator: ",")
20 | return "[\(elements)]"
21 | case .dictionary(let dict):
22 | let elements = dict.map { "\($0.key): \($0.value)" }.joined(separator: ",")
23 | return "[\(elements)]"
24 | }
25 | }
26 | }
27 |
28 | // MARK: - CustomDebugStringConvertible
29 |
30 | extension ExplorerValue: CustomDebugStringConvertible {
31 |
32 | public var debugDescription: String { description }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValue/Other/ExplorerValue+ExpressibleBy.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | // MARK: - ExpressibleByStringLiteral
7 |
8 | extension ExplorerValue: ExpressibleByStringLiteral {
9 |
10 | public init(stringLiteral value: String) {
11 | self = .string(value)
12 | }
13 | }
14 |
15 | // MARK: - ExpressibleByIntegerLiteral
16 |
17 | extension ExplorerValue: ExpressibleByIntegerLiteral {
18 |
19 | public init(integerLiteral value: Int) {
20 | self = .int(value)
21 | }
22 | }
23 |
24 | // MARK: - ExpressibleByFloatLiteral
25 |
26 | extension ExplorerValue: ExpressibleByFloatLiteral {
27 |
28 | public init(floatLiteral value: Double) {
29 | self = .double(value)
30 | }
31 | }
32 |
33 | // MARK: - ExpressibleByBooleanLiteral
34 |
35 | extension ExplorerValue: ExpressibleByBooleanLiteral {
36 |
37 | public init(booleanLiteral value: Bool) {
38 | self = .bool(value)
39 | }
40 | }
41 |
42 | // MARK: - ExpressibleByArrayLiteral
43 |
44 | extension ExplorerValue: ExpressibleByArrayLiteral {
45 |
46 | public init(arrayLiteral elements: ExplorerValue...) {
47 | self = .array(elements)
48 | }
49 | }
50 |
51 | // MARK: - ExpressibleByDictionaryLiteral
52 |
53 | extension ExplorerValue: ExpressibleByDictionaryLiteral {
54 |
55 | public init(dictionaryLiteral elements: (String, ExplorerValue)...) {
56 | self = .dictionary(Dictionary(uniqueKeysWithValues: elements))
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValue/Other/ExplorerValue+Folded.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - Folding
9 |
10 | extension ExplorerValue {
11 |
12 | // MARK: Constants
13 |
14 | private var foldedKey: String { Folding.foldedKey }
15 | private var foldedMark: String { Folding.foldedMark }
16 |
17 | // MARK: Fold
18 |
19 | func folded(upTo level: Int) -> Self {
20 | switch self {
21 | case .string, .int, .double, .bool, .data, .date:
22 | return self
23 |
24 | case .array(let array):
25 | if level <= 0 {
26 | return self.array <^> [Self.string(foldedMark)]
27 | } else {
28 | return self.array <^> array.map { $0.folded(upTo: level - 1) }
29 | }
30 |
31 | case .dictionary(let dict):
32 | if level <= 0 {
33 | return dictionary <^> [foldedKey: .string(foldedMark)]
34 | } else {
35 | return dictionary <^> dict.mapValues { $0.folded(upTo: level - 1) }
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValue/Other/ExplorerValue+Helpers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - Compute index
9 |
10 | extension PathExplorer {
11 |
12 | /// Compute the index, positive or negative. Negative index uses the array count.
13 | /// - Parameters:
14 | /// - index: Index to compute
15 | /// - arrayCount: Array count
16 | static func computeIndex(from index: Int, arrayCount: Int) throws -> Int {
17 | let computedIndex = index < 0 ? arrayCount + index : index
18 |
19 | guard 0 <= computedIndex, computedIndex < arrayCount else {
20 | throw ExplorerError.wrong(index: index, arrayCount: arrayCount)
21 | }
22 |
23 | return computedIndex
24 | }
25 | }
26 |
27 | // MARK: - Operators
28 |
29 | infix operator <^>
30 |
31 | /// Apply the left function to the right operand.
32 | /// - note: Mainly used as synthetic sugar to avoid over use of brackets.
33 | func <^>(lhs: (A) -> B, rhs: A) -> B { lhs(rhs) }
34 |
35 | extension ExplorerValue: EquatablePathExplorer {
36 | public init(value: ExplorerValue, name: String?) {
37 | self = value
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValueSerialization/ExplorerValueConvertible+Codable/CodableFormat/CodableFormat.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - CodableFormat
9 |
10 | public protocol CodableFormat {
11 |
12 | // MARK: Properties
13 |
14 | static var dataFormat: DataFormat { get }
15 |
16 | /// Regex used to find folded marks in the description of a folded explorer
17 | static var foldedRegexPattern: String { get }
18 |
19 | // MARK: Encode
20 |
21 | static func encode(_ value: E, rootName: String?) throws -> Data
22 |
23 | // MARK: Decode
24 |
25 | static func decode(_ type: D.Type, from data: Data) throws -> D
26 | }
27 |
28 | // MARK: Encode
29 |
30 | public extension CodableFormat {
31 |
32 | static func encode(_ value: E) throws -> Data {
33 | try encode(value, rootName: nil)
34 | }
35 | }
36 |
37 | // MARK: - Constants
38 |
39 | extension CodableFormat {
40 |
41 | static var foldedKey: String { Folding.foldedKey }
42 | static var foldedMark: String { Folding.foldedMark }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValueSerialization/ExplorerValueConvertible+Codable/CodableFormat/CodableFormats+JsonDateIso8601.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - JsonDateIso8601
9 |
10 | extension CodableFormats {
11 |
12 | public enum JsonDateIso8601: CodableFormat {
13 |
14 | // MARK: Constants
15 |
16 | public static let dataFormat: DataFormat = .json
17 | public static var foldedRegexPattern: String { JsonDefault.foldedRegexPattern }
18 |
19 | private static let decoder: JSONDecoder = {
20 | let decoder = JSONDecoder()
21 | decoder.dateDecodingStrategy = .iso8601
22 | return decoder
23 | }()
24 |
25 | private static let encoder: JSONEncoder = {
26 | let encoder = JSONEncoder()
27 | encoder.dateEncodingStrategy = .iso8601
28 | encoder.outputFormatting = .prettyPrinted
29 | return encoder
30 | }()
31 |
32 | // MARK: Encode
33 |
34 | public static func decode(_ type: D.Type, from data: Data) throws -> D where D: Decodable {
35 | try decoder.decode(type, from: data)
36 | }
37 |
38 | // MARK: Decode
39 |
40 | public static func encode(_ value: E, rootName: String?) throws -> Data where E: Encodable {
41 | try encoder.encode(value)
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValueSerialization/ExplorerValueConvertible+Codable/CodableFormat/CodableFormats+JsonDefault.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - JsonDefault
9 |
10 | public extension CodableFormats {
11 |
12 | enum JsonDefault: CodableFormat {
13 |
14 | // MARK: Constants
15 |
16 | public static var dataFormat: DataFormat { .json }
17 | public static var foldedRegexPattern: String {
18 | #"(?<=\[)\s*"\#(foldedMark)"\s*(?=\])"# // array
19 | + #"|(?<=\{)\s*"\#(foldedKey)"\s*:\s*"\#(foldedMark)"\s*(?=\})"# // dict
20 | }
21 |
22 | private static let encoder: JSONEncoder = {
23 | let encoder = JSONEncoder()
24 | encoder.outputFormatting = .prettyPrinted
25 | return encoder
26 | }()
27 |
28 | private static let decoder: JSONDecoder = JSONDecoder()
29 |
30 | // MARK: Encode
31 |
32 | public static func encode(_ value: E, rootName: String?) throws -> Data {
33 | try encoder.encode(value)
34 | }
35 |
36 | // MARK: Decode
37 |
38 | public static func decode(_ type: D.Type, from data: Data) throws -> D where D: Decodable {
39 | try decoder.decode(type, from: data)
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValueSerialization/ExplorerValueConvertible+Codable/CodableFormat/CodableFormats+Namespace.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | // MARK: - CodableFormats
7 |
8 | /// Namespace for types implementing ``CodableFormat``.
9 | public enum CodableFormats {}
10 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValueSerialization/ExplorerValueConvertible+Codable/CodableFormat/CodableFormats+PlistDefault.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - PlistDefault
9 |
10 | public extension CodableFormats {
11 |
12 | enum PlistDefault: CodableFormat {
13 |
14 | // MARK: Constants
15 |
16 | public static var dataFormat: DataFormat { .plist }
17 |
18 | public static var foldedRegexPattern: String {
19 | #"(?<=)\s*\#(foldedMark)\s*(?=)"# // array
20 | + #"|(?<=)\s*\#(foldedKey)\s*\#(foldedMark)\s*(?=)"# // dict
21 | }
22 |
23 | private static let encoder: PropertyListEncoder = {
24 | let encoder = PropertyListEncoder()
25 | encoder.outputFormat = .xml
26 | return encoder
27 | }()
28 |
29 | private static let decoder: PropertyListDecoder = PropertyListDecoder()
30 |
31 | // MARK: Encode
32 |
33 | public static func encode(_ value: E, rootName: String?) throws -> Data where E: Encodable {
34 | try encoder.encode(value)
35 | }
36 |
37 | // MARK: Decode
38 |
39 | public static func decode(_ type: D.Type, from data: Data) throws -> D where D: Decodable {
40 | try decoder.decode(type, from: data)
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValueSerialization/ExplorerValueConvertible+Codable/CodableFormat/CodableFormats+YamlDefault.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Yams
7 | import Foundation
8 |
9 | // MARK: - YamlDefault
10 |
11 | public extension CodableFormats {
12 |
13 | enum YamlDefault: CodableFormat {
14 |
15 | // MARK: Constants
16 |
17 | public static var dataFormat: DataFormat { .yaml }
18 |
19 | public static var foldedRegexPattern: String {
20 | #"\#(foldedMark)\s*(?=\n)"# // array
21 | + #"|\#(foldedKey)\s*:\s*\#(foldedMark)\s*(?=\n)"# // dict
22 | }
23 |
24 | private static let encoder = YAMLEncoder()
25 | private static let decoder = YAMLDecoder()
26 |
27 | // MARK: Encode
28 |
29 | public static func encode(_ value: E, rootName: String?) throws -> Data where E: Encodable {
30 | try encoder.encode(value).data(using: .utf8).unwrapOrThrow(.stringToData)
31 | }
32 |
33 | // MARK: Decode
34 |
35 | public static func decode(_ type: D.Type, from data: Data) throws -> D where D: Decodable {
36 | try decoder.decode(type, from: data)
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValueSerialization/ExplorerValueConvertible+Codable/Decoding/ExplorerValueDecoder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - ExplorerValueDecoder
9 |
10 | final class ExplorerValueDecoder: Decoder {
11 |
12 | // MARK: Properties
13 |
14 | var codingPath: [CodingKey]
15 | var userInfo: [CodingUserInfoKey: Any] = [:]
16 | let value: ExplorerValue
17 |
18 | // MARK: Init
19 |
20 | init(_ value: ExplorerValue, codingPath: [CodingKey] = []) {
21 | self.value = value
22 | self.codingPath = codingPath
23 | }
24 | }
25 |
26 | // MARK: - Containers
27 |
28 | extension ExplorerValueDecoder {
29 |
30 | func container(keyedBy type: Key.Type) throws -> KeyedDecodingContainer where Key: CodingKey {
31 | KeyedDecodingContainer(Container(value: value, codingPath: codingPath, decoder: self))
32 | }
33 |
34 | func unkeyedContainer() throws -> UnkeyedDecodingContainer {
35 | let array = try value.array.unwrapOrThrow(error: valueTypeError(type: [ExplorerValue].self))
36 | return UnkeyedContainer(array: array, codingPath: codingPath, decoder: self)
37 | }
38 |
39 | func singleValueContainer() throws -> SingleValueDecodingContainer {
40 | SingleValueContainer(value: value, codingPath: codingPath, decoder: self)
41 | }
42 | }
43 |
44 | // MARK: - Error
45 |
46 | extension ExplorerValueDecoder {
47 |
48 | func valueTypeError(type: T.Type) -> DecodingError {
49 | DecodingError.typeMismatch(
50 | T.self,
51 | DecodingError.Context(codingPath: codingPath, debugDescription: ""))
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValueSerialization/ExplorerValueConvertible+Codable/DecodingError+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - typeMismatch
9 |
10 | extension DecodingError {
11 |
12 | static func typeMismatch(_ type: T.Type, codingPath: [CodingKey]) -> DecodingError {
13 | DecodingError.typeMismatch(
14 | T.self,
15 | DecodingError.Context(codingPath: codingPath, debugDescription: ""))
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValueSerialization/ExplorerValueConvertible+Codable/Encoding/ExplorerValueEncoder.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - ExplorerValueEncoder
9 |
10 | final class ExplorerValueEncoder: Encoder {
11 |
12 | // MARK: Properties
13 |
14 | var codingPath: [CodingKey]
15 | var userInfo: [CodingUserInfoKey: Any] = [:]
16 | var value: ExplorerValue!
17 |
18 | // MARK: Init
19 |
20 | init(codingPath: [CodingKey] = []) {
21 | self.codingPath = codingPath
22 | }
23 | }
24 |
25 | // MARK: - Containers
26 |
27 | extension ExplorerValueEncoder {
28 |
29 | func container(keyedBy type: Key.Type) -> KeyedEncodingContainer where Key: CodingKey {
30 | value = .dictionary([:])
31 | return KeyedEncodingContainer(Container(codingPath: codingPath, encoder: self, path: .empty))
32 | }
33 |
34 | func unkeyedContainer() -> UnkeyedEncodingContainer {
35 | value = .array([])
36 | return UnkeyedContainer(codingPath: codingPath, encoder: self, path: .empty)
37 | }
38 |
39 | func singleValueContainer() -> SingleValueEncodingContainer {
40 | value = .bool(false)
41 | return SingleContainer(codingPath: codingPath, encoder: self, path: .empty)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValueSerialization/ExplorerValueConvertible.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - ExplorerValueRepresentable
9 |
10 | /// Can be represented as an `ExplorerValue`
11 | /// - note: Default implementation provided for types conforming to `Encodable`
12 | public protocol ExplorerValueRepresentable {
13 |
14 | /// Convert `self` to an ``ExplorerValue``
15 | func explorerValue() throws -> ExplorerValue
16 | }
17 |
18 | // MARK: - ExplorerValueCreatable
19 |
20 | /// Can be instantiated from an ``ExplorerValue``
21 | /// - note: Default implementation provided for types conforming to `Decodable`
22 | public protocol ExplorerValueCreatable {
23 |
24 | /// Instantiate a new value from an ``ExplorerValue``
25 | init(from explorerValue: ExplorerValue) throws
26 | }
27 |
28 | // MARK: - ExplorerValueConvertible
29 |
30 | /// Can be represented *as* and instantiated *from* an ``ExplorerValue``
31 | /// - note: Default implementation provided for types conforming to `Codable`
32 | public typealias ExplorerValueConvertible = ExplorerValueRepresentable & ExplorerValueCreatable
33 |
34 | // MARK: - Encodable
35 |
36 | public extension ExplorerValueRepresentable where Self: Encodable {
37 |
38 | func explorerValue() throws -> ExplorerValue {
39 | let encoder = ExplorerValueEncoder()
40 | try encode(to: encoder)
41 | return encoder.value
42 | }
43 | }
44 |
45 | // MARK: - Decodable
46 |
47 | public extension ExplorerValueCreatable where Self: Decodable {
48 |
49 | init(from explorerValue: ExplorerValue) throws {
50 | let decoder = ExplorerValueDecoder(explorerValue)
51 | try self.init(from: decoder)
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerValueSerialization/SerializationError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - SerializationError
9 |
10 | /// Error that can be thrown during serialization operations.
11 | public enum SerializationError {
12 |
13 | case dataToString
14 | case stringToData
15 | case notCSVExportable(description: String)
16 | }
17 |
18 | // MARK: - LocalizedError
19 |
20 | extension SerializationError: LocalizedError {
21 |
22 | public var errorDescription: String? {
23 | switch self {
24 | case .dataToString: return "The data value cannot be represented as a String"
25 | case .stringToData: return "The string value cannot be represented as Data"
26 | case .notCSVExportable(let description): return "The value is not properly exportable to CSV. \(description)"
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerXML/ExplorerXML+Fold.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension ExplorerXML {
9 |
10 | private var foldedKey: String { Folding.foldedKey }
11 | private var foldedMark: String { Folding.foldedMark }
12 | var foldedRegexPattern: String { #"(?<=>)\s*<\#(foldedKey)>\#(foldedMark)\#(foldedKey)>\s*(?=<)"# }
13 |
14 | public func folded(upTo level: Int) -> Self {
15 | guard level > 0 else {
16 | if children.isEmpty {
17 | return copy()
18 | } else {
19 | let copy = copyWithoutChildren()
20 | copy.addChild(ExplorerXML(name: foldedKey, value: foldedMark))
21 | return copy
22 | }
23 | }
24 |
25 | return copyMappingChildren { $0.folded(upTo: level - 1) }
26 | }
27 |
28 | public func exportFoldedString(upTo level: Int) throws -> String {
29 | try folded(upTo: level)
30 | .exportString()
31 | .replacingOccurrences(of: foldedRegexPattern, with: "...", options: .regularExpression)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerXML/ExplorerXML+Serialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 | import AEXML
8 |
9 | extension ExplorerXML: SerializablePathExplorer {
10 |
11 | public static var format: DataFormat { .xml }
12 |
13 | public init(data: Data) throws {
14 | let document = try AEXMLDocument(xml: data)
15 | self.init(element: document.root)
16 | }
17 |
18 | /// Export the path explorer value to data
19 | public func exportData() throws -> Data {
20 | try description.data(using: .utf8).unwrapOrThrow(.dataToString)
21 | }
22 |
23 | public func exportString() throws -> String { description }
24 |
25 | public func exportData(to format: DataFormat, rootName: String?) throws -> Data {
26 | switch format {
27 | case .json: return try CodableFormats.JsonDefault.encode(explorerValue(), rootName: rootName)
28 | case .plist: return try CodableFormats.PlistDefault.encode(explorerValue(), rootName: rootName)
29 | case .yaml: return try CodableFormats.YamlDefault.encode(explorerValue(), rootName: rootName)
30 | case .xml: return try exportData()
31 | }
32 | }
33 |
34 | public func exportString(to format: DataFormat, rootName: String?) throws -> String {
35 | switch format {
36 | case .json: return try PathExplorers.Json(value: explorerValue()).exportString()
37 | case .plist: return try PathExplorers.Plist(value: explorerValue()).exportString()
38 | case .yaml: return try PathExplorers.Yaml(value: explorerValue()).exportString()
39 | case .xml: return try exportString()
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerXML/ExplorerXML+SingleChildStrategy.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | // MARK: - SingleChildStrategy
7 |
8 | extension ExplorerXML {
9 |
10 | public struct SingleChildStrategy {
11 |
12 | // MARK: Type alias
13 |
14 | public typealias Transform = (_ key: String, _ value: ExplorerValue) -> ExplorerValue
15 |
16 | // MARK: Properties
17 |
18 | var transform: Transform
19 |
20 | // MARK: Init
21 |
22 | init(transform: @escaping Transform) {
23 | self.transform = transform
24 | }
25 | }
26 | }
27 |
28 | // MARK: - Static
29 |
30 | extension ExplorerXML.SingleChildStrategy {
31 |
32 | public static let dictionary = ExplorerXML.SingleChildStrategy { (key, value) -> ExplorerValue in .dictionary([key: value]) }
33 | public static let array = ExplorerXML.SingleChildStrategy { (_, value) -> ExplorerValue in .array([value]) }
34 | public static func custom(_ transform: @escaping Transform) -> ExplorerXML.SingleChildStrategy {
35 | ExplorerXML.SingleChildStrategy { (key, value) in transform(key, value) }
36 | }
37 |
38 | /// Check the the element name. With a default name, an array is returned.
39 | /// Otherwise a dictionary
40 | public static let `default` = ExplorerXML.SingleChildStrategy { (key, value) in
41 | if key == ExplorerXML.Element.defaultName {
42 | return array.transform(key, value)
43 | } else {
44 | return dictionary.transform(key, value)
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Sources/Scout/ExplorerXML/ExplorerXML+ValueSetter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | // MARK: - ValueSetter
7 |
8 | extension ExplorerXML {
9 |
10 | /// Wrapper to more easily handle setting an ExplorerValue or Element.
11 | enum ValueSetter {
12 | case explorerValue(ExplorerValue)
13 | case explorerXML(ExplorerXML)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/Scout/Extensions/AEXML/AEXMLElement+Equal.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import AEXML
7 |
8 | extension AEXMLElement {
9 |
10 | static let defaultName = "element"
11 | static let root = "root"
12 |
13 | func isEqual(to other: AEXMLElement) -> Bool {
14 |
15 | if children.count != other.children.count {
16 | return false
17 | }
18 |
19 | if children.isEmpty, other.children.isEmpty {
20 | return attributes == other.attributes
21 | && (name == other.name || [name, other.name].contains("root") || [name, other.name].contains(Self.defaultName)) // root names are not always the same
22 | && value == other.value
23 | }
24 |
25 | var sortedChildren: [AEXMLElement]
26 | var otherSortedChildren: [AEXMLElement]
27 |
28 | if commonChildrenName != nil { // array
29 | // sort by value
30 | sortedChildren = children.sorted { $0.string < $1.string }
31 | otherSortedChildren = other.children.sorted { $0.string < $1.string }
32 | } else {
33 | // sort by key
34 | sortedChildren = children.sorted { $0.name < $1.name }
35 | otherSortedChildren = other.children.sorted { $0.name < $1.name }
36 | }
37 |
38 | return zip(sortedChildren, otherSortedChildren).first { !$0.isEqual(to: $1) } == nil
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Sources/Scout/Extensions/AEXML/AEXMLElement+Group.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import AEXML
7 |
8 | extension AEXMLElement {
9 |
10 | /// Array or dictionary value type
11 | enum GroupValue: String {
12 | case array, dictionary
13 | }
14 |
15 | private struct GroupCount {
16 | var arrays = 0
17 | var dictionaries = 0
18 |
19 | var max: GroupValue {
20 | if arrays > dictionaries {
21 | return .array
22 | }
23 | return .dictionary // dictionary in case of equality (arbitrary)
24 | }
25 | }
26 |
27 | /// Indicates whether the children are most likely to be arrays or dictionaries
28 | ///
29 | /// #### Complexity
30 | /// O(nm) where
31 | /// - n: Children count
32 | /// - m: Maximum children's children count
33 | var bestChildrenGroupFit: GroupValue {
34 | var groupCounts = GroupCount()
35 |
36 | children.forEach { child in
37 | if child.children.count > 1, child.commonChildrenName != nil {
38 | groupCounts.arrays += 1
39 | } else {
40 | groupCounts.dictionaries += 1
41 | }
42 | }
43 |
44 | return groupCounts.max
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Sources/Scout/Extensions/Array+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension Array {
9 |
10 | func getIfPresent(at index: Int) -> Element? {
11 | guard index >= 0, index < count else { return nil }
12 |
13 | return self[index]
14 | }
15 |
16 | func remove(in range: ClosedRange) -> Self {
17 | assert(range.lowerBound >= 0)
18 | assert(range.upperBound < count)
19 |
20 | let leftPart = self[0.. Void) rethrows {
33 | try self = map { element in
34 | var element = element
35 | try modify(&element)
36 | return element
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Scout/Extensions/CodingKey+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension CodingKey {
9 |
10 | /// Path element string description
11 | var pathDescription: String {
12 | let split = stringValue.components(separatedBy: " ")
13 |
14 | if split.count == 2, split[0] == "Index", let index = Int(split[1]) {
15 | return "[\(index)]"
16 | } else {
17 | return stringValue
18 | }
19 | }
20 | }
21 |
22 | extension Array where Element == CodingKey {
23 |
24 | /// String description of the coding path
25 | var pathDescription: String {
26 | var path = reduce("") { "\($0)\($1.pathDescription)" }
27 |
28 | if path.hasPrefix(".") {
29 | path.removeFirst()
30 | }
31 |
32 | return path
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/Scout/Extensions/Collection+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension RandomAccessCollection {
9 |
10 | /// When not empty, return the first element and self without the first element
11 | func headAndTail() -> (head: Element, tail: SubSequence)? {
12 | guard let head = first else { return nil }
13 | return (head, dropFirst())
14 | }
15 | }
16 |
17 | extension Collection {
18 |
19 | /// Unwrap all the elements mapped by the provided function. If one unwrap fails, `nil` is returned
20 | func unwrapAll(_ transform: (Element) throws -> T?) rethrows -> [T]? {
21 | var unwrapped: [T] = []
22 |
23 | for element in self {
24 | if let transformed = try transform(element) {
25 | unwrapped.append(transformed)
26 | } else {
27 | return nil
28 | }
29 | }
30 |
31 | return unwrapped
32 | }
33 |
34 | /// Unwrap all the elements mapped by the provided key path. If one unwrap fails, `nil` is returned
35 | func unwrapAll(_ keyPath: KeyPath) -> [T]? {
36 | unwrapAll { $0[keyPath: keyPath] }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/Scout/Extensions/Collection+Path.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | public extension Collection where Element == PathElement {
9 |
10 | /// Compare key or index when found at the same position
11 | func comparedByKeyAndIndexes(with otherPath: Path) -> Bool {
12 | var lhsIterator = makeIterator()
13 | var rhsIterator = otherPath.makeIterator()
14 |
15 | while let lhsElement = lhsIterator.next(), let rhsElement = rhsIterator.next() {
16 | switch (lhsElement, rhsElement) {
17 |
18 | case (.key(let lhsLabel), .key(let rhsLabel)):
19 | if lhsLabel != rhsLabel {
20 | return lhsLabel < rhsLabel
21 | }
22 |
23 | case (.index(let lhsIndex), .index(let rhsIndex)):
24 | if lhsIndex != rhsIndex {
25 | return lhsIndex < rhsIndex
26 | }
27 |
28 | default:
29 | return true
30 | }
31 | }
32 |
33 | return count < otherPath.count // put the shorter path before
34 | }
35 | }
36 |
37 | public extension Collection where Element == Path {
38 |
39 | /// Sort by key or index when found at the same position
40 | func sortedByKeysAndIndexes() -> [Path] {
41 | sorted { (lhs, rhs) in lhs.comparedByKeyAndIndexes(with: rhs) }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/Scout/Extensions/Dictionary+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension Dictionary where Key == String {
9 |
10 | /// Return the value for the key if it exists. Otherwise throw an error `missingKey` with the best Jaro-Winkler match found
11 | func jaroWinkler(key: String) throws -> Value {
12 | try self[key]
13 | .unwrapOrThrow(
14 | .missing(
15 | key: key,
16 | bestMatch: key.bestJaroWinklerMatchIn(propositions: Set(keys))
17 | )
18 | )
19 | }
20 | }
21 |
22 | extension Dictionary {
23 |
24 | mutating func modifyEachValue(_ modify: (inout Value) throws -> Void) rethrows {
25 | self = try mapValues { value in
26 | var value = value
27 | try modify(&value)
28 | return value
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/Scout/Extensions/Int+LastIndex.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension Int {
9 | /// Represents the last index in an array
10 | static let lastIndex = -1
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/Scout/Extensions/NSRegularExpression+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension NSRegularExpression {
9 |
10 | convenience init(with pattern: String) throws {
11 | do {
12 | try self.init(pattern: pattern)
13 | } catch {
14 | throw ExplorerError.wrong(regexPattern: pattern)
15 | }
16 | }
17 |
18 | /// Validate a string if the first match found by the regex is the overall string
19 | func validate(_ string: String) -> Bool {
20 | guard
21 | let firstMatch = firstMatch(in: string, options: [], range: NSRange(location: 0, length: string.count)),
22 | firstMatch.range.length >= 0
23 | else {
24 | return false
25 | }
26 |
27 | if firstMatch.range.length == 0 {
28 | if string.isEmpty {
29 | return true
30 | } else {
31 | return false
32 | }
33 | }
34 |
35 | return string[firstMatch.range] == string
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Sources/Scout/Extensions/Optional+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | infix operator !!
9 |
10 | /// Force unwrap an optional when required, with a relevant error message if the optional is `nil`
11 | /// - Parameters:
12 | /// - optional: The optional to unwrap
13 | /// - errorMessage: An error message
14 | /// - Returns: The unwrapped optional
15 | /// - note: Idea from [Advanced Swift](https://www.objc.io/books/advanced-swift/)
16 | func !!(optional: T?, errorMessage: @autoclosure () -> String) -> T {
17 | if let unwrapped = optional {
18 | return unwrapped
19 | }
20 | fatalError(errorMessage())
21 | }
22 |
23 | extension Optional {
24 |
25 | func unwrapOrThrow(error: Error) throws -> Wrapped {
26 | guard let wrapped = self else {
27 | throw error
28 | }
29 | return wrapped
30 | }
31 |
32 | func unwrapOrThrow(_ error: ExplorerError) throws -> Wrapped {
33 | try unwrapOrThrow(error: error)
34 | }
35 |
36 | func unwrapOrThrow(_ error: DecodingError) throws -> Wrapped {
37 | try unwrapOrThrow(error: error)
38 | }
39 |
40 | func unwrapOrThrow(_ error: SerializationError) throws -> Wrapped {
41 | try unwrapOrThrow(error: error)
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/Scout/Extensions/Slice+Etensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension Slice where Base == Path {
9 |
10 | /// The part from base start to the beginning of the slice
11 | var leftPart: Self {
12 | base[.. Substring {
16 | let sliceStartIndex = index(startIndex, offsetBy: range.location)
17 | let sliceEndIndex = index(startIndex, offsetBy: range.upperBound - 1)
18 |
19 | return self[sliceStartIndex...sliceEndIndex]
20 | }
21 |
22 | func isEnclosed(by string: String) -> Bool { hasPrefix(string) && hasSuffix(string) }
23 |
24 | /// Remove the enclosing brackets '(' ')' if found
25 | func removingEnclosingBrackets() -> String {
26 | if hasPrefix("("), hasSuffix(")") {
27 | return String(self[index(after: startIndex).. String {
34 | if contains(string) {
35 | return #""\#(self)""#
36 | } else {
37 | return self
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/Error/PathError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - PathError
9 |
10 | enum PathError {
11 |
12 | case invalidStringPath(_ string: String)
13 | case invalidSeparator(String)
14 | case invalidRegex(pattern: String)
15 | }
16 |
17 | // MARK: - LocalizedError
18 |
19 | extension PathError: LocalizedError {
20 |
21 | var errorDescription: String? {
22 | switch self {
23 | case .invalidStringPath(let string): return "The part '\(string)' of the path is invalid"
24 | case .invalidSeparator(let separator): return "The separator \(separator) is not forbidden or must be escaped"
25 | case .invalidRegex(let pattern): return "The regular expression '\(pattern)' to split the path string is not valid."
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/Path/Bounds+Bound.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | // MARK: - Bound
7 |
8 | public extension Bounds {
9 |
10 | struct Bound: ExpressibleByIntegerLiteral, Hashable {
11 |
12 | // MARK: Type alias
13 |
14 | public typealias IntegerLiteralType = Int
15 |
16 | // MARK: Constants
17 |
18 | public static let first = Bound(0, identifier: "first")
19 | public static let last = Bound(-1, identifier: "last")
20 |
21 | // MARK: Properties
22 |
23 | var value: Int
24 | private(set) var identifier: String?
25 |
26 | // MARK: Init
27 |
28 | public init(integerLiteral value: Int) {
29 | self.value = value
30 | }
31 |
32 | public init(_ value: Int) {
33 | self.value = value
34 | }
35 |
36 | private init(_ value: Int, identifier: String) {
37 | self.value = value
38 | self.identifier = identifier
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/Path/Bounds+IntWrapper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | // MARK: - IntWrapper
7 |
8 | extension Bounds {
9 |
10 | /// Wrapper around an `Int` value to avoid to make all the `Bounds` mutable.
11 | /// - note: `Bounds` will only mutate those `IntWrapper` values internally.
12 | @propertyWrapper
13 | final class IntWrapper {
14 |
15 | // MARK: Properties
16 |
17 | var wrappedValue: Int?
18 | }
19 | }
20 |
21 | // MARK: - Hashable
22 |
23 | extension Bounds.IntWrapper: Hashable {
24 |
25 | static func == (lhs: Bounds.IntWrapper, rhs: Bounds.IntWrapper) -> Bool {
26 | lhs.wrappedValue == rhs.wrappedValue
27 | }
28 |
29 | func hash(into hasher: inout Hasher) {
30 | hasher.combine(wrappedValue)
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/Path/Path+Miscellaneous.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | public extension Collection where Element == PathElement {
9 |
10 | /// Retrieve all the index elements
11 | var compactMapIndexes: [Int] { compactMap(\.index) }
12 |
13 | /// Retrieve all the key elements
14 | var compactMapKeys: [String] { compactMap(\.key) }
15 |
16 | /// Retrieve all the slices bounds elements
17 | var compactMapSlices: [Bounds] {
18 | compactMap {
19 | if case let .slice(bounds) = $0 {
20 | return bounds
21 | }
22 | return nil
23 | }
24 | }
25 |
26 | /// Retrieve all the filter elements
27 | var compactMapFilter: [String] {
28 | compactMap {
29 | if case let .filter(pattern) = $0 {
30 | return pattern
31 | }
32 | return nil
33 | }
34 | }
35 | }
36 |
37 | public extension Collection where SubSequence == Slice {
38 |
39 | /// The greatest prefix that both paths have in common
40 | func commonPrefix(with otherPath: Self) -> Slice {
41 | var iterator = makeIterator()
42 | var otherIterator = otherPath.makeIterator()
43 | var lastIndex = 0
44 |
45 | while
46 | let element = iterator.next(), let otherElement = otherIterator.next(),
47 | element == otherElement {
48 | lastIndex += 1
49 | }
50 |
51 | return self[0.. PathElement {
12 | .slice(Bounds(lower: lower, upper: upper))
13 | }
14 |
15 | /// Get all elements (convenience for testing)
16 | static var sliceAll: PathElement { .slice(.first, .last) }
17 |
18 | /// Get all elements (convenience for testing)
19 | static var filterAll: PathElement { .filter(".*") }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/Path/PathElementRepresentable.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | /// Protocol to allow to subscript a `PathExplorer` without using directly the ``PathElement`` enum.
7 | ///
8 | /// As `PathElement` already conforms to `ExpressibleByStringLiteral` and `ExpressibleByIntegerLiteral`,
9 | /// it is possible to instantiate a Path without the need of using the `PathElementRepresentable` protocol:
10 | /// ```
11 | /// let path: Path = ["people", "Tom", "hobbies", 1]
12 | /// ```
13 | /// But the "Expressible" protocols do not allow to do the same with variables.
14 | /// Thus, using `PathElementRepresentable` allows to instantiate a Path from a mix of Strings and Integers variables:
15 | /// ```swift
16 | /// let tom = "Tom"
17 | /// let hobbies = "hobbies"
18 | /// let index = 1
19 | /// let path: Path = [tom, hobbies, index]
20 | /// ```
21 | /// - note: This only works for keys and indexes. When dealing with other elements like `.count` or `.slice`,
22 | /// it's required to use the full name `PathElement.count`, `PathElement.slice`. Otherwise,
23 | /// the `Path.init(element:)` works with `PathElement` directly although the possibility to use variables
24 | /// without the `PathElement` specification becomes unavailable.
25 | public protocol PathElementRepresentable {
26 | var pathValue: PathElement { get }
27 | }
28 |
29 | extension String: PathElementRepresentable {
30 | public var pathValue: PathElement { .key(self) }
31 | }
32 |
33 | extension Int: PathElementRepresentable {
34 | public var pathValue: PathElement { .index(self) }
35 | }
36 |
37 | extension PathElement: PathElementRepresentable {
38 | public var pathValue: PathElement { self }
39 | }
40 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/Path/PathTree+ValueType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | // MARK: - ValueType
7 |
8 | extension PathTree {
9 |
10 | enum ValueType: Equatable {
11 | case uninitializedLeaf
12 | case leaf(value: Value)
13 | case node(children: [PathTree])
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/PathExplorer/CodablePathExplorer+Serialization.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension CodablePathExplorer: SerializablePathExplorer {
9 |
10 | public static var format: DataFormat { Format.dataFormat }
11 |
12 | public init(data: Data) throws {
13 | let value = try Format.decode(ExplorerValue.self, from: data)
14 | self.init(value: value)
15 | }
16 |
17 | public func exportData() throws -> Data {
18 | try Format.encode(value)
19 | }
20 |
21 | public func exportString() throws -> String {
22 | try String(data: exportData(), encoding: .utf8)
23 | .unwrapOrThrow(.dataToString)
24 | }
25 |
26 | public func exportData(to format: DataFormat, rootName: String?) throws -> Data {
27 | switch format {
28 | case .json: return try CodableFormats.JsonDefault.encode(value)
29 | case .plist: return try CodableFormats.PlistDefault.encode(value)
30 | case .yaml: return try CodableFormats.YamlDefault.encode(value)
31 | case .xml: return try ExplorerXML(value: value, name: rootName).exportData()
32 | }
33 | }
34 |
35 | public func exportString(to format: DataFormat, rootName: String?) throws -> String {
36 | switch format {
37 | case .json, .plist, .yaml:
38 | return try String(data: exportData(to: format, rootName: rootName), encoding: .utf8).unwrapOrThrow(.dataToString)
39 |
40 | case .xml: return try ExplorerXML(value: value, name: rootName).exportString()
41 | }
42 | }
43 |
44 | public func exportCSV(separator: String?) throws -> String {
45 | try value.exportCSV(separator: separator ?? defaultCSVSeparator)
46 | }
47 |
48 | public static func fromCSV(string: String, separator: Character, hasHeaders: Bool) throws -> CodablePathExplorer {
49 | try Self(value: .fromCSV(string: string, separator: separator, hasHeaders: hasHeaders))
50 | }
51 |
52 | public func folded(upTo level: Int) -> Self {
53 | Self(value: value.folded(upTo: level))
54 | }
55 |
56 | public func exportFoldedString(upTo level: Int) throws -> String {
57 | try folded(upTo: level)
58 | .exportString()
59 | .replacingOccurrences(of: Format.foldedRegexPattern, with: "...", options: .regularExpression)
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/PathExplorer/EquatablePathExplorer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - EquatablePathExplorer
9 |
10 | /// Internal protocol to declare how to test equality to another PathExplorer of the same type without publicly declare conformance to `Equatable`.
11 | protocol EquatablePathExplorer: PathExplorer {
12 |
13 | /// `true` when self is equal to the provided other element.
14 | ///
15 | /// ### Complexity
16 | /// Most often `O(n)` where `n` is the children count.
17 | func isEqual(to other: Self) -> Bool
18 | }
19 |
20 | // MARK: - Default implementation
21 |
22 | extension EquatablePathExplorer where Self: Equatable {
23 |
24 | func isEqual(to other: Self) -> Bool { self == other }
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/PathExplorer/PathExplorer+Helpers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension PathExplorer {
9 |
10 | /// Add the element to the thrown `ValueTypeError` if any
11 | func doAdd(_ element: PathElementRepresentable, _ block: () throws -> T) rethrows -> T {
12 | do {
13 | return try block()
14 | } catch let error as ExplorerError {
15 | throw error.adding(element)
16 | }
17 | }
18 |
19 | /// Add the element to the thrown `ValueTypeError` if any
20 | func doAdd(_ element: PathElementRepresentable, _ block: () throws -> Void) rethrows {
21 | do {
22 | try block()
23 | } catch let error as ExplorerError {
24 | throw error.adding(element)
25 | }
26 | }
27 |
28 | /// Add the element to the thrown `ValueTypeError` if any
29 | func doAdd(_ element: PathElement, _ block: () throws -> T) rethrows -> T {
30 | do {
31 | return try block()
32 | } catch let error as ExplorerError {
33 | throw error.adding(element)
34 | }
35 | }
36 |
37 | /// Add the element to the thrown `ValueTypeError` if any
38 | func doAdd(_ element: PathElement, _ block: () throws -> Void) rethrows {
39 | do {
40 | try block()
41 | } catch let error as ExplorerError {
42 | throw error.adding(element)
43 | }
44 | }
45 |
46 | /// do/catch on the provided block to catch a `ValueTypeError` and set the provided path on it
47 | func doSettingPath(_ path: Slice, _ block: () throws -> Void) rethrows {
48 | do {
49 | try block()
50 | } catch let error as ExplorerError {
51 | throw error.with(path: path)
52 | }
53 | }
54 |
55 | /// do/catch on the provided block to catch a `ValueTypeError` and set the provided path on it
56 | func doSettingPath(_ path: Slice, _ block: () throws -> T) rethrows -> T {
57 | do {
58 | return try block()
59 | } catch let error as ExplorerError {
60 | throw error.with(path: path)
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/PathExplorer/PathExplorers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - PathExplorers
9 |
10 | /// Namespace to find all default PathExplorers in a single place.
11 | ///
12 | /// Use default explorers for a format: `PathExplorers.Json`, `PathExplorers.Xml`...
13 | public enum PathExplorers {
14 |
15 | public typealias Json = CodablePathExplorer
16 | public typealias Plist = CodablePathExplorer
17 | public typealias Yaml = CodablePathExplorer
18 | public typealias Xml = ExplorerXML
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/PathsFilter/PathsFilter+FunctionPredicate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import BooleanExpressionEvaluation
7 |
8 | // MARK: - FunctionPredicate
9 |
10 | extension PathsFilter {
11 |
12 | /// Specify a function to filter the value
13 | public final class FunctionPredicate: ValuePredicate {
14 |
15 | // MARK: Type alias
16 |
17 | public typealias Evaluation = (ExplorerValue) throws -> Bool
18 |
19 | // MARK: Properties
20 |
21 | public var evaluation: Evaluation
22 |
23 | // MARK: Init
24 |
25 | public init(evaluation: @escaping Evaluation) {
26 | self.evaluation = evaluation
27 | }
28 | }
29 | }
30 |
31 | // MARK: - Evaluate
32 |
33 | extension PathsFilter.FunctionPredicate {
34 |
35 | public func evaluate(with value: ExplorerValue) throws -> Bool {
36 | try evaluation(value)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/PathsFilter/ValuePredicate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 | import BooleanExpressionEvaluation
8 |
9 | // MARK: - ValuePredicate
10 |
11 | /// Expression or function to evaluate a value
12 | public protocol ValuePredicate {
13 |
14 | /// Evaluate the predicate with the value.
15 | ///
16 | /// - note: Ignore the error of mismatching types between the value and an operand and return `false`
17 | func evaluate(with value: ExplorerValue) throws -> Bool
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/Scout/Models/PathsFilter/ValueTarget.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | // MARK: - ValueTarget
9 |
10 | extension PathsFilter {
11 |
12 | /// Specifies if group (array, dictionary) values, single (string, bool...) values or both should be targeted.
13 | public enum ValueTarget: String, CaseIterable {
14 |
15 | /// Allows the key with a single or a group value.
16 | case singleAndGroup
17 |
18 | /// Allows the key with a single value.
19 | case group
20 |
21 | /// Allows the key with a group (array, dictionary) value.
22 | case single
23 | }
24 | }
25 |
26 | // MARK: - Computed
27 |
28 | extension PathsFilter.ValueTarget {
29 |
30 | /// Allows group values (array, dictionaries)?
31 | var groupAllowed: Bool { [.singleAndGroup, .group].contains(self) }
32 |
33 | /// Allow single values (string, bool...)?
34 | var singleAllowed: Bool { [.singleAndGroup, .single].contains(self) }
35 | }
36 |
--------------------------------------------------------------------------------
/Sources/Scout/Scout.docc/Extensions/explorer-value.md:
--------------------------------------------------------------------------------
1 | # ``Scout/ExplorerValue``
2 |
3 | @Metadata {
4 | @DocumentationExtension(mergeBehavior: append)
5 | }
6 |
7 | ## Overview
8 |
9 | `ExplorerValue` is the back bone of serializable ``PathExplorer`` (JSON, Plist, YAML). It's the type that implements all the logic to conform to `PathExplorer`. Then ``CodablePathExplorer`` simply interfaces it with the proper data format to conform to ``SerializablePathExplorer``. Also, it's the type that is used to encode and decode to those formats.
10 |
11 | But it also allows to use your own types to inject them in a `PathExplorer`. Read more with
12 |
--------------------------------------------------------------------------------
/Sources/Scout/Scout.docc/Extensions/path-element.md:
--------------------------------------------------------------------------------
1 | # ``Scout/PathElement``
2 |
3 | @Metadata {
4 | @DocumentationExtension(mergeBehavior: append)
5 | }
6 |
7 | ## Topics
8 |
9 | ### Basics
10 |
11 | - ``key(_:)``
12 | - ``index(_:)``
13 |
14 | ### Getting a group information
15 |
16 | - ``count``
17 | - ``keysList``
18 |
19 | ### Scope groups
20 |
21 | - ``filter(_:)``
22 | - ``slice(_:)``
23 | - ``slice(_:_:)``
24 |
--------------------------------------------------------------------------------
/Sources/Scout/Scout.docc/Extensions/path.md:
--------------------------------------------------------------------------------
1 | # ``Scout/Path``
2 |
3 | @Metadata {
4 | @DocumentationExtension(mergeBehavior: append)
5 | }
6 |
7 | ## Overview
8 |
9 | Paths are the way to feed a ``PathExplorer`` to navigate through data. `PathExplorer`'s operations will often take a `Path` (or a collection of ``PathElement``s) to target precisely where to run.
10 |
11 | Basically, a `Path` is a collection of ``PathElement``s in a specific order. The sequence of `PathElement`s lets the explorer know what value to target next. When navigating to a value is not possible, the explorer will throw an error.
12 |
13 | ## Topics
14 |
15 | ### Instantiate an empty Path
16 |
17 | - ``init()``
18 | - ``empty``
19 |
20 | ### Instantiate from PathElement values
21 |
22 | - ``init(elements:)-8dch4``
23 | - ``init(elements:)-9i64v``
24 |
25 | ### Instantiate from PathElementRepresentable values
26 |
27 | ``PathElementRepresentable`` is a protocol to erase the `PathElement` type when instantiating a `Path` with non-literal values.
28 |
29 | - ``init(_:)-1b2iy``
30 | - ``init(_:)-cgb7``
31 | - ``init(arrayLiteral:)``
32 |
33 | ### Instantiate from a String
34 |
35 | A `Path` is easily represented as a `String`, which is especially useful when working in the command-line.
36 |
37 | - ``init(string:separator:)``
38 | - ``defaultSeparator``
39 | - ``parser(separator:keyForbiddenCharacters:)``
40 |
41 | ### Appending elements
42 |
43 | `Path` conforms to several collection protocols. Additionally, those convenience functions are offered.
44 |
45 | - ``append(_:)-9l194``
46 | - ``appending(_:)-2ptn6``
47 | - ``appending(_:)-3mvwq``
48 |
49 | ### Flatten a Path
50 |
51 | When a `Path` contains special group scoping elements like ``PathElement/slice(_:)`` or ``PathElement/filter(_:)``, specifying a `PathElement.index` or `PathElement.key` will not refer to an immediate dictionary or array. The "flatten" operation will replace the slices and the filters in the `Path` with the proper values when the path is complete. Mainly used in paths listing ``PathExplorer/listPaths(startingAt:)``.
52 |
53 | - ``flattened()``
54 |
55 | ### Map elements (Collection)
56 |
57 | - ``Path/compactMapIndexes``
58 | - ``Path/compactMapKeys``
59 | - ``Path/compactMapSlices``
60 | - ``Path/compactMapFilter``
61 |
62 | ### Compare path (Collection)
63 |
64 | - ``Path/commonPrefix(with:)``
65 |
--------------------------------------------------------------------------------
/Sources/Scout/Scout.docc/Extensions/paths-filter.md:
--------------------------------------------------------------------------------
1 | # ``Scout/PathsFilter``
2 |
3 | @Metadata {
4 | @DocumentationExtension(mergeBehavior: append)
5 | }
6 |
7 | ## Overview
8 |
9 | Allows to target single or group values, specific keys with regular expressions and values with predicates.
10 |
11 | When filtering keys or values, it's always possible to specify single, group values or both.
12 |
13 | ## Topics
14 |
15 | ### No filter
16 |
17 | - ``noFilter``
18 | - ``targetOnly(_:)``
19 | - ``ValueTarget``
20 |
21 | ### Filter keys
22 |
23 | - ``key(regex:)``
24 | - ``key(regex:target:)``
25 | - ``key(pattern:target:)``
26 |
27 | ### Filter values
28 |
29 | - ``value(_:)``
30 | - ``value(_:_:)-8tfx1``
31 | - ``value(_:_:)-2wxh0``
32 |
33 | ### Filter keys and values
34 |
35 | - ``keyAndValue(pattern:valuePredicate:)``
36 | - ``keyAndValue(keyRegex:valuePredicate:)``
37 | - ``keyAndValue(keyRegex:valuePredicates:)``
38 | - ``keyAndValue(keyRegex:valuePredicates:_:)``
39 | - ``keyAndValue(pattern:valuePredicatesFormat:_:)``
40 |
41 | ### Predicates
42 |
43 | - ``ValuePredicate``
44 | - ``ExpressionPredicate``
45 | - ``FunctionPredicate``
46 |
47 |
--------------------------------------------------------------------------------
/Sources/Scout/Scout.docc/Extensions/serializable-path-explorer-export-folder.md:
--------------------------------------------------------------------------------
1 | # ``Scout/SerializablePathExplorer/exportFoldedString(upTo:)``
2 |
3 | @Metadata {
4 | @DocumentationExtension(mergeBehavior: append)
5 | }
6 | ### Examples
7 |
8 | With the following JSON stored in a `SerializablePathExplorer` named `json`.
9 |
10 | ```json
11 | {
12 | "Tom" : {
13 | "age" : 68,
14 | "hobbies" : [
15 | "cooking",
16 | "guitar"
17 | ],
18 | "height" : 175
19 | },
20 | "Robert" : {
21 | "age" : 23,
22 | "hobbies" : [
23 | "video games",
24 | "party",
25 | "tennis"
26 | ],
27 | "running_records" : [
28 | [
29 | 10,
30 | 12,
31 | 9,
32 | 10
33 | ],
34 | [
35 | 9,
36 | 12,
37 | 11
38 | ]
39 | ],
40 | "height" : 181
41 | },
42 | "Suzanne" : {
43 | "job" : "actress",
44 | "movies" : [
45 | {
46 | "title" : "Tomorrow is so far",
47 | "awards" : "Best speech for a silent movie"
48 | },
49 | {
50 | "title" : "Yesterday will never go",
51 | "awards" : "Best title"
52 | },
53 | {
54 | "title" : "What about today?"
55 | }
56 | ]
57 | }
58 | }
59 | ```
60 |
61 | The following
62 |
63 | ```swift
64 | json.exportFoldedString(upTo: 2)
65 | ```
66 |
67 | will return the string:
68 |
69 | ```json
70 | {
71 | "Suzanne" : {
72 | "job" : "actress",
73 | "movies" : [...]
74 | },
75 | "Tom" : {
76 | "hobbies" : [...],
77 | "age" : 68,
78 | "height" : 175
79 | },
80 | "Robert" : {
81 | "running_records" : [...],
82 | "age" : 23,
83 | "hobbies" : [...],
84 | "height" : 181
85 | }
86 | }
87 | ```
88 |
--------------------------------------------------------------------------------
/Sources/Scout/Scout.docc/Extensions/serializable-path-explorer.md:
--------------------------------------------------------------------------------
1 | # ``Scout/SerializablePathExplorer``
2 |
3 | @Metadata {
4 | @DocumentationExtension(mergeBehavior: append)
5 | }
6 |
7 | ## Overview
8 |
9 | Protocol refining ``PathExplorer`` to offer features like conversion to another format or serialization. Explorers in ``PathExplorers`` implement this protocol.
10 |
11 | ## Topics
12 |
13 | ### Initializers
14 |
15 | - ``init(data:)``
16 | - ``fromCSV(string:separator:hasHeaders:)``
17 |
18 | ### Get format info
19 |
20 | - ``format``
21 |
22 | ### Export as Data
23 |
24 | - ``exportData()``
25 | - ``exportData(to:)``
26 | - ``exportData(to:rootName:)``
27 |
28 | ### Export as String
29 |
30 | - ``exportString()``
31 | - ``exportString(to:)``
32 | - ``exportString(to:rootName:)``
33 |
34 | ### Export as CSV
35 |
36 | - ``exportCSV()``
37 | - ``exportCSV(separator:)``
38 |
39 | ### Export folded String
40 |
41 | - ``exportFoldedString(upTo:)``
42 | - ``folded(upTo:)``
43 |
--------------------------------------------------------------------------------
/Sources/Scout/Scout.docc/Scout.md:
--------------------------------------------------------------------------------
1 | # ``Scout``
2 |
3 | This library aims to make specific formats data values reading and writing simple when the data format is not known at build time.
4 |
5 | ## Overview
6 |
7 | Supported formats:
8 | - JSON
9 | - Plist
10 | - YAML
11 | - XML
12 |
13 | ## Topics
14 |
15 | ### Updates
16 | -
17 |
18 | ### Essential
19 | -
20 | - ``PathExplorer``
21 | - ``Path``
22 |
23 | ### Explore data
24 |
25 | - ``PathExplorer``
26 | - ``PathExplorers``
27 | - ``ExplorerValue``
28 | - ``ExplorerError``
29 |
30 | ### Manipulate paths
31 |
32 | -
33 | -
34 | - ``Path``
35 | - ``PathElement``
36 | - ``PathElementRepresentable``
37 | - ``PathsFilter``
38 | - ``ValuePredicate``
39 | - ``Bounds``
40 |
41 | ### Convert and export explorers
42 |
43 | - ``SerializablePathExplorer``
44 | - ``DataFormat``
45 | - ``CodablePathExplorer``
46 | - ``CodableFormat``
47 | - ``CodableFormats``
48 | - ``ExplorerXML``
49 | - ``SerializationError``
50 |
51 | ### Set and add custom types
52 |
53 | -
54 | - ``ExplorerValueCreatable``
55 | - ``ExplorerValueRepresentable``
56 | - ``ExplorerValueConvertible``
57 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/AdvancedTopicsDoc/AdvancedTopic.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 | import ArgumentParser
8 |
9 | extension DocCommand {
10 | }
11 |
12 | enum AdvancedDocumentation {
13 |
14 | enum Topic: String, ExpressibleByArgument {
15 | case predicates
16 |
17 | var doc: String {
18 | switch self {
19 | case .predicates: return Predicates.text
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/CRUD/Add/AddCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ArgumentParser
7 | import Scout
8 | import ScoutCLTCore
9 |
10 | struct AddCommand: SADCommand {
11 |
12 | // MARK: - Constants
13 |
14 | static let configuration = CommandConfiguration(
15 | commandName: "add",
16 | abstract: "Add value at a given path",
17 | discussion: "To find examples and advanced explanations, please type `scout doc -c add`")
18 |
19 | // MARK: - Properties
20 |
21 | @Option(name: .dataFormat, help: .dataFormat)
22 | var dataFormat: Scout.DataFormat
23 |
24 | @Argument(help: PathAndValue.help)
25 | var pathsCollection = [PathAndValue]()
26 |
27 | @Option(name: .inputFilePath, help: .inputFilePath, completion: .file())
28 | var inputFilePath: String?
29 |
30 | @Option(name: .outputFilePath, help: .outputFilePath, completion: .file())
31 | var outputFilePath: String?
32 |
33 | @Option(name: .modifyFilePath, help: .modifyFilePath, completion: .file())
34 | var modifyFilePath: String?
35 |
36 | @Flag(help: .colorise)
37 | var color = ColorFlag.color
38 |
39 | @Option(name: .fold, help: .fold)
40 | var level: Int?
41 |
42 | @Option(name: .csvSeparator, help: .csvSeparator)
43 | var csvSeparator: String?
44 |
45 | @Option(name: .export, help: .export)
46 | var exportFormat: ExportFormat?
47 |
48 | // MARK: - Functions
49 |
50 | func perform(pathExplorer: inout P, pathAndValue: PathAndValue) throws {
51 | let (path, value) = (pathAndValue.readingPath, pathAndValue.value)
52 | try pathExplorer.add(value, at: path)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/CRUD/Add/AddDocumentation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ArgumentParser
7 | import Lux
8 |
9 | enum AddDocumentation: Documentation {
10 |
11 | private static let examples =
12 | [(#"`scout add "Tom.hobbies[#]=Playing music"`"#, #"will add the hobby "Playing music" to Tom hobbies at the end of the array"#),
13 | (#"`scout add "Arnaud.hobbies[-1]=Playing music"`"#, #"will insert the hobby "Playing music" to Arnaud hobbies before the last hobby 'tennis'."#),
14 | (#"`scout add "Arnaud.hobbies[1]=reading"`"#, #"will insert the hobby "reading" to Arnaud hobbies between the hobby "video games" and "party""#),
15 | (#"`scout add "Franklin={}"`"#, #"will create a new empty dictionary at the key #Franklin#"#),
16 | (#"`scout add "Tom.colors=[]"`"#, #"will add a new empty #colors# array to Tom"#),
17 | (#"`scout add "Tom.score=/165/"`"#, #"will add a new #score# key to Tom with the String value "165""#)]
18 |
19 | static let text =
20 | """
21 |
22 | -----------
23 | Add command
24 | -----------
25 |
26 | \(AddCommand.configuration.abstract)
27 |
28 | \(notesHeader)
29 |
30 | \(commonDoc)
31 |
32 | \(header: "Several paths")
33 | It's possible to add multiple values in one command by specifying several path/value pairs.
34 |
35 | \(header: "Keys creation")
36 | Only when a key is the last one in the path will it be created. When an index is specified as the last element of the path,
37 | the value to add will be inserted at the index location.
38 |
39 | \(header: "Append a value")
40 | To add a value at the end of an array, specify the '[#]' symbol rather than an index
41 |
42 | \(valueSpecificationDoc)
43 |
44 | \(examplesHeader)
45 |
46 | JSON file
47 |
48 | \(injectedJSONExample)
49 |
50 | \(examplesText(from: examples))
51 | """
52 | }
53 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/CRUD/Delete/DeleteCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ArgumentParser
7 | import Scout
8 | import ScoutCLTCore
9 |
10 | struct DeleteCommand: SADCommand {
11 |
12 | // MARK: - Constants
13 |
14 | static let configuration = CommandConfiguration(
15 | commandName: "delete",
16 | abstract: "Delete a value at a given path",
17 | discussion: "To find examples and advanced explanations, please type `scout doc -c delete-key`")
18 |
19 | // MARK: - Properties
20 |
21 | @Option(name: .dataFormat, help: .dataFormat)
22 | var dataFormat: Scout.DataFormat
23 |
24 | @Argument(help: "Paths to indicate the keys to be deleted")
25 | var pathsCollection = [Path]()
26 |
27 | @Option(name: .inputFilePath, help: .inputFilePath, completion: .file())
28 | var inputFilePath: String?
29 |
30 | @Option(name: .outputFilePath, help: .outputFilePath, completion: .file())
31 | var outputFilePath: String?
32 |
33 | @Option(name: .modifyFilePath, help: .modifyFilePath, completion: .file())
34 | var modifyFilePath: String?
35 |
36 | @Flag(help: .colorise)
37 | var color = ColorFlag.color
38 |
39 | @Option(name: .fold, help: .fold)
40 | var level: Int?
41 |
42 | @Flag(name: [.short, .long], help: "When the deleted value leaves the array or dictionary holding it empty, delete it too")
43 | var recursive = false
44 |
45 | @Option(name: .csvSeparator, help: .csvSeparator)
46 | var csvSeparator: String?
47 |
48 | @Option(name: .export, help: .export)
49 | var exportFormat: ExportFormat?
50 |
51 | // MARK: - Functions
52 |
53 | func perform(pathExplorer: inout P, pathAndValue: Path) throws {
54 | try pathExplorer.delete(pathAndValue, deleteIfEmpty: recursive)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/CRUD/Delete/DeleteDocumentation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ArgumentParser
7 | import Lux
8 |
9 | enum DeleteDocumentation: Documentation {
10 |
11 | static let recursive = zshInjector.delegate.inject(.optionNameOrFlag, in: .terminal, "-r")
12 |
13 | private static let examples =
14 | [(#"`scout delete "Tom.height"`"#, #"will delete Tom height"#),
15 | (#"`scout delete "Tom.hobbies[0]"`"#, #"will delete Tom first hobby"#),
16 | (#"`scout delete "Tom.hobbies[-1]"`"#, #"will delete Tom last hobby"#),
17 | (#"`scout delete "Arnaud.#h.*#"`"#, #"will delete Arnaud's height and hobbies"#),
18 | (#"`scout delete "Arnaud.hobbies[-2:]"`"#, #"will delete Arnaud's last two hobbies"#),
19 | (##"`scout delete "#.*#.hobbies[:1]`""##, #"will delete Tom's and Arnaud's first two hobbies"#),
20 | (##"`scout delete -r "#.*#.hobbies[:1]"`"##, #"will delete Arnaud's first two hobbies and Tom hobbies"#),
21 | (#"`scout delete "Tom.height -e plist"`"#, #"will delete Tom height and convert the modified data to a Plist format"#)]
22 |
23 | static let text =
24 | """
25 |
26 | --------------
27 | Delete command
28 | --------------
29 |
30 | \(DeleteCommand.configuration.abstract)
31 |
32 | \(notesHeader)
33 |
34 | \(commonDoc)
35 |
36 | \(header: "Several paths")
37 | It's possible to set multiple values in one command by specifying several path/value pairs.
38 |
39 | \(header: "Delete if empty")
40 | Use the flag \(recursive) to delete an array or a dictionary key when left empty
41 |
42 | \(slicingAndFilteringDoc)
43 |
44 | \(miscDoc)
45 |
46 | \(examplesHeader)
47 |
48 | JSON file
49 |
50 | \(injectedJSONExample)
51 |
52 | \(examplesText(from: examples))
53 | """
54 | }
55 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/CRUD/Read/ReadDocumentation.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ArgumentParser
7 |
8 | enum ReadDocumentation: Documentation {
9 |
10 | private static let examples =
11 | [(#"`scout read "Tom.hobbies[0]"`"#, #"will output Tom first hobby "cooking""#),
12 | (#"`scout read "Arnaud.height"`"#, #"will output Arnaud's height "180""#),
13 | (#"`scout read "Tom.hobbies[-1]"`"#, #"will output Tom last hobby: "guitar""#),
14 | (#"`scout read "Tom"`"#, #"will output Tom dictionary"#),
15 | (#"`scout read "[#]"`"#, #"will output the people count: 2"#),
16 | (#"`scout read "Arnaud.hobbies[#]"`"#, #"will output Arnaud's hobbies count: 3"#),
17 | (#"`scout read "Arnaud.#h.*#"`"#, #"will output Arnaud's height and hobbies"#),
18 | (#"`scout read "Arnaud.hobbies[1:]"`"#, #"will output Arnaud's last two hobbies"#),
19 | (#"`scout read "Arnaud.hobbies[-2:]"`"#, #"will output Arnaud's last two hobbies"#),
20 | (##"`scout read "#.*#.hobbies[:1]"`"##, #"will output Tom's and Arnaud's first two hobbies"#),
21 | (##"`scout read "#.*#.hobbies[#]"`"##, #"will output Tom's and Arnaud's hobbies count"#),
22 | (#"`scout read "Tom.hobbies[:]" --csv-exp ";"`"#, #"will ouput Tom hobbies as CSV"#),
23 | (#"`scout read -i People.json -f json -e yaml`"#, #"will convert the JSON file to YAML"#)]
24 |
25 | static let text =
26 | """
27 |
28 | ------------
29 | Read command
30 | ------------
31 |
32 | \(ReadCommand.configuration.abstract)
33 |
34 | Notes
35 | =====
36 |
37 | \(commonDoc)
38 |
39 | \(header: "Count/Keys symbols")
40 | - Get a dictionary or an array count with the '[#]' symbol.
41 | - List the keys of a dictionary with the '{#}' symbol.
42 |
43 | \(slicingAndFilteringDoc)
44 |
45 | \(miscDoc)
46 |
47 | \(examplesHeader)
48 |
49 | JSON file
50 |
51 | \(injectedJSONExample)
52 |
53 | \(examplesText(from: examples))
54 | """
55 | }
56 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/CRUD/Set/SetCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ArgumentParser
7 | import Scout
8 | import ScoutCLTCore
9 |
10 | struct SetCommand: SADCommand {
11 |
12 | // MARK: - Constants
13 |
14 | static let configuration = CommandConfiguration(
15 | commandName: "set",
16 | abstract: "Change a value at a given path.",
17 | discussion: "To find examples and advanced explanations, please type `scout doc -c set`")
18 |
19 | // MARK: - Properties
20 |
21 | @Option(name: .dataFormat, help: .dataFormat)
22 | var dataFormat: Scout.DataFormat
23 |
24 | @Argument(help: PathAndValue.help)
25 | var pathsCollection = [PathAndValue]()
26 |
27 | @Option(name: .inputFilePath, help: .inputFilePath, completion: .file())
28 | var inputFilePath: String?
29 |
30 | @Option(name: .outputFilePath, help: .outputFilePath, completion: .file())
31 | var outputFilePath: String?
32 |
33 | @Option(name: .modifyFilePath, help: .modifyFilePath, completion: .file())
34 | var modifyFilePath: String?
35 |
36 | @Flag(help: .colorise)
37 | var color = ColorFlag.color
38 |
39 | @Option(name: .fold, help: .fold)
40 | var level: Int?
41 |
42 | @Option(name: .csvSeparator, help: .csvSeparator)
43 | var csvSeparator: String?
44 |
45 | @Option(name: .export, help: .export)
46 | var exportFormat: ExportFormat?
47 |
48 | // MARK: - Functions
49 |
50 | func perform(pathExplorer: inout P, pathAndValue: PathAndValue) throws {
51 | let (path, value) = (pathAndValue.readingPath, pathAndValue.value)
52 |
53 | if case let .keyName(keyName) = value {
54 | try pathExplorer.set(path, keyNameTo: keyName)
55 | } else {
56 | try pathExplorer.set(path, to: value)
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/ColorDelegates/ColorFile.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | struct JsonColors: Codable {
7 | var punctuation: Int?
8 | var keyName: Int?
9 | var keyValue: Int?
10 | }
11 |
12 | struct YamlColors: Codable {
13 | var punctuation: Int?
14 | var keyName: Int?
15 | var keyValue: Int?
16 | }
17 |
18 | struct PlistColors: Codable {
19 | var tag: Int?
20 | var keyName: Int?
21 | var keyValue: Int?
22 | var header: Int?
23 | var comment: Int?
24 | }
25 |
26 | struct XmlColors: Codable {
27 | var punctuation: Int?
28 | var openingTag: Int?
29 | var closingTag: Int?
30 | var key: Int?
31 | var header: Int?
32 | var comment: Int?
33 | }
34 |
35 | /// Plist file to specify custom colors
36 | struct ColorFile: Codable {
37 | var json: JsonColors?
38 | var yaml: YamlColors?
39 | var plist: PlistColors?
40 | var xml: XmlColors?
41 | }
42 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/ColorDelegates/JSONInjectorDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Lux
7 |
8 | final class JSONInjectorColorDelegate: JSONDelegate {
9 |
10 | // MARK: - Properties
11 |
12 | let colors: JsonColors
13 |
14 | // MARK: - Initialisation
15 |
16 | init(colors: JsonColors) {
17 | self.colors = colors
18 | }
19 |
20 | required init() {
21 | colors = JsonColors()
22 | super.init()
23 | }
24 |
25 | // MARK: - Functions
26 |
27 | override func terminalModifier(for category: JSONCategory) -> TerminalModifier {
28 | var colorCode: Int?
29 |
30 | // retrieve the color code in the colors plist if any
31 | switch category {
32 | case .punctuation: colorCode = colors.punctuation
33 | case .keyName: colorCode = colors.keyName
34 | case .keyValue: colorCode = colors.keyValue
35 | }
36 |
37 | if let code = colorCode {
38 | return TerminalModifier(colorCode: code)
39 | } else {
40 | return super.terminalModifier(for: category)
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/ColorDelegates/PlistInjectorColorDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Lux
7 |
8 | final class PlistInjectorColorDelegate: PlistDelegate {
9 |
10 | // MARK: - Properties
11 |
12 | let colors: PlistColors
13 |
14 | // MARK: - Initialisation
15 |
16 | init(colors: PlistColors) {
17 | self.colors = colors
18 | }
19 |
20 | required init() {
21 | colors = PlistColors()
22 | super.init()
23 | }
24 |
25 | // MARK: - Functions
26 |
27 | override func terminalModifier(for category: PlistCategory) -> TerminalModifier {
28 | var colorCode: Int?
29 |
30 | switch category {
31 | case .tag: colorCode = colors.tag
32 | case .keyName: colorCode = colors.keyName
33 | case .keyValue: colorCode = colors.keyValue
34 | case .comment: colorCode = colors.comment
35 | case .header: colorCode = colors.header
36 | }
37 |
38 | if let code = colorCode {
39 | return TerminalModifier(colorCode: code)
40 | } else {
41 | return super.terminalModifier(for: category)
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/ColorDelegates/XMLInjectorColorDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Lux
7 |
8 | final class XMLInjectorColorDelegate: XMLEnhancedDelegate {
9 |
10 | // MARK: - Properties
11 |
12 | let colors: XmlColors
13 |
14 | // MARK: - Initialisation
15 |
16 | init(colors: XmlColors) {
17 | self.colors = colors
18 | }
19 |
20 | required init() {
21 | colors = XmlColors()
22 | super.init()
23 | }
24 |
25 | // MARK: - Functions
26 |
27 | override func terminalModifier(for category: XMLEnhancedCategory) -> TerminalModifier {
28 | var colorCode: Int?
29 |
30 | switch category {
31 | case .openingTag: colorCode = colors.openingTag
32 | case .closingTag: colorCode = colors.closingTag
33 | case .punctuation: colorCode = colors.punctuation
34 | case .key: colorCode = colors.key
35 | case .comment: colorCode = colors.comment
36 | case .header: colorCode = colors.header
37 | }
38 |
39 | if let code = colorCode {
40 | return TerminalModifier(colorCode: code)
41 | } else {
42 | return super.terminalModifier(for: category)
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/ColorDelegates/YAMLInjectorColorDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Lux
7 |
8 | final class YAMLInjectorColorDelegate: YAMLDelegate {
9 |
10 | // MARK: - Properties
11 |
12 | let colors: YamlColors
13 |
14 | // MARK: - Initialisation
15 |
16 | init(colors: YamlColors) {
17 | self.colors = colors
18 | }
19 |
20 | required init() {
21 | colors = YamlColors()
22 | super.init()
23 | }
24 |
25 | // MARK: - Functions
26 |
27 | override func terminalModifier(for category: YAMLCategory) -> TerminalModifier {
28 | var colorCode: Int?
29 |
30 | // retrieve the color code in the colors plist if any
31 | switch category {
32 | case .punctuation: colorCode = colors.punctuation
33 | case .keyName: colorCode = colors.keyName
34 | case .keyValue: colorCode = colors.keyValue
35 | }
36 |
37 | if let code = colorCode {
38 | return TerminalModifier(colorCode: code)
39 | } else {
40 | return super.terminalModifier(for: category)
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Extensions/ArgumentHelp+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ArgumentParser
7 |
8 | extension ArgumentHelp {
9 |
10 | static var readingPath: ArgumentHelp {
11 | ArgumentHelp(
12 | "Path in the data where to read the key value",
13 | discussion: """
14 | A path is a sequence of keys separated with dots to navigate through the data.
15 | A dot '.' is used to subscript a dictionary. For example 'dictionary.key'.
16 | An integer enclosed by square brakets '[1]' is used to subscript an array. For example 'array[5]'.
17 | """)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Extensions/ArgumentParserConformance/DataFormat+ArgumentParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Scout
7 | import ArgumentParser
8 |
9 | extension DataFormat: ExpressibleByArgument {
10 |
11 | public var defaultValueDescription: String { "The data format to read the input" }
12 | }
13 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Extensions/ArgumentParserConformance/ExportFormat+ArgumentParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ScoutCLTCore
7 | import ArgumentParser
8 |
9 | extension ExportFormat: ExpressibleByArgument {}
10 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Extensions/ArgumentParserConformance/ParsableCommand+PathCompletion.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 | import Scout
8 |
9 | /// A PathExplorer without the Self requirement to try to get a path.
10 | protocol PathExplorerGet {
11 | func tryToGet(_ path: Path) throws
12 | }
13 |
14 | extension CodablePathExplorer: PathExplorerGet {
15 | func tryToGet(_ path: Path) throws {
16 | _ = try get(path)
17 | }
18 | }
19 |
20 | extension ExplorerXML: PathExplorerGet {
21 | func tryToGet(_ path: Path) throws {
22 | _ = try get(path)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Extensions/ArgumentParserConformance/PathAndValue+ArgumentParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ScoutCLTCore
7 | import ArgumentParser
8 |
9 | private let _abstract =
10 | """
11 |
12 |
13 | \(header: "Value specification")
14 |
15 | Specify a path with an associated value.
16 | Like "firstKey.secondKey[index].thirdKey=value".
17 |
18 | The following notes indicates how to specify the value.
19 |
20 | \(subheader: "Automatic")
21 | Let Scout automatically infer the type.
22 | Ex: 123 will be treated as an integer, and Endo as a string.
23 |
24 | \(subheader: "String")
25 | Force the specified value to be a string.
26 | Usage: enclose the value with single quotes 'value' or slash /value/.
27 |
28 | \(subheader: "Real")
29 | Force the specified value to be a real (Plist only).
30 | Usage: enclose the value with tildes: ~value~.
31 |
32 | \(subheader: "Array")
33 | Usage: enclose with square brackets a list of values and separate them with commas ','.
34 | Use single quote to specify strings with commas.
35 | It's possible to nest arrays or dictionaries.
36 |
37 | Examples
38 | ````````
39 | [Endo, 'String, with a comma', 123, ~40~]
40 | [Endo, [values, in, nested, array]]
41 |
42 | \(subheader: "Dictionary")
43 | Usage: enclose with curl brackets a list of (key, value) pairs separated with a double point ':' and separate them with commas ','.
44 | Use single quote to specify strings with commas or a key with a commas.
45 | It's possible to nest dictionaries or arrays.
46 |
47 | Examples
48 | ````````
49 | {Riri: 20, Fifi: duck, Loulou: '60'}
50 | ducks: {Riri, Fifi, Loulou}, mouses: {Mickey: 20, Minnie: 30}}
51 |
52 | """
53 |
54 | extension PathAndValue: ExpressibleByArgument {
55 |
56 | static var abstract: String { _abstract }
57 |
58 | static var help: ArgumentHelp { ArgumentHelp(abstract, valueName: "path=value") }
59 |
60 | public init?(argument: String) {
61 | self.init(string: argument)
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Extensions/FileHandle+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension FileHandle {
9 |
10 | /// `true` is the file handle is piped
11 | ///
12 | /// For example on the standard output, this allows to know whether the output is piped or printed in the terminal
13 | /// - note: I think it's O(1) but I cant find any documentation on `isatty()`
14 | var isPiped: Bool { isatty(fileDescriptor) == 0 }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Extensions/Optional+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension Optional {
9 |
10 | func unwrapOrThrow(error: Error) throws -> Wrapped {
11 | guard let wrapped = self else {
12 | throw error
13 | }
14 | return wrapped
15 | }
16 |
17 | func unwrapOrThrow(_ error: RuntimeError) throws -> Wrapped {
18 | try unwrapOrThrow(error: error)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Extensions/Path+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Scout
7 | import ArgumentParser
8 | import Foundation
9 |
10 | extension Path: ExpressibleByArgument {
11 |
12 | public init?(argument: String) {
13 | try? self.init(string: argument)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Main/CommandsRecords.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ArgumentParser
7 |
8 | extension NameSpecification {
9 |
10 | static let dataFormat: NameSpecification = [.customShort("f", allowingJoined: true), .customLong("format")]
11 | static let inputFilePath: NameSpecification = [.short, .customLong("input")]
12 | static let outputFilePath: NameSpecification = [.short, .customLong("output")]
13 | static let modifyFilePath: NameSpecification = [.short, .customLong("modify")]
14 | static let fold: NameSpecification = [.short, .long]
15 | static let csvSeparator: NameSpecification = [.customLong("csv-export")]
16 | static let export: NameSpecification = [.short, .customLong("export")]
17 | }
18 |
19 | extension ArgumentHelp {
20 |
21 | static let dataFormat = ArgumentHelp("The data format of the input")
22 | static let inputFilePath = ArgumentHelp("A file path from which to read the data")
23 | static let outputFilePath = ArgumentHelp("Write the modified data into the file at the given path")
24 | static let modifyFilePath = ArgumentHelp("Read and write the data into the same file at the given path")
25 | static let colorise = ArgumentHelp("Highlight the output. --no-color or --nc to prevent it")
26 | static let fold = ArgumentHelp("Fold the data at the given depth level")
27 | static let csvSeparator = ArgumentHelp("Convert the array data into CSV with the given separator")
28 | static let export = ArgumentHelp("Convert the data to the specified format")
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Main/ScoutMainCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ArgumentParser
7 | import Scout
8 |
9 | private let abstract =
10 | """
11 | Read and modify values in specific format file or data. Currently supported: Json, Plist, YAML and Xml.
12 | """
13 |
14 | private let discussion =
15 | """
16 | To find advanced help and rich examples, please type `scout doc`.
17 |
18 |
19 | Written by Alexis Bridoux. Copyright (c) 2020-present.
20 | \u{001B}[38;5;88mhttps://www.woodys-findings.com/scout\u{001B}[0;0m
21 | MIT license, see LICENSE file for details
22 | """
23 |
24 | @main
25 | struct ScoutMainCommand: ParsableCommand {
26 |
27 | // MARK: - Constants
28 |
29 | static let configuration = CommandConfiguration(
30 | commandName: "scout",
31 | abstract: abstract,
32 | discussion: discussion,
33 | version: ScoutVersion.current,
34 | subcommands: [
35 | ReadCommand.self,
36 | SetCommand.self,
37 | DeleteCommand.self,
38 | AddCommand.self,
39 | DocCommand.self,
40 | PathsCommand.self,
41 | CSVCommand.self,
42 | InstallCompletionScriptCommand.self],
43 | defaultSubcommand: ReadCommand.self)
44 | }
45 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Models/ColorFlag.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 | import ArgumentParser
8 |
9 | enum ColorFlag: String, EnumerableFlag {
10 |
11 | /// Specify to colorise the output. Prevented if the program is piped.
12 | case color
13 |
14 | /// Force the colorisation whether the program is piped or not
15 | case forceColor
16 |
17 | /// Specify to not colorise the output
18 | case noColor
19 |
20 | /// Specify to not colorise the output
21 | case nc
22 |
23 | var colorise: Bool {
24 | switch self {
25 | case .color, .forceColor: return true
26 | case .noColor, .nc: return false
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Models/Command.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import ArgumentParser
7 |
8 | enum Command: String, ExpressibleByArgument, CaseIterable {
9 | case read, set, delete, add, paths
10 |
11 | static var documentationDescription: String {
12 | "\(Self.read.rawValue.mainColor), \(Self.set.rawValue.mainColor), \(Self.delete.rawValue.mainColor) and \(Self.add.rawValue.mainColor)"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Models/PathExplorer+Alias.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Scout
7 |
8 | typealias Xml = PathExplorers.Xml
9 | typealias Json = CodablePathExplorer
10 | typealias Plist = PathExplorers.Plist
11 | typealias Yaml = PathExplorers.Yaml
12 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Models/RuntimeError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | enum RuntimeError: LocalizedError {
9 | case invalidData(String)
10 | case dataToString
11 | case noValueAt(path: String)
12 | case unknownFormat(String)
13 | case completionScriptInstallation(description: String)
14 | case invalidRegex(String)
15 | case invalidArgumentsCombination(description: String)
16 | case valueConversion(value: String, type: String)
17 | case custom(String)
18 |
19 | var errorDescription: String? {
20 | switch self {
21 | case .invalidData(let description): return description
22 | case .dataToString: return "The input data cannot be converted to UTF-8 String"
23 | case .noValueAt(let path): return "No value at '\(path)'"
24 | case .unknownFormat(let description): return description
25 | case .completionScriptInstallation(let description): return "Error while installing the completion script. \(description)"
26 | case .invalidRegex(let pattern): return "The regular expression '\(pattern)' is invalid"
27 | case .invalidArgumentsCombination(let description): return description
28 | case .valueConversion(let value, let type): return "The value \(value) is not convertible to \(type)"
29 | case .custom(let description): return description
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/ScoutCLT/Models/ValidationError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | struct ValidationError: LocalizedError {
9 |
10 | var message: String
11 |
12 | var errorDescription: String? { message }
13 | }
14 |
--------------------------------------------------------------------------------
/Sources/ScoutCLTCore/Extensions/Collection+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension Collection where Element: Hashable {
9 |
10 | /// Find a duplicate in the collection.
11 | ///
12 | /// ### Complexity
13 | /// `O(n)`
14 | func duplicate() -> Element? {
15 | var foundElements: Set = []
16 |
17 | for element in self {
18 | if foundElements.contains(element) {
19 | return element
20 | } else {
21 | foundElements.insert(element)
22 | }
23 | }
24 | return nil
25 | }
26 | }
27 |
28 | extension Dictionary where Key: Hashable {
29 |
30 | /// Find a duplicate in the collection.
31 | ///
32 | /// ### Complexity
33 | /// `O(n)`
34 | func duplicateKey() -> Key? {
35 | var foundElements: Set = []
36 |
37 | for element in self {
38 | if foundElements.contains(element.key) {
39 | return element.key
40 | } else {
41 | foundElements.insert(element.key)
42 | }
43 | }
44 | return nil
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/Sources/ScoutCLTCore/Extensions/ExplorerValue+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 | import Scout
8 |
9 | extension ExplorerValue {
10 |
11 | init(fromSingle string: String) {
12 | if let int = Int(string) {
13 | self = .int(int)
14 | } else if let double = Double(string) {
15 | self = .double(double)
16 | } else if let bool = Bool(string) {
17 | self = .bool(bool)
18 | } else {
19 | self = .string(string)
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/ScoutCLTCore/Extensions/URL+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension URL {
9 |
10 | var lastPathComponentWithoutExtension: String {
11 | let splitted = lastPathComponent.split(separator: ".")
12 |
13 | guard splitted.count > 1 else {
14 | return lastPathComponent
15 | }
16 |
17 | return String(splitted[splitted .count - 2])
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Sources/ScoutCLTCore/Models/CLTCoreError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | public enum CLTCoreError: LocalizedError {
9 |
10 | case exportConflict
11 | case valueConversion(value: String, type: String)
12 | case wrongUsage(String)
13 |
14 | public var errorDescription: String? {
15 | switch self {
16 | case .exportConflict: return "Ambiguous export specification. '--csv-exp' and --export-format' cannot be used simultaneously"
17 | case .valueConversion(let value, let type): return "The value '\(value)' is not convertible to \(type)"
18 | case .wrongUsage(let description): return description
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/ScoutCLTCore/Models/ExportCommand.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 | import Scout
8 |
9 | public enum Export: Equatable {
10 | case noExport
11 | case csv(separator: String)
12 | case dataFormat(format: DataFormat)
13 | case array
14 | case dictionary
15 | }
16 |
17 | public protocol ExportCommand {
18 | var csvSeparator: String? { get }
19 | var exportFormat: ExportFormat? { get }
20 | }
21 |
22 | public extension ExportCommand {
23 |
24 | /// Returns the export option specified depending on several inputs: csv, data format, Zsh group values
25 | func exportOption() throws -> Export {
26 | switch (csvSeparator, exportFormat) {
27 | case (let separator?, nil): return .csv(separator: separator)
28 | case (nil, let format?):
29 | switch format {
30 | case .array: return .array
31 | case .dictionary: return .dictionary
32 | case .json: return .dataFormat(format: .json)
33 | case .plist: return .dataFormat(format: .plist)
34 | case .yaml: return .dataFormat(format: .yaml)
35 | case .xml: return .dataFormat(format: .xml)
36 | }
37 | case (nil, nil): return .noExport
38 | case (.some, .some): throw CLTCoreError.exportConflict
39 | }
40 | }
41 |
42 | /// Get the file name of the file path
43 | func fileName(of filePath: String?) -> String? {
44 | guard let filePath = filePath else { return nil }
45 | return URL(fileURLWithPath: filePath).lastPathComponentWithoutExtension
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Sources/ScoutCLTCore/Models/ExportFormat.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Scout
7 |
8 | /// Models the value the export process can take
9 | public enum ExportFormat: String, CaseIterable, Equatable {
10 | case json, plist, yaml, xml, array, dictionary
11 | }
12 |
--------------------------------------------------------------------------------
/Sources/ScoutCLTCore/Models/GroupExportValue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 | import Scout
8 |
9 | /// Type serving only the purpose to map dictionaries or arrays
10 | /// returned by a `PathExplorer` to a `String` value.
11 | public struct GroupExportValue: ExplorerValueCreatable {
12 |
13 | public let value: String
14 |
15 | /// - throws: if the value is not single.
16 | public init(from explorerValue: ExplorerValue) throws {
17 | switch explorerValue {
18 | case .string(let string): value = string
19 | case .int(let int): value = int.description
20 | case .double(let double): value = double.description
21 | case .bool(let bool): value = bool.description
22 | case .data(let data): value = data.base64EncodedString()
23 | case .date(let date): value = date.description
24 | case .dictionary: throw CLTCoreError.wrongUsage("Trying to export a dictionary of values that are not single")
25 | case .array: throw CLTCoreError.wrongUsage("Trying to export an array of values that are not single")
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/ScoutCLTCore/Models/PathAndValue.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | import Scout
7 |
8 | /// Represents a reading path and an associated value, like `path.component[0]=value`.
9 | ///
10 | /// ### Forcing a type
11 | /// The `value` property can be forced to be a string or a double when the automatic type inferring will return another type.
12 | /// For instance with "123", the value will be treated as an `Int`, so specifying `string` rather than `automatic` prevents that.
13 | ///
14 | public struct PathAndValue {
15 |
16 | // MARK: - Properties
17 |
18 | public let readingPath: Path
19 | public let value: ValueType
20 |
21 | public init?(string: String) {
22 | guard
23 | let result = Self.parser.run(string)
24 | else { return nil }
25 |
26 | if let error = result.result.value.firstError {
27 | print("An error occurred while parsing the argument '\(string)'")
28 | print(error)
29 | return nil
30 | }
31 |
32 | guard result.remainder.isEmpty else {
33 | return nil
34 | }
35 |
36 | readingPath = Path(elements: result.result.pathElements)
37 | value = result.result.value
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Tests/ScoutCLTCoreTests/ExportCommandTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) Alexis Bridoux 2020
4 | // MIT license, see LICENSE file for details
5 |
6 | import XCTest
7 | import Scout
8 | import ScoutCLTCore
9 |
10 | final class ExportCommandTests: XCTestCase {
11 |
12 | func testExportCSVSeparator() throws {
13 | var command = StubCommand()
14 | command.csvSeparator = "/"
15 |
16 | XCTAssertEqual(try command.exportOption(), .csv(separator: "/"))
17 | }
18 |
19 | func testExportDataFormat() throws {
20 | var command = StubCommand()
21 | command.exportFormat = .plist
22 |
23 | XCTAssertEqual(try command.exportOption(), .dataFormat(format: .plist))
24 | }
25 |
26 | func testExportCSVAndDataFormatThrows() throws {
27 | var command = StubCommand()
28 | command.csvSeparator = ";"
29 | command.exportFormat = .plist
30 |
31 | XCTAssertThrowsError(try command.exportOption())
32 | }
33 | }
34 |
35 | extension ExportCommandTests {
36 |
37 | struct StubCommand: ExportCommand {
38 | var csvSeparator: String?
39 | var exportFormat: ExportFormat?
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Tests/ScoutTests/Definitions/Path/PathTests+Miscellaneous.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) Alexis Bridoux 2020
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 | import Scout
8 | import XCTest
9 |
10 | final class PathMiscellanousTests: XCTestCase {
11 |
12 | func testCommonPrefix_Middle() {
13 | let path = Path(elements: "toto", 1, "Endo", .count)
14 | let otherPath = Path(elements: "toto", 1, "Endo")
15 |
16 | let intersection = path.commonPrefix(with: otherPath)
17 |
18 | XCTAssertEqual(Path(path[0...2]), Path(intersection))
19 | }
20 |
21 | func testCommonPrefix_Empty() {
22 | let path = Path(elements: "toto", 1, "Endo", .count)
23 | let otherPath = Path(elements: "Riri", "Fifi", "Loulou")
24 |
25 | let intersection = path.commonPrefix(with: otherPath)
26 |
27 | XCTAssertEqual(Path.empty, Path(intersection))
28 | }
29 |
30 | func testCommonPrefix_All() {
31 | let path = Path(elements: "toto", 1, "Endo", .count)
32 | let otherPath = Path(elements: "toto", 1, "Endo", .count)
33 |
34 | let intersection = path.commonPrefix(with: otherPath)
35 |
36 | XCTAssertEqual(path, Path(intersection))
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Tests/ScoutTests/ExplorerXML/PathExplorerXMLTests+COW.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) Alexis Bridoux 2020
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 | import AEXML
8 | @testable import Scout
9 | import XCTest
10 |
11 | final class ExplorerXMLCOWTests: XCTestCase {
12 |
13 | func testSet() throws {
14 | let explorer = ExplorerXML(value: ["Endo": true, "Toto": 20])
15 | var copy = explorer
16 |
17 | try copy.set("Endo", to: false)
18 |
19 | XCTAssertEqual(explorer.explorerValue(), ["Endo": true, "Toto": 20])
20 | XCTAssertEqual(copy.explorerValue(), ["Endo": false, "Toto": 20])
21 | }
22 |
23 | func testDelete() throws {
24 | let explorer = ExplorerXML(value: ["Endo": true, "Toto": 20])
25 | var copy = explorer
26 |
27 | try copy.delete("Toto")
28 |
29 | XCTAssertEqual(explorer.explorerValue(), ["Endo": true, "Toto": 20])
30 | try XCTAssertEqual(copy.dictionary(of: Bool.self), ["Endo": true])
31 | }
32 |
33 | func testAdd() throws {
34 | let explorer = ExplorerXML(value: ["Endo": true, "Toto": 20])
35 | var copy = explorer
36 |
37 | try copy.add("Riri", at: "duck")
38 |
39 | XCTAssertEqual(explorer.explorerValue(), ["Endo": true, "Toto": 20])
40 | XCTAssertEqual(copy.explorerValue(), ["Endo": true, "Toto": 20, "duck": "Riri"])
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Tests/ScoutTests/Extensions/PathExplorers+Alias.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) Alexis Bridoux 2020
4 | // MIT license, see LICENSE file for details
5 |
6 | import Scout
7 |
8 | typealias Xml = PathExplorers.Xml
9 | typealias Json = PathExplorers.Json
10 | typealias Plist = PathExplorers.Plist
11 | typealias Yaml = PathExplorers.Yaml
12 |
--------------------------------------------------------------------------------
/Tests/ScoutTests/Extensions/URL+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) Alexis Bridoux 2020
4 | // MIT license, see LICENSE file for details
5 |
6 | import Foundation
7 |
8 | extension URL {
9 |
10 | private static let peopleURL: URL = {
11 | /**https://stackoverflow.com/questions/57555856/get-url-to-a-local-file-with-spm-swift-package-manager/57708634#57708634 */
12 | let currentFileURL = URL(fileURLWithPath: "\(#file)", isDirectory: false)
13 | return currentFileURL
14 | .deletingLastPathComponent()
15 | .deletingLastPathComponent()
16 | .deletingLastPathComponent()
17 | .deletingLastPathComponent()
18 | .appendingPathComponent("Playground", isDirectory: true)
19 | .appendingPathComponent("People")
20 | }()
21 |
22 | static let peopleJson: URL = { Self.peopleURL.appendingPathExtension("json") }()
23 | static let peoplePlist: URL = { Self.peopleURL.appendingPathExtension("plist") }()
24 | static let peopleXml: URL = { Self.peopleURL.appendingPathExtension("xml") }()
25 | }
26 |
--------------------------------------------------------------------------------
/Tests/ScoutTests/Extensions/XCTestCase+Extensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) Alexis Bridoux 2020
4 | // MIT license, see LICENSE file for details
5 |
6 | import XCTest
7 | @testable import Scout
8 |
9 | extension XCTestCase {
10 |
11 | func XCTAssertErrorsEqual(_ expression: @autoclosure () throws -> T,
12 | _ expectedError: ExplorerError,
13 | file: StaticString = #file, line: UInt = #line) {
14 | XCTAssertThrowsError(
15 | _ = try expression(), "", file: file, line: line) { error in
16 | guard
17 | let resultPathExplorerError = error as? ExplorerError,
18 | resultPathExplorerError == expectedError
19 | else {
20 | XCTFail("The expression did not throw the error \(expectedError). Error thrown: \(error)", file: file, line: line)
21 | return
22 | }
23 | }
24 | }
25 |
26 | func XCTAssertExplorersEqual(
27 | _ p1: @autoclosure () throws -> P,
28 | _ p2: @autoclosure () throws -> P,
29 | file: StaticString = #file, line: UInt = #line) rethrows {
30 | let p1 = try p1()
31 | let p2 = try p2()
32 |
33 | XCTAssertTrue(p1.isEqual(to: p2), "\(p1) not equal to \(p2)", file: file, line: line)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Tests/ScoutTests/ExtensionsTests/ArrayTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) Alexis Bridoux 2020
4 | // MIT license, see LICENSE file for details
5 |
6 | import XCTest
7 | @testable import Scout
8 |
9 | final class ArrayExtensionsTests: XCTestCase {}
10 |
11 | // MARK: - Delete range
12 |
13 | extension ArrayExtensionsTests {
14 |
15 | // MARK: Stubs
16 |
17 | var stubArray: [String] { ["Riri", "Fifi", "Loulou", "Scrooge", "Donald", "Daisy"] }
18 |
19 | // MARK: Tests
20 |
21 | func testDeleteRange1() throws {
22 | let range = 2...4
23 |
24 | XCTAssertEqual(stubArray.remove(in: range), ["Riri", "Fifi", "Daisy"])
25 | }
26 |
27 | func testDeleteRange2() throws {
28 | let range = 2...5
29 |
30 | XCTAssertEqual(stubArray.remove(in: range), ["Riri", "Fifi"])
31 | }
32 |
33 | func testDeleteRange3() throws {
34 | let range = 0...3
35 |
36 | XCTAssertEqual(stubArray.remove(in: range), ["Donald", "Daisy"])
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/Tests/ScoutTests/ExtensionsTests/NSRegularExpressionExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) Alexis Bridoux 2020
4 | // MIT license, see LICENSE file for details
5 |
6 | import XCTest
7 | @testable import Scout
8 |
9 | final class NSRegularExpressionExtensionsTests: XCTestCase {
10 |
11 | func testValidate1() throws {
12 | let pattern = "[0-9]+"
13 | let regex = try NSRegularExpression(pattern: pattern)
14 |
15 | XCTAssertTrue(regex.validate("1234"))
16 | XCTAssertFalse(regex.validate("123A4"))
17 | }
18 |
19 | func testValidate2() throws {
20 | let pattern = #"[a-zA-Z]+\s+[0-9]+"#
21 | let regex = try NSRegularExpression(pattern: pattern)
22 |
23 | XCTAssertTrue(regex.validate("John 117"))
24 | XCTAssertFalse(regex.validate("Arbiter"))
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Tests/ScoutTests/ExtensionsTests/PathExplorerHelperTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) 2020-present Alexis Bridoux
4 | // MIT license, see LICENSE file for details
5 |
6 | @testable import Scout
7 | import XCTest
8 |
9 | final class PathExplorerHelpersTest: XCTestCase {
10 |
11 | func testComputeIndex_PositiveIndex() throws {
12 | let result = try PathExplorers.Json.computeIndex(from: 5, arrayCount: 10)
13 |
14 | XCTAssertEqual(result, 5)
15 | }
16 |
17 | func testComputeIndex_NegativeIndex() throws {
18 | let result = try PathExplorers.Json.computeIndex(from: -3, arrayCount: 10)
19 |
20 | XCTAssertEqual(result, 7)
21 | }
22 |
23 | func testComputeIndex_EmptyArray_PositiveIndexThrows() throws {
24 | XCTAssertErrorsEqual(try PathExplorers.Json.computeIndex(from: 1, arrayCount: 0),
25 | .wrong(index: 1, arrayCount: 0))
26 | }
27 |
28 | func testComputeIndex_EmptyArray_NegativeIndexThrows() throws {
29 | XCTAssertErrorsEqual(try PathExplorers.Json.computeIndex(from: -1, arrayCount: 0),
30 | .wrong(index: -1, arrayCount: 0))
31 | }
32 |
33 | func testComputeIndex_EmptyArray_ZeroIndexThrows() throws {
34 | XCTAssertErrorsEqual(try PathExplorers.Json.computeIndex(from: 0, arrayCount: 0),
35 | .wrong(index: 0, arrayCount: 0))
36 | }
37 |
38 | func testComputeIndex_SingleElementArray_PositiveIndexThrows() throws {
39 | XCTAssertErrorsEqual(try PathExplorers.Json.computeIndex(from: 1, arrayCount: 1),
40 | .wrong(index: 1, arrayCount: 1))
41 | }
42 |
43 | func testComputeIndex_SingleElementArray_NegativeIndex() throws {
44 | let result = try PathExplorers.Json.computeIndex(from: -1, arrayCount: 1)
45 |
46 | XCTAssertEqual(result, 0)
47 | }
48 |
49 | func testComputeIndex_OutOfBounds_PositiveIndexThrows() throws {
50 | XCTAssertErrorsEqual(try PathExplorers.Json.computeIndex(from: 5, arrayCount: 4),
51 | .wrong(index: 5, arrayCount: 4))
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/Tests/ScoutTests/ExtensionsTests/String+Jaro-WinklerTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) Alexis Bridoux 2020
4 | // MIT license, see LICENSE file for details
5 |
6 | import XCTest
7 | @testable import Scout
8 |
9 | final class String_JaroWinklerTests: XCTestCase {
10 |
11 | let target = "verson"
12 | let propositions: Set = ["tag", "date", "name", "owner", "release", "version", "forest", "mouse", "versionning"]
13 |
14 | func testMartha() {
15 | let distance = "MARTHA".jaroWinklerDistance(from: "MARHTA")
16 |
17 | XCTAssertEqual(distance, 0.961, accuracy: 0.3)
18 | }
19 |
20 | func testDWAYNE() {
21 | let distance = "DWAYNE".jaroWinklerDistance(from: "DUANE")
22 |
23 | XCTAssertEqual(distance, 0.84, accuracy: 0.3)
24 | }
25 |
26 | func testDIXON() {
27 | let distance = "DIXON".jaroWinklerDistance(from: "DICKSONX")
28 |
29 | XCTAssertEqual(distance, 0.813, accuracy: 0.3)
30 | }
31 |
32 | func testBestMatch() {
33 | let result = target.bestJaroWinklerMatchIn(propositions: propositions)
34 | XCTAssertEqual(result, "version")
35 | }
36 |
37 | func testMatchSingleCharacters_Equals0() {
38 | let result = "b".jaroWinklerDistance(from: "a")
39 | XCTAssertEqual(result, 0)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Tests/ScoutTests/ExtensionsTests/StringExtensionsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) Alexis Bridoux 2020
4 | // MIT license, see LICENSE file for details
5 |
6 | import XCTest
7 | @testable import Scout
8 |
9 | final class StringExtensionsTests: XCTestCase {
10 |
11 | func testEscape1() {
12 | let string = "Hello, there"
13 | XCTAssertEqual(#""Hello, there""#, string.escapingCSV(","))
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Tests/ScoutTests/Models/PathsFilterTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Scout
3 | // Copyright (c) Alexis Bridoux 2020
4 | // MIT license, see LICENSE file for details
5 |
6 | import XCTest
7 | @testable import Scout
8 |
9 | final class PathsFilterTests: XCTestCase {
10 |
11 | func testPredicateMismatchedTypes() throws {
12 | let predicate = try PathsFilter.ExpressionPredicate(format: "value > 10")
13 |
14 | _ = try predicate.evaluate(with: "yo")
15 |
16 | XCTAssertEqual(predicate.operatorsValueTypes, Set(arrayLiteral: .double))
17 | }
18 |
19 | func testPredicateMismatchedTypesReturnsFalse() throws {
20 | let predicate = try PathsFilter.ExpressionPredicate(format: "value > 10")
21 |
22 | XCTAssertFalse(try predicate.evaluate(with: "yo"))
23 | }
24 |
25 | func testPredicateValueTypes() throws {
26 | let predicate = try PathsFilter.ExpressionPredicate(format: "!(value hasPrefix 'yo')")
27 |
28 | XCTAssertFalse(try predicate.evaluate(with: 10))
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | ignore:
3 | - "Tests"
--------------------------------------------------------------------------------
/docs/css/documentation-topic~topic.b6287bcf.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * This source file is part of the Swift.org open source project
3 | *
4 | * Copyright (c) 2021 Apple Inc. and the Swift project authors
5 | * Licensed under Apache License v2.0 with Runtime Library Exception
6 | *
7 | * See https://swift.org/LICENSE.txt for license information
8 | * See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9 | */.generic-modal[data-v-795f7b59]{position:fixed;top:0;left:0;right:0;bottom:0;margin:0;z-index:11000;display:flex;align-items:center;justify-content:center;flex-wrap:wrap;background:none;overflow:auto}.modal-fullscreen[data-v-795f7b59]{align-items:stretch}.modal-fullscreen .container[data-v-795f7b59]{margin:0;flex:1;width:100%;height:100%;padding-top:env(safe-area-inset-top);padding-right:env(safe-area-inset-right);padding-bottom:env(safe-area-inset-bottom);padding-left:env(safe-area-inset-left)}.modal-standard[data-v-795f7b59]{padding:20px}.modal-standard .container[data-v-795f7b59]{padding:60px;border-radius:var(--border-radius,4px)}@media screen{[data-color-scheme=dark] .modal-standard .container[data-v-795f7b59]{background:#1d1d1f}}@media screen and (prefers-color-scheme:dark){[data-color-scheme=auto] .modal-standard .container[data-v-795f7b59]{background:#1d1d1f}}@media only screen and (max-width:735px){.modal-standard[data-v-795f7b59]{padding:0;align-items:stretch}.modal-standard .container[data-v-795f7b59]{margin:20px 0 0;padding:50px 30px;flex:1;width:100%;border-bottom-left-radius:0;border-bottom-right-radius:0}}.backdrop[data-v-795f7b59]{overflow:auto;background:var(--backdrop-background,rgba(0,0,0,.4));-webkit-overflow-scrolling:touch;width:100%;height:100%;position:fixed}.container[data-v-795f7b59]{margin-left:auto;margin-right:auto;width:980px;background:var(--colors-generic-modal-background,var(--color-generic-modal-background));z-index:1;position:relative;overflow:auto;max-width:100%}@media only screen and (max-width:1250px){.container[data-v-795f7b59]{width:692px}}@media only screen and (max-width:735px){.container[data-v-795f7b59]{width:87.5%}}@media only screen and (max-width:320px){.container[data-v-795f7b59]{width:215px}}.close[data-v-795f7b59]{position:absolute;z-index:9999;top:22px;left:22px;width:17px;height:17px;color:#666;cursor:pointer;background:none;border:0;display:flex;align-items:center}.close .close-icon[data-v-795f7b59]{fill:currentColor;width:100%;height:100%}.theme-dark .container[data-v-795f7b59]{background:#000}.theme-dark .container .close[data-v-795f7b59]{color:#b0b0b0}.theme-code .container[data-v-795f7b59]{background-color:var(--code-background,var(--color-code-background))}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/bounds/equatable-implementations.json:
--------------------------------------------------------------------------------
1 | {"sections":[],"metadata":{"modules":[{"name":"Scout"}],"title":"Equatable Implementations","role":"collectionGroup"},"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/Bounds\/Equatable-Implementations"},"kind":"article","hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/Bounds"]]},"variants":[{"paths":["\/documentation\/scout\/bounds\/equatable-implementations"],"traits":[{"interfaceLanguage":"swift"}]}],"topicSections":[{"generated":true,"title":"Operators","identifiers":["doc:\/\/Scout\/documentation\/Scout\/Bounds\/!=(_:_:)"]}],"schemaVersion":{"patch":0,"major":0,"minor":3},"references":{"doc://Scout/documentation/Scout/Bounds":{"abstract":[{"type":"text","text":"Lower and upper bounds to be used to slice an array"}],"type":"topic","url":"\/documentation\/scout\/bounds","role":"symbol","kind":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/Bounds","title":"Bounds","fragments":[{"text":"struct","kind":"keyword"},{"text":" ","kind":"text"},{"kind":"identifier","text":"Bounds"}],"navigatorTitle":[{"kind":"identifier","text":"Bounds"}]},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/Bounds/!=(_:_:)":{"identifier":"doc:\/\/Scout\/documentation\/Scout\/Bounds\/!=(_:_:)","role":"symbol","title":"!=(_:_:)","abstract":[],"fragments":[{"kind":"keyword","text":"static"},{"text":" ","kind":"text"},{"text":"func","kind":"keyword"},{"text":" ","kind":"text"},{"text":"!=","kind":"identifier"},{"text":" ","kind":"text"},{"kind":"text","text":"("},{"kind":"typeIdentifier","text":"Self"},{"text":", ","kind":"text"},{"text":"Self","kind":"typeIdentifier"},{"text":") -> ","kind":"text"},{"text":"Bool","kind":"typeIdentifier","preciseIdentifier":"s:Sb"}],"type":"topic","kind":"symbol","url":"\/documentation\/scout\/bounds\/!=(_:_:)"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/dataformat/equatable-implementations.json:
--------------------------------------------------------------------------------
1 | {"schemaVersion":{"major":0,"minor":3,"patch":0},"metadata":{"role":"collectionGroup","modules":[{"name":"Scout"}],"title":"Equatable Implementations"},"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/DataFormat"]]},"topicSections":[{"title":"Operators","identifiers":["doc:\/\/Scout\/documentation\/Scout\/DataFormat\/!=(_:_:)"],"generated":true}],"kind":"article","identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/DataFormat\/Equatable-Implementations"},"sections":[],"variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/dataformat\/equatable-implementations"]}],"references":{"doc://Scout/documentation/Scout/DataFormat":{"navigatorTitle":[{"kind":"identifier","text":"DataFormat"}],"type":"topic","fragments":[{"text":"enum","kind":"keyword"},{"kind":"text","text":" "},{"kind":"identifier","text":"DataFormat"}],"title":"DataFormat","abstract":[{"type":"text","text":"Unique identifier of a data format"}],"kind":"symbol","url":"\/documentation\/scout\/dataformat","role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/DataFormat"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/DataFormat/!=(_:_:)":{"abstract":[],"type":"topic","kind":"symbol","fragments":[{"text":"static","kind":"keyword"},{"kind":"text","text":" "},{"text":"func","kind":"keyword"},{"kind":"text","text":" "},{"text":"!=","kind":"identifier"},{"text":" ","kind":"text"},{"kind":"text","text":"("},{"text":"Self","kind":"typeIdentifier"},{"text":", ","kind":"text"},{"text":"Self","kind":"typeIdentifier"},{"text":") -> ","kind":"text"},{"preciseIdentifier":"s:Sb","text":"Bool","kind":"typeIdentifier"}],"identifier":"doc:\/\/Scout\/documentation\/Scout\/DataFormat\/!=(_:_:)","url":"\/documentation\/scout\/dataformat\/!=(_:_:)","title":"!=(_:_:)","role":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/dataformat/json.json:
--------------------------------------------------------------------------------
1 | {"metadata":{"roleHeading":"Case","role":"symbol","title":"DataFormat.json","externalID":"s:5Scout10DataFormatO4jsonyA2CmF","fragments":[{"text":"case","kind":"keyword"},{"text":" ","kind":"text"},{"kind":"identifier","text":"json"}],"modules":[{"name":"Scout"}],"symbolKind":"case"},"sections":[],"primaryContentSections":[{"declarations":[{"tokens":[{"text":"case","kind":"keyword"},{"kind":"text","text":" "},{"kind":"identifier","text":"json"}],"languages":["swift"],"platforms":["macOS"]}],"kind":"declarations"}],"variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/dataformat\/json"]}],"identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/DataFormat\/json","interfaceLanguage":"swift"},"schemaVersion":{"major":0,"minor":3,"patch":0},"kind":"symbol","hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/DataFormat"]]},"references":{"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/DataFormat/json":{"role":"symbol","title":"DataFormat.json","abstract":[],"fragments":[{"text":"case","kind":"keyword"},{"text":" ","kind":"text"},{"kind":"identifier","text":"json"}],"kind":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/DataFormat\/json","type":"topic","url":"\/documentation\/scout\/dataformat\/json"},"doc://Scout/documentation/Scout/DataFormat":{"navigatorTitle":[{"kind":"identifier","text":"DataFormat"}],"type":"topic","fragments":[{"text":"enum","kind":"keyword"},{"kind":"text","text":" "},{"kind":"identifier","text":"DataFormat"}],"title":"DataFormat","abstract":[{"type":"text","text":"Unique identifier of a data format"}],"kind":"symbol","url":"\/documentation\/scout\/dataformat","role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/DataFormat"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/dataformat/plist.json:
--------------------------------------------------------------------------------
1 | {"primaryContentSections":[{"declarations":[{"tokens":[{"kind":"keyword","text":"case"},{"kind":"text","text":" "},{"text":"plist","kind":"identifier"}],"languages":["swift"],"platforms":["macOS"]}],"kind":"declarations"}],"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/DataFormat"]]},"variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/dataformat\/plist"]}],"schemaVersion":{"minor":3,"major":0,"patch":0},"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/DataFormat\/plist"},"kind":"symbol","sections":[],"metadata":{"externalID":"s:5Scout10DataFormatO5plistyA2CmF","role":"symbol","modules":[{"name":"Scout"}],"roleHeading":"Case","title":"DataFormat.plist","symbolKind":"case","fragments":[{"kind":"keyword","text":"case"},{"kind":"text","text":" "},{"text":"plist","kind":"identifier"}]},"references":{"doc://Scout/documentation/Scout/DataFormat/plist":{"url":"\/documentation\/scout\/dataformat\/plist","fragments":[{"text":"case","kind":"keyword"},{"kind":"text","text":" "},{"kind":"identifier","text":"plist"}],"identifier":"doc:\/\/Scout\/documentation\/Scout\/DataFormat\/plist","kind":"symbol","title":"DataFormat.plist","abstract":[],"role":"symbol","type":"topic"},"doc://Scout/documentation/Scout/DataFormat":{"navigatorTitle":[{"kind":"identifier","text":"DataFormat"}],"type":"topic","fragments":[{"text":"enum","kind":"keyword"},{"kind":"text","text":" "},{"kind":"identifier","text":"DataFormat"}],"title":"DataFormat","abstract":[{"type":"text","text":"Unique identifier of a data format"}],"kind":"symbol","url":"\/documentation\/scout\/dataformat","role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/DataFormat"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/dataformat/xml.json:
--------------------------------------------------------------------------------
1 | {"identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/DataFormat\/xml","interfaceLanguage":"swift"},"kind":"symbol","sections":[],"primaryContentSections":[{"declarations":[{"languages":["swift"],"tokens":[{"text":"case","kind":"keyword"},{"text":" ","kind":"text"},{"text":"xml","kind":"identifier"}],"platforms":["macOS"]}],"kind":"declarations"}],"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/DataFormat"]]},"schemaVersion":{"minor":3,"major":0,"patch":0},"variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/dataformat\/xml"]}],"metadata":{"roleHeading":"Case","title":"DataFormat.xml","modules":[{"name":"Scout"}],"symbolKind":"case","role":"symbol","externalID":"s:5Scout10DataFormatO3xmlyA2CmF","fragments":[{"text":"case","kind":"keyword"},{"text":" ","kind":"text"},{"kind":"identifier","text":"xml"}]},"references":{"doc://Scout/documentation/Scout/DataFormat":{"navigatorTitle":[{"kind":"identifier","text":"DataFormat"}],"type":"topic","fragments":[{"text":"enum","kind":"keyword"},{"kind":"text","text":" "},{"kind":"identifier","text":"DataFormat"}],"title":"DataFormat","abstract":[{"type":"text","text":"Unique identifier of a data format"}],"kind":"symbol","url":"\/documentation\/scout\/dataformat","role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/DataFormat"},"doc://Scout/documentation/Scout/DataFormat/xml":{"url":"\/documentation\/scout\/dataformat\/xml","type":"topic","title":"DataFormat.xml","identifier":"doc:\/\/Scout\/documentation\/Scout\/DataFormat\/xml","role":"symbol","kind":"symbol","abstract":[],"fragments":[{"kind":"keyword","text":"case"},{"text":" ","kind":"text"},{"text":"xml","kind":"identifier"}]},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/dataformat/yaml.json:
--------------------------------------------------------------------------------
1 | {"sections":[],"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/DataFormat"]]},"schemaVersion":{"patch":0,"major":0,"minor":3},"kind":"symbol","metadata":{"role":"symbol","externalID":"s:5Scout10DataFormatO4yamlyA2CmF","roleHeading":"Case","modules":[{"name":"Scout"}],"fragments":[{"text":"case","kind":"keyword"},{"kind":"text","text":" "},{"kind":"identifier","text":"yaml"}],"symbolKind":"case","title":"DataFormat.yaml"},"primaryContentSections":[{"declarations":[{"languages":["swift"],"tokens":[{"kind":"keyword","text":"case"},{"text":" ","kind":"text"},{"kind":"identifier","text":"yaml"}],"platforms":["macOS"]}],"kind":"declarations"}],"identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/DataFormat\/yaml","interfaceLanguage":"swift"},"variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/dataformat\/yaml"]}],"references":{"doc://Scout/documentation/Scout/DataFormat/yaml":{"kind":"symbol","role":"symbol","type":"topic","fragments":[{"text":"case","kind":"keyword"},{"kind":"text","text":" "},{"text":"yaml","kind":"identifier"}],"url":"\/documentation\/scout\/dataformat\/yaml","abstract":[],"identifier":"doc:\/\/Scout\/documentation\/Scout\/DataFormat\/yaml","title":"DataFormat.yaml"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/DataFormat":{"navigatorTitle":[{"kind":"identifier","text":"DataFormat"}],"type":"topic","fragments":[{"text":"enum","kind":"keyword"},{"kind":"text","text":" "},{"kind":"identifier","text":"DataFormat"}],"title":"DataFormat","abstract":[{"type":"text","text":"Unique identifier of a data format"}],"kind":"symbol","url":"\/documentation\/scout\/dataformat","role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/DataFormat"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/bool(_:).json:
--------------------------------------------------------------------------------
1 | {"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/bool(_:)"},"schemaVersion":{"major":0,"patch":0,"minor":3},"sections":[],"kind":"symbol","primaryContentSections":[{"declarations":[{"languages":["swift"],"platforms":["macOS"],"tokens":[{"text":"case","kind":"keyword"},{"text":" ","kind":"text"},{"kind":"identifier","text":"bool"},{"kind":"text","text":"("},{"preciseIdentifier":"s:Sb","text":"Bool","kind":"typeIdentifier"},{"kind":"text","text":")"}]}],"kind":"declarations"}],"variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/explorervalue\/bool(_:)"]}],"metadata":{"modules":[{"name":"Scout"}],"roleHeading":"Case","symbolKind":"case","title":"ExplorerValue.bool(_:)","externalID":"s:5Scout13ExplorerValueO4boolyACSbcACmF","role":"symbol","fragments":[{"text":"case","kind":"keyword"},{"text":" ","kind":"text"},{"text":"bool","kind":"identifier"},{"text":"(","kind":"text"},{"preciseIdentifier":"s:Sb","text":"Bool","kind":"typeIdentifier"},{"kind":"text","text":")"}]},"references":{"doc://Scout/documentation/Scout/ExplorerValue/bool(_:)":{"title":"ExplorerValue.bool(_:)","url":"\/documentation\/scout\/explorervalue\/bool(_:)","type":"topic","abstract":[],"kind":"symbol","role":"symbol","fragments":[{"kind":"keyword","text":"case"},{"text":" ","kind":"text"},{"text":"bool","kind":"identifier"},{"text":"(","kind":"text"},{"text":"Bool","kind":"typeIdentifier","preciseIdentifier":"s:Sb"},{"text":")","kind":"text"}],"identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/bool(_:)"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/customdebugstringconvertible-implementations.json:
--------------------------------------------------------------------------------
1 | {"topicSections":[{"identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/debugDescription"],"title":"Instance Properties","generated":true}],"metadata":{"modules":[{"name":"Scout"}],"title":"CustomDebugStringConvertible Implementations","role":"collectionGroup"},"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/CustomDebugStringConvertible-Implementations"},"schemaVersion":{"minor":3,"patch":0,"major":0},"variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/explorervalue\/customdebugstringconvertible-implementations"]}],"kind":"article","hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"sections":[],"references":{"doc://Scout/documentation/Scout/ExplorerValue/debugDescription":{"kind":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/debugDescription","role":"symbol","fragments":[{"text":"var","kind":"keyword"},{"text":" ","kind":"text"},{"kind":"identifier","text":"debugDescription"},{"kind":"text","text":": "},{"preciseIdentifier":"s:SS","kind":"typeIdentifier","text":"String"}],"title":"debugDescription","type":"topic","url":"\/documentation\/scout\/explorervalue\/debugdescription","abstract":[]},"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/customstringconvertible-implementations.json:
--------------------------------------------------------------------------------
1 | {"topicSections":[{"generated":true,"title":"Instance Properties","identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/description"]}],"metadata":{"modules":[{"name":"Scout"}],"title":"CustomStringConvertible Implementations","role":"collectionGroup"},"sections":[],"schemaVersion":{"patch":0,"major":0,"minor":3},"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/CustomStringConvertible-Implementations"},"variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/explorervalue\/customstringconvertible-implementations"]}],"kind":"article","references":{"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"},"doc://Scout/documentation/Scout/ExplorerValue/description":{"type":"topic","url":"\/documentation\/scout\/explorervalue\/description","role":"symbol","abstract":[],"fragments":[{"text":"var","kind":"keyword"},{"kind":"text","text":" "},{"text":"description","kind":"identifier"},{"kind":"text","text":": "},{"kind":"typeIdentifier","preciseIdentifier":"s:SS","text":"String"}],"identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/description","title":"description","kind":"symbol"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/decodable-implementations.json:
--------------------------------------------------------------------------------
1 | {"schemaVersion":{"minor":3,"patch":0,"major":0},"metadata":{"title":"Decodable Implementations","modules":[{"name":"Scout"}],"role":"collectionGroup"},"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"sections":[],"kind":"article","topicSections":[{"generated":true,"identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(from:)"],"title":"Initializers"}],"identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/Decodable-Implementations","interfaceLanguage":"swift"},"variants":[{"paths":["\/documentation\/scout\/explorervalue\/decodable-implementations"],"traits":[{"interfaceLanguage":"swift"}]}],"references":{"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/ExplorerValue/init(from:)":{"title":"init(from:)","url":"\/documentation\/scout\/explorervalue\/init(from:)","fragments":[{"text":"init","kind":"identifier"},{"text":"(","kind":"text"},{"text":"from","kind":"externalParam"},{"text":": ","kind":"text"},{"text":"Decoder","preciseIdentifier":"s:s7DecoderP","kind":"typeIdentifier"},{"kind":"text","text":") "},{"kind":"keyword","text":"throws"}],"role":"symbol","abstract":[],"type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(from:)","kind":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/encodable-implementations.json:
--------------------------------------------------------------------------------
1 | {"metadata":{"title":"Encodable Implementations","role":"collectionGroup","modules":[{"name":"Scout"}]},"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"sections":[],"topicSections":[{"identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/encode(to:)"],"generated":true,"title":"Instance Methods"}],"schemaVersion":{"minor":3,"patch":0,"major":0},"kind":"article","identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/Encodable-Implementations","interfaceLanguage":"swift"},"variants":[{"paths":["\/documentation\/scout\/explorervalue\/encodable-implementations"],"traits":[{"interfaceLanguage":"swift"}]}],"references":{"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/ExplorerValue/encode(to:)":{"identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/encode(to:)","title":"encode(to:)","abstract":[],"fragments":[{"text":"func","kind":"keyword"},{"text":" ","kind":"text"},{"kind":"identifier","text":"encode"},{"text":"(","kind":"text"},{"kind":"externalParam","text":"to"},{"text":": ","kind":"text"},{"preciseIdentifier":"s:s7EncoderP","text":"Encoder","kind":"typeIdentifier"},{"text":") ","kind":"text"},{"text":"throws","kind":"keyword"}],"type":"topic","url":"\/documentation\/scout\/explorervalue\/encode(to:)","kind":"symbol","role":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/equatable-implementations.json:
--------------------------------------------------------------------------------
1 | {"schemaVersion":{"patch":0,"major":0,"minor":3},"identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/Equatable-Implementations","interfaceLanguage":"swift"},"kind":"article","variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/explorervalue\/equatable-implementations"]}],"topicSections":[{"identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/!=(_:_:)"],"title":"Operators","generated":true}],"metadata":{"role":"collectionGroup","modules":[{"name":"Scout"}],"title":"Equatable Implementations"},"sections":[],"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"references":{"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"},"doc://Scout/documentation/Scout/ExplorerValue/!=(_:_:)":{"title":"!=(_:_:)","abstract":[],"fragments":[{"text":"static","kind":"keyword"},{"kind":"text","text":" "},{"kind":"keyword","text":"func"},{"text":" ","kind":"text"},{"text":"!=","kind":"identifier"},{"kind":"text","text":" "},{"kind":"text","text":"("},{"text":"Self","kind":"typeIdentifier"},{"text":", ","kind":"text"},{"text":"Self","kind":"typeIdentifier"},{"text":") -> ","kind":"text"},{"text":"Bool","kind":"typeIdentifier","preciseIdentifier":"s:Sb"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/!=(_:_:)","url":"\/documentation\/scout\/explorervalue\/!=(_:_:)","role":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/expressiblebyarrayliteral-implementations.json:
--------------------------------------------------------------------------------
1 | {"metadata":{"modules":[{"name":"Scout"}],"title":"ExpressibleByArrayLiteral Implementations","role":"collectionGroup"},"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"sections":[],"topicSections":[{"generated":true,"title":"Initializers","identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(arrayLiteral:)"]}],"schemaVersion":{"major":0,"patch":0,"minor":3},"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/ExpressibleByArrayLiteral-Implementations"},"kind":"article","variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/explorervalue\/expressiblebyarrayliteral-implementations"]}],"references":{"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"},"doc://Scout/documentation/Scout/ExplorerValue/init(arrayLiteral:)":{"url":"\/documentation\/scout\/explorervalue\/init(arrayliteral:)","abstract":[],"kind":"symbol","fragments":[{"kind":"identifier","text":"init"},{"text":"(","kind":"text"},{"text":"arrayLiteral","kind":"externalParam"},{"kind":"text","text":": "},{"preciseIdentifier":"s:5Scout13ExplorerValueO","text":"ExplorerValue","kind":"typeIdentifier"},{"kind":"text","text":"...)"}],"role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(arrayLiteral:)","type":"topic","title":"init(arrayLiteral:)"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/expressiblebybooleanliteral-implementations.json:
--------------------------------------------------------------------------------
1 | {"identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/ExpressibleByBooleanLiteral-Implementations","interfaceLanguage":"swift"},"metadata":{"role":"collectionGroup","title":"ExpressibleByBooleanLiteral Implementations","modules":[{"name":"Scout"}]},"sections":[],"kind":"article","hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"variants":[{"paths":["\/documentation\/scout\/explorervalue\/expressiblebybooleanliteral-implementations"],"traits":[{"interfaceLanguage":"swift"}]}],"schemaVersion":{"minor":3,"major":0,"patch":0},"topicSections":[{"identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(booleanLiteral:)"],"title":"Initializers","generated":true}],"references":{"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"},"doc://Scout/documentation/Scout/ExplorerValue/init(booleanLiteral:)":{"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(booleanLiteral:)","abstract":[],"fragments":[{"kind":"identifier","text":"init"},{"kind":"text","text":"("},{"kind":"externalParam","text":"booleanLiteral"},{"kind":"text","text":": "},{"kind":"typeIdentifier","text":"Bool","preciseIdentifier":"s:Sb"},{"text":")","kind":"text"}],"role":"symbol","url":"\/documentation\/scout\/explorervalue\/init(booleanliteral:)","title":"init(booleanLiteral:)"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/expressiblebydictionaryliteral-implementations.json:
--------------------------------------------------------------------------------
1 | {"sections":[],"metadata":{"role":"collectionGroup","modules":[{"name":"Scout"}],"title":"ExpressibleByDictionaryLiteral Implementations"},"kind":"article","schemaVersion":{"major":0,"minor":3,"patch":0},"topicSections":[{"title":"Initializers","identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(dictionaryLiteral:)"],"generated":true}],"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/ExpressibleByDictionaryLiteral-Implementations"},"variants":[{"paths":["\/documentation\/scout\/explorervalue\/expressiblebydictionaryliteral-implementations"],"traits":[{"interfaceLanguage":"swift"}]}],"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"references":{"doc://Scout/documentation/Scout/ExplorerValue/init(dictionaryLiteral:)":{"url":"\/documentation\/scout\/explorervalue\/init(dictionaryliteral:)","type":"topic","title":"init(dictionaryLiteral:)","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(dictionaryLiteral:)","role":"symbol","kind":"symbol","abstract":[],"fragments":[{"kind":"identifier","text":"init"},{"kind":"text","text":"("},{"kind":"externalParam","text":"dictionaryLiteral"},{"kind":"text","text":": ("},{"kind":"typeIdentifier","preciseIdentifier":"s:SS","text":"String"},{"text":", ","kind":"text"},{"kind":"typeIdentifier","preciseIdentifier":"s:5Scout13ExplorerValueO","text":"ExplorerValue"},{"text":")...)","kind":"text"}]},"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/expressiblebyfloatliteral-implementations.json:
--------------------------------------------------------------------------------
1 | {"schemaVersion":{"major":0,"patch":0,"minor":3},"topicSections":[{"title":"Initializers","identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(floatLiteral:)"],"generated":true}],"sections":[],"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"variants":[{"paths":["\/documentation\/scout\/explorervalue\/expressiblebyfloatliteral-implementations"],"traits":[{"interfaceLanguage":"swift"}]}],"identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/ExpressibleByFloatLiteral-Implementations","interfaceLanguage":"swift"},"kind":"article","metadata":{"title":"ExpressibleByFloatLiteral Implementations","modules":[{"name":"Scout"}],"role":"collectionGroup"},"references":{"doc://Scout/documentation/Scout/ExplorerValue/init(floatLiteral:)":{"role":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(floatLiteral:)","fragments":[{"text":"init","kind":"identifier"},{"text":"(","kind":"text"},{"text":"floatLiteral","kind":"externalParam"},{"kind":"text","text":": "},{"kind":"typeIdentifier","preciseIdentifier":"s:Sd","text":"Double"},{"text":")","kind":"text"}],"url":"\/documentation\/scout\/explorervalue\/init(floatliteral:)","kind":"symbol","title":"init(floatLiteral:)","abstract":[]},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/expressiblebyintegerliteral-implementations.json:
--------------------------------------------------------------------------------
1 | {"schemaVersion":{"major":0,"patch":0,"minor":3},"topicSections":[{"title":"Initializers","generated":true,"identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(integerLiteral:)"]}],"sections":[],"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"variants":[{"paths":["\/documentation\/scout\/explorervalue\/expressiblebyintegerliteral-implementations"],"traits":[{"interfaceLanguage":"swift"}]}],"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/ExpressibleByIntegerLiteral-Implementations"},"kind":"article","metadata":{"modules":[{"name":"Scout"}],"title":"ExpressibleByIntegerLiteral Implementations","role":"collectionGroup"},"references":{"doc://Scout/documentation/Scout/ExplorerValue/init(integerLiteral:)":{"role":"symbol","title":"init(integerLiteral:)","fragments":[{"kind":"identifier","text":"init"},{"text":"(","kind":"text"},{"kind":"externalParam","text":"integerLiteral"},{"text":": ","kind":"text"},{"preciseIdentifier":"s:Si","kind":"typeIdentifier","text":"Int"},{"text":")","kind":"text"}],"type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(integerLiteral:)","kind":"symbol","url":"\/documentation\/scout\/explorervalue\/init(integerliteral:)","abstract":[]},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/expressiblebystringliteral-implementations.json:
--------------------------------------------------------------------------------
1 | {"metadata":{"title":"ExpressibleByStringLiteral Implementations","role":"collectionGroup","modules":[{"name":"Scout"}]},"topicSections":[{"title":"Initializers","generated":true,"identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(stringLiteral:)"]}],"sections":[],"kind":"article","schemaVersion":{"major":0,"minor":3,"patch":0},"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/ExpressibleByStringLiteral-Implementations"},"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"variants":[{"paths":["\/documentation\/scout\/explorervalue\/expressiblebystringliteral-implementations"],"traits":[{"interfaceLanguage":"swift"}]}],"references":{"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/ExplorerValue/init(stringLiteral:)":{"title":"init(stringLiteral:)","url":"\/documentation\/scout\/explorervalue\/init(stringliteral:)","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/init(stringLiteral:)","fragments":[{"text":"init","kind":"identifier"},{"kind":"text","text":"("},{"kind":"externalParam","text":"stringLiteral"},{"kind":"text","text":": "},{"preciseIdentifier":"s:SS","text":"String","kind":"typeIdentifier"},{"text":")","kind":"text"}],"type":"topic","abstract":[],"kind":"symbol","role":"symbol"},"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorervalue/int(_:).json:
--------------------------------------------------------------------------------
1 | {"schemaVersion":{"patch":0,"major":0,"minor":3},"variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/explorervalue\/int(_:)"]}],"identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/int(_:)","interfaceLanguage":"swift"},"kind":"symbol","hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerValue"]]},"metadata":{"roleHeading":"Case","role":"symbol","externalID":"s:5Scout13ExplorerValueO3intyACSicACmF","title":"ExplorerValue.int(_:)","modules":[{"name":"Scout"}],"symbolKind":"case","fragments":[{"text":"case","kind":"keyword"},{"text":" ","kind":"text"},{"kind":"identifier","text":"int"},{"kind":"text","text":"("},{"kind":"typeIdentifier","text":"Int","preciseIdentifier":"s:Si"},{"text":")","kind":"text"}]},"primaryContentSections":[{"kind":"declarations","declarations":[{"tokens":[{"text":"case","kind":"keyword"},{"kind":"text","text":" "},{"text":"int","kind":"identifier"},{"kind":"text","text":"("},{"kind":"typeIdentifier","text":"Int","preciseIdentifier":"s:Si"},{"kind":"text","text":")"}],"languages":["swift"],"platforms":["macOS"]}]}],"sections":[],"references":{"doc://Scout/documentation/Scout/ExplorerValue":{"fragments":[{"kind":"keyword","text":"enum"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerValue"}],"kind":"symbol","type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue","title":"ExplorerValue","abstract":[{"type":"text","text":"The values a "},{"type":"codeVoice","code":"PathExplorer"},{"type":"text","text":" can take"}],"role":"symbol","navigatorTitle":[{"text":"ExplorerValue","kind":"identifier"}],"url":"\/documentation\/scout\/explorervalue"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/ExplorerValue/int(_:)":{"title":"ExplorerValue.int(_:)","role":"symbol","kind":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerValue\/int(_:)","url":"\/documentation\/scout\/explorervalue\/int(_:)","type":"topic","abstract":[],"fragments":[{"text":"case","kind":"keyword"},{"text":" ","kind":"text"},{"kind":"identifier","text":"int"},{"kind":"text","text":"("},{"kind":"typeIdentifier","preciseIdentifier":"s:Si","text":"Int"},{"text":")","kind":"text"}]}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorerxml/element.json:
--------------------------------------------------------------------------------
1 | {"primaryContentSections":[{"kind":"declarations","declarations":[{"platforms":["macOS"],"tokens":[{"kind":"keyword","text":"typealias"},{"text":" ","kind":"text"},{"text":"Element","kind":"identifier"},{"text":" = ","kind":"text"},{"text":"AEXMLElement","kind":"typeIdentifier","preciseIdentifier":"s:5AEXML12AEXMLElementC"}],"languages":["swift"]}]}],"metadata":{"externalID":"s:5Scout11ExplorerXMLV7Elementa","title":"ExplorerXML.Element","symbolKind":"typealias","modules":[{"name":"Scout"}],"fragments":[{"text":"typealias","kind":"keyword"},{"text":" ","kind":"text"},{"kind":"identifier","text":"Element"}],"roleHeading":"Type Alias","navigatorTitle":[{"text":"Element","kind":"identifier"}],"role":"symbol"},"sections":[],"schemaVersion":{"major":0,"minor":3,"patch":0},"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerXML"]]},"identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML\/Element","interfaceLanguage":"swift"},"variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/explorerxml\/element"]}],"kind":"symbol","references":{"doc://Scout/documentation/Scout/ExplorerXML":{"title":"ExplorerXML","url":"\/documentation\/scout\/explorerxml","abstract":[],"type":"topic","kind":"symbol","fragments":[{"kind":"keyword","text":"struct"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerXML"}],"navigatorTitle":[{"text":"ExplorerXML","kind":"identifier"}],"role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/ExplorerXML/Element":{"fragments":[{"kind":"keyword","text":"typealias"},{"text":" ","kind":"text"},{"text":"Element","kind":"identifier"}],"abstract":[],"url":"\/documentation\/scout\/explorerxml\/element","kind":"symbol","title":"ExplorerXML.Element","role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML\/Element","type":"topic","navigatorTitle":[{"kind":"identifier","text":"Element"}]}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorerxml/expressiblebyunicodescalarliteral-implementations.json:
--------------------------------------------------------------------------------
1 | {"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML\/ExpressibleByUnicodeScalarLiteral-Implementations"},"variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/explorerxml\/expressiblebyunicodescalarliteral-implementations"]}],"sections":[],"schemaVersion":{"patch":0,"major":0,"minor":3},"metadata":{"modules":[{"name":"Scout"}],"role":"collectionGroup","title":"ExpressibleByUnicodeScalarLiteral Implementations"},"kind":"article","topicSections":[{"title":"Initializers","generated":true,"identifiers":["doc:\/\/Scout\/documentation\/Scout\/ExplorerXML\/init(unicodeScalarLiteral:)"]}],"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerXML"]]},"references":{"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/ExplorerXML":{"title":"ExplorerXML","url":"\/documentation\/scout\/explorerxml","abstract":[],"type":"topic","kind":"symbol","fragments":[{"kind":"keyword","text":"struct"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerXML"}],"navigatorTitle":[{"text":"ExplorerXML","kind":"identifier"}],"role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML"},"doc://Scout/documentation/Scout/ExplorerXML/init(unicodeScalarLiteral:)":{"url":"\/documentation\/scout\/explorerxml\/init(unicodescalarliteral:)","fragments":[{"kind":"identifier","text":"init"},{"kind":"text","text":"("},{"kind":"externalParam","text":"unicodeScalarLiteral"},{"text":": ","kind":"text"},{"text":"Self","kind":"typeIdentifier"},{"kind":"text","text":"."},{"kind":"typeIdentifier","text":"ExtendedGraphemeClusterLiteralType"},{"kind":"text","text":")"}],"identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML\/init(unicodeScalarLiteral:)","abstract":[],"kind":"symbol","title":"init(unicodeScalarLiteral:)","role":"symbol","conformance":{"constraints":[{"type":"codeVoice","code":"ExtendedGraphemeClusterLiteralType"},{"text":" is ","type":"text"},{"type":"codeVoice","code":"Self.UnicodeScalarLiteralType"},{"type":"text","text":"."}],"availabilityPrefix":[{"text":"Available when","type":"text"}],"conformancePrefix":[{"type":"text","text":"Conforms when"}]},"type":"topic"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorerxml/int.json:
--------------------------------------------------------------------------------
1 | {"metadata":{"roleHeading":"Instance Property","symbolKind":"property","modules":[{"name":"Scout"}],"title":"int","externalID":"s:5Scout11ExplorerXMLV3intSiSgvp","fragments":[{"text":"var","kind":"keyword"},{"kind":"text","text":" "},{"text":"int","kind":"identifier"},{"kind":"text","text":": "},{"kind":"typeIdentifier","preciseIdentifier":"s:Si","text":"Int"},{"text":"?","kind":"text"}],"role":"symbol"},"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerXML"]]},"variants":[{"paths":["\/documentation\/scout\/explorerxml\/int"],"traits":[{"interfaceLanguage":"swift"}]}],"sections":[],"kind":"symbol","primaryContentSections":[{"kind":"declarations","declarations":[{"languages":["swift"],"tokens":[{"text":"var","kind":"keyword"},{"text":" ","kind":"text"},{"text":"int","kind":"identifier"},{"text":": ","kind":"text"},{"text":"Int","preciseIdentifier":"s:Si","kind":"typeIdentifier"},{"kind":"text","text":"? { "},{"text":"get","kind":"keyword"},{"kind":"text","text":" }"}],"platforms":["macOS"]}]}],"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML\/int"},"abstract":[{"text":"Inherited from ","type":"text"},{"type":"codeVoice","code":"PathExplorer.int"},{"type":"text","text":"."}],"schemaVersion":{"major":0,"minor":3,"patch":0},"references":{"doc://Scout/documentation/Scout/ExplorerXML":{"title":"ExplorerXML","url":"\/documentation\/scout\/explorerxml","abstract":[],"type":"topic","kind":"symbol","fragments":[{"kind":"keyword","text":"struct"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerXML"}],"navigatorTitle":[{"text":"ExplorerXML","kind":"identifier"}],"role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML"},"doc://Scout/documentation/Scout":{"title":"Scout","url":"\/documentation\/scout","abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"type":"topic","kind":"symbol","role":"collection","identifier":"doc:\/\/Scout\/documentation\/Scout"},"doc://Scout/documentation/Scout/ExplorerXML/int":{"title":"int","url":"\/documentation\/scout\/explorerxml\/int","abstract":[],"type":"topic","kind":"symbol","fragments":[{"text":"var","kind":"keyword"},{"kind":"text","text":" "},{"text":"int","kind":"identifier"},{"kind":"text","text":": "},{"text":"Int","kind":"typeIdentifier","preciseIdentifier":"s:Si"},{"text":"?","kind":"text"}],"role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML\/int"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/explorerxml/isgroup.json:
--------------------------------------------------------------------------------
1 | {"kind":"symbol","variants":[{"traits":[{"interfaceLanguage":"swift"}],"paths":["\/documentation\/scout\/explorerxml\/isgroup"]}],"identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML\/isGroup","interfaceLanguage":"swift"},"sections":[],"metadata":{"title":"isGroup","fragments":[{"text":"var","kind":"keyword"},{"text":" ","kind":"text"},{"text":"isGroup","kind":"identifier"},{"kind":"text","text":": "},{"text":"Bool","kind":"typeIdentifier","preciseIdentifier":"s:Sb"}],"symbolKind":"property","role":"symbol","externalID":"s:5Scout11ExplorerXMLV7isGroupSbvp","roleHeading":"Instance Property","modules":[{"name":"Scout"}]},"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/ExplorerXML"]]},"abstract":[{"type":"text","text":"Inherited from "},{"code":"PathExplorer.isGroup","type":"codeVoice"},{"type":"text","text":"."}],"primaryContentSections":[{"declarations":[{"languages":["swift"],"platforms":["macOS"],"tokens":[{"kind":"keyword","text":"var"},{"text":" ","kind":"text"},{"text":"isGroup","kind":"identifier"},{"kind":"text","text":": "},{"text":"Bool","preciseIdentifier":"s:Sb","kind":"typeIdentifier"},{"text":" { ","kind":"text"},{"text":"get","kind":"keyword"},{"text":" }","kind":"text"}]}],"kind":"declarations"}],"schemaVersion":{"minor":3,"patch":0,"major":0},"references":{"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/ExplorerXML":{"title":"ExplorerXML","url":"\/documentation\/scout\/explorerxml","abstract":[],"type":"topic","kind":"symbol","fragments":[{"kind":"keyword","text":"struct"},{"text":" ","kind":"text"},{"kind":"identifier","text":"ExplorerXML"}],"navigatorTitle":[{"text":"ExplorerXML","kind":"identifier"}],"role":"symbol","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML"},"doc://Scout/documentation/Scout/ExplorerXML/isGroup":{"kind":"symbol","title":"isGroup","identifier":"doc:\/\/Scout\/documentation\/Scout\/ExplorerXML\/isGroup","fragments":[{"text":"var","kind":"keyword"},{"text":" ","kind":"text"},{"text":"isGroup","kind":"identifier"},{"text":": ","kind":"text"},{"preciseIdentifier":"s:Sb","text":"Bool","kind":"typeIdentifier"}],"role":"symbol","abstract":[],"type":"topic","url":"\/documentation\/scout\/explorerxml\/isgroup"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/serializationerror/datatostring.json:
--------------------------------------------------------------------------------
1 | {"schemaVersion":{"patch":0,"minor":3,"major":0},"kind":"symbol","metadata":{"modules":[{"name":"Scout"}],"symbolKind":"case","title":"SerializationError.dataToString","fragments":[{"kind":"keyword","text":"case"},{"kind":"text","text":" "},{"text":"dataToString","kind":"identifier"}],"roleHeading":"Case","externalID":"s:5Scout18SerializationErrorO12dataToStringyA2CmF","role":"symbol"},"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/SerializationError"]]},"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/SerializationError\/dataToString"},"variants":[{"paths":["\/documentation\/scout\/serializationerror\/datatostring"],"traits":[{"interfaceLanguage":"swift"}]}],"sections":[],"primaryContentSections":[{"kind":"declarations","declarations":[{"tokens":[{"text":"case","kind":"keyword"},{"kind":"text","text":" "},{"text":"dataToString","kind":"identifier"}],"platforms":["macOS"],"languages":["swift"]}]}],"references":{"doc://Scout/documentation/Scout/SerializationError/dataToString":{"url":"\/documentation\/scout\/serializationerror\/datatostring","fragments":[{"kind":"keyword","text":"case"},{"text":" ","kind":"text"},{"kind":"identifier","text":"dataToString"}],"identifier":"doc:\/\/Scout\/documentation\/Scout\/SerializationError\/dataToString","abstract":[],"title":"SerializationError.dataToString","kind":"symbol","role":"symbol","type":"topic"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/SerializationError":{"type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/SerializationError","navigatorTitle":[{"text":"SerializationError","kind":"identifier"}],"url":"\/documentation\/scout\/serializationerror","abstract":[],"title":"SerializationError","role":"symbol","fragments":[{"kind":"keyword","text":"enum"},{"kind":"text","text":" "},{"text":"SerializationError","kind":"identifier"}],"kind":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/serializationerror/error-implementations.json:
--------------------------------------------------------------------------------
1 | {"identifier":{"interfaceLanguage":"swift","url":"doc:\/\/Scout\/documentation\/Scout\/SerializationError\/Error-Implementations"},"variants":[{"paths":["\/documentation\/scout\/serializationerror\/error-implementations"],"traits":[{"interfaceLanguage":"swift"}]}],"sections":[],"schemaVersion":{"patch":0,"major":0,"minor":3},"kind":"article","metadata":{"modules":[{"name":"Scout"}],"role":"collectionGroup","title":"Error Implementations"},"topicSections":[{"generated":true,"identifiers":["doc:\/\/Scout\/documentation\/Scout\/SerializationError\/localizedDescription"],"title":"Instance Properties"}],"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/SerializationError"]]},"references":{"doc://Scout/documentation/Scout/SerializationError":{"type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/SerializationError","navigatorTitle":[{"text":"SerializationError","kind":"identifier"}],"url":"\/documentation\/scout\/serializationerror","abstract":[],"title":"SerializationError","role":"symbol","fragments":[{"kind":"keyword","text":"enum"},{"kind":"text","text":" "},{"text":"SerializationError","kind":"identifier"}],"kind":"symbol"},"doc://Scout/documentation/Scout/SerializationError/localizedDescription":{"identifier":"doc:\/\/Scout\/documentation\/Scout\/SerializationError\/localizedDescription","title":"localizedDescription","abstract":[],"fragments":[{"kind":"keyword","text":"var"},{"kind":"text","text":" "},{"text":"localizedDescription","kind":"identifier"},{"text":": ","kind":"text"},{"preciseIdentifier":"s:SS","text":"String","kind":"typeIdentifier"}],"type":"topic","url":"\/documentation\/scout\/serializationerror\/localizeddescription","kind":"symbol","role":"symbol"},"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"}}}
--------------------------------------------------------------------------------
/docs/data/documentation/scout/serializationerror/stringtodata.json:
--------------------------------------------------------------------------------
1 | {"schemaVersion":{"patch":0,"minor":3,"major":0},"variants":[{"paths":["\/documentation\/scout\/serializationerror\/stringtodata"],"traits":[{"interfaceLanguage":"swift"}]}],"kind":"symbol","primaryContentSections":[{"declarations":[{"tokens":[{"kind":"keyword","text":"case"},{"text":" ","kind":"text"},{"text":"stringToData","kind":"identifier"}],"languages":["swift"],"platforms":["macOS"]}],"kind":"declarations"}],"hierarchy":{"paths":[["doc:\/\/Scout\/documentation\/Scout","doc:\/\/Scout\/documentation\/Scout\/SerializationError"]]},"metadata":{"modules":[{"name":"Scout"}],"roleHeading":"Case","symbolKind":"case","title":"SerializationError.stringToData","externalID":"s:5Scout18SerializationErrorO12stringToDatayA2CmF","role":"symbol","fragments":[{"kind":"keyword","text":"case"},{"kind":"text","text":" "},{"text":"stringToData","kind":"identifier"}]},"sections":[],"identifier":{"url":"doc:\/\/Scout\/documentation\/Scout\/SerializationError\/stringToData","interfaceLanguage":"swift"},"references":{"doc://Scout/documentation/Scout":{"abstract":[{"type":"text","text":"This library aims to make specific formats data values reading and writing simple when the data format is not known at build time."}],"identifier":"doc:\/\/Scout\/documentation\/Scout","url":"\/documentation\/scout","type":"topic","role":"collection","title":"Scout","kind":"symbol"},"doc://Scout/documentation/Scout/SerializationError/stringToData":{"title":"SerializationError.stringToData","identifier":"doc:\/\/Scout\/documentation\/Scout\/SerializationError\/stringToData","abstract":[],"fragments":[{"kind":"keyword","text":"case"},{"text":" ","kind":"text"},{"text":"stringToData","kind":"identifier"}],"type":"topic","url":"\/documentation\/scout\/serializationerror\/stringtodata","kind":"symbol","role":"symbol"},"doc://Scout/documentation/Scout/SerializationError":{"type":"topic","identifier":"doc:\/\/Scout\/documentation\/Scout\/SerializationError","navigatorTitle":[{"text":"SerializationError","kind":"identifier"}],"url":"\/documentation\/scout\/serializationerror","abstract":[],"title":"SerializationError","role":"symbol","fragments":[{"kind":"keyword","text":"enum"},{"kind":"text","text":" "},{"text":"SerializationError","kind":"identifier"}],"kind":"symbol"}}}
--------------------------------------------------------------------------------
/docs/developer-og-twitter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ABridoux/scout/37453749ef2d3e81a542cc9dacf0d8f636f848c1/docs/developer-og-twitter.jpg
--------------------------------------------------------------------------------
/docs/developer-og.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ABridoux/scout/37453749ef2d3e81a542cc9dacf0d8f636f848c1/docs/developer-og.jpg
--------------------------------------------------------------------------------
/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ABridoux/scout/37453749ef2d3e81a542cc9dacf0d8f636f848c1/docs/favicon.ico
--------------------------------------------------------------------------------
/docs/favicon.svg:
--------------------------------------------------------------------------------
1 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/img/added-icon.d6f7e47d.svg:
--------------------------------------------------------------------------------
1 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/img/deprecated-icon.015b4f17.svg:
--------------------------------------------------------------------------------
1 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/img/modified-icon.f496e73d.svg:
--------------------------------------------------------------------------------
1 |
10 |
11 |
--------------------------------------------------------------------------------
/docs/img/no-image@2x.df2a0a50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ABridoux/scout/37453749ef2d3e81a542cc9dacf0d8f636f848c1/docs/img/no-image@2x.df2a0a50.png
--------------------------------------------------------------------------------
/docs/js/highlight-js-diff.62d66733.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * This source file is part of the Swift.org open source project
3 | *
4 | * Copyright (c) 2021 Apple Inc. and the Swift project authors
5 | * Licensed under Apache License v2.0 with Runtime Library Exception
6 | *
7 | * See https://swift.org/LICENSE.txt for license information
8 | * See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9 | */
10 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["highlight-js-diff"],{"48b8":function(e,n){function a(e){const n=e.regex;return{name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,match:n.either(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/)},{className:"comment",variants:[{begin:n.either(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/),end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/,end:/$/}]}}e.exports=a}}]);
--------------------------------------------------------------------------------
/docs/js/highlight-js-http.163e45b6.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * This source file is part of the Swift.org open source project
3 | *
4 | * Copyright (c) 2021 Apple Inc. and the Swift project authors
5 | * Licensed under Apache License v2.0 with Runtime Library Exception
6 | *
7 | * See https://swift.org/LICENSE.txt for license information
8 | * See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9 | */
10 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["highlight-js-http"],{c01d:function(e,n){function a(e){const n=e.regex,a="HTTP/(2|1\\.[01])",s=/[A-Za-z][A-Za-z0-9-]*/,t={className:"attribute",begin:n.concat("^",s,"(?=\\:\\s)"),starts:{contains:[{className:"punctuation",begin:/: /,relevance:0,starts:{end:"$",relevance:0}}]}},i=[t,{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0}}];return{name:"HTTP",aliases:["https"],illegal:/\S/,contains:[{begin:"^(?="+a+" \\d{3})",end:/$/,contains:[{className:"meta",begin:a},{className:"number",begin:"\\b\\d{3}\\b"}],starts:{end:/\b\B/,illegal:/\S/,contains:i}},{begin:"(?=^[A-Z]+ (.*?) "+a+"$)",end:/$/,contains:[{className:"string",begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{className:"meta",begin:a},{className:"keyword",begin:"[A-Z]+"}],starts:{end:/\b\B/,illegal:/\S/,contains:i}},e.inherit(t,{relevance:0})]}}e.exports=a}}]);
--------------------------------------------------------------------------------
/docs/js/highlight-js-json.471128d2.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * This source file is part of the Swift.org open source project
3 | *
4 | * Copyright (c) 2021 Apple Inc. and the Swift project authors
5 | * Licensed under Apache License v2.0 with Runtime Library Exception
6 | *
7 | * See https://swift.org/LICENSE.txt for license information
8 | * See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9 | */
10 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["highlight-js-json"],{"5ad2":function(n,e){function a(n){const e={className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01},a={match:/[{}[\],:]/,className:"punctuation",relevance:0},s={beginKeywords:["true","false","null"].join(" ")};return{name:"JSON",contains:[e,a,n.QUOTE_STRING_MODE,s,n.C_NUMBER_MODE,n.C_LINE_COMMENT_MODE,n.C_BLOCK_COMMENT_MODE],illegal:"\\S"}}n.exports=a}}]);
--------------------------------------------------------------------------------
/docs/js/highlight-js-markdown.90077643.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * This source file is part of the Swift.org open source project
3 | *
4 | * Copyright (c) 2021 Apple Inc. and the Swift project authors
5 | * Licensed under Apache License v2.0 with Runtime Library Exception
6 | *
7 | * See https://swift.org/LICENSE.txt for license information
8 | * See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9 | */
10 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["highlight-js-markdown"],{"04b0":function(n,e){function a(n){const e=n.regex,a={begin:/<\/?[A-Za-z_]/,end:">",subLanguage:"xml",relevance:0},i={begin:"^[-\\*]{3,}",end:"$"},s={className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},c={className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",end:"\\s+",excludeEnd:!0},t={begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]},g=/[A-Za-z][A-Za-z0-9+.-]*/,d={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/,relevance:2},{begin:e.concat(/\[.+?\]\(/,g,/:\/\/.*?\)/),relevance:2},{begin:/\[.+?\]\([./?].*?\)/,relevance:1},{begin:/\[.*?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{match:/\[(?=\])/},{className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}]},l={className:"strong",contains:[],variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},o={className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{begin:/_(?!_)/,end:/_/,relevance:0}]};l.contains.push(o),o.contains.push(l);let b=[a,d];l.contains=l.contains.concat(b),o.contains=o.contains.concat(b),b=b.concat(l,o);const r={className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:b},{begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",contains:b}]}]},m={className:"quote",begin:"^>\\s+",contains:b,end:"$"};return{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[r,a,c,l,o,m,s,i,d,t]}}n.exports=a}}]);
--------------------------------------------------------------------------------
/docs/js/highlight-js-shell.dd7f411f.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * This source file is part of the Swift.org open source project
3 | *
4 | * Copyright (c) 2021 Apple Inc. and the Swift project authors
5 | * Licensed under Apache License v2.0 with Runtime Library Exception
6 | *
7 | * See https://swift.org/LICENSE.txt for license information
8 | * See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9 | */
10 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["highlight-js-shell"],{b65b:function(s,n){function e(s){return{name:"Shell Session",aliases:["console","shellsession"],contains:[{className:"meta",begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{end:/[^\\](?=\s*$)/,subLanguage:"bash"}}]}}s.exports=e}}]);
--------------------------------------------------------------------------------
/docs/js/highlight-js-xml.9c3688c7.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * This source file is part of the Swift.org open source project
3 | *
4 | * Copyright (c) 2021 Apple Inc. and the Swift project authors
5 | * Licensed under Apache License v2.0 with Runtime Library Exception
6 | *
7 | * See https://swift.org/LICENSE.txt for license information
8 | * See https://swift.org/CONTRIBUTORS.txt for Swift project authors
9 | */
10 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["highlight-js-xml"],{"8dcb":function(e,n){function a(e){const n=e.regex,a=n.concat(/[A-Z_]/,n.optional(/[A-Z0-9_.-]*:/),/[A-Z0-9_.-]*/),s=/[A-Za-z0-9._:-]+/,t={className:"symbol",begin:/&[a-z]+;|[0-9]+;|[a-f0-9]+;/},i={begin:/\s/,contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},c=e.inherit(i,{begin:/\(/,end:/\)/}),l=e.inherit(e.APOS_STRING_MODE,{className:"string"}),r=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),g={endsWithParent:!0,illegal:/,relevance:0,contains:[{className:"attr",begin:s,relevance:0},{begin:/=\s*/,relevance:0,contains:[{className:"string",endsParent:!0,variants:[{begin:/"/,end:/"/,contains:[t]},{begin:/'/,end:/'/,contains:[t]},{begin:/[^\s"'=<>`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin://,relevance:10,contains:[i,r,l,c,{begin:/\[/,end:/\]/,contains:[{className:"meta",begin://,contains:[i,c,r,l]}]}]},e.COMMENT(//,{relevance:10}),{begin://,relevance:10},t,{className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag",begin:/