├── .editorconfig
├── .gitignore
├── .paket
└── Paket.Restore.targets
├── CHANGELOG.md
├── Directory.Build.props
├── LICENSE
├── PickAll.sln
├── README.md
├── appveyor.yml
├── assets
└── icon.png
├── azure-pipelines.yml
├── paket.dependencies
├── paket.lock
├── samples
└── PickAll.Sample
│ ├── .editorconfig
│ ├── Options.cs
│ ├── OptionsExtensions.cs
│ ├── PickAll.Sample.csproj
│ ├── Program.cs
│ └── paket.references
├── src
└── PickAll
│ ├── .editorconfig
│ ├── Abstractions
│ ├── IFetchedDocument.cs
│ ├── IFetchingContext.cs
│ ├── PostProcessor.cs
│ ├── Searcher.cs
│ └── Service.cs
│ ├── AssemblyInfo.cs
│ ├── ContextSettings.cs
│ ├── Events.cs
│ ├── FetchedDocument.cs
│ ├── FetchedDocumentExtensions.cs
│ ├── FetchingContext.cs
│ ├── Internal
│ ├── EventHelper.cs
│ ├── Fuzzy.cs
│ ├── Guard.cs
│ ├── HtmlElementExtensions.cs
│ ├── ObjectExtensions.cs
│ └── TypeExtensions.cs
│ ├── PickAll.csproj
│ ├── PostProcessors
│ ├── FuzzyMatch.cs
│ ├── Improve.cs
│ ├── Order.cs
│ ├── Textify.cs
│ └── Uniqueness.cs
│ ├── ResultInfo.cs
│ ├── ResultInfoExtensions.cs
│ ├── RuntimeInfo.cs
│ ├── SearchContext.cs
│ ├── SearchContextExtensions.cs
│ ├── Searchers
│ ├── Bing.cs
│ ├── BingNews.cs
│ ├── DuckDuckGo.cs
│ ├── Google.cs
│ └── Yahoo.cs
│ └── paket.references
└── tests
└── PickAll.Specs
├── .editorconfig
├── Fakes
├── Arbitrary.cs
├── ArbitrarySearcher.cs
└── Marker.cs
├── Helpers
├── ResultInfoExtensions.cs
└── ResultInfoHelper.cs
├── Outcomes
├── FetchedDocumentExtensionsSpecs.cs
├── FetchedDocumentSpecs.cs
├── FetchingContextSpecs.cs
├── FuzzyMatchSpecs.cs
├── ImproveSpecs.cs
├── OrderSpecs.cs
├── SearchContextExtensionsSpecs.cs
├── SearchContextSpecs.Events.cs
├── SearchContextSpecs.cs
└── UniquenessSpecs.cs
├── PickAll.Specs.csproj
└── paket.references
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | []
4 | end_of_line = crlf
5 | insert_final_newline = true
6 |
7 | [*.xml]
8 | indent_style = space
9 | indent_size = 4
10 |
11 | [*.{json,yml}]
12 | indent_style = space
13 | indent_size = 2
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .DS_Store
3 | .vscode/
4 | .vs
5 | tools/
6 | paket-files/
7 | [Oo]bj/
8 | [Bb]in/
9 | .nuget/
10 | _ReSharper.*
11 | packages/
12 | artifacts/
13 | *.user
14 | *.suo
15 | *.userprefs
16 | *DS_Store
17 | *.sln.ide
18 |
--------------------------------------------------------------------------------
/.paket/Paket.Restore.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
8 |
9 | $(MSBuildVersion)
10 | 15.0.0
11 | false
12 | true
13 |
14 | true
15 | $(MSBuildThisFileDirectory)
16 | $(MSBuildThisFileDirectory)..\
17 | $(PaketRootPath)paket-files\paket.restore.cached
18 | $(PaketRootPath)paket.lock
19 | classic
20 | proj
21 | assembly
22 | native
23 | /Library/Frameworks/Mono.framework/Commands/mono
24 | mono
25 |
26 |
27 | $(PaketRootPath)paket.bootstrapper.exe
28 | $(PaketToolsPath)paket.bootstrapper.exe
29 | $([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\
30 |
31 | "$(PaketBootStrapperExePath)"
32 | $(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)"
33 |
34 |
35 |
36 |
37 | true
38 | true
39 |
40 |
41 | True
42 |
43 |
44 | False
45 |
46 | $(BaseIntermediateOutputPath.TrimEnd('\').TrimEnd('\/'))
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | $(PaketRootPath)paket
56 | $(PaketToolsPath)paket
57 |
58 |
59 |
60 |
61 |
62 | $(PaketRootPath)paket.exe
63 | $(PaketToolsPath)paket.exe
64 |
65 |
66 |
67 |
68 |
69 | <_DotnetToolsJson Condition="Exists('$(PaketRootPath)/.config/dotnet-tools.json')">$([System.IO.File]::ReadAllText("$(PaketRootPath)/.config/dotnet-tools.json"))
70 | <_ConfigContainsPaket Condition=" '$(_DotnetToolsJson)' != ''">$(_DotnetToolsJson.Contains('"paket"'))
71 | <_ConfigContainsPaket Condition=" '$(_ConfigContainsPaket)' == ''">false
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | <_PaketCommand>dotnet paket
83 |
84 |
85 |
86 |
87 |
88 | $(PaketToolsPath)paket
89 | $(PaketBootStrapperExeDir)paket
90 |
91 |
92 | paket
93 |
94 |
95 |
96 |
97 | <_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)"))
98 | <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(_PaketExeExtension)' == '.dll' ">dotnet "$(PaketExePath)"
99 | <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(OS)' != 'Windows_NT' AND '$(_PaketExeExtension)' == '.exe' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)"
100 | <_PaketCommand Condition=" '$(_PaketCommand)' == '' ">"$(PaketExePath)"
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | true
122 | $(NoWarn);NU1603;NU1604;NU1605;NU1608
123 | false
124 | true
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | $([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)'))
134 |
135 |
136 |
137 |
138 |
139 |
141 | $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[0].Replace(`"`, ``).Replace(` `, ``))
142 | $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[1].Replace(`"`, ``).Replace(` `, ``))
143 |
144 |
145 |
146 |
147 | %(PaketRestoreCachedKeyValue.Value)
148 | %(PaketRestoreCachedKeyValue.Value)
149 |
150 |
151 |
152 |
153 | true
154 | false
155 | true
156 |
157 |
158 |
162 |
163 | true
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 | $(PaketIntermediateOutputPath)\$(MSBuildProjectFile).paket.references.cached
183 |
184 | $(MSBuildProjectFullPath).paket.references
185 |
186 | $(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references
187 |
188 | $(MSBuildProjectDirectory)\paket.references
189 |
190 | false
191 | true
192 | true
193 | references-file-or-cache-not-found
194 |
195 |
196 |
197 |
198 | $([System.IO.File]::ReadAllText('$(PaketReferencesCachedFilePath)'))
199 | $([System.IO.File]::ReadAllText('$(PaketOriginalReferencesFilePath)'))
200 | references-file
201 | false
202 |
203 |
204 |
205 |
206 | false
207 |
208 |
209 |
210 |
211 | true
212 | target-framework '$(TargetFramework)' or '$(TargetFrameworks)' files @(PaketResolvedFilePaths)
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 | false
224 | true
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',').Length)
236 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0])
237 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1])
238 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4])
239 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5])
240 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[6])
241 | $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[7])
242 |
243 |
244 | %(PaketReferencesFileLinesInfo.PackageVersion)
245 | All
246 | runtime
247 | $(ExcludeAssets);contentFiles
248 | $(ExcludeAssets);build;buildMultitargeting;buildTransitive
249 | true
250 | true
251 |
252 |
253 |
254 |
255 | $(PaketIntermediateOutputPath)/$(MSBuildProjectFile).paket.clitools
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 | $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[0])
265 | $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[1])
266 |
267 |
268 | %(PaketCliToolFileLinesInfo.PackageVersion)
269 |
270 |
271 |
272 |
276 |
277 |
278 |
279 |
280 |
281 | false
282 |
283 |
284 |
285 |
286 |
287 | <_NuspecFilesNewLocation Include="$(PaketIntermediateOutputPath)\$(Configuration)\*.nuspec"/>
288 |
289 |
290 |
291 |
292 |
293 | $(MSBuildProjectDirectory)/$(MSBuildProjectFile)
294 | true
295 | false
296 | true
297 | false
298 | true
299 | false
300 | true
301 | false
302 | true
303 | false
304 | true
305 | $(PaketIntermediateOutputPath)\$(Configuration)
306 | $(PaketIntermediateOutputPath)
307 |
308 |
309 |
310 | <_NuspecFiles Include="$(AdjustedNuspecOutputPath)\*.$(PackageVersion.Split(`+`)[0]).nuspec"/>
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
370 |
371 |
420 |
421 |
466 |
467 |
511 |
512 |
555 |
556 |
557 |
558 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased]
9 |
10 | ## [1.3.0] - 2022-01-14
11 |
12 | - Added Bing news searcher as class `BingNews`.
13 |
14 | ## [1.2.2] - 2021-11-20
15 |
16 | - SharpX upgraded to version 1.0.3.
17 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | $(MSBuildThisFileDirectory)
4 | false
5 |
6 |
7 | $(DefineConstants);NETFRAMEWORK
8 |
9 |
10 |
11 |
12 | runtime; build; native; contentfiles; analyzers
13 | all
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 - 2022 Giacomo Stelluti Scala
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.
22 |
--------------------------------------------------------------------------------
/PickAll.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio Version 16
3 | VisualStudioVersion = 16.0.31729.503
4 | MinimumVisualStudioVersion = 15.0.26124.0
5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{F2416294-558A-41FA-A2CC-843435B27551}"
6 | ProjectSection(SolutionItems) = preProject
7 | paket.dependencies = paket.dependencies
8 | EndProjectSection
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PickAll", "src\PickAll\PickAll.csproj", "{B936C659-C656-40A8-A7D5-35EBCF27BA74}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PickAll.Specs", "tests\PickAll.Specs\PickAll.Specs.csproj", "{6CD5FED7-D697-413F-A763-EF95FEB77F8A}"
13 | EndProject
14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PickAll.Sample", "samples\PickAll.Sample\PickAll.Sample.csproj", "{2DA9658E-F760-4122-8589-4B7CBD8AAD20}"
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Release|Any CPU = Release|Any CPU
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {B936C659-C656-40A8-A7D5-35EBCF27BA74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {B936C659-C656-40A8-A7D5-35EBCF27BA74}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {B936C659-C656-40A8-A7D5-35EBCF27BA74}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {B936C659-C656-40A8-A7D5-35EBCF27BA74}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {6CD5FED7-D697-413F-A763-EF95FEB77F8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {6CD5FED7-D697-413F-A763-EF95FEB77F8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {6CD5FED7-D697-413F-A763-EF95FEB77F8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {6CD5FED7-D697-413F-A763-EF95FEB77F8A}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {2DA9658E-F760-4122-8589-4B7CBD8AAD20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {2DA9658E-F760-4122-8589-4B7CBD8AAD20}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {2DA9658E-F760-4122-8589-4B7CBD8AAD20}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {2DA9658E-F760-4122-8589-4B7CBD8AAD20}.Release|Any CPU.Build.0 = Release|Any CPU
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | GlobalSection(ExtensibilityGlobals) = postSolution
39 | SolutionGuid = {FF6DB9EB-A535-4CCD-9E7A-1C9058EF5D99}
40 | EndGlobalSection
41 | EndGlobal
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://dev.azure.com/gsscoder/pickall/_build/latest?definitionId=2&branchName=master)
2 | [](https://nuget.org/packages/pickall)
3 | [](https://www.nuget.org/packages/pickall)
4 | [](https://gitter.im/pickallwebsearcher/community#)
5 |
6 | # PickAll
7 |
8 | 
9 |
10 | .NET agile and extensible web searching API. Built with [AngleSharp](https://anglesharp.github.io/).
11 |
12 | ## Philosophy
13 |
14 | PickAll is primarily designed to collect a limited amount of results (possibly the more relavant) from different sources and process these in a chain of steps. Results are essentially URLs and descriptions, but more data can be handled.
15 |
16 | ## Documentation
17 |
18 | Documentation is available in the project [wiki](https://github.com/gsscoder/pickall/wiki).
19 |
20 | ## Targets
21 |
22 | - .NET Standard 2.0
23 | - .NET Core 3.1
24 | - .NET 5.0
25 |
26 | ## Install via NuGet
27 |
28 | ```sh
29 | $ dotnet add package PickAll --version 1.3.1
30 | Determining projects to restore...
31 | ...
32 | ```
33 |
34 | ## Build and sample
35 |
36 | ```sh
37 | # clone the repository
38 | $ git clone https://github.com/gsscoder/pickall.git
39 |
40 | # build the package
41 | $ cd pickall/src/PickAll
42 | $ dotnet build -c release
43 |
44 | # execute sample
45 | $ cd pickall/samples/PickAll.Sample
46 | $ dotnet build -c release
47 | $ cd ../../artifacts/PickAll.Sample/Release/netcoreapp3.0/PickAll.Sample
48 | ./PickAll.Sample "Steve Jobs" -e bing:duckduckgo
49 | Searching 'Steve Jobs' ...
50 | [0] Bing: "Steve Jobs - Wikipedia": "https://it.wikipedia.org/wiki/Steve_Jobs"
51 | [0] DuckDuckGo: "Steve Jobs - Wikipedia": "https://en.wikipedia.org/wiki/Steve_Jobs"
52 | [1] DuckDuckGo: "Steve Jobs - Apple, Family & Death - Biography": "https://www.biography.com/business-figure/steve-jobs"
53 | [2] Bing: "CC-BY-SA licenza": "http://creativecommons.org/licenses/by-sa/3.0/"
54 | [2] DuckDuckGo: "Steve Jobs - IMDb": "https://www.imdb.com/name/nm0423418/"
55 | [3] Bing: "Biografia di Steve Jobs - Biografieonline": "https://biografieonline.it/biografia.htm?BioID=1560&biografia=Steve+Jobs"
56 | ```
57 |
58 | ## Test
59 |
60 | ```sh
61 | # change to tests directory
62 | $ cd pickall/tests/PickAll.Specs
63 |
64 | # build with debug configuration
65 | $ dotnet build -c debug
66 | ...
67 |
68 | # execute tests
69 | $ dotnet test
70 | ...
71 | ```
72 |
73 | ## At a glance
74 |
75 | **CSharp:**
76 | ```csharp
77 | using PickAll;
78 |
79 | var context = new SearchContext()
80 | .WithEvents()
81 | .With() // search on google.com
82 | .With() // search on yahoo.com
83 | .With() // remove duplicates
84 | .With() // prioritize results
85 | // match Levenshtein distance with maximum of 15
86 | .With(new FuzzyMatchSettings { Text = "mechanics", MaximumDistance = 15 });
87 | // repeat a search using more frequent words of previous results
88 | .With(new ImproveSettings { WordCount = 2, NoiseLength = 3 })
89 | // scrape result pages and extract all text
90 | .With(new TextifySettings { IncludeTitle = true, NoiseLength = 3 });
91 | // attach events
92 | context.ResultCreated += (sender, e) => Console.WriteLine($"Result created from {e.Result.Originator}");
93 | // execute services (order of addition)
94 | var results = await context.SearchAsync("quantum physics");
95 | // do anything you need with LINQ
96 | var scientific = results.Where(result => result.Url.Contains("wikipedia"));
97 | foreach (var result in scientific) {
98 | Console.WriteLine($"{result.Url} {result.Description}");
99 | }
100 | ```
101 |
102 | **FSharp:**
103 | ```fsharp
104 | let context = new SearchContext(typeof,
105 | typeof,
106 | typeof)
107 | let results = context.SearchAsync("quantum physics")
108 | |> Async.AwaitTask
109 | |> Async.RunSynchronously
110 |
111 | results |> Seq.iter (fun x -> printfn "%s %s" x.Url x.Description)
112 | ```
113 |
114 | ## Libraries
115 |
116 | - [AngleSharp](https://github.com/AngleSharp/AngleSharp)
117 | - [AngleSharp.Io](https://github.com/AngleSharp/AngleSharp.Io)
118 | - [SharpX](https://github.com/gsscoder/sharpx)
119 | - [CommandLineParser](https://github.com/commandlineparser/commandline)
120 | - [xUnit.net](https://github.com/xunit/xunit)
121 | - [FluentAssertions](https://github.com/fluentassertions/fluentassertions)
122 | - [WaffleGenerator](https://github.com/SimonCropp/WaffleGenerator)
123 | - [Bogus](https://github.com/bchavez/Bogus)
124 |
125 | ## Tools
126 |
127 | - [Paket](https://github.com/fsprojects/Paket)
128 |
129 | ## Icon
130 |
131 | - [Search Engine](https://thenounproject.com/search/?q=search%20engine&i=2054907) icon designed by Vectors Market from [The Noun Project](https://thenounproject.com/).
132 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 1.0.{build}
2 | build:
3 | verbosity: minimal
4 |
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gsscoder/pickall/070ac05614e2b538383b81a192b08b56281cc6fa/assets/icon.png
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | trigger:
2 | - master
3 |
4 | pool:
5 | vmImage: 'windows-2019'
6 |
7 | steps:
8 | - task: UseDotNet@2
9 | displayName: '.NET Core: install 5.0.x'
10 | inputs:
11 | packageType: 'sdk'
12 | version: '5.0.x'
13 |
14 | - task: DotNetCoreCLI@2
15 | displayName: 'Paket: global install'
16 | inputs:
17 | command: 'custom'
18 | custom: 'tool'
19 | arguments: 'install -g paket'
20 |
21 | - task: PaketRestore@0
22 | displayName: 'Paket: restore'
23 | inputs:
24 | PaketPath: '.paket'
25 |
26 | - task: CmdLine@2
27 | displayName: '.NET Core CLI: restore'
28 | inputs:
29 | script: 'dotnet restore'
30 |
31 | - task: DotNetCoreCLI@2
32 | displayName: '.NET Core CLI: build'
33 | inputs:
34 | command: 'build'
35 | projects: 'src/**/*.csproj'
36 | arguments: '-c release'
37 |
--------------------------------------------------------------------------------
/paket.dependencies:
--------------------------------------------------------------------------------
1 | group main
2 | source https://www.nuget.org/api/v2
3 | framework: netstandard20, netcoreapp31, net50
4 | nuget AngleSharp 0.14.0
5 | nuget AngleSharp.Io 0.14.0
6 | nuget SharpX 1.1.5
7 |
8 | group specs
9 | source https://www.nuget.org/api/v2
10 | framework: net50
11 | nuget Microsoft.NET.Test.Sdk 16.9.4
12 | nuget coverlet.collector 1.0.1
13 | nuget xunit 2.4.1
14 | nuget xunit.runner.visualstudio 2.4.3
15 | nuget FluentAssertions 6.2.0
16 | nuget SharpX 1.1.5
17 | nuget Bogus 33.1.1
18 | nuget WaffleGenerator 4.2.1
19 | nuget WaffleGenerator.Bogus 4.2.1
20 |
21 | group sample
22 | source https://www.nuget.org/api/v2
23 | framework: net50
24 | nuget CommandLineParser 2.7.82
25 |
--------------------------------------------------------------------------------
/paket.lock:
--------------------------------------------------------------------------------
1 | RESTRICTION: || (== net5.0) (== netcoreapp3.1) (== netstandard2.0)
2 | NUGET
3 | remote: https://www.nuget.org/api/v2
4 | AngleSharp (0.14)
5 | System.Text.Encoding.CodePages (>= 4.5)
6 | AngleSharp.Io (0.14)
7 | AngleSharp (>= 0.14)
8 | FSharp.Core (6.0.1)
9 | Microsoft.NETCore.Platforms (3.1) - restriction: || (== net5.0) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0)) (&& (== netstandard2.0) (>= netcoreapp3.1))
10 | SharpX (1.1.5)
11 | FSharp.Core (>= 4.7)
12 | System.Runtime.CompilerServices.Unsafe (4.7) - restriction: || (&& (== net5.0) (>= net461)) (&& (== net5.0) (< netcoreapp2.0)) (&& (== net5.0) (< netcoreapp3.1)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (== netstandard2.0)
13 | System.Text.Encoding.CodePages (4.7)
14 | Microsoft.NETCore.Platforms (>= 3.1) - restriction: || (== net5.0) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp2.0)) (&& (== netstandard2.0) (>= netcoreapp3.1))
15 | System.Runtime.CompilerServices.Unsafe (>= 4.7) - restriction: || (&& (== net5.0) (>= net461)) (&& (== net5.0) (< netcoreapp2.0)) (&& (== net5.0) (< netcoreapp3.1)) (&& (== netcoreapp3.1) (>= net461)) (&& (== netcoreapp3.1) (< netcoreapp2.0)) (== netstandard2.0)
16 |
17 | GROUP sample
18 | RESTRICTION: == net5.0
19 | NUGET
20 | remote: https://www.nuget.org/api/v2
21 | CommandLineParser (2.7.82)
22 |
23 | GROUP specs
24 | RESTRICTION: == net5.0
25 | NUGET
26 | remote: https://www.nuget.org/api/v2
27 | Bogus (33.1.1)
28 | coverlet.collector (1.0.1)
29 | FluentAssertions (6.2)
30 | System.Configuration.ConfigurationManager (>= 4.4)
31 | FSharp.Core (6.0.1)
32 | Microsoft.CodeCoverage (17.0)
33 | Microsoft.NET.Test.Sdk (16.9.4)
34 | Microsoft.CodeCoverage (>= 16.9.4)
35 | Microsoft.TestPlatform.TestHost (>= 16.9.4)
36 | Microsoft.NETCore.Platforms (5.0.4)
37 | Microsoft.TestPlatform.ObjectModel (17.0)
38 | NuGet.Frameworks (>= 5.0)
39 | System.Reflection.Metadata (>= 1.6)
40 | Microsoft.TestPlatform.TestHost (17.0)
41 | Microsoft.TestPlatform.ObjectModel (>= 17.0)
42 | Newtonsoft.Json (>= 9.0.1)
43 | Microsoft.Win32.SystemEvents (5.0)
44 | Microsoft.NETCore.Platforms (>= 5.0)
45 | NETStandard.Library (2.0.3)
46 | Microsoft.NETCore.Platforms (>= 1.1)
47 | Newtonsoft.Json (13.0.1)
48 | NuGet.Frameworks (5.11)
49 | SharpX (1.1.5)
50 | FSharp.Core (>= 4.7)
51 | System.Configuration.ConfigurationManager (5.0)
52 | System.Security.Cryptography.ProtectedData (>= 5.0)
53 | System.Security.Permissions (>= 5.0)
54 | System.Drawing.Common (5.0.2)
55 | Microsoft.Win32.SystemEvents (>= 5.0)
56 | System.Reflection.Metadata (5.0)
57 | System.Security.AccessControl (5.0)
58 | Microsoft.NETCore.Platforms (>= 5.0)
59 | System.Security.Principal.Windows (>= 5.0)
60 | System.Security.Cryptography.ProtectedData (5.0)
61 | System.Security.Permissions (5.0)
62 | System.Security.AccessControl (>= 5.0)
63 | System.Windows.Extensions (>= 5.0)
64 | System.Security.Principal.Windows (5.0)
65 | System.Windows.Extensions (5.0)
66 | System.Drawing.Common (>= 5.0)
67 | WaffleGenerator (4.2.1)
68 | WaffleGenerator.Bogus (4.2.1)
69 | Bogus (>= 33.0.2)
70 | WaffleGenerator (>= 4.2.1)
71 | xunit (2.4.1)
72 | xunit.analyzers (>= 0.10)
73 | xunit.assert (2.4.1)
74 | xunit.core (2.4.1)
75 | xunit.abstractions (2.0.3)
76 | xunit.analyzers (0.10)
77 | xunit.assert (2.4.1)
78 | NETStandard.Library (>= 1.6.1)
79 | xunit.core (2.4.1)
80 | xunit.extensibility.core (2.4.1)
81 | xunit.extensibility.execution (2.4.1)
82 | xunit.extensibility.core (2.4.1)
83 | NETStandard.Library (>= 1.6.1)
84 | xunit.abstractions (>= 2.0.3)
85 | xunit.extensibility.execution (2.4.1)
86 | NETStandard.Library (>= 1.6.1)
87 | xunit.extensibility.core (2.4.1)
88 | xunit.runner.visualstudio (2.4.3)
89 |
--------------------------------------------------------------------------------
/samples/PickAll.Sample/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{csproj,config}]
2 | indent_style = space
3 | indent_size = 2
4 |
5 | # C# files
6 | [*.cs]
7 |
8 | #### Core EditorConfig Options ####
9 |
10 | # Indentation and spacing
11 | indent_size = 4
12 | indent_style = space
13 | tab_width = 4
14 |
15 | # New line preferences
16 | end_of_line = crlf
17 | insert_final_newline = false
18 |
19 | #### .NET Coding Conventions ####
20 |
21 | # Organize usings
22 | dotnet_separate_import_directive_groups = false
23 | dotnet_sort_system_directives_first = true
24 | file_header_template = unset
25 |
26 | # this. and Me. preferences
27 | dotnet_style_qualification_for_event = false
28 | dotnet_style_qualification_for_field = false
29 | dotnet_style_qualification_for_method = false
30 | dotnet_style_qualification_for_property = false
31 |
32 | # Language keywords vs BCL types preferences
33 | dotnet_style_predefined_type_for_locals_parameters_members = true
34 | dotnet_style_predefined_type_for_member_access = true
35 |
36 | # Parentheses preferences
37 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
38 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
39 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary
40 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
41 |
42 | # Modifier preferences
43 | dotnet_style_require_accessibility_modifiers = for_non_interface_members
44 |
45 | # Expression-level preferences
46 | dotnet_style_coalesce_expression = true
47 | dotnet_style_collection_initializer = true
48 | dotnet_style_explicit_tuple_names = true
49 | dotnet_style_null_propagation = true
50 | dotnet_style_object_initializer = true
51 | dotnet_style_operator_placement_when_wrapping = beginning_of_line
52 | dotnet_style_prefer_auto_properties = true
53 | dotnet_style_prefer_compound_assignment = true
54 | dotnet_style_prefer_conditional_expression_over_assignment = true
55 | dotnet_style_prefer_conditional_expression_over_return = true
56 | dotnet_style_prefer_inferred_anonymous_type_member_names = true
57 | dotnet_style_prefer_inferred_tuple_names = true
58 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true
59 | dotnet_style_prefer_simplified_boolean_expressions = true
60 | dotnet_style_prefer_simplified_interpolation = true
61 |
62 | # Field preferences
63 | dotnet_style_readonly_field = true
64 |
65 | # Parameter preferences
66 | dotnet_code_quality_unused_parameters = all
67 |
68 | # Suppression preferences
69 | dotnet_remove_unnecessary_suppression_exclusions = none
70 |
71 | #### C# Coding Conventions ####
72 |
73 | # var preferences
74 | csharp_style_var_elsewhere = false
75 | csharp_style_var_for_built_in_types = false
76 | csharp_style_var_when_type_is_apparent = false
77 |
78 | # Expression-bodied members
79 | csharp_style_expression_bodied_accessors = true
80 | csharp_style_expression_bodied_constructors = false
81 | csharp_style_expression_bodied_indexers = true
82 | csharp_style_expression_bodied_lambdas = true
83 | csharp_style_expression_bodied_local_functions = false
84 | csharp_style_expression_bodied_methods = false
85 | csharp_style_expression_bodied_operators = false
86 | csharp_style_expression_bodied_properties = true
87 |
88 | # Pattern matching preferences
89 | csharp_style_pattern_matching_over_as_with_null_check = true
90 | csharp_style_pattern_matching_over_is_with_cast_check = true
91 | csharp_style_prefer_not_pattern = true
92 | csharp_style_prefer_pattern_matching = true
93 | csharp_style_prefer_switch_expression = true
94 |
95 | # Null-checking preferences
96 | csharp_style_conditional_delegate_call = true
97 |
98 | # Modifier preferences
99 | csharp_prefer_static_local_function = true
100 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
101 |
102 | # Code-block preferences
103 | csharp_prefer_braces = true
104 | csharp_prefer_simple_using_statement = true
105 |
106 | # Expression-level preferences
107 | csharp_prefer_simple_default_expression = true
108 | csharp_style_deconstructed_variable_declaration = true
109 | csharp_style_implicit_object_creation_when_type_is_apparent = true
110 | csharp_style_inlined_variable_declaration = true
111 | csharp_style_pattern_local_over_anonymous_function = true
112 | csharp_style_prefer_index_operator = true
113 | csharp_style_prefer_range_operator = true
114 | csharp_style_throw_expression = true
115 | csharp_style_unused_value_assignment_preference = discard_variable
116 | csharp_style_unused_value_expression_statement_preference = discard_variable
117 |
118 | # 'using' directive preferences
119 | csharp_using_directive_placement = outside_namespace
120 |
121 | #### C# Formatting Rules ####
122 |
123 | # New line preferences
124 | csharp_new_line_before_catch = true
125 | csharp_new_line_before_else = true
126 | csharp_new_line_before_finally = true
127 | csharp_new_line_before_members_in_anonymous_types = true
128 | csharp_new_line_before_members_in_object_initializers = true
129 | csharp_new_line_before_open_brace = anonymous_methods,anonymous_types,lambdas,methods,object_collection_array_initializers,properties,types
130 | csharp_new_line_between_query_expression_clauses = true
131 |
132 | # Indentation preferences
133 | csharp_indent_block_contents = true
134 | csharp_indent_braces = false
135 | csharp_indent_case_contents = true
136 | csharp_indent_case_contents_when_block = true
137 | csharp_indent_labels = one_less_than_current
138 | csharp_indent_switch_labels = true
139 |
140 | # Space preferences
141 | csharp_space_after_cast = false
142 | csharp_space_after_colon_in_inheritance_clause = true
143 | csharp_space_after_comma = true
144 | csharp_space_after_dot = false
145 | csharp_space_after_keywords_in_control_flow_statements = true
146 | csharp_space_after_semicolon_in_for_statement = true
147 | csharp_space_around_binary_operators = before_and_after
148 | csharp_space_around_declaration_statements = false
149 | csharp_space_before_colon_in_inheritance_clause = true
150 | csharp_space_before_comma = false
151 | csharp_space_before_dot = false
152 | csharp_space_before_open_square_brackets = false
153 | csharp_space_before_semicolon_in_for_statement = false
154 | csharp_space_between_empty_square_brackets = false
155 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
156 | csharp_space_between_method_call_name_and_opening_parenthesis = false
157 | csharp_space_between_method_call_parameter_list_parentheses = false
158 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
159 | csharp_space_between_method_declaration_name_and_open_parenthesis = false
160 | csharp_space_between_method_declaration_parameter_list_parentheses = false
161 | csharp_space_between_parentheses = false
162 | csharp_space_between_square_brackets = false
163 |
164 | # Wrapping preferences
165 | csharp_preserve_single_line_blocks = true
166 | csharp_preserve_single_line_statements = true
167 |
168 | #### Naming styles ####
169 |
170 | # Naming rules
171 |
172 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
173 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
174 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
175 |
176 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
177 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types
178 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
179 |
180 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
181 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
182 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
183 |
184 | # Symbol specifications
185 |
186 | dotnet_naming_symbols.interface.applicable_kinds = interface
187 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
188 | dotnet_naming_symbols.interface.required_modifiers =
189 |
190 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
191 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
192 | dotnet_naming_symbols.types.required_modifiers =
193 |
194 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
195 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
196 | dotnet_naming_symbols.non_field_members.required_modifiers =
197 |
198 | # Naming styles
199 |
200 | dotnet_naming_style.pascal_case.required_prefix =
201 | dotnet_naming_style.pascal_case.required_suffix =
202 | dotnet_naming_style.pascal_case.word_separator =
203 | dotnet_naming_style.pascal_case.capitalization = pascal_case
204 |
205 | dotnet_naming_style.begins_with_i.required_prefix = I
206 | dotnet_naming_style.begins_with_i.required_suffix =
207 | dotnet_naming_style.begins_with_i.word_separator =
208 | dotnet_naming_style.begins_with_i.capitalization = pascal_case
209 |
--------------------------------------------------------------------------------
/samples/PickAll.Sample/Options.cs:
--------------------------------------------------------------------------------
1 | using CommandLine;
2 | using System.Collections.Generic;
3 |
4 | sealed class Options
5 | {
6 | [Value(0, MetaName = "search query", HelpText = "Query to submit to search engines",
7 | Required = true)]
8 | public string Query { get; set; }
9 |
10 | [Option("timeout", HelpText = "Maximum timeout for HTTP requests in seconds")]
11 | public uint? Timeout { get; set; }
12 |
13 | [Option('f', "fuzzy", HelpText = "Fuzzy matching of Levenshtein distance 0-10")]
14 | public string FuzzyMatch { get; set; }
15 |
16 | [Option('i', "improve", HelpText = "Enable improve search post processor")]
17 | public bool Improve { get; set; }
18 |
19 | [Option('t', "textify", HelpText = "Enable textify post processor")]
20 | public bool Wordify { get; set; }
21 |
22 | [Option('e', "engines", HelpText = "Search engines to use separated by ':'",
23 | Separator = ':')]
24 | public IEnumerable Engines { get; set; }
25 | }
26 |
--------------------------------------------------------------------------------
/samples/PickAll.Sample/OptionsExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using PickAll;
4 |
5 | static class OptionsExtensions
6 | {
7 | public static SearchContext ToContext(this Options options)
8 | {
9 | SearchContext context;
10 | if (!options.Engines.Any()) {
11 | context = SearchContext.Default;
12 | }
13 | else {
14 | context = new SearchContext();
15 | foreach (var engine in options.Engines) {
16 | context = context.With(engine);
17 | }
18 | context = context
19 | .With()
20 | .With();
21 | }
22 | context = context.WithEvents();
23 | if (options.Timeout.HasValue) {
24 | context = context.WithConfiguration(
25 | new ContextSettings {
26 | Timeout = TimeSpan.FromSeconds(options.Timeout.Value) },
27 | merge: true);
28 | }
29 | if (!string.IsNullOrEmpty(options.FuzzyMatch)) {
30 | context = context.With(
31 | new FuzzyMatchSettings {
32 | Text = options.FuzzyMatch,
33 | MaximumDistance = 10 });
34 | }
35 | if (options.Improve) {
36 | context = context.With(
37 | new ImproveSettings {
38 | WordCount = 2,
39 | NoiseLength = 3});
40 | }
41 | if (options.Wordify) {
42 | context = context.With(
43 | new TextifySettings {
44 | SanitizeText = true,
45 | NoiseLength = 3});
46 | }
47 | return context;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/samples/PickAll.Sample/PickAll.Sample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Exe
8 | net5.0
9 | 9.0
10 | gsscoder
11 | PickAll
12 | gsscoder
13 | false
14 |
15 |
16 | ../../artifacts/PickAll.Sample/Debug
17 |
18 |
19 | ../../artifacts/PickAll.Sample/Release
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/samples/PickAll.Sample/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using CommandLine;
4 |
5 | sealed class Program
6 | {
7 | const int exitOK = 0;
8 | const int exitFail = 1;
9 |
10 | static int Main(string[] args)
11 | {
12 | return Parser.Default.ParseArguments(args)
13 | .MapResult(options => ExecuteSearch(options).Result,
14 | _ => exitFail);
15 | }
16 |
17 | static async Task ExecuteSearch(Options options)
18 | {
19 | var context = options.ToContext();
20 | context.SearchBegin += (sender, e) => Console.WriteLine($"Searching '{e.Query}' ...");
21 | var results = await context.SearchAsync(options.Query);
22 | foreach (var result in results) {
23 | Console.WriteLine(
24 | $"[{result.Index}] {result.Originator}: \"{result.Description}\": \"{result.Url}\"");
25 | if (result.Data != null) {
26 | Console.WriteLine(
27 | $"\tData:\n\t\t{result.Data}");
28 | }
29 | }
30 | return exitOK;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/samples/PickAll.Sample/paket.references:
--------------------------------------------------------------------------------
1 | group sample
2 | CommandLineParser
3 |
--------------------------------------------------------------------------------
/src/PickAll/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{csproj,config}]
2 | indent_style = space
3 | indent_size = 2
4 |
5 | # C# files
6 | [*.cs]
7 |
8 | #### Core EditorConfig Options ####
9 |
10 | # Indentation and spacing
11 | indent_size = 4
12 | indent_style = space
13 | tab_width = 4
14 |
15 | # New line preferences
16 | end_of_line = crlf
17 | insert_final_newline = false
18 |
19 | #### .NET Coding Conventions ####
20 |
21 | # Organize usings
22 | dotnet_separate_import_directive_groups = false
23 | dotnet_sort_system_directives_first = true
24 | file_header_template = unset
25 |
26 | # this. and Me. preferences
27 | dotnet_style_qualification_for_event = false
28 | dotnet_style_qualification_for_field = false
29 | dotnet_style_qualification_for_method = false
30 | dotnet_style_qualification_for_property = false
31 |
32 | # Language keywords vs BCL types preferences
33 | dotnet_style_predefined_type_for_locals_parameters_members = true
34 | dotnet_style_predefined_type_for_member_access = true
35 |
36 | # Parentheses preferences
37 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
38 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
39 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary
40 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
41 |
42 | # Modifier preferences
43 | dotnet_style_require_accessibility_modifiers = for_non_interface_members
44 |
45 | # Expression-level preferences
46 | dotnet_style_coalesce_expression = true
47 | dotnet_style_collection_initializer = true
48 | dotnet_style_explicit_tuple_names = true
49 | dotnet_style_null_propagation = true
50 | dotnet_style_object_initializer = true
51 | dotnet_style_operator_placement_when_wrapping = beginning_of_line
52 | dotnet_style_prefer_auto_properties = true
53 | dotnet_style_prefer_compound_assignment = true
54 | dotnet_style_prefer_conditional_expression_over_assignment = true
55 | dotnet_style_prefer_conditional_expression_over_return = true
56 | dotnet_style_prefer_inferred_anonymous_type_member_names = true
57 | dotnet_style_prefer_inferred_tuple_names = true
58 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true
59 | dotnet_style_prefer_simplified_boolean_expressions = true
60 | dotnet_style_prefer_simplified_interpolation = true
61 |
62 | # Field preferences
63 | dotnet_style_readonly_field = true
64 |
65 | # Parameter preferences
66 | dotnet_code_quality_unused_parameters = all
67 |
68 | # Suppression preferences
69 | dotnet_remove_unnecessary_suppression_exclusions = none
70 |
71 | #### C# Coding Conventions ####
72 |
73 | # var preferences
74 | csharp_style_var_elsewhere = false
75 | csharp_style_var_for_built_in_types = false
76 | csharp_style_var_when_type_is_apparent = false
77 |
78 | # Expression-bodied members
79 | csharp_style_expression_bodied_accessors = true
80 | csharp_style_expression_bodied_constructors = false
81 | csharp_style_expression_bodied_indexers = true
82 | csharp_style_expression_bodied_lambdas = true
83 | csharp_style_expression_bodied_local_functions = false
84 | csharp_style_expression_bodied_methods = false
85 | csharp_style_expression_bodied_operators = false
86 | csharp_style_expression_bodied_properties = true
87 |
88 | # Pattern matching preferences
89 | csharp_style_pattern_matching_over_as_with_null_check = true
90 | csharp_style_pattern_matching_over_is_with_cast_check = true
91 | csharp_style_prefer_not_pattern = true
92 | csharp_style_prefer_pattern_matching = true
93 | csharp_style_prefer_switch_expression = true
94 |
95 | # Null-checking preferences
96 | csharp_style_conditional_delegate_call = true
97 |
98 | # Modifier preferences
99 | csharp_prefer_static_local_function = true
100 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
101 |
102 | # Code-block preferences
103 | csharp_prefer_braces = true
104 | csharp_prefer_simple_using_statement = true
105 |
106 | # Expression-level preferences
107 | csharp_prefer_simple_default_expression = true
108 | csharp_style_deconstructed_variable_declaration = true
109 | csharp_style_implicit_object_creation_when_type_is_apparent = true
110 | csharp_style_inlined_variable_declaration = true
111 | csharp_style_pattern_local_over_anonymous_function = true
112 | csharp_style_prefer_index_operator = true
113 | csharp_style_prefer_range_operator = true
114 | csharp_style_throw_expression = true
115 | csharp_style_unused_value_assignment_preference = discard_variable
116 | csharp_style_unused_value_expression_statement_preference = discard_variable
117 |
118 | # 'using' directive preferences
119 | csharp_using_directive_placement = outside_namespace
120 |
121 | #### C# Formatting Rules ####
122 |
123 | # New line preferences
124 | csharp_new_line_before_catch = true
125 | csharp_new_line_before_else = true
126 | csharp_new_line_before_finally = true
127 | csharp_new_line_before_members_in_anonymous_types = true
128 | csharp_new_line_before_members_in_object_initializers = true
129 | csharp_new_line_before_open_brace = anonymous_methods,anonymous_types,lambdas,methods,object_collection_array_initializers,properties,types
130 | csharp_new_line_between_query_expression_clauses = true
131 |
132 | # Indentation preferences
133 | csharp_indent_block_contents = true
134 | csharp_indent_braces = false
135 | csharp_indent_case_contents = true
136 | csharp_indent_case_contents_when_block = true
137 | csharp_indent_labels = one_less_than_current
138 | csharp_indent_switch_labels = true
139 |
140 | # Space preferences
141 | csharp_space_after_cast = false
142 | csharp_space_after_colon_in_inheritance_clause = true
143 | csharp_space_after_comma = true
144 | csharp_space_after_dot = false
145 | csharp_space_after_keywords_in_control_flow_statements = true
146 | csharp_space_after_semicolon_in_for_statement = true
147 | csharp_space_around_binary_operators = before_and_after
148 | csharp_space_around_declaration_statements = false
149 | csharp_space_before_colon_in_inheritance_clause = true
150 | csharp_space_before_comma = false
151 | csharp_space_before_dot = false
152 | csharp_space_before_open_square_brackets = false
153 | csharp_space_before_semicolon_in_for_statement = false
154 | csharp_space_between_empty_square_brackets = false
155 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
156 | csharp_space_between_method_call_name_and_opening_parenthesis = false
157 | csharp_space_between_method_call_parameter_list_parentheses = false
158 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
159 | csharp_space_between_method_declaration_name_and_open_parenthesis = false
160 | csharp_space_between_method_declaration_parameter_list_parentheses = false
161 | csharp_space_between_parentheses = false
162 | csharp_space_between_square_brackets = false
163 |
164 | # Wrapping preferences
165 | csharp_preserve_single_line_blocks = true
166 | csharp_preserve_single_line_statements = true
167 |
168 | #### Naming styles ####
169 |
170 | # Naming rules
171 |
172 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
173 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
174 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
175 |
176 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
177 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types
178 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
179 |
180 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
181 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
182 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
183 |
184 | # Symbol specifications
185 |
186 | dotnet_naming_symbols.interface.applicable_kinds = interface
187 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
188 | dotnet_naming_symbols.interface.required_modifiers =
189 |
190 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
191 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
192 | dotnet_naming_symbols.types.required_modifiers =
193 |
194 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
195 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
196 | dotnet_naming_symbols.non_field_members.required_modifiers =
197 |
198 | # Naming styles
199 |
200 | dotnet_naming_style.pascal_case.required_prefix =
201 | dotnet_naming_style.pascal_case.required_suffix =
202 | dotnet_naming_style.pascal_case.word_separator =
203 | dotnet_naming_style.pascal_case.capitalization = pascal_case
204 |
205 | dotnet_naming_style.begins_with_i.required_prefix = I
206 | dotnet_naming_style.begins_with_i.required_suffix =
207 | dotnet_naming_style.begins_with_i.word_separator =
208 | dotnet_naming_style.begins_with_i.capitalization = pascal_case
209 |
--------------------------------------------------------------------------------
/src/PickAll/Abstractions/IFetchedDocument.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 |
4 | namespace PickAll
5 | {
6 | /// Represents a document fetched without HTML DOM.
7 | public interface IFetchedDocument : IEquatable
8 | {
9 | byte[] Content { get; }
10 |
11 | int Length { get; }
12 |
13 | long LongLength { get; }
14 |
15 | string Text();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/PickAll/Abstractions/IFetchingContext.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace PickAll
4 | {
5 | /// Represents a context in which the a document without HTML DOM is fetched.
6 | public interface IFetchingContext
7 | {
8 | Task FetchAsync(string address);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/PickAll/Abstractions/PostProcessor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace PickAll
5 | {
6 | /// Represents a post processor service managed by SearchContext.
7 | public abstract class PostProcessor : Service
8 | {
9 | public PostProcessor(object settings)
10 | {
11 | Settings = settings;
12 | }
13 |
14 | public virtual bool PublishEvents => false;
15 |
16 | public abstract IEnumerable Process(IEnumerable results);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/PickAll/Abstractions/Searcher.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Threading.Tasks;
4 |
5 | namespace PickAll
6 | {
7 | /// Represents a searching service managed by SearchContext.
8 | public abstract class Searcher : Service
9 | {
10 | public Searcher(object settings)
11 | {
12 | Settings = settings;
13 | Name = GetType().Name;
14 | }
15 |
16 | internal event EventHandler ResultCreated;
17 |
18 | /// The searcher identifier set to class name.
19 | public string Name { get; private set; }
20 |
21 | /// Performs the actual search and returns a sequence of ResultInfo.
22 | public abstract Task> SearchAsync(string query);
23 |
24 | protected ResultInfo CreateResult(
25 | int index, string url, string description, object data = null)
26 | {
27 | var result = new ResultInfo(Name, index, url, description, data);
28 | EventHelper.RaiseEvent(this, ResultCreated,
29 | () => new ResultHandledEventArgs(result, ServiceType.Searcher), Context.Settings.EnableRaisingEvents);
30 | return result;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/PickAll/Abstractions/Service.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace PickAll
4 | {
5 | /// Represents a service managed by SearchContext.
6 | public abstract class Service
7 | {
8 | SearchContext _context;
9 | internal event EventHandler Load;
10 |
11 | public SearchContext Context
12 | {
13 | get { return _context; }
14 | set
15 | {
16 | _context = value;
17 | // Guard against raising load event before configuration happens.
18 | // A service is loaded when is bound to a search context.
19 | if (_context == null) return;
20 | EventHelper.RaiseEvent(this, Load, EventArgs.Empty, _context.Settings.EnableRaisingEvents);
21 | }
22 | }
23 |
24 | public RuntimeInfo Runtime { get; internal set; }
25 |
26 | protected object Settings { get; set; }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/PickAll/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | #if DEBUG
2 | using System;
3 | [assembly: CLSCompliant(true)]
4 | #endif
5 |
--------------------------------------------------------------------------------
/src/PickAll/ContextSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace PickAll
4 | {
5 | /// Settings for a search context.
6 | public struct ContextSettings
7 | {
8 | int? _maximumResults;
9 |
10 | /// Maximum results a search is allowed to return.
11 | public int? MaximumResults
12 | {
13 | get { return _maximumResults; }
14 | set
15 | {
16 | if (value.HasValue) Guard.AgainstNegative("MaximumResults", value.Value);
17 | _maximumResults = value;
18 | }
19 | }
20 |
21 | /// Timeout for each HTTP request performed.
22 | public TimeSpan? Timeout { get; set; }
23 |
24 | /// Enables events in search context and services.
25 | public bool EnableRaisingEvents { get; set; }
26 |
27 | internal ContextSettings Clone()
28 | {
29 | return new ContextSettings
30 | {
31 | MaximumResults = MaximumResults,
32 | Timeout = Timeout,
33 | EnableRaisingEvents = EnableRaisingEvents
34 | };
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/PickAll/Events.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace PickAll
4 | {
5 | /// Defines the service type.
6 | public enum ServiceType
7 | {
8 | /// Searcher service.
9 | Searcher,
10 | /// Post processor service.
11 | PostProcessor
12 | }
13 |
14 | /// Holds event data for the SearchBegin event.
15 | public sealed class SearchBeginEventArgs : EventArgs
16 | {
17 | public SearchBeginEventArgs(string query) => Query = query;
18 |
19 | public string Query { get; private set; }
20 | }
21 |
22 | /// Holds event data for the ResultProcessed event.
23 | public sealed class ResultHandledEventArgs : EventArgs
24 | {
25 | public ResultHandledEventArgs(ResultInfo result, ServiceType type)
26 | {
27 | Result = result;
28 | Type = type;
29 | }
30 |
31 | public ResultInfo Result { get; private set; }
32 |
33 | public ServiceType Type { get; private set; }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/PickAll/FetchedDocument.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using System.Text;
3 |
4 | namespace PickAll
5 | {
6 | /// Default implementation of a document fetched without HTML DOM.
7 | public sealed class FetchedDocument : IFetchedDocument
8 | {
9 | public static readonly IFetchedDocument Empty = new FetchedDocument();
10 |
11 | FetchedDocument() => Content = new byte[] {};
12 |
13 | #if DEBUG
14 | public FetchedDocument(byte[] content) => Content = content;
15 | #else
16 | internal FetchedDocument(byte[] content) => Content = content;
17 | #endif
18 |
19 | public override bool Equals(object value) =>
20 | value is FetchedDocument f &&
21 | Enumerable.SequenceEqual(f.Content, Content) &&
22 | f.Length.Equals(Length) &&
23 | f.LongLength.Equals(LongLength);
24 |
25 | public bool Equals(IFetchedDocument other) =>
26 | Enumerable.SequenceEqual(other.Content, Content) &&
27 | other.Length.Equals(Length) &&
28 | other.LongLength.Equals(LongLength);
29 |
30 | public override int GetHashCode()
31 | {
32 | unchecked {
33 | var hash = 17;
34 | hash = hash * 31 + Content.GetHashCode();
35 | hash = hash * 31 + Length.GetHashCode();
36 | return hash;
37 | }
38 | }
39 |
40 | public byte[] Content { get; private set; }
41 |
42 | public string Text() => Encoding.UTF8.GetString(Content);
43 |
44 | public int Length => Content.Length;
45 |
46 | public long LongLength => Content.LongLength;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/PickAll/FetchedDocumentExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Text.RegularExpressions;
3 | using System.Linq;
4 |
5 | namespace PickAll
6 | {
7 | public static class FetchedDocumentExtensions
8 | {
9 | public static string ElementSelector(this IFetchedDocument document, string tag)
10 | {
11 | Guard.AgainstNull(nameof(document), document);
12 |
13 | return document.ElementSelectorAll(tag).SingleOrDefault() ?? string.Empty;
14 | }
15 |
16 | public static IEnumerable ElementSelectorAll(this IFetchedDocument document, string tag)
17 | {
18 | Guard.AgainstNull(nameof(document), document);
19 | Guard.AgainstNull(nameof(tag), tag);
20 | Guard.AgainstEmptyWhiteSpace(nameof(tag), tag);
21 |
22 | var getElement = new Regex($@"(?<=<{tag}>)(.|\n)*?(?=<\/{tag}>)",
23 | RegexOptions.Compiled | RegexOptions.Multiline);
24 | var matches = getElement.Matches(document.Text());
25 | var contents = new List();
26 | foreach (Match match in matches) {
27 | contents.Add(match.Value);
28 | }
29 | return contents;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/PickAll/FetchingContext.cs:
--------------------------------------------------------------------------------
1 | using System.Net.Http;
2 | using System.Threading.Tasks;
3 |
4 | namespace PickAll
5 | {
6 | /// The context in which the a document without HTML DOM is fetched.
7 | public sealed class FetchingContext : IFetchingContext
8 | {
9 | private readonly HttpClient _client;
10 |
11 | #if DEBUG
12 | public FetchingContext(HttpClient httpClient) => _client = httpClient;
13 | #else
14 | internal FetchingContext(HttpClient httpClient) => _client = httpClient;
15 | #endif
16 |
17 | public async Task FetchAsync(string address)
18 | {
19 | Guard.AgainstNull(nameof(address), address);
20 | Guard.AgainstEmptyWhiteSpace(nameof(address), address);
21 |
22 | try {
23 | var response = await _client.GetAsync(address);
24 | if (!response.IsSuccessStatusCode) {
25 | return FetchedDocument.Empty;
26 | }
27 | return new FetchedDocument(await response.Content.ReadAsByteArrayAsync());
28 | }
29 | catch (HttpRequestException) {
30 | return FetchedDocument.Empty;
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/PickAll/Internal/EventHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.CompilerServices;
3 |
4 | static class EventHelper
5 | {
6 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
7 | public static void RaiseEvent(object sender, EventHandler handler, EventArgs args, bool enabled)
8 | {
9 | if (enabled && handler != null) {
10 | handler(sender, args);
11 | }
12 | }
13 |
14 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
15 | public static void RaiseEvent(object sender, EventHandler handler, Func args, bool enabled)
16 | where T : EventArgs
17 | {
18 | if (enabled && handler != null) {
19 | handler(sender, args());
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/PickAll/Internal/Fuzzy.cs:
--------------------------------------------------------------------------------
1 | // From: https://github.com/gsscoder/sharprhythm/blob/master/src/SharpRhythm/Algorithms/LevenshteinFuzzyMatch.cs
2 |
3 | using System;
4 |
5 | interface IFuzzyMatch
6 | {
7 | uint Compare(string first, string second);
8 | }
9 |
10 | sealed class LevenshteinFuzzyMatch : IFuzzyMatch
11 | {
12 | public uint Compare(string first, string second)
13 | {
14 | if (first == null) throw new ArgumentNullException(nameof(first));
15 | if (second == null) throw new ArgumentNullException(nameof(second));
16 |
17 | uint n = (uint)first.Length;
18 | uint m = (uint)second.Length;
19 | uint[,] d = new uint[n + 1, m + 1];
20 |
21 | // Step 1
22 | if (n == 0) {
23 | return m;
24 | }
25 | if (m == 0) {
26 | return n;
27 | }
28 | // Step 2
29 | for (uint i = 0; i <= n; d[i, 0] = i++) {
30 | }
31 | for (uint j = 0; j <= m; d[0, j] = j++) {
32 | }
33 | // Step 3
34 | for (uint i = 1; i <= n; i++) {
35 | //Step 4
36 | for (uint j = 1; j <= m; j++) {
37 | // Step 5
38 | uint cost = (second[(int)j - 1] == first[(int)i - 1]) ? 0 : 1u;
39 | // Step 6
40 | d[i, j] = Math.Min(
41 | Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
42 | d[i - 1, j - 1] + cost);
43 | }
44 | }
45 | // Step 7
46 | return d[n, m];
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/PickAll/Internal/Guard.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Runtime.CompilerServices;
4 |
5 | static class Guard
6 | {
7 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
8 | public static void AgainstNull(string argumentName, object value)
9 | {
10 | if (value == null) throw new ArgumentNullException(argumentName,
11 | $"{argumentName} cannot be null.");
12 | }
13 |
14 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
15 | public static void AgainstEmptyWhiteSpace(string argumentName, string value)
16 | {
17 | if (value.Trim() == string.Empty) throw new ArgumentException(
18 | $"{argumentName} cannot be empty or contains only white spaces.", argumentName);
19 | }
20 |
21 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
22 | public static void AgainstNegative(string argumentName, int value)
23 | {
24 | if (value < 0) throw new ArgumentException(argumentName,
25 | $"{argumentName} cannot be lesser than zero.");
26 | }
27 |
28 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
29 | public static void AgainstSubclassExcept(string argumentName, object value)
30 | {
31 | if (!value.GetType().IsSubclassOf(typeof(T))) throw new NotSupportedException(
32 | $"{argumentName} must inherit from {nameof(T)}.");
33 | }
34 |
35 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
36 | public static void AgainstSubclassExcept(string argumentName, params Type[] types)
37 | {
38 | if (types.Any(t => !t.IsSubclassOf(typeof(T)))) throw new NotSupportedException(
39 | $"All {argumentName} must inherit from {nameof(T)}.");
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/PickAll/Internal/HtmlElementExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using AngleSharp.Dom;
3 | using AngleSharp.Html.Dom;
4 |
5 | static class HtmlElementExtensions
6 | {
7 | public static string FirstChildText(this IHtmlElement element,
8 | params string[] selectorsGroup)
9 | {
10 | foreach (var selectors in selectorsGroup) {
11 | var selected = element.QuerySelector(selectors);
12 | if (selected != null) {
13 | if (selected.ChildNodes.Count() > 0) {
14 | return selected.FirstChild.Text();
15 | }
16 | }
17 | }
18 | return string.Empty;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/PickAll/Internal/ObjectExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | static class ObjectExtensions
5 | {
6 | public static IEnumerable Add(this IEnumerable collection, T newElement)
7 | {
8 | foreach (var element in collection) {
9 | yield return element;
10 | }
11 | yield return newElement;
12 | }
13 |
14 | public static IEnumerable