├── CONTRIBUTING.md ├── CHANGELOG.md ├── src ├── DotNetSearch │ ├── SearchResponse.cs │ ├── PackageVersion.cs │ ├── Extensions │ │ └── IntegerFormatExtensions.cs │ ├── Package.cs │ ├── Program.cs │ ├── DotNetSearch.csproj │ └── SearchCommand.cs └── DotNetSearch.sln ├── .vscode ├── tasks.json └── launch.json ├── .github ├── dependabot.yml └── workflows │ └── dotnet-core.yml ├── LICENSE ├── .gitignore └── README.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | A few simple rules for the road. 5 | 6 | 1. Before opening a PR with a significant change, open an issue so we can discuss design issues. 7 | 1. Play nice. -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [v1.0.1] 4 | Support .NET 6, 7 and 8. 5 | 6 | ## [v1.0.0] 7 | Bump to v1 with the GA release of .NET Core 2.1 8 | 9 | ## [v0.1.0] 10 | Initial release 11 | - Provides a simple command-line web server for dotnet -------------------------------------------------------------------------------- /src/DotNetSearch/SearchResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace DotNetSearch 4 | { 5 | public class SearchResponse 6 | { 7 | public int TotalHits { get; set; } 8 | public IEnumerable Data { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/DotNetSearch/PackageVersion.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace DotNetSearch 4 | { 5 | public class PackageVersion 6 | { 7 | [JsonProperty("@id")] 8 | public string Id { get; set; } 9 | public string Version { get; set; } 10 | public int Downloads { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/src/DotNetSearch/DotNetSearch.csproj" 11 | ], 12 | "problemMatcher": "$msCompile" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "nuget" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | target-branch: "master" 13 | open-pull-requests-limit: 20 14 | -------------------------------------------------------------------------------- /src/DotNetSearch/Extensions/IntegerFormatExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace DotNetSearch.Extensions 4 | { 5 | public static class NumberFormatExtensions 6 | { 7 | public static string ToAbbrString(this long value) 8 | { 9 | switch(value) 10 | { 11 | case var exp when (value > 999999): 12 | return exp.ToString("0,,.#0M", CultureInfo.InvariantCulture); 13 | case var exp when (value > 999): 14 | return exp.ToString("0,.#0K", CultureInfo.InvariantCulture); 15 | default: 16 | return value.ToString(); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/dotnet-core.yml: -------------------------------------------------------------------------------- 1 | name: .NET Core 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Setup .NET 17 | uses: actions/setup-dotnet@v4.0.0 18 | with: 19 | dotnet-version: | 20 | 6.0.x 21 | 7.0.x 22 | 8.0.x 23 | - name: Install dependencies 24 | run: dotnet restore src/DotNetSearch.sln 25 | - name: Build 26 | run: dotnet build --configuration Release --no-restore src/DotNetSearch.sln 27 | - name: Test 28 | run: dotnet test --no-restore --verbosity normal src/DotNetSearch.sln 29 | -------------------------------------------------------------------------------- /src/DotNetSearch/Package.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Newtonsoft.Json; 3 | 4 | namespace DotNetSearch 5 | { 6 | public class Package 7 | { 8 | [JsonProperty("@id")] 9 | public string ApiId { get; set; } 10 | 11 | [JsonProperty("@package")] 12 | public string Type { get; set; } 13 | 14 | public string Registration { get; set; } 15 | public string Id { get; set; } 16 | public string Version { get; set; } 17 | public string Description { get; set; } 18 | public string Summary { get; set; } 19 | public string Title { get; set; } 20 | public string IconUrl { get; set; } 21 | public string LicenseUrl { get; set; } 22 | public string ProjectUrl { get; set; } 23 | public IEnumerable Tags { get; set; } 24 | public IEnumerable Authors { get; set; } 25 | public long TotalDownloads { get; set; } 26 | public bool Verified { get; set; } 27 | public IEnumerable Versions { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Bill Pratt 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 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to find out which attributes exist for C# debugging 3 | // Use hover for the description of the existing attributes 4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (console)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/src/DotNetSearch/bin/Debug/netcoreapp2.1/DotNetSearch.dll", 14 | "args": [], 15 | "cwd": "${workspaceFolder}/src/DotNetSearch", 16 | // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window 17 | "console": "externalTerminal", 18 | "stopAtEntry": false, 19 | "internalConsoleOptions": "openOnSessionStart" 20 | }, 21 | { 22 | "name": ".NET Core Attach", 23 | "type": "coreclr", 24 | "request": "attach", 25 | "processId": "${command:pickProcess}" 26 | } 27 | ,] 28 | } -------------------------------------------------------------------------------- /src/DotNetSearch/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Threading.Tasks; 7 | using McMaster.Extensions.CommandLineUtils; 8 | using Newtonsoft.Json; 9 | using Newtonsoft.Json.Linq; 10 | 11 | namespace DotNetSearch 12 | { 13 | class Program 14 | { 15 | static int Main(string[] args) 16 | { 17 | #if DEBUG 18 | while (true) 19 | { 20 | var input = Prompt.GetString("> "); 21 | var inputSplit = input?.Split(' ') ?? new string[1]; 22 | 23 | if (inputSplit[0] == "clear") 24 | { 25 | Console.Clear(); 26 | continue; 27 | } 28 | else if (inputSplit[0] == "exit") 29 | { 30 | // Exit out 31 | return 0; 32 | } 33 | 34 | var result = RunApp(inputSplit).GetAwaiter().GetResult(); 35 | } 36 | #else 37 | return RunApp(args).GetAwaiter().GetResult(); 38 | #endif 39 | } 40 | 41 | private static async Task RunApp(string[] args) 42 | { 43 | return await CommandLineApplication.ExecuteAsync(args); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/DotNetSearch/DotNetSearch.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0;net7.0;net8.0 6 | true 7 | true 8 | dotnet-search 9 | dotnet-search 10 | Bill Pratt 11 | Search for Nuget packages using the .NET Core CLI. 12 | 13 | Example: dotnet search json.net 14 | 15 | true 16 | true 17 | portable 18 | dotnet-search 19 | README.md 20 | MIT 21 | https://github.com/billpratt/dotnet-search 22 | dotnet, search 23 | 1.0.1 24 | 1.0.1 25 | git 26 | https://github.com/billpratt/dotnet-search 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/DotNetSearch.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26124.0 5 | MinimumVisualStudioVersion = 15.0.26124.0 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetSearch", "DotNetSearch\DotNetSearch.csproj", "{53B2BE75-18D3-4B64-848C-6F9CCF823BB0}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x64 = Debug|x64 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Debug|x64.ActiveCfg = Debug|Any CPU 21 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Debug|x64.Build.0 = Debug|Any CPU 22 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Debug|x86.ActiveCfg = Debug|Any CPU 23 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Debug|x86.Build.0 = Debug|Any CPU 24 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Release|x64.ActiveCfg = Release|Any CPU 27 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Release|x64.Build.0 = Release|Any CPU 28 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Release|x86.ActiveCfg = Release|Any CPU 29 | {53B2BE75-18D3-4B64-848C-6F9CCF823BB0}.Release|x86.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {BF3E2E71-073A-4D7F-A05A-D362EBDD2E98} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | 290 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | dotnet-search 2 | ============ 3 | 4 | [![NuGet][main-nuget-badge]][main-nuget] [![NuGet][nuget-dl-badge]][main-nuget] 5 | 6 | [main-nuget]: https://www.nuget.org/packages/dotnet-search/ 7 | [main-nuget-badge]: https://img.shields.io/nuget/v/dotnet-search.svg?style=flat-square&label=nuget 8 | [nuget-dl-badge]: https://img.shields.io/nuget/dt/dotnet-search.svg?style=flat-square 9 | 10 | 11 | Search for Nuget packages using the .NET Core CLI. 12 | 13 | ## Installation 14 | 15 | Download and install the one of the currently supported [.NET SDKs](https://www.microsoft.com/net/download). Once installed, run the following command: 16 | 17 | ```bash 18 | dotnet tool install --global dotnet-search 19 | ``` 20 | 21 | If you already have a previous version of **dotnet-search** installed, you can upgrade to the latest version using the following command: 22 | 23 | ```bash 24 | dotnet tool update --global dotnet-search 25 | ``` 26 | ## Usage 27 | 28 | ### Help 29 | 30 | ``` 31 | $ dotnet search --help 32 | 33 | dotnet-search 34 | 35 | Usage: dotnet search [arguments] [options] 36 | 37 | Arguments: 38 | query The search terms used to find packages 39 | 40 | Options: 41 | --version Show version information 42 | -?|-h|--help Show help information 43 | --include-prerelease Include prerelease packages 44 | -s|--skip Number of results to skip. (Default: 0) 45 | -t|--take Number of results to display. (Default: 10) 46 | ``` 47 | 48 | ### Search 49 | 50 | ``` 51 | $ dotnet search json.net 52 | 53 | Name Description Authors Version Downloads Verified 54 | _______________________________________________________________________________________________________________________________ 55 | Newtonsoft.Json Json.NET is a James Newton-King 11.0.2 113.78M * 56 | popular 57 | high-performance 58 | JSON framework for 59 | .NET 60 | ------------------------------------------------------------------------------------------------------------------------------- 61 | Json.NET.Web Json.NET web client Caelan 1.0.49 24.32K 62 | ------------------------------------------------------------------------------------------------------------------------------- 63 | Fluent-Json.NET See the project page Miguel Angelo (masbicudo) 0.2.0 1.14K 64 | for more. 65 | ------------------------------------------------------------------------------------------------------------------------------- 66 | TagCache.Redis.Json.Net JSON.NET Jon Menzies-Smith 1.0.0.2 1.10K 67 | serialization for and Fabian Nicollier 68 | TagCache.Redis 69 | ------------------------------------------------------------------------------------------------------------------------------- 70 | Fluent-Json.NET.Lib_v10 Fluent configuration Miguel Angelo (masbicudo) 0.2.1 51 71 | for Json.NET v10 72 | library. Tried to 73 | follow Fluent 74 | NHibernate mapping 75 | style. Implemented 76 | as converter and 77 | contract resolver. 78 | ------------------------------------------------------------------------------------------------------------------------------- 79 | Fluent-Json.NET.Lib_v9 Fluent configuration Miguel Angelo (masbicudo) 0.2.1 60 80 | for Json.NET v9 81 | library. Tried to 82 | follow Fluent 83 | NHibernate mapping 84 | style. Implemented 85 | as converter and 86 | contract resolver. 87 | ------------------------------------------------------------------------------------------------------------------------------- 88 | NanoMessageBus.Json.NET Additional Jonathan Oliver 2.0.51 13.01K 89 | serialization 90 | provider for 91 | NanoMessageBus based 92 | on the Newtonsoft 93 | Json.NET library. 94 | ------------------------------------------------------------------------------------------------------------------------------- 95 | SOLIDplate.Json.Net A set of boilerplate Afzal Hassen 1.0.0.10 1.54K 96 | code libraries that 97 | facilitate 98 | implementation of 99 | S.O.L.I.D principles 100 | in .Net solutions 101 | ------------------------------------------------------------------------------------------------------------------------------- 102 | Json.Net.Unity3D Forked Esun Kim 9.0.1 627 103 | Newtonsoft.Json to 104 | support Unity3D 105 | ------------------------------------------------------------------------------------------------------------------------------- 106 | Invisual.Serialization.Json.Net Json Serializer Invisual 3.0.5886.24324 456 107 | built with Json.Net 108 | 109 | 1 - 10 of 259 results 110 | ``` 111 | 112 | ### Search including prerelease 113 | 114 | ``` 115 | $ dotnet search microsoft.aspnetcore.all --include-prerelease 116 | 117 | Name Description Authors Version Downloads Verified 118 | _____________________________________________________________________________________________________________ 119 | Microsoft.AspNetCore.All Microsoft.AspNetCore.All Microsoft 2.1.0-preview2-final 2.23M * 120 | 121 | 1 - 1 of 1 results 122 | ``` 123 | 124 | ### Pagination 125 | ``` 126 | $ dotnet search [query] --skip 10 # skip 10, take default 127 | $ dotnet search [query] --take 50 # skip 0, take 50 128 | $ dotnet search [query] --skip 10 --take 50 # skip 10, take 50 129 | ``` 130 | 131 | ## Build 132 | 133 | ``` 134 | git clone https://github.com/billpratt/dotnet-search 135 | ``` 136 | ``` 137 | cd dotnet-search/src/DotNetSearch 138 | ``` 139 | ``` 140 | dotnet pack -c release -o nupkg 141 | ``` 142 | 143 | Output is located in ```src/DotNetSearch/nupkg``` 144 | 145 | ### Uninstall 146 | 147 | ``` 148 | dotnet tool uninstall -g dotnet-search 149 | ``` 150 | 151 | ## Useful Links 152 | 153 | * [How to manage .NET tools](https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools) 154 | * [.NET Core Global Tools and Gotchas](https://www.natemcmaster.com/blog/2018/02/02/dotnet-global-tool/) 155 | -------------------------------------------------------------------------------- /src/DotNetSearch/SearchCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Reflection; 7 | using System.Threading.Tasks; 8 | using DotNetSearch.Extensions; 9 | using McMaster.Extensions.CommandLineUtils; 10 | 11 | namespace DotNetSearch 12 | { 13 | [Command( 14 | Name = "dotnet search", 15 | FullName = "dotnet-search", 16 | Description = "Search for Nuget packages" 17 | )] 18 | [HelpOption] 19 | [VersionOptionFromMember(MemberName = nameof(GetVersion))] 20 | class SearchCommand 21 | { 22 | private static int MaxWordWrapLineLength = 20; 23 | private static int MaxWordWrapColumnWidth = MaxWordWrapLineLength + 5; 24 | private static int SkipResultsDefault = 0; 25 | private static int TakeDefault = 10; 26 | 27 | [Required] 28 | [Argument(0, "query", Description = "The search terms used to find packages")] 29 | public string Query { get; set; } 30 | 31 | [Option("--include-prerelease", "Include prerelease packages", CommandOptionType.NoValue)] 32 | public bool IncludePrerelease { get; set; } 33 | 34 | [Option("-s|--skip", "Number of results to skip. (Default: 0)", CommandOptionType.SingleValue)] 35 | public int Skip { get; set; } = SkipResultsDefault; 36 | 37 | [Option("-t|--take", "Number of results to display. (Default: 10)", CommandOptionType.SingleValue)] 38 | public int Take { get; set; } = TakeDefault; 39 | 40 | private async Task OnExecuteAsync() 41 | { 42 | var httpClient = new HttpClient(); 43 | var url = $"https://api-v2v3search-0.nuget.org/query?q={Query}&prerelease={IncludePrerelease}&skip={Skip}&take={Take}"; 44 | var response = await httpClient.GetAsync(url); 45 | var searchResponse = await response.Content.ReadAsAsync(); 46 | 47 | if (!response.IsSuccessStatusCode) 48 | { 49 | Console.WriteLine($"No results found for {Query}"); 50 | return; 51 | } 52 | 53 | PrintResults(searchResponse); 54 | } 55 | 56 | private void PrintResults(SearchResponse searchResponse) 57 | { 58 | PrintTable(searchResponse); 59 | 60 | var numResultsToDisplay = Take < searchResponse.TotalHits ? Take : searchResponse.TotalHits; 61 | var starting = Skip + 1; 62 | var page = (Skip + Take) / Take; 63 | var ending = page * Take; 64 | if (ending > searchResponse.TotalHits) 65 | ending = searchResponse.TotalHits; 66 | 67 | Console.WriteLine($"{Skip+1} - {ending} of {searchResponse.TotalHits} results"); 68 | } 69 | 70 | private void PrintTable(SearchResponse searchResponse) 71 | { 72 | var data = searchResponse.Data; 73 | 74 | var columnPad = " "; 75 | var headerBoarder = '_'; 76 | var rowDivider = '-'; 77 | 78 | var items = new List<(string header, bool wordWrap, Func valueFunc)> 79 | { 80 | ("Name", false, x => x.Id), 81 | ("Description", true, x => x.Description), 82 | ("Authors", true, x => string.Join(",", x.Authors)), 83 | ("Version", false, x => x.Version), 84 | ("Downloads", false, x => x.TotalDownloads.ToAbbrString()), 85 | ("Verified", false, x => x.Verified ? " *" : "") 86 | }; 87 | 88 | var columns = new List[items.Count]; 89 | var headers = new string[items.Count]; 90 | var columnWidths = new int[items.Count]; 91 | var valueCount = 0; 92 | 93 | foreach (var d in data) 94 | { 95 | int index = 0; 96 | foreach (var act in items) 97 | { 98 | headers[index] = act.header; 99 | var columnValue = act.valueFunc(d)?.ToString() ?? "(null)"; 100 | columnValue = columnValue.Replace("\r\n", " ").Replace("\r", " ").Replace("\n", " "); 101 | 102 | if (columns[index] == null) 103 | { 104 | columns[index] = new List(); 105 | } 106 | 107 | columns[index++].Add(columnValue); 108 | } 109 | valueCount++; 110 | } 111 | 112 | if (valueCount == 0) 113 | { 114 | Console.WriteLine("No results founds"); 115 | return; 116 | } 117 | 118 | for (var i = 0; i < columns.Length; i++) 119 | { 120 | var wordWrap = items[i].wordWrap; 121 | 122 | var width = Math.Max(columns[i].Max(x => x.Length), headers[i].Length); 123 | if (wordWrap) 124 | { 125 | width = Math.Min(width, MaxWordWrapColumnWidth); 126 | } 127 | 128 | columnWidths[i] = width; 129 | } 130 | 131 | int headerWidth = columnWidths.Sum() + columnPad.Length * (items.Count - 1); 132 | 133 | // Determine final layout, word wrapping etc 134 | var rows = new List(); 135 | for (var i = 0; i < valueCount; i++) 136 | { 137 | var rowsToAdd = new List(); 138 | var newRow = new string[columns.Length]; 139 | rowsToAdd.Add(newRow); 140 | for (var j = 0; j < columns.Length; j++) 141 | { 142 | var value = columns[j][i]; 143 | if (value.Length <= columnWidths[j]) 144 | { 145 | newRow[j] = value; 146 | continue; 147 | } 148 | 149 | // Word wrap it 150 | var wordWrapRows = GetWordWrapRows(value); 151 | newRow[j] = wordWrapRows[0]; 152 | 153 | for (var x = 1; x < wordWrapRows.Count; x++) 154 | { 155 | if (rowsToAdd.Count < x + 1) 156 | { 157 | rowsToAdd.Add(new string[columns.Length]); 158 | } 159 | 160 | rowsToAdd[x][j] = wordWrapRows[x]; 161 | } 162 | } 163 | 164 | rows.AddRange(rowsToAdd); 165 | } 166 | 167 | // Print output 168 | 169 | //Print headers 170 | for (var i = 0; i < headers.Length; i++) 171 | { 172 | Console.Write(headers[i].PadRight(columnWidths[i])); 173 | 174 | if (i < headers.Length - 1) 175 | Console.Write(columnPad); 176 | } 177 | 178 | Console.WriteLine(); 179 | 180 | // Print header border 181 | Console.WriteLine("".PadRight(headerWidth, headerBoarder)); 182 | 183 | // Print rows 184 | for (var i = 0; i < rows.Count; i++) 185 | { 186 | int j = 0; 187 | for (; j < columns.Length; j++) 188 | { 189 | var value = rows[i][j] ?? ""; 190 | 191 | if (j == 0 && i > 0 && !string.IsNullOrEmpty(value)) 192 | { 193 | // We found a new package. Print divider 194 | Console.WriteLine("".PadRight(headerWidth, rowDivider)); 195 | 196 | } 197 | 198 | Console.Write(value.PadRight(columnWidths[j])); 199 | 200 | if (j < columnWidths.Length - 1) 201 | { 202 | Console.Write(columnPad); 203 | } 204 | } 205 | 206 | Console.WriteLine(); 207 | } 208 | 209 | Console.WriteLine(); 210 | } 211 | 212 | private static List GetWordWrapRows(string value) 213 | { 214 | var words = value.Split(' '); 215 | var rows = new List(); 216 | var line = ""; 217 | for (var i = 0; i < words.Length; i++) 218 | { 219 | var word = words[i].Replace("\r\n", " ").Replace("\r", " ").Replace("\n", " "); 220 | if ((line + word).Length > MaxWordWrapLineLength) 221 | { 222 | rows.Add(line); 223 | line = ""; 224 | } 225 | 226 | line += $"{word} "; 227 | } 228 | 229 | rows.Add(line); 230 | 231 | return rows; 232 | } 233 | 234 | private void PrintFullDetails(SearchResponse searchResponse) 235 | { 236 | foreach (var data in searchResponse.Data) 237 | { 238 | Console.ForegroundColor = ConsoleColor.Green; 239 | Console.Write(data.Id); 240 | Console.ResetColor(); 241 | Console.WriteLine($" by {string.Join(",", data.Authors)}\tv{data.Version}"); 242 | Console.WriteLine($"{data.Description}{Environment.NewLine}"); 243 | Console.WriteLine($"Tags: {string.Join(',', data.Tags)}"); 244 | Console.WriteLine($"Downloads: {data.TotalDownloads.ToAbbrString()}"); 245 | Console.WriteLine($"{Environment.NewLine}----------------------{Environment.NewLine}"); 246 | } 247 | } 248 | 249 | private static string GetVersion() 250 | => typeof(SearchCommand).Assembly.GetCustomAttribute().InformationalVersion; 251 | } 252 | } --------------------------------------------------------------------------------